3

I have a Cement application that runs inside of a docker container. In this image I have to connect to etcd. Inside of my docker image I have config that for etcd is set to localhost that I know is not correct!

On my local machine etcd is up and running:

tcp4       0      0  localhost.2379         localhost.51949        ESTABLISHED

The question is how should I connect to etcd server which is outside of docker container? etcd is installed normally without using docker.

Output of my python application when I run it with docker run -p 8084:8084 my_python_image:

Traceback (most recent call last):
  File "my_app.py", line 64, in <module>
    app.run()
  File "/usr/local/lib/python2.7/site-packages/cement/core/foundation.py", line 882, in run
    return_val = self.controller._dispatch()
  File "/usr/local/lib/python2.7/site-packages/cement/core/controller.py", line 477, in _dispatch
    return func()
  File "my_app.py", line 45, in default
    module_rpc = rpc.Rpc('my_module', params=app.config.get_section_dict('etcd'))
  File "/usr/local/lib/python2.7/site-packages/rpc_server/rpc.py", line 31, in __init__
    self.etcd_client.write(self.etcd_nodes, None, dir=True)
  File "/usr/local/lib/python2.7/site-packages/etcd/client.py", line 500, in write
    response = self.api_execute(path, method, params=params)
  File "/usr/local/lib/python2.7/site-packages/etcd/client.py", line 893, in wrapper
    cause=e
etcd.EtcdConnectionFailed: Connection to etcd failed due to MaxRetryError(u"HTTPConnectionPool(host=u'localhost', port=2379): Max retries exceeded with url: /v2/keys/my_module/nodes (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fcc33eaa690>: Failed to establish a new connection: [Errno 111] Connection refused',))",)

2 Answers 2

1
+50

One option is to use the host network driver. If you run the container with the host network driver, localhost will resolve and route to your local machine where etcd is running.

docker run --network=host --userns=host -p 8084:8084 my_python_image

When using the host network driver, the IP of the container will be the same as your local machine's IP address, giving it access to all of the services that are listening on it.

The --userns flag is required for kernels that have namespacing enabled and provides additional permissions to the container in order for it to use host networking.

2
  • Your command raised the same error that could not connect to etcd on localhost: docker run --network=host --userns=host -p 8084:8084 my_python_image
    – Alireza
    Oct 4, 2017 at 8:48
  • From your other comment, it sounds like you're on a Mac. Maybe try connecting to docker.for.mac.localhost from within the container instead of localhost? docs.docker.com/docker-for-mac/networking/… Oct 4, 2017 at 11:06
3

The error you see in your container is:

etcd.EtcdConnectionFailed: Connection to etcd failed due to MaxRetryError(u"HTTPConnectionPool(host=u'localhost', port=2379): Max retries exceeded with url: /v2/keys/my_module/nodes (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused',))",)

If you take a close look there, you can see that it's trying to connect to localhost. Inside your container, localhost is means "the current container" (much like localhost on your host means "the current host"). If you want to connect to an etcd instance outside of the container, you'll need to use the ip address (or hostname) of another server.

If you're running (a) running Docker locally, (b) etcd on your host is listening on all addresses, and (c) there are no firewall rules that would otherwise prohibit the connection, then you can use the address of the Docker bridge associated with your container as the address of your host. This will be the default gateway as seen from inside the container. You can extract the address with something like:

ip route show | awk '$1 == "default" {print $3}'
4
  • ip route show command not found on OS X. Is there any other command I can use on OS X
    – Alireza
    Sep 20, 2017 at 16:34
  • You run that command inside the container, which is running Linux. The command may not be available; sometimes you will need to install the iproute package.
    – larsks
    Sep 20, 2017 at 17:12
  • As I said in the question when I want to run the image it gives error and exits! I don't have access to inside of the container when it fails by docker run (or maybe there is and I'm unaware of).
    – Alireza
    Sep 20, 2017 at 17:28
  • To have access to the container, you would have to change the entrypoint to something like: /bin/bash
    – Sergiu
    Oct 2, 2017 at 20:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.