I'm working with Docker 1.12.5 on macOS 10.12, and am setting up a development environment with with I have an application image, and a shared redis image which has some pre-populated configuration variables.
Even after following a few tutorials (and reading about how docker0
isn't available on Mac) I'm struggling to connect the two containers.
I start my redis
image using:
docker run -d -p 6379:6379 (IMAGE ID)
In my redis
image, I have:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dffb89854618 d59 "docker-entrypoint.sh" 20 seconds ago Up 19 seconds 0.0.0.0:6379->6379/tcp drunk_williams
And from my Mac I can successfully connect via the redis-cli
command without issue.
However when I start a simple ubuntu
image, I can't seem to connect to this separate redis
image:
root@2d4eda315f4f:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:03
inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:20707 errors:0 dropped:0 overruns:0 frame:0
TX packets:11515 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:28252929 (28.2 MB) TX bytes:635848 (635.8 KB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:680 (680.0 B) TX bytes:680 (680.0 B)
root@2d4eda315f4f:/# telnet localhost 6379
Trying ::1...
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
root@2d4eda315f4f:/# telnet 172.17.0.3 6379
Trying 172.17.0.3...
telnet: Unable to connect to remote host: Connection refused
Is this a result of not having the docker0
interface available in the host? Is there some straightforward workaround for allowing these containers to communicate (when being run on the same host) in a development environment?
Update: Attempting to use named containers, I still can't connect.
docker run -d --name redis_server redis
Results in:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5d05820aa985 redis "docker-entrypoint.sh" 43 hours ago Up 1 seconds 6379/tcp redis_server
But then if I start a new Ubuntu container:
root@e92b47419bc4:/# redis-cli -h redis_server
Could not connect to Redis at redis_server:6379: Name or service not known
I'm not sure how to find/connect to the first redis_server
container.
Each container has its own localhost
Each service runs in its own container. From the perspective of the Ubuntu container, redis is not listening on localhost.
Use Docker networks
To get your containers to communicate, they should be on the same Docker network. This consists of three steps:
With this done, the containers can talk to each other using their names as if they were hostnames.
There's more than one way to skin this cat... I will look at two in this answer, but there are probably a few other ways to do it that I am not familiar with (like using Kubernetes or Swarm, for instance).
Doing it by hand
You can create a network for this application using
docker network
commands.When you run the redis container, make sure it has a name, and is on this network. You can expose the ports externally (to macOS) if you want to (using
-p
), but that is not necessary just for other containers to talk to redis.Now run your Ubuntu container. You can name it as well if you like, but I won't bother in this example because this one isn't running any services.
Now from inside the Ubuntu container, you should be able to reach redis using the name
redis_server
, as if it were a DNS name.Doing it using Compose
I tend to build setups like this using Compose, because it's easier to write it into a YAML file (IMO). Here's an example of the above, re-written in docker-compose.yml form:
With this in place, you can run
docker-compose up -d redis
and have your redis service online using a specific Docker network. Compose will create the network for you, if it doesn't already exist.It makes less sense to run the Ubuntu container that way... it is interactive, of course. But I assume once you have redis going, you will add some kind of application container, and perhaps a web proxy like nginx... just put the others under
services
as well, and you can manage them all together.Since
ubuntu
is interactive, you can run it interactively:And now in Ubuntu, you should be able to connect to redis using its name, which in this example is simply
redis
.