Make docker use IPv4 for port binding

129,456

Solution 1

As @daniel-t points out in the comment: github.com/docker/docker/issues/2174 is about showing binding only to IPv6 in netstat, but that is not an issue. As that github issues states:

When setting up the proxy, Docker requests the loopback address '127.0.0.1', Linux realises this is an address that exists in IPv6 (as ::0) and opens on both (but it is formally an IPv6 socket). When you run netstat it sees this and tells you it is an IPv6 - but it is still listening on IPv4. If you have played with your settings a little, you may have disabled this trick Linux does - by setting net.ipv6.bindv6only = 1.

In other words, just because you see it as IPv6 only, it is still able to communicate on IPv4 unless you have IPv6 set to only bind on IPv6 with the net.ipv6.bindv6only setting. To be clear, net.ipv6.bindv6only should be 0 - you can run sysctl net.ipv6.bindv6only to verify.

Solution 2

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 3

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 4

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 5

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

Share:
129,456
user3214546
Author by

user3214546

Updated on July 08, 2022

Comments

  • user3214546
    user3214546 almost 2 years

    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
    
  • Thomas Decaux
    Thomas Decaux almost 9 years
    This is a big problem actually. Public cloud like Azure, doesnt speak IPV6 very well, for instance the public Azure load-balancer is attempting an IPV4 as backend.
  • Michael
    Michael almost 9 years
    Seems you may need to install the "Docker VM Extension" in Azure and use Ubuntu 14.04 LTS. However, I do not think there is an issue with ipv6 as this is only on the local host, not the network.
  • Thomas Decaux
    Thomas Decaux almost 9 years
    You are right, the issue was in my config (disabling IPV6 is not a good idea ^^)
  • Dimitri Kopriwa
    Dimitri Kopriwa almost 8 years
    does this work on debian ? shouldn't it be /etc/default/docker ?
  • Dimitri Kopriwa
    Dimitri Kopriwa almost 8 years
    still doesn't work for me, is there a way to completely turn off ipv6?
  • Michael
    Michael almost 8 years
    @bigdong you want ipv6 on.
  • Sylvain
    Sylvain almost 8 years
    @BigDong thanks for the comment, I'm on RedHat like OS so the path is a little different from one OS to the other I tried to reflect your comment in the answer
  • lv0gun9
    lv0gun9 almost 6 years
    @Michael You are my timesaver. :)
  • pkoperek
    pkoperek almost 4 years
    This answer has one advantage: it allows you to "fix" the issue without having to restart the docker daemon (the answer with changing docker config below does). Regarding the top, selected answer: I actually had sysctl net.ipv6.bindv6only=0 so changing this config did not help.
  • ir0h
    ir0h almost 3 years
    Great answer also add it to /etc/sysctl.d/97-ipv6-fwd.conf so it will persist after reboot
  • Barry Chum
    Barry Chum over 2 years
    this should be the 'new' answer to this old thread
  • Alex
    Alex over 2 years
    On macOS I think it's sudo sysctl net.inet6.ip6.forwarding=1
  • Alex
    Alex over 2 years
    sysctl net.inet6.ip6.v6only on macOS