Docker DNS
Introduction
When working with Docker containers, especially in multi-container environments, having a reliable way for containers to find and communicate with each other is essential. This is where Docker's built-in DNS (Domain Name System) comes into play. Docker DNS provides automatic name resolution between containers, allowing them to communicate using container names instead of IP addresses, which can change frequently in dynamic container environments.
In this guide, we'll explore how Docker DNS works, how containers resolve hostnames, and how to configure and troubleshoot DNS in Docker environments.
How Docker DNS Works
Docker implements an embedded DNS server that provides name resolution services to containers. When you create a Docker network (other than the default bridge network), Docker automatically configures a DNS server for that network.
Here's how it works at a high level:
When a container tries to communicate with another container using its name, the following happens:
- The container sends a DNS query to the Docker DNS server
- The Docker DNS server looks up the name in its records
- If found, it returns the IP address of the target container
- The original container can now connect to the target container using the IP address
Docker DNS Resolution Rules
Docker follows specific rules for DNS resolution:
- Containers on user-defined networks can resolve each other by name or alias
- Containers on the default bridge network can't resolve each other by name unless you use the
--link
option (though this is legacy and not recommended) - The Docker DNS server always resolves the container's hostname to its IP address
- External DNS queries are forwarded to the DNS servers configured on the Docker host
Creating a Network with DNS
Let's create a simple example to demonstrate Docker DNS in action:
# Create a user-defined bridge network
docker network create my-network
# Run two containers on this network
docker run -d --name container1 --network my-network nginx
docker run -d --name container2 --network my-network nginx
# Connect to container1 and ping container2 by name
docker exec -it container1 ping container2
Output:
PING container2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: icmp_seq=0 ttl=64 time=0.114 ms
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.118 ms
As you can see, container1
can resolve and ping container2
using just its name, without needing to know its IP address.
Custom DNS Configuration
Docker allows you to customize DNS settings for your containers:
Setting Custom DNS Servers
You can configure containers to use specific DNS servers:
# Run a container with custom DNS servers
docker run -d --name custom-dns --dns 8.8.8.8 --dns 8.8.4.4 nginx
This configures the container to use Google's public DNS servers.
DNS Search Domains
You can also set DNS search domains:
docker run -d --name search-domain --dns-search example.com nginx
With this setting, if you try to access a host called db
, Docker will first try to resolve db
, and if that fails, it will try db.example.com
.
Docker Compose and DNS
When using Docker Compose, DNS resolution works automatically for services defined in the same docker-compose.yml
file. Services can reach each other by their service names.
Here's an example docker-compose.yml
file demonstrating this:
version: '3'
services:
web:
image: nginx
ports:
- "8080:80"
db:
image: postgres
environment:
POSTGRES_PASSWORD: example
app:
image: my-app
depends_on:
- web
- db
In this setup, the app
service can connect to the db
service using the hostname db
and to the web
service using the hostname web
.
Troubleshooting Docker DNS
If you're having issues with DNS resolution in Docker, here are some troubleshooting steps:
1. Check container DNS settings
docker exec container1 cat /etc/resolv.conf
Output:
nameserver 127.0.0.11
options ndots:0
The nameserver 127.0.0.11
is Docker's embedded DNS server.
2. Test DNS resolution
docker exec container1 nslookup container2
Output:
Server: 127.0.0.11
Address 1: 127.0.0.11
Name: container2
Address 1: 172.18.0.3
3. Check network configuration
docker network inspect my-network
This will show all the containers connected to the network and their IP addresses.
4. DNS debug tools
Install DNS debugging tools in your container:
docker exec -it container1 sh -c "apt-get update && apt-get install -y dnsutils"
docker exec -it container1 dig container2
Advanced DNS Features
Custom /etc/hosts
Entries
You can add custom host entries to a container:
docker run -d --name custom-hosts --add-host db.example.com:192.168.1.2 nginx
This adds an entry for db.example.com
to the container's /etc/hosts
file.
DNS Round-Robin
Docker supports DNS round-robin, where multiple containers can be accessed through a single DNS name:
# Create a network
docker network create my-network
# Run multiple containers with the same network alias
docker run -d --name web1 --network my-network --network-alias webserver nginx
docker run -d --name web2 --network my-network --network-alias webserver nginx
# Test DNS round-robin
docker run --rm --network my-network appropriate/curl -s http://webserver/
Multiple requests to the hostname webserver
will be distributed among the containers sharing that alias.
Docker DNS and Container Restart
When a container restarts, it may receive a different IP address. Docker DNS automatically updates its records, so you can still reach the container by its name, which is another advantage of using DNS instead of hardcoded IP addresses.
Practical Example: Multi-tier Application
Let's build a practical example with a web server, API, and database:
# Create a network
docker network create app-network
# Start a database
docker run -d --name db --network app-network \
-e POSTGRES_PASSWORD=password \
postgres
# Start an API service
docker run -d --name api --network app-network \
-e DB_HOST=db \
my-api-image
# Start a web server
docker run -d --name web --network app-network \
-e API_URL=http://api:8000 \
-p 80:80 \
my-web-image
In this example:
- The web container connects to the API using the hostname
api
- The API container connects to the database using the hostname
db
- No IP addresses are hardcoded, making the setup resilient to container restarts or recreations
Docker DNS Caching
Docker's embedded DNS server caches DNS responses, which can improve performance but might also cause issues if hostnames are being reused for different containers quickly.
If you need to clear the DNS cache, you usually need to restart the container:
docker restart container1
Summary
Docker DNS is a powerful feature that simplifies container networking by allowing containers to discover and communicate with each other using names instead of IP addresses. Key points to remember:
- Docker provides an embedded DNS server for user-defined networks
- Containers on the same user-defined network can resolve each other by name
- The default bridge network doesn't support automatic name resolution
- Custom DNS servers, search domains, and
/etc/hosts
entries can be configured - DNS round-robin allows for simple load balancing
By understanding and properly using Docker DNS, you can build more resilient containerized applications that don't depend on hardcoded IP addresses and can automatically adapt to changes in the container environment.
Additional Resources
For further learning:
- Experiment with creating complex multi-container applications using Docker Compose
- Learn how to implement service discovery in larger environments using tools like Consul or etcd
- Practice debugging DNS issues in containers using tools like
dig
,nslookup
, andping
Exercises
- Create a user-defined bridge network and launch multiple containers. Practice connecting between them using their names.
- Set up a round-robin DNS configuration with multiple web servers behind a common alias.
- Configure a container to use custom DNS servers and verify the configuration works.
- Build a three-tier application (web, api, database) using Docker DNS for service discovery.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)