- 1.Open the DNS dashboard and add a CNAME by hand.
- 2.Look up the tunnel, load balancer or IP to point it at.
- 3.Write a script — or remember — to update it when the container moves.
- 4.Forget to remove it when the container is gone. The stale record stays.
External-DNS for plain Docker hosts
v0.7.4DNS records that follow your containers.
DockRoute watches your Docker containers, reads dockroute.* labels and keeps your DNS provider in sync. Your Compose file is the source of truth. No Kubernetes required.
MIT licensed · single container · Cloudflare DNS + Tunnel today, more providers on the route
services:
whoami:
image: traefik/whoami
labels:
dockroute.enabled: "true"
dockroute.hostname: "whoami.example.com"
dockroute.tunnel.service: "http://whoami:80"create CNAME whoami.example.com → tunnel
create TXT _dockroute-cname.whoami.example.com
● route published — in sync
Why DockRoute
Stop clicking. Start labeling.
labels:
dockroute.enabled: "true"
dockroute.hostname: "whoami.example.com"
dockroute.tunnel.service: "http://whoami:80"A few labels. DockRoute creates the record, keeps it in sync while the container runs, and removes it when the container is gone (with the default sync policy).
What DockRoute never touches: any record it can't prove it owns. Without its own TXT ownership record, a record made by hand, by another tool, or by a DockRoute instance with a different owner ID is left alone — see the full safety model below.
The route
Docker Compose
your labels
DockRoute
watch + reconcile
DNS provider
records + routes
Your domain
live
How it works
From Docker labels to live DNS.
01
Label your containers
Add dockroute.enabled and dockroute.hostname to any service in your Compose file. That label is the whole contract — no sidecar config, no templates.
02
DockRoute watches Docker
It streams container lifecycle events — start, die, stop, destroy — from the Docker socket, with a periodic full resync as a safety net. Desired state always comes from what is actually running.
03
Records reconcile
The provider diffs desired against actual and creates, updates or removes records — plus Cloudflare Tunnel ingress routes when you ask for them.
Safety model
It never alters what it cannot prove it manages.
Your DNS zone usually holds more than your containers. DockRoute treats everything it did not create as someone else's — including records made by another DockRoute instance.
Ownership is proven, not assumed
Every record DockRoute creates gets a companion TXT record carrying its owner id — the same registry model as Kubernetes ExternalDNS.
Unowned records are untouchable
A record without proof of ownership is never modified, deleted or adopted. Conflicts are logged and skipped, under every policy.
Cleanup only when you allow it
Orphaned records are removed only under the default sync policy, and only when ownership is proven. upsert-only and create-only never delete.
Your tunnel rules stay yours
Tunnel ingress rules DockRoute did not create are preserved verbatim, in their original order, ahead of managed rules.
Configuration
One more service in your stack.
DockRoute runs as a single container next to your services. Point it at the Docker socket, pick a provider, and it starts reconciling. Start with the log provider for a zero-credential dry run.
services:
dockroute:
image: ghcr.io/dockroute/dockroute:latest
environment:
DOCKROUTE_PROVIDER: cloudflare
DOCKROUTE_OWNER_ID: home-lab
CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:roSimple enough for a homelab. Reliable enough for your SaaS.
Homelab
Expose services without the ritual
Publish through an existing Cloudflare Tunnel with one label — no port forwarding, no dynamic-DNS scripts, no hand-edited zone files. Take a service down and its records follow.
Small teams
Compose in production, safely
Sync policies, per-instance owner ids and a domain allowlist let several stacks share one zone without stepping on each other — or on the records you manage by hand.
Open source
MIT licensed, built in the open.
DockRoute borrows its safety model from Kubernetes ExternalDNS and applies it where most homelabs actually live: plain Docker hosts. Providers are pluggable behind one interface — Cloudflare works end to end today, and the planner, ownership rules and tests are provider-agnostic, so a new provider slots in cleanly.
Latest release
v0.7.4
Bug Fixes docker: switch the base image to Alpine to drop Debian's unfixed CVEs (#77) (7844190), closes #76
Eating our own dog food
This site runs from a Docker Compose stack in a homelab, and the DNS record you used to reach it was published by DockRoute itself — from a dockroute.hostname label on the site's own container.
Your services know where to go.
Start with the dry-run provider — no credentials, no risk — and see the records DockRoute computes before it ever touches a zone.
