This guide covers deploying Knot Resolver in Docker containers, from basic setups to production-ready configurations.
⚠️ Production Readiness Note:
- Version 6.x: Production-capable with kres-manager. Developers note limited production experience with Docker deployments.
- Version 5.x: Not recommended for production in containerized environments.
- Kubernetes/SDN: Performance penalties may occur. Test thoroughly in your environment.
docker run -d \
--name knot-resolver \
-p 53:53/tcp -p 53:53/udp \
-v ./config.yaml:/etc/knot-resolver/config.yaml:ro \
-v ./cache:/var/cache/knot-resolver \
docker.io/cznic/knot-resolver:6.1.0
dig @127.0.0.1 example.com
| Image | Version | Architecture | Status |
|---|---|---|---|
docker.io/cznic/knot-resolver:latest |
Latest v6 | multi-arch | ✅ Recommended |
docker.io/cznic/knot-resolver:6.1.0 |
Specific v6 | multi-arch | ✅ Stable |
docker.io/cznic/knot-resolver:latest5 |
Latest v5 | amd64 | ⚠️ Legacy |
docker.io/cznic/knot-resolver:5.7.6 |
Specific v5 | amd64 | ⚠️ Legacy |
Version 6.x:
Version 5.x:
latest - Latest version 6latest6 - Latest version 6latest5 - Latest version 5<version> - Specific version (e.g., 6.1.0, 5.7.6)docker run -d \
--name knot-resolver \
-p 53:53/tcp -p 53:53/udp \
--restart unless-stopped \
docker.io/cznic/knot-resolver:6.1.0
Note: This uses default configuration. For production, mount persistent volumes.
docker run -d \
--name knot-resolver \
-p 53:53/tcp -p 53:53/udp \
-v ./config.yaml:/etc/knot-resolver/config.yaml:ro \
-v ./cache:/var/cache/knot-resolver \
--restart unless-stopped \
--cap-add NET_BIND_SERVICE \
docker.io/cznic/knot-resolver:6.1.0
| Path | Purpose | Recommended |
|---|---|---|
/etc/knot-resolver/config.yaml |
Configuration | ✅ Mount for persistence |
/var/cache/knot-resolver |
DNS cache | ✅ Mount for persistence |
/etc/knot-resolver/certs |
TLS certificates | ✅ For DoT/DoH |
/etc/knot-resolver/policy |
Policy scripts | Optional |
knot-resolver-docker/
├── config.yaml # Main configuration
├── cache/ # Cache directory (mounted volume)
├── certs/
│ ├── tls.crt # TLS certificate
│ └── tls.key # TLS private key
└── docker-compose.yml # Docker Compose file
# Basic server configuration
server:
interfaces:
- "0.0.0.0:53"
- ":::53"
# DNSSEC validation
dnssec:
enable: true
# Upstream forwarders
forward:
- address: "1.0.0.1"
- address: "8.8.8.8"
- address: "9.9.9.9"
# Cache configuration
cache:
max_size: 524288000 # 500 MB
# Logging
logging:
level: "notice"
# Monitoring
monitoring:
metrics: true
port: 8453
# Rate limiting
rate_limiting:
enable: true
limit: 100
docker run -d \
--name knot-resolver \
-p 53:53/tcp -p 53:53/udp \
-p 8453:8453/tcp \
-v $(pwd)/config.yaml:/etc/knot-resolver/config.yaml:ro \
-v $(pwd)/cache:/var/cache/knot-resolver \
-v $(pwd)/certs:/etc/knot-resolver/certs:ro \
--restart unless-stopped \
--cap-add NET_BIND_SERVICE \
--read-only \
--tmpfs /tmp:noexec,nosuid,size=64m \
docker.io/cznic/knot-resolver:6.1.0
docker run -d \
--name knot-resolver \
--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 ./config.yaml:/etc/knot-resolver/config.yaml:ro \
-v ./cache:/var/cache/knot-resolver \
--restart unless-stopped \
docker.io/cznic/knot-resolver:6.1.0
version: '3.8'
services:
knot-resolver:
image: docker.io/cznic/knot-resolver:6.1.0
container_name: knot-resolver
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "8453:8453/tcp" # Prometheus metrics
volumes:
- ./config.yaml:/etc/knot-resolver/config.yaml:ro
- ./cache:/var/cache/knot-resolver
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", "kresctl", "status"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
networks:
dns-net:
driver: bridge
version: '3.8'
services:
knot-resolver:
image: docker.io/cznic/knot-resolver:6.1.0
container_name: knot-resolver
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "853:853/tcp" # DNS over TLS
- "443:443/tcp" # DNS over HTTPS
- "8453:8453/tcp" # Prometheus metrics
volumes:
- ./config.yaml:/etc/knot-resolver/config.yaml:ro
- ./cache:/var/cache/knot-resolver
- ./certs:/etc/knot-resolver/certs:ro
cap_add:
- NET_BIND_SERVICE
networks:
- dns-net
networks:
dns-net:
driver: bridge
version: '3.8'
services:
knot-resolver-primary:
image: docker.io/cznic/knot-resolver:6.1.0
container_name: knot-resolver-primary
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
volumes:
- ./config-primary.yaml:/etc/knot-resolver/config.yaml:ro
- ./cache-primary:/var/cache/knot-resolver
networks:
- dns-net
knot-resolver-backup:
image: docker.io/cznic/knot-resolver:6.1.0
container_name: knot-resolver-backup
restart: unless-stopped
ports:
- "5354:53/tcp"
- "5354:53/udp"
volumes:
- ./config-backup.yaml:/etc/knot-resolver/config.yaml:ro
- ./cache-backup:/var/cache/knot-resolver
networks:
- dns-net
networks:
dns-net:
driver: bridge
# Create directory
mkdir -p certs
# Generate self-signed certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout certs/tls.key \
-out certs/tls.crt \
-subj "/CN=dns.example.com"
config.yaml:
server:
interfaces:
- "0.0.0.0:53"
- ":::53"
dnssec:
enable: true
forward:
- address: "1.0.0.1"
- address: "8.8.8.8"
# DNS over TLS
tls:
enable: true
listen:
- address: "0.0.0.0:853"
cert: "/etc/knot-resolver/certs/tls.crt"
key: "/etc/knot-resolver/certs/tls.key"
# DNS over HTTPS
http:
enable: true
listen:
- address: "0.0.0.0:443"
cert: "/etc/knot-resolver/certs/tls.crt"
key: "/etc/knot-resolver/certs/tls.key"
path: "/dns-query"
version: '3.8'
services:
knot-resolver:
image: docker.io/cznic/knot-resolver:6.1.0
container_name: knot-resolver
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "853:853/tcp"
- "443:443/tcp"
volumes:
- ./config.yaml:/etc/knot-resolver/config.yaml:ro
- ./cache:/var/cache/knot-resolver
- ./certs:/etc/knot-resolver/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/tls.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/tls.crt
# Using dog (DNS client)
dog https://localhost/dns-query example.com
The developers note that Knot Resolver Docker images may experience performance penalties when running with software-defined networks (Kubernetes, Docker Swarm, etc.). No benchmark data is available comparing Docker vs. native installations.
apiVersion: apps/v1
kind: Deployment
metadata:
name: knot-resolver
spec:
replicas: 2
selector:
matchLabels:
app: knot-resolver
template:
metadata:
labels:
app: knot-resolver
spec:
hostNetwork: true # Better performance
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: knot-resolver
image: docker.io/cznic/knot-resolver:6.1.0
ports:
- containerPort: 53
protocol: UDP
- containerPort: 53
protocol: TCP
volumeMounts:
- name: config
mountPath: /etc/knot-resolver
readOnly: true
- name: cache
mountPath: /var/cache/knot-resolver
securityContext:
capabilities:
add: ["NET_BIND_SERVICE"]
drop: ["ALL"]
volumes:
- name: config
configMap:
name: knot-resolver-config
- name: cache
emptyDir: {}
docker ps -a | grep knot-resolver
docker logs knot-resolver
# Execute commands in container
docker exec -it knot-resolver kresctl status
# Interactive shell
docker exec -it knot-resolver /bin/bash
# View status
docker exec knot-resolver kresctl status
# View statistics
docker exec knot-resolver kresctl stats
# Clear cache
docker exec knot-resolver kresctl cache clear
# Reload configuration
docker exec knot-resolver kresctl reload
# Validate configuration
docker exec knot-resolver kresctl validate
# Pull new image
docker pull docker.io/cznic/knot-resolver:6.1.0
# Stop and remove old container
docker stop knot-resolver
docker rm knot-resolver
# Start new container (same command as before)
docker run -d \
--name knot-resolver \
...
# Backup cache
docker exec knot-resolver tar czf - /var/cache/knot-resolver > cache-backup.tar.gz
# Backup configuration
docker exec knot-resolver cat /etc/knot-resolver/config.yaml > config-backup.yaml
# Restore cache
docker exec -i knot-resolver tar xzf - /var/cache/knot-resolver < cache-backup.tar.gz
Access metrics at http://localhost:8453/metrics:
curl http://localhost:8453/metrics
resolver_request_total - Total DNS requestsresolver_answer_total - Total answered queriesresolver_answer_cached - Queries answered from cacheresolver_latency_sum_ms - Sum of all latencies# 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 knot-resolver
# Check configuration
docker exec knot-resolver kresctl validate
# Verify volume mounts
docker inspect knot-resolver | grep Mounts -A 20
# Check if port is in use
sudo ss -tlnp | grep :53
# Stop conflicting services
sudo systemctl stop systemd-resolved
# Check resource usage
docker stats knot-resolver
# View statistics
docker exec knot-resolver kresctl stats
# Check cache
docker exec knot-resolver kresctl cache stats
# Test from inside container
docker exec knot-resolver kresctl resolve example.com
# Test from host
dig @127.0.0.1 example.com
# Check configuration
docker exec knot-resolver cat /etc/knot-resolver/config.yaml
latest in production)Questions? Find all contact information on our contact page.