question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

port_bindings don't really expose the container

See original GitHub issue

I originally asked this on SO, but since more people confirmed that this seems like unexpected behaviour, I’ll report it here as well.

I am trying to mimic running a containerized web app exposed at some port

sudo docker run -d -p 1338:1337 kermit/hellonode

in Python using docker-py. So far I got this code to start the instance:

container = c.create_container('kermit/hellonode', name='hello')
c.start(container, port_bindings={1337: ('0.0.0.0', 1338)})

But I can’t access the container at the public port 1338 (which works normally with the first command) - I’m getting connection refused errors. Does anyone know if I’m missing some option to make the Python call create the functional, accessible container?

Inspecting the container tells me that the port is set up as it should be:

$ sudo docker port hello 1337
0.0.0.0:1338

I also experimented with the ports=[1337] option in the create_container call, but it didn’t help either.

As the answer noted, this works if publish_all_ports is used, but then you can’t control the port number.

container = c.create_container('kermit/hellonode', name='hello', ports=[1337])
c.start(container, publish_all_ports=True)
info = c.inspect_container(container)
host_port = info['NetworkSettings']['Ports']['1337'][0]['HostPort']

Issue Analytics

  • State:closed
  • Created 10 years ago
  • Comments:11 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
mpetazzonicommented, Jan 15, 2014

Ok, I found what the problem was. When creating the container, if you don’t define the protocol type (TCP or UDP), the HostConfig will contain an invalid port mapping for the same port that was requested on the start() call:

  u'Ports': {u'8000': None,
   u'8000/tcp': [{u'HostIp': u'0.0.0.0', u'HostPort': u'8082'}]}},

This seems to confuse Docker and it doesn’t create the iptables NAT rule. If you do the following, it works:

43> container = c.create_container('stackbrew/ubuntu:12.04',
    command=['python', '-m', 'SimpleHTTPServer'], ports=[(8000, 'tcp')])
43> c.start(container, port_bindings={8000: ('0.0.0.0', 8082)})
44> c.inspect_container(container)['HostConfig']
44:
{u'Binds': None,
 u'ContainerIDFile': u'',
 u'Links': None,
 u'LxcConf': None,
 u'PortBindings': {u'8000/tcp': [{u'HostIp': u'0.0.0.0',
    u'HostPort': u'8082'}]},
 u'Privileged': False,
 u'PublishAllPorts': False}

45> c.inspect_container(container)['NetworkSettings']
45:
{u'Bridge': u'docker0',
 u'Gateway': u'172.17.42.1',
 u'IPAddress': u'172.17.0.99',
 u'IPPrefixLen': 16,
 u'PortMapping': None,
 u'Ports': {u'8000/tcp': [{u'HostIp': u'0.0.0.0', u'HostPort': u'8082'}]}}

Checks out:

$ sudo iptables -t nat -L -v -n | grep 8000
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8082 to:172.17.0.99:8000
$ docker ps
CONTAINER ID        IMAGE                                                           COMMAND                CREATED             STATUS              PORTS                                                                                              NAMES
159381063215        stackbrew/ubuntu:12.04                                          python -m SimpleHTTP   26 seconds ago      Up 6 seconds        0.0.0.0:8082->8000/tcp                                                                             tender_archimedes
$ echo "HEAD / HTTP/1.0" | nc localhost 8082
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.7.3
Date: Wed, 15 Jan 2014 00:28:16 GMT
Content-type: text/html; charset=ANSI_X3.4-1968
Content-Length: 846
0reactions
mpetazzonicommented, Jan 16, 2014

So, what’s the final word? I agree that the Docker API shouldn’t accept it, but to prevent people from falling into the trap/bug while using docker-py we could default to tcp in create_container() if the protocol is not specified, what do you think?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Docker port binding not working as expected - Stack Overflow
Port binding/publishing in docker is actually publishing container's port to docker-machine's, instead of to localhost's. For example, with
Read more >
Docker Port Binding explained | Better Programming
1. Expose all Docker ports. docker container run -P -d nginx. The -P command opens every port the container exposes ...
Read more >
A Brief Primer on Docker Networking Rules: EXPOSE, -p
However, neither EXPOSE nor --expose depend on the host in any way; these rules don't make ports accessible from the host by default....
Read more >
How to expose port on live containers? - Jhooq
1.1 Edit config.v2.json and update port details · 1.2 Update the PortBindings inside hostconfig.json · 1.3 Restart your docker engine.
Read more >
Docker — How to Edit Bind Exist Container Ports to the Host
Stop the running container which you want to edit, in my case it is mgt-dev-71. ... And add or edit to PortBindings, in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found