This guide covers deploying dnsdist in Docker containers, from basic setups to production-ready configurations.
docker run -d \
--name dnsdist \
-p 53:53/tcp -p 53:53/udp \
-p 8083:8083/tcp \
-v ./config:/etc/dnsdist:ro \
--restart unless-stopped \
--cap-add NET_BIND_SERVICE \
powerdns/dnsdist-20:2.0.2
dig @127.0.0.1 example.com
| Image | Version | Architecture | Status |
|---|---|---|---|
powerdns/dnsdist-20:latest |
Latest v2.0 | multi-arch | ✅ Recommended |
powerdns/dnsdist-20:2.0 |
Latest 2.0.x | multi-arch | ✅ Stable |
powerdns/dnsdist-20:2.0.2 |
Specific version | multi-arch | ✅ Stable |
latest - Latest version 2.0.x2.0 - Latest 2.0.x patch release<version> - Specific version (e.g., 2.0.1, 2.0.2)docker pull powerdns/dnsdist-20:2.0.2
docker run -d \
--name dnsdist \
-p 53:53/tcp -p 53:53/udp \
--restart unless-stopped \
powerdns/dnsdist-20:2.0.2
Note: This uses default configuration. For production, mount persistent volumes.
docker run -d \
--name dnsdist \
-p 53:53/tcp -p 53:53/udp \
-p 8083:8083/tcp \
-v $(pwd)/config:/etc/dnsdist:ro \
-v $(pwd)/certs:/etc/dnsdist/certs:ro \
--restart unless-stopped \
--cap-add NET_BIND_SERVICE \
powerdns/dnsdist-20:2.0.2
| Path | Purpose | Recommended |
|---|---|---|
/etc/dnsdist/dnsdist.conf |
Configuration (Lua) | ✅ Mount for persistence |
/etc/dnsdist/dnsdist.yml |
Configuration (YAML) | ✅ For v2.0+ YAML config |
/etc/dnsdist/certs |
TLS certificates | ✅ For DoT/DoH |
/var/cache/dnsdist |
Cache directory | Optional |
dnsdist-docker/
├── dnsdist.conf # Main configuration (Lua)
├── dnsdist.yml # YAML configuration (v2.0+)
├── certs/
│ ├── dnsdist.crt # TLS certificate
│ └── dnsdist.key # TLS private key
└── docker-compose.yml # Docker Compose file
dnsdist.conf:
-- Listen on standard DNS port
addLocal("0.0.0.0:53")
addLocal(":::53")
-- Backend servers
newServer{address="192.168.1.10:53"}
newServer{address="192.168.1.11:53"}
newServer{address="192.168.1.12:53"}
-- Load balancing policy
setServerPolicy(roundrobin)
-- Web interface for statistics
webserver("0.0.0.0:8083", "secure_password")
-- Rate limiting
addAction(AllRule(), MaxQPSRule(10000))
dnsdist.yml:
servers:
- address: "192.168.1.10:53"
- address: "192.168.1.11:53"
- address: "192.168.1.12:53"
listen:
- "0.0.0.0:53"
- ":::53"
load_balancing:
policy: roundrobin
webserver:
address: "0.0.0.0:8083"
password: "secure_password"
rate_limiting:
- rule: "all"
qps: 10000
action: "drop"
docker run -d \
--name dnsdist \
-p 53:53/tcp -p 53:53/udp \
-p 8083:8083/tcp \
-v $(pwd)/dnsdist.conf:/etc/dnsdist/dnsdist.conf:ro \
-v $(pwd)/certs:/etc/dnsdist/certs:ro \
--restart unless-stopped \
--cap-add NET_BIND_SERVICE \
--read-only \
--tmpfs /tmp:noexec,nosuid,size=64m \
powerdns/dnsdist-20:2.0.2
docker run -d \
--name dnsdist \
--user 1000:1000 \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges:true \
--read-only \
--tmpfs /tmp:noexec,nosuid,size=64m \
--tmpfs /run:noexec,nosuid,size=64m \
-p 53:53/tcp -p 53:53/udp \
-v ./dnsdist.conf:/etc/dnsdist/dnsdist.conf:ro \
-v ./certs:/etc/dnsdist/certs:ro \
--restart unless-stopped \
powerdns/dnsdist-20:2.0.2
version: '3.8'
services:
dnsdist:
image: powerdns/dnsdist-20:2.0.2
container_name: dnsdist
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "8083:8083/tcp" # Web interface
volumes:
- ./dnsdist.conf:/etc/dnsdist/dnsdist.conf:ro
- ./certs:/etc/dnsdist/certs:ro
cap_add:
- NET_BIND_SERVICE
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=64m
- /run:noexec,nosuid,size=64m
networks:
- dns-net
healthcheck:
test: ["CMD", "dnsdist", "-e", "showServers()"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
networks:
dns-net:
driver: bridge
version: '3.8'
services:
dnsdist:
image: powerdns/dnsdist-20:2.0.2
container_name: dnsdist
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "853:853/tcp" # DNS over TLS
- "443:443/tcp" # DNS over HTTPS
- "8083:8083/tcp" # Web interface
volumes:
- ./dnsdist.conf:/etc/dnsdist/dnsdist.conf:ro
- ./certs:/etc/dnsdist/certs:ro
cap_add:
- NET_BIND_SERVICE
networks:
- dns-net
networks:
dns-net:
driver: bridge
version: '3.8'
services:
dnsdist-primary:
image: powerdns/dnsdist-20:2.0.2
container_name: dnsdist-primary
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
volumes:
- ./config-primary:/etc/dnsdist:ro
networks:
- dns-net
dnsdist-backup:
image: powerdns/dnsdist-20:2.0.2
container_name: dnsdist-backup
restart: unless-stopped
ports:
- "5354:53/tcp"
- "5354:53/udp"
volumes:
- ./config-backup:/etc/dnsdist:ro
networks:
- dns-net
networks:
dns-net:
driver: bridge
version: '3.8'
services:
dnsdist:
image: powerdns/dnsdist-20:2.0.2
container_name: dnsdist
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "853:853/tcp"
volumes:
- ./dnsdist.conf:/etc/dnsdist/dnsdist.conf:ro
- ./certs:/etc/dnsdist/certs:ro
depends_on:
- pdns-authoritative
networks:
- dns-net
pdns-authoritative:
image: powerdns/pdns-auth-48:latest
container_name: pdns-authoritative
restart: unless-stopped
environment:
- PDNS_master=yes
- PDNS_api=yes
- PDNS_api_key=api_key
- PDNS_webserver=yes
- PDNS_webserver_address=0.0.0.0
- PDNS_webserver_password=web_password
- PDNS_webserver-allow-from=127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8
- PDNS_version_string=anonymous
- PDMS_mode=native
- PDMS_gmysql_host=db
- PDMS_gmysql_port=3306
- PDMS_gmysql_dbname=pdns
- PDMS_gmysql_user=pdns
- PDMS_gmysql_password=pdns_password
networks:
- dns-net
- db-net
db:
image: mariadb:10.11
container_name: pdns-db
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=pdns
- MYSQL_USER=pdns
- MYSQL_PASSWORD=pdns_password
volumes:
- db-data:/var/lib/mysql
networks:
- db-net
volumes:
db-data:
networks:
dns-net:
driver: bridge
db-net:
driver: bridge
# Create directory
mkdir -p certs
# Generate private key
openssl genrsa -out certs/dnsdist.key 2048
# Generate certificate
openssl req -new -x509 -key certs/dnsdist.key \
-out certs/dnsdist.crt \
-days 365 \
-subj "/CN=dns.example.com/O=Example Corp/C=US"
dnsdist.conf:
-- Standard DNS
addLocal("0.0.0.0:53")
-- DNS over TLS
addTLSLocal("0.0.0.0:853",
"/etc/dnsdist/certs/dnsdist.crt",
"/etc/dnsdist/certs/dnsdist.key")
-- DNS over HTTPS
addDOHLocal("0.0.0.0:443",
"/etc/dnsdist/certs/dnsdist.crt",
"/etc/dnsdist/certs/dnsdist.key",
"/dns-query")
-- Backend servers
newServer{address="192.168.1.10:53"}
newServer{address="192.168.1.11:53"}
-- TLS configuration
setTLSConfig({
ciphers = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384",
ciphers13 = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256",
minTLSVersion = "TLSv1.2"
})
version: '3.8'
services:
dnsdist:
image: powerdns/dnsdist-20:2.0.2
container_name: dnsdist
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "853:853/tcp"
- "443:443/tcp"
- "8083:8083/tcp"
volumes:
- ./dnsdist.conf:/etc/dnsdist/dnsdist.conf:ro
- ./cache:/var/cache/dnsdist
- ./certs:/etc/dnsdist/certs:ro
cap_add:
- NET_BIND_SERVICE
networks:
- dns-net
networks:
dns-net:
driver: bridge
# Using kdig
kdig @localhost example.com +tls +tls-ca=certs/dnsdist.crt
# Using getdns-query
getdns-query @localhost example.com
# Using curl
curl -H "accept: application/dns-json" \
"https://localhost/dns-query?name=example.com&type=A" \
--cacert certs/dnsdist.crt
# Using dog (DNS client)
dog https://localhost/dns-query example.com
docker ps -a | grep dnsdist
docker logs dnsdist
# Execute commands in container
docker exec -it dnsdist dnsdist -e "showServers()"
# Interactive console
docker exec -it dnsdist dnsdist
# View server status
docker exec dnsdist dnsdist -e "showServers()"
# View statistics
docker exec dnsdist dnsdist -e "showStats()"
# View rules
docker exec dnsdist dnsdist -e "showRules()"
# View dynamic blocks
docker exec dnsdist dnsdist -e "showDynamicBlocks()"
# Reload configuration
docker exec dnsdist dnsdist -e "reloadConfig()"
# Pull new image
docker pull powerdns/dnsdist-20:2.0.2
# Stop and remove old container
docker stop dnsdist
docker rm dnsdist
# Start new container
docker run -d \
--name dnsdist \
...
# Backup configuration
docker exec dnsdist cat /etc/dnsdist/dnsdist.conf > dnsdist.conf.backup
# Backup certificates (if stored in container)
docker cp dnsdist:/etc/dnsdist/certs ./certs-backup
Access statistics at http://localhost:8083/
Default credentials:
dnsdistwebserver()# Access metrics endpoint
curl http://localhost:8083/metrics
# Key metrics
curl http://localhost:8083/metrics | grep dnsdist_
dnsdist_queries - Total queriesdnsdist_responses - Total responsesdnsdist_cache_hits - Cache hitsdnsdist_cache_misses - Cache missesdnsdist_downstream_servers - Backend server statusdnsdist_latency - Query latency# Add to docker-compose.yml
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
# Check logs
docker logs dnsdist
# Check configuration
docker exec dnsdist dnsdist --check-config
# Verify volume mounts
docker inspect dnsdist | grep Mounts -A 20
# Check if port is in use
sudo ss -tlnp | grep :53
# Stop conflicting services
sudo systemctl stop systemd-resolved
# Check backend status
docker exec dnsdist dnsdist -e "showServers()"
# View statistics
docker exec dnsdist dnsdist -e "showStats()"
# Check configuration syntax
docker exec dnsdist dnsdist --check-config
# Test with specific config file
docker exec dnsdist dnsdist --config=/etc/dnsdist/dnsdist.conf --check
latest in production)Deploying dnsdist in containers for production? Our consulting covers:
Get expert help: office@linux-server-admin.com | Contact Page