New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Different port number are getting mapped on ipv4 and ipv6 for same expose port #42442
Comments
This is observed on
This seems to happen after docker has been running a while (a few weeks) and/or have many left-over containers. This happens in an 32 bit armv7 ubuntu lxc container on an aarch64 ubuntu host. |
Any update on this? Even a simple docker run after keeping the daemon running for long time we can see this being reproduced: # docker run --rm -it -p 6650 -p 8080 apachepulsar/pulsar-standalone:2.7.2 On another terminal: # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
883b78808f76 apachepulsar/pulsar-standalone:2.7.2 "supervisord -n" 24 seconds ago Up 23 seconds 80/tcp, 0.0.0.0:49686->6650/tcp, :::49685->6650/tcp, 0.0.0.0:49685->8080/tcp, :::49684->8080/tcp pedantic_zhukovsky This causes the services to be not accessible e.g. # curl --verbose http://localhost:49685/admin/v2/brokers/ready
* About to connect() to localhost port 49685 (#0)
* Trying ::1...
* Connected to localhost (::1) port 49685 (#0)
> GET //admin/v2/brokers/ready HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:49685
> Accept: */*
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server |
Update.. after daemon restart the ports are correctly assigned.. however we can not restart daemon frequently # systemctl restart docker
...
# docker run --rm -it -p 6650 -p 8080 apachepulsar/pulsar-standalone:2.7.2 From another terminal # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26792898aea6 apachepulsar/pulsar-standalone:2.7.2 "supervisord -n" 24 seconds ago Up 23 seconds 80/tcp, 0.0.0.0:49158->6650/tcp, :::49158->6650/tcp, 0.0.0.0:49157->8080/tcp, :::49157->8080/tcp angry_gates
# curl --verbose http://localhost:49157/admin/v2/brokers/ready
* About to connect() to localhost port 49157 (#0)
* Trying ::1...
* Connected to localhost (::1) port 49157 (#0)
> GET /admin/v2/brokers/ready HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:49157
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 16 Jun 2021 12:52:14 GMT
< broker-address: localhost
< Content-Type: application/json
< Content-Length: 2
< Server: Jetty(9.4.39.v20210325)
<
* Connection #0 to host localhost left intact
ok |
confirming that we're experiencing this as well, the same host port is getting mapped twice onto different container ports, resulting in randomly broken packet routing. |
Same here (Version: 20.10.7-0ubuntu1~20.04.1). Any news? |
Is there any workaround available, other than downgrading? Is there any logging available we could provide to you to further investigate the issue? |
Hi @thaJeztah , That would help a lot as a workaround to this bug (which was created almost 1year ago btw!!) Thanks! |
@kylecarbs and I were debugging a gnarly postgres issue over the weekend, and unfortunately it looks like it is still coming up occassionally: https://github.com/coder/coder/runs/5014420662?check_suite_focus=true#step:8:35 - so thought this might be a good testing Monday task. Intermittently, the test would fail with something like a `401` - invalid e-mail, or a `409` - initial user already created. This was quite surprising, because the tests are designed to spin up their own, isolated database. We tried a few things to debug this... ## Attempt 1: Log out the generated port numbers when running the docker image. Based on the errors, it seemed like one test must be connecting to another test's database - that would explain why we'd get these conflicts! However, logging out the port number that came from docker always gave a unique number... and we couldn't find evidence of one database connecting to another. ## Attempt 2: Store the database in unique, temporary folder. @kylecarbs and I found that the there was a [volume](https://github.com/docker-library/postgres/blob/a83005b407ee6d810413500d8a041c957fb10cf0/11/alpine/Dockerfile#L155) for the postgres data... so @kylecarbs implemented mounting the volume to a unique, per-test temporary folder in #89 It sounded really promising... but unfortunately we hit the issue again! ### Attempt 3... this PR After we hit the failure again, we noticed in the `docker ps` logs something quite strange: ![image](https://user-images.githubusercontent.com/88213859/151913133-522a6c2e-977a-4a65-9315-804531ab7d77.png) When the docker image is run - it creates two port bindings, an IPv4 and an IPv6 one. These _should be the same_ - but surprisingly, they can sometimes be different. It isn't deterministic, and seems to be more common when there are multiple containers running. Importantly, __they can overlap__ as in the above image. Turns out, it seems this is a docker bug: moby/moby#42442 - which may be fixed in newer versions. To work around this bug, we have to manipulate the port bindings (like you would with `-p`) at the command line. We can do this with `docker`/`dockertest`, but it means we have to get a free port ahead of time to know which port to map. With that fix in - the `docker ps` is a little more sane: ![image](https://user-images.githubusercontent.com/88213859/151913432-5f86bc09-8604-4355-ad49-0abeaf8cc0fe.png) ...and hopefully means we can safely run the containers in parallel again.
We have been frequently encountering the same port mapping issue with latest docker engine. If there are any further updates to this same thread please share us the info. |
I am starting multiple testcontainers and the same port leads to different services if accessed via 127.0.0.1 or via ::1 This can be disastrous.
Contrary to what @ncopa said in #42442 (comment) , this happened on a monday morning to me, so the docker host had less than 2 hours of uptime and there were close to 0 left-over containers. |
@n1ngu Can you share which version of Testcontainers are you using when you observe this issue? This seems to be related to dotnet/Docker.DotNet#565 as well. Furthermore, I wonder if this is a bug or intended behavior and users cannot rely on IPv4 and IPv6 having the same mapping in case of random port publishing? |
@kiview I was using python's testcontainers package https://pypi.org/project/testcontainers , I will guess it was version 3.6.1 at that time, but I couldn't tell. While it is clearly technically possible to bind an application to different port numbers on each internet protocol version, I know of no other software that does anything similar. Just as you could also bind to different ports on different IPv4 network interfaces, but you never would. I guess there is some kind of event that introduces a leap between IP v4 and v6 ports sequences, which were intentionally aligned otherwise. This betrays very basic intuitions on how IP works and I honestly think this a bug beyond debate, not a corner case. Darn, in a dual stack network this causes a simple |
No, it's not. It doesn't matter which container is used. We're seeing this on our custom (Linux) containers we use for building. And when it happens, I can try whatever image I want. The problem persists until Docker has been restarted. |
Thanks for sharing that you used the Python implementation @n1ngu. That confirms that this is likely no Testcontainers language implementation specific issue (e.g., the bug observed for .NET) but present in all Testcontainers implementations, regarding the assumptions about how Docker maps random ports. It would be great to get a confirmation from the Docker team whether this is a bug (which I would assume, since very unintuitive and likely caused by some race conditions and misaligned internal state) or it works as intended and we as a client integrating against Docker need to take care of it (our even our users). |
I came up with some reproduction steps. It is essentially about using the port that docker would pick next but only in the IPv4 interface, and then starting a container with a bound port.
My guess is that, in either a workstation or in a shared CI agent or in a production docker cluster, any process can bind an arbitrary high port to itself, accidentally triggering this issue if the port is in the sequence that docker expects to be free. |
Looping back to this #41805 (comment) from @thaJeztah, shall we assume this behaviour works as intended and there are no guarantees about them being mapped onto the same port? |
No. Loopback to #42442 (comment)
This is unacceptable behaviour. Period. |
... since nearly two years now. When will this get fixed? Since a service restart is required to get correct behaviour again, this is a |
As to this being a "DoS" bug; this issue happens when using randomly selected ports from the ephemeral port range; for those, there are no guarantees in any form for those ports to be the same when (re)starting a container or service. If a stable, predictable port is important, then specifying the port-mapping is the correct approach. As to; assigning the same (random) port for IPv4 and IPv6 mappings; contributions welcome if someone is interested in looking into this. |
If you run: |
As described in moby/moby#42442, docker daemon starts to expose a container port on different host ports for IPv4 and IPv6 which breaks the ssh/safe-ssh/ansible backend tests for some containers. To prevent this behavior and flaky tests, only the first line from the `docker port %s 22` command gets parsed to acquire the mapped SSH port.
As described in moby/moby#42442, docker daemon starts to expose a container port on different host ports for IPv4 and IPv6 which breaks the ssh/safe-ssh/ansible backend tests for some containers. To prevent this behavior and flaky tests, only the first line from the `docker port %s 22` command gets parsed to acquire the mapped SSH port.
As described in moby/moby#42442, docker daemon starts to expose a container port on different host ports for IPv4 and IPv6 which breaks the ssh/safe-ssh/ansible backend tests for some containers. To prevent this behavior and flaky tests, only the first line from the `docker port %s 22` command gets parsed to acquire the mapped SSH port.
As described in moby/moby#42442, docker daemon starts to expose a container port on different host ports for IPv4 and IPv6 which breaks the ssh/safe-ssh/ansible backend tests for some containers. To prevent this behavior and flaky tests, only the first line from the `docker port %s 22` command gets parsed to acquire the mapped SSH port.
As described in moby/moby#42442, docker daemon starts to expose a container port on different host ports for IPv4 and IPv6 which breaks the ssh/safe-ssh/ansible backend tests for some containers. To prevent this behavior and flaky tests, only the first line from the `docker port %s 22` command gets parsed to acquire the mapped SSH port.
As described in moby/moby#42442, docker daemon starts to expose a container port on different host ports for IPv4 and IPv6 which breaks the ssh/safe-ssh/ansible backend tests for some containers. To prevent this behavior and flaky tests, only the first line from the `docker port %s 22` command gets parsed to acquire the mapped SSH port.
This affects GitHub Actions runner as well. Using these docs: When I specify only a port: services:
postgres:
image: postgres:11
ports:
- 5432
Result is two different ports are created:
|
Associated docker port mapping bugs: moby/moby#42442 moby/moby#42375 If ipv6 is enabled in docker then these bugs affect this library. This is even if we build the docker network with ipv6 disabled since the ipv6 ports are still forwarded. This creates the potential for localhost for a container to be mapped to two different ports between ipv4 and ipv6. This is fine if you only have one container but once you have multiple containers spun up these ports can overlap where one containers ipv4 port is the same as another containers ipv6 port, at which point if you use localhost you are not guaranteed the ipv4 address and thus can end up calling into the wrong container.
Associated docker port mapping bugs: moby/moby#42442 moby/moby#42375 If ipv6 is enabled in docker then these bugs affect this library. This is even if we build the docker network with ipv6 disabled since the ipv6 ports are still forwarded. This creates the potential for localhost for a container to be mapped to two different ports between ipv4 and ipv6. This is fine if you only have one container but once you have multiple containers spun up these ports can overlap where one containers ipv4 port is the same as another containers ipv6 port, at which point if you use localhost you are not guaranteed the ipv4 address and thus can end up calling into the wrong container.
Kafka tests have been flaky lately and it seems to be due to two factors: - Redpanda RPK tries to create a temporary configuration file in the same location as the `redpanda.yaml` file. If we mount a volume containing `redpanda.yaml` this fails because the `redpanda` user (uid 101) doesn't have permission to chmod. - A manifestation of moby/moby#42442 This PR includes some refactoring to: - Skip the RPK and start redpanda directly using a templated config file - Combine the Kafka launch configuration to avoid repetition - Output the Kafka container logs if `CERBOS_DEBUG_KAFKA` is set Fixes #1875 Signed-off-by: Charith Ellawala <charith@cerbos.dev> --------- Signed-off-by: Charith Ellawala <charith@cerbos.dev>
I came here via testcontainers/testcontainers-dotnet#386 and dotnet/Docker.DotNet#511, and I'm a bit at a loss what to do. Would you say this is a #wontfix on your end, and that the testcontainers project should choose random ports from a lower range, or is this still a bug worth fixing at this level? |
…1775) * Add HTTPStrategy WithForcedIPv4LocalHost To Fix Docker Port Map Bug Associated docker port mapping bugs: moby/moby#42442 moby/moby#42375 If ipv6 is enabled in docker then these bugs affect this library. This is even if we build the docker network with ipv6 disabled since the ipv6 ports are still forwarded. This creates the potential for localhost for a container to be mapped to two different ports between ipv4 and ipv6. This is fine if you only have one container but once you have multiple containers spun up these ports can overlap where one containers ipv4 port is the same as another containers ipv6 port, at which point if you use localhost you are not guaranteed the ipv4 address and thus can end up calling into the wrong container. * chore: rename variable * chore: add print for the assertion --------- Co-authored-by: Manuel de la Peña <mdelapenya@gmail.com>
Description
With docker version
20.10.6, build 370c289
observed that different port is assigned for same exposed port on ipv4 and ipv6. This is causing random failures in application with docker compose up which spawns many different apps containersSteps to reproduce the issue:
Describe the results you received:
Describe the results you expected:
Additional information you deem important (e.g. issue happens only occasionally):
Output of
docker version
:Output of
docker info
:Additional environment details (AWS, VirtualBox, physical, etc.):
The text was updated successfully, but these errors were encountered: