内网服务一多,Jenkins、Git、测试环境各一个 IP,开发运维各记一套,换台机器还得重新配。
与其继续维护 hosts,不如在内网放一台自己的 DNS:内部域名统一解析,外部域名缓存转发,客户端只改一个 DNS 地址。dnsmasq 轻量、配置直观,很适合干这件事。
先写 dnsmasq 配置
先在宿主机上建一个工作目录,把配置文件和 compose 文件放在一起,后面改起来方便。
bash
mkdir ~/dnsmasq-docker && cd ~/dnsmasq-docker
nano dnsmasq.conf
配置文件可以这样写:
conf
# 监听所有地址(容器内 0.0.0.0 才能被外部访问)
listen-address=0.0.0.0
bind-interfaces
port=53
# 不读取容器内的 /etc/resolv.conf,避免行为不可控
no-resolv
server=223.5.5.5
server=119.29.29.29
# 你的内部域名(以 internal.com 为例)
local=/internal.com/
address=/jenkins.internal.com/10.8.0.2
address=/git.internal.com/10.8.0.2
# 记录查询日志,方便排障
log-queries
log-facility=-
用 Docker Compose 启动
同目录下新建 docker-compose.yml:
yml
services:
dnsmasq:
image: dockurr/dnsmasq:latest
container_name: dnsmasq
ports:
- "53:53/tcp"
- "53:53/udp"
volumes:
- ./dnsmasq.conf:/etc/dnsmasq.conf:ro
restart: unless-stopped
cap_add:
- NET_ADMIN
启动并看状态:
bash
docker compose up -d
docker ps | grep dnsmasq
docker logs dnsmasq
如果启动后发现 53 端口被占用
有时候 docker compose up -d 之后容器反复重启,docker logs dnsmasq 里能看到 53 端口绑定失败。先确认一下宿主机上是谁占着:
ss -lunpt | grep :53
比较常见的情况是宿主机上的 systemd-resolved 在监听 127.0.0.53:53,和 dnsmasq 要绑定的 0.0.0.0:53 冲突了。
不建议直接 systemctl disable systemd-resolved。这样做会连带影响 Netplan 的 DNS 渲染、VPN 的分离 DNS,以及部分软件对 systemd-resolved 的依赖。更稳妥的做法是只关闭它的 53 监听,保留服务本身:
bash
sudo mkdir -p /etc/systemd/resolved.conf.d/
sudo tee /etc/systemd/resolved.conf.d/disable-stub.conf <<'EOF'
[Resolve]
DNSStubListener=no
EOF
sudo systemctl restart systemd-resolved
执行完后再启动一次容器:
docker compose up -d
测试 DNS 解析
先在宿主机上直接向容器查询:
bash
dig @127.0.0.1 jenkins.internal.com
dig @192.168.1.10 git.internal.com
应返回你在 dnsmasq.conf 中配置的 10.8.0.2。
然后从另一台内网机器测试:
bash
dig @192.168.1.10 jenkins.internal.com
这一步很关键。如果本机成功但远程失败,通常是两个原因。
- 宿主机防火墙未放行 53 端口
- dnsmasq 在容器内监听的地址不对。
如果dnsmasq.conf里写的是listen-address=127.0.0.1,容器内的 dnsmasq 只监听容器自己的回环地址,外部流量根本进不来。需要改成listen-address=0.0.0.0,或者按你的规划改成宿主机具体内网 IP。
让内网服务器把 DNS 指向 dnsmasq
dnsmasq 跑通后,还需要让内网机器把查询发给它。不同系统改法不一样,但原则相同:首选 DNS 指向 dnsmasq,备用 DNS 放一个可用的公网上游,避免 dnsmasq 本身故障时整网解析中断。
使用 systemd-resolved 的系统,编辑 /etc/systemd/resolved.conf:
ini
[Resolve]
DNS=192.168.1.10 223.5.5.5
然后重启:
bash
sudo systemctl restart systemd-resolved
使用 Netplan 的 Ubuntu 服务器,在对应网卡下添加:
yml
nameservers:
addresses: [192.168.1.10, 223.5.5.5]
改完后用 dig 或 resolvectl 确认解析结果。到这里,内网 DNS 的主体部分就已经可用了。