'Make docker use IPv4 for port binding

I have docker host and inside I have one container.

The docker host is binding the port on IPv6 interface only, not on IPv4.

This is the output

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:55082           0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      -
tcp6       0      0 :::80                   :::*                    LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
tcp6       0      0 :::40280                :::*                    LISTEN      -
tcp6       0      0 :::5432                 :::*                    LISTEN      -
tcp6       0      0 :::40122                :::*                    LISTEN      -
tcp6       0      0 :::36378                :::*                    LISTEN      -
tcp6       0      0 :::40543                :::*                    LISTEN      -
tcp6       0      0 :::111                  :::*                    LISTEN      -

Now I have 40122 port on host to link with port 22 on container.

I want to SSH into that container but I am not able to as its only bound to IPv6

This is my docker version Docker version 1.5.0, build a8a31ef

docker ps

201bde6c839a        myapp:latest   "supervisord -n"    3 weeks ago         Up 2 hours          0.0.0.0:40122->22/tcp, 0.0.0.0:40280->80/tcp, 0.0.0.0:40543->443/tcp   myapp

I ran using docker run -d -P -p 40122:22

netstat -tlna

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:3031          0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 :::6379                 :::*                    LISTEN

ps aux

root         1  0.0  0.8  52440 16668 ?        Ss   00:53   0:03 /usr/bin/python /usr/bin/supervisord -n
root        49  0.0  0.1  17980  3048 ?        S    01:32   0:00 bash
root        64  0.0  0.1  46632  2712 ?        S    01:32   0:00 su -l vagrant
vagrant     65  0.0  0.1  21308  3760 ?        S    01:32   0:00 -su
root       288  0.0  0.1  17980  3088 ?        S    02:01   0:00 bash
root       304  0.0  0.1  46632  2720 ?        S    02:01   0:00 su -l vagrant
vagrant    305  0.0  0.1  21304  3804 ?        S    02:01   0:00 -su
vagrant    308  0.0  3.7 429616 75840 ?        Sl+  02:01   0:05 python ./manage.py shell_plus
root       654  0.0  0.4  47596  9848 ?        S    03:12   0:01 /usr/local/bin/uwsgi --die-on-term --ini /var/www/conf/uwsgi.ini
root       655  0.0  0.3  90280  7732 ?        S    03:12   0:00 nginx: master process /usr/sbin/nginx
www-data   656  0.0  0.1  90600  3624 ?        S    03:12   0:00 nginx: worker process
www-data   657  0.0  0.1  90600  3624 ?        S    03:12   0:00 nginx: worker process
www-data   658  0.0  0.1  90600  3624 ?        S    03:12   0:00 nginx: worker process
www-data   659  0.0  0.2  90940  4500 ?        S    03:12   0:00 nginx: worker process
root       660  0.0  0.2  61372  5332 ?        S    03:12   0:00 /usr/sbin/sshd -D
root       669  0.0  0.4  37004  8892 ?        Sl   03:12   0:01 redis-server *:6379
root       856  8.0  2.8 388720 57792 ?        Sl   04:07   0:18 /usr/local/bin/uwsgi --die-on-term --ini /var/www/conf/uwsgi.ini
root       857  8.0  2.8 388720 57792 ?        Sl   04:07   0:18 /usr/local/bin/uwsgi --die-on-term --ini /var/www/conf/uwsgi.ini
root       858  8.0  2.8 388720 57792 ?        Sl   04:07   0:18 /usr/local/bin/uwsgi --die-on-term --ini /var/www/conf/uwsgi.ini
root       859  8.0  2.8 388720 57792 ?        Sl   04:07   0:18 /usr/local/bin/uwsgi --die-on-term --ini /var/www/conf/uwsgi.ini
vagrant    889  0.0  0.1  18692  2508 ?        R+   04:11   0:00 ps aux


Solution 1:[1]

2021 Update:

Currently docker binds to both IPv4 and IPv6 by default.

If you want to explicitly "Make docker use IPv4 for port binding" (as in, have it only bind on the IPv4 port) add 0.0.0.0: before the ports in the -p/--publish option(s), like so:

$ docker run --publish "0.0.0.0:80:80" --publish "0.0.0.0:443:443" --detach nginx

The result will look like this when you're done:

$ docker ps

CONTAINER ID   IMAGE   COMMAND                  CREATED          STATUS         PORTS                                      NAMES
2459bd225751   nginx   "/docker-entrypoint.…"   4 seconds ago    Up 2 seconds   0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   jovial_yonath

The netstat results will look like this:

$ sudo netstat -tulnp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State    PID/Program name
tcp        0      0 0.0.0.0:443   0.0.0.0:*       LISTEN   22676/docker-proxy
tcp        0      0 0.0.0.0:80    0.0.0.0:*       LISTEN   22698/docker-proxy

You can browse or curl to the device to make sure it works, of course.

If you don't add the "0.0.0.0", it will bind on both IP versions, and the PORTS will read 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp, which may not be desirable for security, console spam or predictability reasons.

Solution 2:[2]

Setting net.ipv6.conf.all.forwarding=1 will fix the issue.

This can be done on a live system using sudo sysctl -w net.ipv6.conf.all.forwarding=1

Solution 3:[3]

ISSUE RESOVLED:

USE docker run -it -p 80:80 --name nginx --net=host -d nginx

that's issue we face with VM some time instead of bridge network try with host that will work for you

tcp     0    0 0.0.0.0:80            0.0.0.0:*             LISTEN      - 
tcp6    0    0 :::80                 :::*                  LISTEN      -  

Solution 4:[4]

By default, docker uses AF_INET6 sockets which can be used for both IPv4 and IPv6 connections. This causes netstat to report an IPv6 address for the listening address.

From RedHat https://access.redhat.com/solutions/3114021

Solution 5:[5]

If you want your container ports to bind on your ipv4 address, just :

  • find the settings file
    • /etc/sysconfig/docker-network on RedHat alike
    • /etc/default/docker-network on Debian ans alike
  • edit the network settings
    • add DOCKER_NETWORK_OPTIONS=-ip=xx.xx.xx.xx
    • xx.xx.xx.xx being your real ipv4 (and not 0.0.0.0)
  • restart docker deamon

works for me on docker 1.9.1

Solution 6:[6]

For CentOS users,

I've got same issue on CentOS7 and setting net.ipv4.ip_forward to 1 solves the issue. Please, refer to Docker Networking Disabled: WARNING: IPv4 forwarding is disabled. Networking will not work for more details.

Solution 7:[7]

Try to remove --attachable flag for created networks

Doesn't work

docker network create --attachable --driver overlay --subnet=10.0.3.0/24 --gateway=10.0.3.1 dev

It works, but listeness IPv4 ports still not seeing when you check with sudo netstat -tulnp4

docker network create --attachable --driver overlay --subnet=10.0.3.0/24 --gateway=10.0.3.1 dev

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Archimedes Trajano
Solution 3 agentsmith
Solution 4 Gerassimos Mitropoulos
Solution 5
Solution 6 Youngchae Kim
Solution 7 Dennis V