for-linux icon indicating copy to clipboard operation
for-linux copied to clipboard

Binding to `localhost` inside a container fails because ::1 doesn't exist

Open couling opened this issue 3 years ago • 1 comments

  • [x] This is a bug report
  • [ ] This is a feature request
  • [x] I searched existing issues before opening this one

Expected behavior

Programs should be able to safely bind to localhost to create listening sockets inside docker. In particular localhost should always resolve to a valid loopback address.

Either ::1 should exist as a loopback address or /etc/hosts should NOT contain a reference to ::1 localhost.

Actual behavior

By default (without enabling any IPv6 support) containers have a hosts file (/etc/hosts) which looks like this:

127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.8	158872fd16d1

But it does not add ::1 as an IP address on the loopback device:

# ip address show lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever

As a result software attempting to bind to localhost and fails because localhost resolved to ::1 and ::1 is not an address inside the container.

A concrete example; this happens when using python asyncio's create_server (manual page). This call should basically never fail, and yet it always fails inside a docker container:

await asyncio.get_running_loop().create_server(callback, "localhost")

Error:

OSError: [Errno 99] error while attempting to bind on address ('::1', 0, 0, 0): cannot assign requested address

Steps to reproduce the behavior

Output of docker version:

Client:
 Version:           20.10.7
 API version:       1.41
 Go version:        go1.15.14
 Git commit:        f0df350
 Built:             Wed Nov 17 03:05:36 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server:
 Engine:
  Version:          20.10.7
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.15.14
  Git commit:       b0f5bc3
  Built:            Wed Nov 17 03:06:14 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.6
  GitCommit:        d71fcd7d8303cbf684402823e425e9dd2e99285d
 runc:
  Version:          1.0.0
  GitCommit:        84113eef6fc27af1b01b3181f31bbaf708715301
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Output of docker info:

Client:
 Context:    default
 Debug Mode: false

Server:
 Containers: 263
  Running: 2
  Paused: 0
  Stopped: 261
 Images: 5
 Server Version: 20.10.7
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: runc io.containerd.runc.v2 io.containerd.runtime.v1.linux nvidia
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: d71fcd7d8303cbf684402823e425e9dd2e99285d
 runc version: 84113eef6fc27af1b01b3181f31bbaf708715301
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 4.14.268-205.500.amzn2.x86_64
 Operating System: Amazon Linux 2
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.793GiB
 Name: ip-10-20-11-38.ap-southeast-2.compute.internal
 ID: BEL3:HYJB:BHSZ:U6CB:FHPP:YNM7:K3RN:J63K:VQBX:RYE7:IM7Q:J2AZ
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

This was running docker as an AWS ECS instance.

couling avatar Mar 24 '22 13:03 couling

Any solutions?

rzimmerdev avatar Sep 03 '23 04:09 rzimmerdev

I just ran into the same issue. Just use the local adapter loopback-ip: 127.0.0.1. For some reason localhost resolves to a ipv6 address. I don't know why this is not addressed really.

mrdobalina2k avatar May 21 '24 11:05 mrdobalina2k

@mrdobalina2k Few things to note:

  • This issue was fixed in v26.0. See https://docs.docker.com/engine/release-notes/26.0/#bug-fixes-and-enhancements-2.
  • Prior versions are EOL'd -- if you're using an outdated version, please upgrade.
  • If your containerized process binds to both IPv4 and IPv6 and you want to bind only to the IPv4 loopback address, you need to use docker run --sysctl=net.ipv6.conf.all.disable_ipv6=1 to disable IPv6 altogether.
  • This is a legacy issue tracker and is kept only because archiving this repo would make all issues read-only. If you encounter an issue with Docker Engine, you should file an issue against https://github.com/moby/moby. If you encounter an issue with Docker Desktop, you should file an issue against either https://github.com/docker/for-mac or https://github.com/docker/for-win.

I'm going to close this issue as it's been fixed by https://github.com/moby/moby/pull/47062.

akerouanton avatar May 21 '24 12:05 akerouanton