Deploy Knot DNS using Docker containers with proper configuration management, volume mounting, and security considerations for Linux DevOps environments. This guide covers both Docker Compose and direct Docker commands for containerized DNS deployments.
For Docker installation, see Docker.
⚠️ Warning: Containerized DNS deployments require special attention to:
⚠️ Note: The official cznic/knot Docker image uses different paths than traditional installations:
/config - Configuration files (not /etc/knot)/storage - Zone data and database (not /var/lib/knot)/rundir - Runtime files (not /var/run)The image has no default CMD or ENTRYPOINT - you must specify the command to run. Use version tags like cznic/knot:3.5 (minor version) for stability.
Create a directory structure for your Knot DNS configuration:
mkdir -p /opt/knotdns/{config,zones,logs}
cd /opt/knotdns
Create docker-compose.yml with proper configuration:
version: '3.8'
services:
knotdns:
image: cznic/knot:3.5 # Use specific version for stability (official tag format)
container_name: knotdns
restart: unless-stopped
network_mode: "host" # Required for port 53 binding
command: knotd -c /config/knot.conf # Explicit command required
volumes:
- ./config:/config:ro # Configuration files (read-only)
- ./zones:/storage:rw # Zone data and database
- ./logs:/var/log/knot:rw # Logs (if configured)
- ./rundir:/rundir:rw # Runtime files (sockets, PID)
environment:
- TZ=Etc/UTC # Set timezone for consistency
healthcheck:
test: ["CMD", "knotc", "conf-check"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
security_opt:
- no-new-privileges:true
read_only: true # Run container in read-only mode
tmpfs:
- /tmp
Create /opt/knotdns/config/knot.conf with a minimal configuration:
server:
listen: [ 0.0.0.0@53, ::@53 ]
rundir: /rundir
user: knot:knot
database:
storage: /storage
zone:
- domain: example.com
file: /storage/zones/example.com.zone
log:
- target: syslog
any: info
Create /opt/knotdns/zones/example.com.zone:
$ORIGIN example.com.
$TTL 3600
@ IN SOA ns1.example.com. admin.example.com. (
2026021401 ; serial
7200 ; refresh (2 hours)
3600 ; retry (1 hour)
1209600 ; expire (2 weeks)
3600 ) ; minimum (1 hour)
IN NS ns1.example.com.
IN A 192.168.1.10
ns1 IN A 192.168.1.10
www IN A 192.168.1.11
Start the container in detached mode:
# Navigate to the project directory
cd /opt/knotdns
# Start the service
docker compose up -d
# Check the status
docker compose ps
# Test DNS resolution
docker exec knotdns kdig @127.0.0.1 example.com
docker pull cznic/knot:3.5
docker run -d \
--name knotdns \
--restart unless-stopped \
--network host \
-v /opt/knotdns/config:/config:ro \
-v /opt/knotdns/zones:/storage:rw \
-v /opt/knotdns/rundir:/rundir:rw \
-v /opt/knotdns/logs:/var/log/knot:rw \
-e TZ=Etc/UTC \
--security-opt no-new-privileges=true \
--read-only \
--tmpfs /tmp \
cznic/knot:3.5 \
knotd -c /config/knot.conf
# Edit the configuration
sudo nano /opt/knotdns/config/knot.conf
# Validate configuration inside container
docker exec knotdns knotc conf-check
docker exec knotdns knotc reload
docker restart knotdns
# Create new zone file
sudo nano /opt/knotdns/zones/newdomain.com.zone
# Add to knot.conf
sudo nano /opt/knotdns/config/knot.conf
docker exec knotdns knotc reload
docker exec knotdns knotc zone-status
# Start, stop, restart
docker compose start
docker compose stop
docker compose restart
# View logs
docker compose logs -f
# Execute commands in container
docker exec -it knotdns sh
# Check zone syntax
docker exec knotdns kzonecheck /storage/zones/example.com.zone
# Reload specific zone
docker exec knotdns knotc zone-reload example.com
# Flush zones to disk
docker exec knotdns knotc zone-flush example.com
# List all zones
docker exec knotdns knotc conf-list zone
/config, /storage, and /rundir directoriesAdd resource limits to your compose file:
services:
knotdns:
# ... other configuration ...
deploy:
resources:
limits:
memory: 1G
cpus: '1.0'
reservations:
memory: 256M
cpus: '0.25'
Enable health checks and monitoring:
services:
knotdns:
# ... other configuration ...
healthcheck:
test: ["CMD", "kdig", "@127.0.0.1", "example.com"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
Implement regular backups of:
/opt/knotdns/config/)/opt/knotdns/zones/)/opt/knotdns/rundir/)Port binding fails:
sudo ss -tulnp | grep :53network_mode: "host" is setPermission errors:
Configuration validation fails:
docker exec knotdns knotc conf-check/config, /storage, /rundir)Container exits immediately:
knotd -c /config/knot.confdocker logs knotdns# Check container logs
docker logs knotdns
# Enter container for debugging
docker exec -it knotdns sh
# Test DNS resolution
docker exec knotdns kdig @127.0.0.1 example.com
# Check server status
docker exec knotdns knotc status
# View configuration
docker exec knotdns knotc conf-list
For automated deployments, consider:
Store your Docker Compose and configuration files in version control:
Deploying Knot DNS in containers for production? Our consulting covers:
Get expert help: office@linux-server-admin.com | Contact Page