docker-traefik-dns - 根据容器标签 URL 自动创建 Cloudflare DNS 记录
status
Published
type
Post
slug
docker-traefik-dns-with-cloudflare
date
Sep 9, 2026
tags
Docker
Tool
DevOps
Cloudflare
Tailscale
summary
一个用 Go 语言编写的轻量级开源工具 docker-traefik-dns,自动化解决自建服务中的 DNS 配置繁琐问题。它能够读取 Docker 容器标签或 Traefik 规则中的域名,并自动调用 Cloudflare API 创建对应的 DNS 解析记录。
在服务器上部署服务后,还要到 Cloudflare 上配置一条 DNS 记录,有点麻烦。
(虽然 AI Agent 能自动去干,但是 token 在这方面烧不起也没必要,而且有时候还有幻觉不确定性)
既然 Traefik 通过 Lable 完成了对其他服务的反向代理,而 Lable 中也有对应的服务域名,那么再来个程序依据 Lable 中的域名自动去调用 Cloudflare 的 API 添加对应的 A 记录或者 CNAME 记录不就完成上线可以访问了。
把想法和 AI 讨论一番后,直接就得到了下面这个简单项目
compose.yaml
services: docker-traefik-dns: image: ghcr.io/hkint/docker-traefik-dns container_name: docker-traefik-dns restart: unless-stopped environment: # Cloudflare Configuration,需要 DNS 编辑权限的 API Token - CF_API_TOKEN=${CF_API_TOKEN} - CF_PROXY=${CF_PROXY:-false} - CF_TTL=${CF_TTL:-1} - DOMAIN_FILTER=${DOMAIN_FILTER:-okhk.net} # Source configuration: "both" (default), "docker", or "traefik" - DNS_SOURCE=both # Default Target IP (Your public IP or Tailscale IP / LAN IP) - DEFAULT_TARGET_IP=${DEFAULT_TARGET_IP} # Docker Socket connection (reads container labels and Traefik rules directly) - DOCKER_HOST=unix:///var/run/docker.sock # Traefik API endpoint (optional if reading directly via docker socket) # - TRAEFIK_API_URL=http://traefik:8080 # - TRAEFIK_TARGET_IP=${DEFAULT_TARGET_IP} # Operational settings - SYNC_INTERVAL=60s - DRY_RUN=false - LOG_LEVEL=info volumes: - /var/run/docker.sock:/var/run/docker.sock:ro networks: - traefik-net networks: traefik-net: driver: bridge
包含如下特性:
自动化感知与解析:服务采用 Go 语言编写,可以直接读取 Docker Socket 或 Traefik API,自动解析
Host(...) / HostSNI(...) 路由规则中的域名,无需重复配置。声明式 Label 覆盖:除了自动抓取 Traefik 规则外,还支持通过自定义 Docker 标签(如
docker-traefik-dns.hostname、docker-traefik-dns.target)甚至兼容 Kubernetes external-dns 的标签,显式指定域名、目标 IP 及是否开启 Cloudflare 代理。基于 TXT 记录的安全所有权校验:为了防止误删手动创建或其他服务管理的 DNS 记录,服务会在更新 DNS 时自动写入带有唯一标识符的 TXT 所有权记录。在 reconcile 同步循环中,仅处理带有该标识符的托管记录,保证了极高的安全边界。
Dry-run 与安全回退:提供
DRY_RUN 模式用于上线前的变更预览,同时支持设置全局 DEFAULT_TARGET_IP 与白名单 DOMAIN_FILTER 过滤。其中
DNS_SOURCE=docker 指的是“从 Docker Engine API 读取容器及其 labels”,并不是说域名必须来自 Docker 专用 label。它会读取容器上的如下 label:# 1. 标准 Traefik labels labels: - "traefik.enable=true" - "traefik.http.routers.app.rule=Host(`app.okhk.net`)" # 2. Docker Traefik DNS 自定义 label labels: - "docker-traefik-dns.hostname=app.okhk.net" # 兼容 ExternalDNS 的 label: - "external-dns.alpha.kubernetes.io/hostname=app.okhk.net"
而
DNS_SOURCE=traefik 则是基于 Traefik API 获取已加载的 router rule,不会读取 Docker 容器上的 docker-traefik-dns.target label,一般会共用一个 Target 和 Proxy 配置。Traefik API → /api/http/routers Traefik API → /api/tcp/routers
故而可采用如下配置:
DNS_SOURCE=docker DEFAULT_TARGET_IP=100.64.0.10 CF_PROXY=false # 如测试配置开启 Dry run # DRY_RUN=true
- 部署内网服务(基于 Tailscale)
只需要默认的 traefik label 即可
labels: - "traefik.enable=true" - "traefik.http.routers.internal.rule=Host(`internal.okhk.net`)"

此处以 whoami 为例,Cloudflare 显示已添加 A 记录,并有 TXT 管理记录

- 部署公网服务(基于 Cloudflare Tunnel)
额外配置覆盖 target 和 proxy
labels: - "traefik.enable=true" - "traefik.http.routers.public.rule=Host(`public.okhk.net`)" - "docker-traefik-dns.target=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.cfargotunnel.com" - "docker-traefik-dns.proxy=true"


注意:Cloudflare Tunnel 需要在 Zero Trust 控制台配置域名通配符转发,不然会被
Catch-all: http_status:403 拦截