When running applications in Docker containers, you might need custom hostname resolutions that aren't possible through the default /etc/hosts
file (which is read-only in containers). The standard approach of modifying /etc/hosts
directly won't work, as Docker overwrites this file during container initialization.
dnsmasq provides a lightweight DNS server that can be configured to:
- Serve custom hostname resolutions
- Cache DNS queries
- Integrate with Docker's networking
Here's how to properly set up dnsmasq in your Docker container:
FROM ubuntu:22.04 # Install dnsmasq and configure it RUN apt-get update && apt-get install -y dnsmasq # Main configuration RUN echo 'listen-address=127.0.0.1' >> /etc/dnsmasq.conf RUN echo 'resolv-file=/etc/resolv.dnsmasq.conf' >> /etc/dnsmasq.conf RUN echo 'conf-dir=/etc/dnsmasq.d,.conf' >> /etc/dnsmasq.conf RUN echo 'user=root' >> /etc/dnsmasq.conf # Upstream DNS servers RUN echo 'nameserver 8.8.8.8' > /etc/resolv.dnsmasq.conf RUN echo 'nameserver 8.8.4.4' >> /etc/resolv.dnsmasq.conf # Custom host entries RUN mkdir -p /etc/dnsmasq.d RUN echo 'address=/mydomain.com/127.0.6.1' > /etc/dnsmasq.d/custom_hosts.conf # Start dnsmasq in the background CMD ["sh", "-c", "dnsmasq && your_application_command"]
The key is to properly configure Docker's DNS settings. Here are the correct approaches:
# Method 1: Using --dns flag docker run --dns=127.0.0.1 my/container # Method 2: Modifying Docker daemon settings (persistent) # Add to /etc/docker/daemon.json { "dns": ["127.0.0.1"] }
To verify your configuration is working:
# Inside the container: dig mydomain.com @127.0.0.1 nslookup mydomain.com 127.0.0.1
For more complex setups, consider:
- Using Docker's
--network host
mode for simpler networking - Creating a custom bridge network with specific DNS settings
- Using Docker Compose with explicit DNS configuration
# docker-compose.yml example version: '3' services: app: build: . dns: - 127.0.0.1 - 8.8.8.8 networks: - mynet networks: mynet: driver: bridge
When using dnsmasq in containers:
- Enable DNS caching in dnsmasq for better performance
- Consider running dnsmasq in a separate container for multi-container setups
- Monitor DNS resolution times to identify bottlenecks
When working with Docker containers, you'll quickly discover that modifying /etc/hosts
directly isn't possible as the file is read-only. This becomes problematic when you need custom hostname resolutions for:
- Local development environments
- Service discovery between containers
- Testing DNS configurations
- Overriding production endpoints
The approach using dnsmasq in your Dockerfile has several fundamental issues:
# Problem 1: The service won't persist after container start RUN service dnsmasq start # This only runs during build phase # Problem 2: Docker's internal DNS takes precedence # Even with --dns flag, Docker manages /etc/resolv.conf
Solution 1: Using Docker's --add-host Flag
The simplest approach for static host mappings:
docker run --add-host="mydomain:127.0.6.1" your_image
For multiple entries:
docker run \ --add-host="mydomain:127.0.6.1" \ --add-host="api.mydomain:192.168.1.100" \ your_image
Solution 2: Custom DNS with docker-compose
For more complex setups using docker-compose.yml:
version: '3' services: app: image: your_image dns: 127.0.0.1 extra_hosts: - "mydomain:127.0.6.1" - "api.mydomain:192.168.1.100" dnsmasq: image: andyshinn/dnsmasq ports: - "53:53/tcp" - "53:53/udp" command: -A "/mydomain/127.0.6.1" --log-queries
Solution 3: Permanent DNS Configuration
For persistent DNS configuration across all containers:
# Create or edit /etc/docker/daemon.json { "dns": ["192.168.1.1", "8.8.8.8"], "dns-search": ["mydomain.com"], "dns-opts": ["timeout:2", "attempts:2"] }
Then restart Docker daemon:
sudo systemctl restart docker
When debugging DNS issues:
# Check container's DNS resolution docker exec -it container_name cat /etc/resolv.conf # Test DNS resolution inside container docker exec -it container_name nslookup mydomain # Verify Docker daemon DNS settings docker info | grep -i dns
For complex DNS requirements, consider using CoreDNS:
FROM coredns/coredns COPY Corefile / EXPOSE 53 53/udp # Corefile contents: .:53 { hosts /etc/hosts.docker { 127.0.6.1 mydomain fallthrough } forward . 8.8.8.8 log errors }