commit 627453eaa6cc4e6dcd8d51374df691d158984e94 Author: Ludwig Behm Date: Fri Mar 14 11:40:20 2025 +0100 The first impact diff --git a/README.md b/README.md new file mode 100644 index 0000000..2093d9e --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# `docker-zonefiled` + +## What's this? + +This generates DNS zone files containing DNS hostnames and aliases of running docker containers in all docker networks for a given docker host. + +It generates zone files like this: + +``` +container_name.network_name.in-docker.internal. A 172.25.1.2 +alias.network_name.in-docker.internal. AAAA 2a02:F00:BA4::1:2 +container_name.backend_network.in-docker.internal. A 192.168.42.2 +``` + +This is currently implemented as an trivial simple bash script utilizing `docker events` for listening on changes, `docker container inspect` to query the network details and some `jq` magic. + +## Why 'tho? + +- I wanted sane dns resolution from the docker host to docker containers. +- nss-docker isn't enough or working. +- DNS operations are well understood. Automagic name resolution via nss leads to unexpected behavior, if container name vanished and queries drop down to dns. +- Using DNS subdomains host and aliases are structured per network name. +- Your networking, routing and firewalling decides if you're able to reach the container interfaces. +- Passing a different docker socket and alternative domain zone name can support multi-docker-setups. + +## Remarks + +### Input sanitization of user controlled values + +Specially grafted host and alias names of docker containers can inject stuff in the generated zone file, I guess. +I'm currently open to discuss, how to catch invalid characters in host names. + + +### Currently used `.internal` TLD + +This is currently used since it should never be resolved in the internet. +Since it could be used in a private / enterprise context, it could be conflicting existing setups. +I'm very open to discuss if a `.in-docker` TLD would be a sane idea. diff --git a/docker-zonefiled b/docker-zonefiled new file mode 100644 index 0000000..50236dc --- /dev/null +++ b/docker-zonefiled @@ -0,0 +1,36 @@ +#!/bin/bash + +ZONE_FILE="$1" +SOA="$(hostname -f). $(whoami).$(hostname -f)." +ZONE="in-docker.internal" + +function generate_records() { + docker container ls -q \ + | xargs docker container inspect 2>/dev/null \ + | jq -r '.[] | select(.State.Running) | .NetworkSettings.Networks | to_entries | map(.key as $net | .value as $conf | (.value.DNSNames[] | (.+"."+$net) as $host | [ ($host + " IN A "+$conf.IPAddress), ($host + " IN AAAA " + $conf.GlobalIPv6Address)])) | flatten | .[]' +} + +function update() { + SN="$(date +%y%m%d%H%M%S)" + cat < $ZONE_FILE +\$ORIGIN $ZONE. +\$TTL 10 ; default time to live + +@ IN SOA $SOA ( + $SN ; serial number + 60 ; Refresh + 60 ; Retry + 60 ; Expire + 10 ; Min TTL + ) + +$(generate_records) +EOF +} +update + +docker events --filter 'type=network' --filter 'event=connect' --filter 'event=disconnect' --format '{{json .}}' \ + | while read _event + do + update + done