Quickstart
Run DockRoute next to your services and watch it reconcile — dry run first, real records after.
Prefer a form to a blank file?
The compose generator builds a compose.yaml and .env for
your setup — provider, optional Cloudflare Tunnel, optional example
service — entirely in your browser.
Requirements
DockRoute runs on linux/amd64 and linux/arm64. On x86-64, the Bun runtime
needs a CPU that reports SSSE3, SSE4.1, SSE4.2 and POPCNT
(the x86-64-v2 microarchitecture level) — true for Intel CPUs since
Nehalem (2008) and AMD since Bulldozer (2011), but not for older Atoms
(pre-2013), Core 2 or Phenom II/Athlon II, nor for a VM pinned to a generic
model such as QEMU's kvm64/qemu64. arm64 is not affected.
dockroute: unsupported CPU, missing ssse3 sse4_1 sse4_2 popcnt
Without SSSE3/SSE4.1/SSE4.2/POPCNT, Bun usually hangs at 100% CPU with no
log output (or crashes with SIGILL) instead of exiting cleanly — so the
entrypoint checks /proc/cpuinfo before starting the app and exits right
away with this message, listing only the flags that are actually missing.
In a VM (Proxmox, libvirt, generic QEMU), set the CPU type to host
(host-passthrough in libvirt) or x86-64-v2 or newer, then restart
the VM.
1. Dry run — no credentials needed
DockRoute defaults to the log provider, which runs the whole pipeline and
prints the desired state it computes instead of touching a zone. It is the
safest way to check your labels.
services:
whoami:
image: traefik/whoami
labels:
dockroute.enabled: "true"
dockroute.hostname: "whoami.example.com"
dockroute:
image: ghcr.io/dockroute/dockroute:latest
environment:
DOCKROUTE_DEFAULT_TARGET: 192.168.1.10
volumes:
- /var/run/docker.sock:/var/run/docker.sock:rodocker compose upYou should see the desired state logged: an A record for
whoami.example.com pointing at 192.168.1.10.
Docker socket permissions
Handled automatically: the entrypoint detects the socket's group, grants it
to the app user and drops privileges before starting — the process itself
runs as non-root. If you set an explicit user: override, add the socket's
group yourself with group_add: ["<gid>"]
(stat -c '%g' /var/run/docker.sock).
2. Go live with Cloudflare
Switch the provider and add a token with Zone → Zone → Read and Zone → DNS → Edit permissions:
dockroute:
image: ghcr.io/dockroute/dockroute:latest
environment:
DOCKROUTE_PROVIDER: cloudflare
DOCKROUTE_OWNER_ID: home-lab
DOCKROUTE_DEFAULT_TARGET: 192.168.1.10
CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:roRestart the stack. DockRoute lists your running containers, computes the
desired records and reconciles them. From now on, every container start and
stop triggers a reconcile, and a full resync runs every 60 seconds.
3. Publish through a Cloudflare Tunnel (optional)
If you already run cloudflared with a tunnel, one extra label publishes a
service through it — no port forwarding at all:
whoami:
image: traefik/whoami
labels:
dockroute.enabled: "true"
dockroute.hostname: "whoami.example.com"
dockroute.tunnel.service: "http://whoami:80"The tunnel needs two more environment variables on the DockRoute container
(CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_TUNNEL_ID) and the token needs
Account → Cloudflare Tunnel → Edit. See the
Cloudflare Tunnel guide for the full setup.
Verify
docker compose logs dockrouteshows every create, update, delete and skipped conflict.- Your zone now contains the record and a companion TXT like
_dockroute-a.whoami.example.com— that TXT is DockRoute's proof of ownership. - Stop the
whoamicontainer: under the defaultsyncpolicy both records are removed once it has been gone forDOCKROUTE_DELETE_GRACE_SECONDS(60 by default), so a restart never takes the hostname down.