Run cannot assign requested address

Issue type: Can’t start container with desired networking. Before I continue endlessly trouble-shooting, I’m hoping someone might just see the problem. I will happily accept referral to the appropriate docs (I have tried to find them). If it shouldn’t have ever worked, please help me see how to do something equivalent.

I want to be able to have only the container assigned to a certain IP address and port combination.

OS Version/build: Debian 8.5 and Ubuntu 14.04.5, at least

Docker versions: 1.11.2, build b9f10c9 & 1.12.3, build 6b644ec

App version: Complicated homemade thing, but can reproduce on others. See below.

Steps to reproduce: Try to use “-p 192.168.x.y:Z:Z” in a docker run command. I’m not sure how to make it always work or not work.

Expected behavior that I got to work at least once: queries to port Z at IP address 192.168.x.y are sent to the container.

Sometimes it works:

For example here: http://dev.glycam.org

  • The docker version is 1.11.2, build b9f10c9
  • The host is Debian 8.5
  • I don’t think the host machine has any other relationship to the ip address, as in:
    ** There is no host interface, real virtual or other, with the address 192.168.x.y.
    ** Neither is the address listed in our internal DNS.
  • Our router does NAT the external address to that one. Could this somehow be the difference?
  • Attempts to start other images in analogous manners on the same host give errors as detailed below.
    ** For example, I can’t get this to work at all: docker run -dit --name my-apache-app -p 192.168.x.y:80:80 -v "$PWD/htdocs/":/usr/local/apache2/htdocs/ httpd:2.4

Here’s how I start the container for the site above:
docker run \ -d -P \ -p 192.168.x.y:80:80 \ --net=DOCKER_NETWORK \ --name NET_NAME \ --net-alias NET_ALIAS \ -v $(pwd)/directory1:/path1/in/container \ -v $(pwd)/directory2:/path2/in/container \ -v $(pwd)/directory3:/path3/in/container \ image_name:image_tag

I stopped and restarted that container tonight to prove that the command still works.

Is there some way to figure out what I did right in this case that I’m not doing in others?

Mostly, it doesn’t work:

I think I’m doing things the same, so there must be something subtle that I’m not seeing. When it doesn’t work, the response is always something like:

docker: Error response from daemon: driver failed programming external connectivity on endpoint my-apache-app (longhash): Error starting userland proxy: listen tcp 192.168.x.y:80: bind: cannot assign requested address.

I haven’t yet duplicated exactly the website (above, that works) elsewhere. Doing that isn’t as simple as you might think. But, I can. Probably.

This has been addressed before. See forum links below. I’ve also found discussion on GitHub. But, I can’t find any resolutions that explain the issue or fix the problem for me. Some of the posts below are under “for mac” or “for windows”, but I’m not convinced that it is an OS thing.

The second thing I quoted causes the third thing.

At a higher level, what are you trying to do, and what’s your end goal? If, as you say, the host system doesn’t have an interface listening on 192.168.x.y, then even if Docker could successfully bind(2), it would be totally ineffectual: the host system can never receive packets on that address, so nothing will ever get sent on to the container.

Is your network topology something like so:

  192.168.x.y +--------+ 10.20.30.1     +-----------------+
<------------ | Router | -------------- | Host +--------+ |
              +--------+     10.20.30.2 |      | Docker | |
                                        |      +--------+ |
                                        +-----------------+

If the host only has a single network interface and your network setup is reasonable, you don’t need the “address” part of the docker run -p option at all. This will cause all inbound packets to the system (including, in my example, the 10.20.30.2/24 private network) on the right port to get forwarded from your container. Your router, on a separate system, is listening on 192.168.x.y (which is what you want) and does reverse NAT to send that port’s traffic to the right place on the internal network.

1 Like

Thanks for the quick reply!

I believe you are saying that this is the problem.

There is no host interface, real virtual or other, with the address 192.168.x.y.

But, this is the situation on the machine where it works. This is also the way I want it (more on that below). From the future (see below): EXCEPT that I was totally wrong about this. So, this post is about how I wish it worked… Sorry for any confusion.

It is also the situation where it doesn’t work.

The network topology on one host that works and one that doesn’t, by design and appearance, if not always behavior, is:

Here:
192.168.x.R – The internal IP address of the gateway/router
192.168.x.H – The IP address of the host on interface if0
192.168.x.D – The intended IP address of the docker container
The ‘bridge’ is ideally an isolated network created for the container, but I’ve tried different permutations in the course of trouble-shooting.

  Public IP                   +----------------------+
    WAN                       | Host                 |
     |                        |          +--------+  |
     V                        | |--------| bridge |  |
 +--------+ 192.168.x.R       +---+      +--------+  |
 | Router | ----------------- |if0|           |      |
 |        |       192.168.x.H +---+           |      |
 |  NAT   |                   |               |      |
 | Pub IP |                   |      +-------------+ |
 |   to   |                   |      |     Docker  | |
 |  .x.D  |                   |      + 192.168.x.D + |
 +--------+                   |      +-------------+ |
                              +----------------------+

What I’m hoping for is that the host won’t have that IP address or answer to it in any way except to forward approved packets to the container.

However, in the instance that works, it does appear that docker has somehow assigned 192.168.x.D to the host, but the host seems unaware of it (per ifconfig and iptables). That is, I can ssh to 192.168.x.D and I get logged into 192.168.x.H, but I don’t want that to happen. The container can’t accept ssh. I don’t want the container’s IP to make it possible to otherwise access the host.

I can almost certainly make a lot of this happen by hand using IPtables, but I had gotten rather excited by the fact that Docker did it automagically, at least in one case, and I’d be very happy if it did it more often.

I really think this should work. VirtualBox does a similar thing with a bridge that always seems to work just fine. And, it has worked at least once with Docker. I do eventually plan to use swarm mode, but only in production: I’d like to use this simpler mechanism for our development environment.

I looked at the threads on GitHub, but they get lengthy and sometimes off-topic, and I kept getting lost in them. Whatever I found that might be a solution didn’t fix my problem.

Maybe I’ll try making a bug report if no one responds soon. To get work done in the meantime, I’ll brush up on IPTables, maybe even check the source code.

OK… I had set up an extra IP address on if0 in the diagram above. I found that using “ip a list if0”. I even had that in my notes but missed it entirely somehow. So, I take back the bits about it working without that (and will edit above to that effect).

But, I still prefer not to have to do that. I would rather that the container - or, better, an isolated docker network - have exclusive access to the IP address so that it could not be used to access the host.