DockRoute

DockRoute

Official

Docker app from DockRoute's Repository

Overview

External-DNS for plain Docker hosts: DockRoute watches your running containers, reads dockroute.* labels and reconciles the matching DNS records - and Cloudflare Tunnel routes - in a pluggable provider. Your Docker labels are the source of truth; DockRoute makes the provider match them, and never alters records it cannot prove it manages (ExternalDNS-style TXT ownership). Opt a container in with labels: dockroute.enabled=true and dockroute.hostname=app.example.com. Start with the default 'log' provider for a zero-credential dry run, then switch to 'cloudflare'. Docs: https://www.dockroute.dev

dockroute

CI CodeQL codecov Release License: MIT

External-DNS for plain Docker hosts: dockroute watches your running containers, reads dockroute.* labels and reconciles the matching DNS records — and Cloudflare Tunnel routes — in a pluggable provider.

Your Docker Compose file is the source of truth; dockroute makes the provider match it, and never alters what it cannot prove it manages (ExternalDNS-style TXT ownership).

Status: MVP + Cloudflare. DNS records, TXT ownership, sync policies and Cloudflare Tunnel routes work end to end. See ARCHITECTURE.md.

Quick start

Label a container:

services:
  whoami:
    image: traefik/whoami
    labels:
      dockroute.enabled: "true"
      dockroute.hostname: "whoami.example.com"
      # publish through an existing Cloudflare Tunnel:
      dockroute.tunnel.service: "http://whoami:80"

Run dockroute next to it:

services:
  dockroute:
    image: ghcr.io/dockroute/dockroute:latest
    environment:
      DOCKROUTE_PROVIDER: cloudflare
      DOCKROUTE_OWNER_ID: home-lab
      CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN}
      # only needed for tunnel publishing:
      CLOUDFLARE_ACCOUNT_ID: ${CLOUDFLARE_ACCOUNT_ID}
      CLOUDFLARE_TUNNEL_ID: ${CLOUDFLARE_TUNNEL_ID}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    # No user/group setup needed: the entrypoint detects the socket's group,
    # grants it to the app user and drops privileges before starting.

Or start with the zero-credential dry run:

bun install
DOCKROUTE_DEFAULT_TARGET=192.168.1.10 bun start   # provider=log by default

Labels

Label Required Default Description
dockroute.enabled yes true opts the container in
dockroute.hostname yes FQDN(s), comma-separated
dockroute.type no A A, AAAA or CNAME
dockroute.target no DOCKROUTE_DEFAULT_TARGET Record value (IP or CNAME target)
dockroute.ttl no 300 TTL in seconds
dockroute.tunnel.service no Origin URL; publish via Cloudflare Tunnel instead of a plain record
dockroute.cloudflare.proxied no false Proxy plain records through Cloudflare

Configuration

Variable Default Description
DOCKER_SOCK /var/run/docker.sock Docker Engine socket path
DOCKROUTE_PROVIDER log log (dry-run) or cloudflare
DOCKROUTE_DEFAULT_TARGET Fallback target when label is omitted
DOCKROUTE_RESYNC_SECONDS 60 Interval of the periodic full reconcile
DOCKROUTE_OWNER_ID default Ownership id — lets several instances share a zone safely
DOCKROUTE_POLICY sync sync, upsert-only or create-only
DOCKROUTE_TXT_PREFIX _dockroute- Ownership TXT name prefix
DOCKROUTE_DOMAIN_FILTER Comma-separated zone allowlist
CLOUDFLARE_API_TOKEN Token with Zone→DNS→Edit (+ Account→Cloudflare Tunnel→Edit for tunnels)
CLOUDFLARE_ACCOUNT_ID For tunnel publishing
CLOUDFLARE_TUNNEL_ID For tunnel publishing (existing tunnel, you run cloudflared)

Safety model

  • Every record dockroute creates gets a companion TXT record (_dockroute-a.whoami.example.com) carrying its owner id.
  • Records without that proof of ownership are never modified, deleted or adopted — conflicts are logged and skipped.
  • Orphan cleanup (container gone → records removed) only happens under the default sync policy and only for records this instance owns.
  • Tunnel ingress rules that dockroute did not create are preserved verbatim; dockroute assumes it is the only automated writer for the tunnels it manages.

Development

bun install
bun test            # unit tests (in-memory fakes, no real HTTP)
bun run typecheck   # strict TypeScript
bun run lint        # Biome — bun run lint:fix to auto-fix

See CONTRIBUTING.md for the ground rules (ownership safety, anti-corruption layer, testing style) and how to add a provider.

License

MIT

Install DockRoute on Unraid in a few clicks.

Find DockRoute in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for DockRoute Review the template variables and paths Click Install

Related apps

Explore more like this

Explore all

Details

Repository
ghcr.io/dockroute/dockroute:latest
Last Updated2026-08-17
First Seen2026-08-15

Runtime arguments

Network
bridge
Shell
sh
Privileged
false

Template configuration

Docker socketPathro

Docker Engine socket (read-only). DockRoute only listens to events and lists containers.

Target
/var/run/docker.sock
Default
/var/run/docker.sock
Value
/var/run/docker.sock
ProviderVariable

DNS provider: 'log' (dry run, prints desired state, no credentials needed) or 'cloudflare'.

Target
DOCKROUTE_PROVIDER
Default
log
Value
log
Owner IDVariable

Ownership id written to companion TXT records; lets several DockRoute instances share a zone safely.

Target
DOCKROUTE_OWNER_ID
Default
default
Value
default
Sync policyVariable

sync = create/update/delete owned records; upsert-only = never delete; create-only = never update or delete.

Target
DOCKROUTE_POLICY
Default
sync
Value
sync
Default targetVariable

Fallback record value (IP or CNAME target) when a container omits the dockroute.target label. E.g. your server's LAN or WAN IP.

Target
DOCKROUTE_DEFAULT_TARGET
Domain filterVariable

Optional comma-separated allowlist of DNS zones DockRoute may touch. Empty = all zones the token can see.

Target
DOCKROUTE_DOMAIN_FILTER
Resync interval (seconds)Variable

Interval of the periodic full reconcile that backs up the event stream.

Target
DOCKROUTE_RESYNC_SECONDS
Default
60
Value
60
Cloudflare API tokenVariable

Required when provider is cloudflare. Needs Zone > DNS > Edit (+ Account > Cloudflare Tunnel > Edit for tunnel publishing).

Target
CLOUDFLARE_API_TOKEN
Cloudflare account IDVariable

Only needed for Cloudflare Tunnel publishing.

Target
CLOUDFLARE_ACCOUNT_ID
Cloudflare tunnel IDVariable

Only needed for Cloudflare Tunnel publishing. Uses an existing tunnel - you keep running cloudflared yourself.

Target
CLOUDFLARE_TUNNEL_ID