How to connect docker containers
Did you know that you can use the service name of a container or id to connect to it on Docker?
If you have used the --link
option when launching a container or docker compose, you can call the container by its name or id from other containers. But how does this work?
The answer is simple: DNS.
Whenever you launch a container, Docker provides a network for you and uses the DNS service provided by the Docker daemon.
You can override the default docker network and DNS settings Check the docs here
Scenario
Let's assume that you have 3 tier application: Frontend, Backend, and a Database.
Your backend needs to be able to connect to the database. The safest way to do so is to keep your database in a private network to connect to it.
With docker you can use the service name or container ID as the server name in your configuration file.
Ex.:
cn = mysql.connect(user='produser',
password='secretvalue',
host='svc_database', # this is the service name in the incoming example
database='mysuperapp')
Launching a few containers
Clone the following repository using the command below:
git clone git@github.com:gdi3d/docker-dns.git .
Now take a look at the file docker-compose.yml
in the repository you just cloned.
version: "3.9" # optional since v1.27.0
services:
svc_frontend:
image: busybox:latest
command: top
svc_database:
image: busybox:latest
command: top
svc_backend:
image: busybox:latest
command: top
You can see three services defined:
- svc_frontend: App frontend
- svc_database: App database
- svc_backend: App backend
To make things easier we're using busybox image to simulate the services.
Launch the containers using docker-compose up -d
.
You can check that the containers are running using docker ps
The Test
We're going to test the following:
- Where's the Docker DNS service running at (the ip address)
- Try to ping a container by its service name and ID.
- Are the requests being resolved by Docker DNS service?.
These are our containers with their service name and IDs:
Service Name | ID |
---|---|
svc_frontend | 1ee9c76938ee |
svc_database | fe0228bd99a5 |
svc_backend | a96e0cb74351 |
Where's the Docker DNS service at?
Let's access svc_backend container and type cat /etc/resolv.conf
Here you can see that nameserver has been pointed to 127.0.0.11. That's the Docker DNS service provided by the Docker daemon.
Pro tip: You don't need to type the whole ID of the container to perform an operation, just use the first two or three characters
Try to ping a container by it's service name and ID
You can check the connectivity against the svc_database using the ping command:
As you can see, we obtain the same response when calling it by its service name svc_database or docker id fe0228bd99a5.
They both resolve to the same IP 172.19.0.3 as expected.
Are the requests being resolved by Docker DNS service?
Let's use nslookup to have a detailed report on what's going on when we try to call a container by its service name or ID.
Running these two commands will give us a better understanding of what's going on: nslookup svc_database
and nslookup fe0228bd99a5
Server: 127.0.0.11
Address: 127.0.0.11:53
Non-authoritative answer:
Name: svc_database
Address: 172.23.0.2
--------------------------
Server: 127.0.0.11
Address: 127.0.0.11:53
Non-authoritative answer:
Name: fe0228bd99a5
Address: 172.19.0.3
From the results of nslookups we can see that the request is made using the docker DNS service at 127.0.0.11 and that, again, using the service name svc_database or the container id fe0228bd99a5 the destination is the same ip 172.19.0.3
Further Reading
If you want to know more about how the docker networking works you can check the official documentation