services: coredns: image: ${COREDNS_IMAGE} container_name: coredns-secondary restart: unless-stopped command: ["-conf", "/etc/coredns/Corefile"] # Host networking is required for two reasons: # # 1. CoreDNS's `secondary` plugin authorizes inbound NOTIFY by # source IP (`transfer from 154.27.180.210`). With bridge # networking, Docker's userland proxy rewrites the visible # source to a 172.x docker0 address, and the auth check fails. # # 2. AXFR responses can be large; UDP/TCP source-IP preservation # matters for both directions of the conversation. # # Host networking means this container OWNS host ports 53/udp + 53/tcp. # On a dedicated NS box that's exactly what you want. network_mode: host volumes: - ./Corefile:/etc/coredns/Corefile:ro # CoreDNS's distroless image has no shell, so the conventional # `wget /health` healthcheck silently fails. The `-version` flag # exits 0 only if the binary is runnable — a thin but honest probe. healthcheck: test: ["CMD", "/coredns", "-version"] interval: 30s timeout: 5s retries: 3 start_period: 10s