Skip to main content
The image is distroless and runs as a non-root user. It listens for DNS on port 53 (UDP and TCP) and serves the dashboard on 8080, with data in the /data volume. Docker lets containers use ports below 1024 without root. Save this as docker-compose.yml:
docker-compose.yml
Then start it:
Open http://<server>:8080 and finish the setup page.

Settings

Settings go in the environment block. The ones you’ll usually want: Every setting is listed in Configuration. The image already sets DNZ_DNS_ADDR=0.0.0.0:53, DNZ_HTTP_ADDR=0.0.0.0:8080 and DNZ_DATABASE_URL=sqlite:///data/dnz.db. Because the environment beats the config file, change those in the environment, not in a mounted dnz.toml. On a Docker bridge network DNZ only sees the container’s own address (172.x.x.x), which other devices can’t reach. The setup guides (the setup wizard’s last step) then use the address you opened the UI at, so open it at the host’s LAN IP (http://192.168.1.10:8080, not localhost). Or set the host’s LAN IP under Settings → General → Device address (the wizard’s last step offers it too), or with DNZ_ADVERTISE. To keep the data in Postgres instead, see Docker with Postgres.

Health

The image has a HEALTHCHECK that runs dnz healthcheck, so docker ps shows healthy once the API answers. If it shows unhealthy, check docker compose logs dnz: usually a port that couldn’t be bound or a /data volume that isn’t writable.

Port 53 on the host

Publishing 53:53 fails when something on the host already uses port 53, most often systemd-resolved. Either free the port (see Port 53 and systemd-resolved), or publish on one address only:

Updating

Database migrations run automatically at startup. Back up the volume first; see Backups and updates. Pin a version tag such as terrificci/dnz:1.0.0 instead of latest to choose when you update.