Dnsmasq 服务搭建完全教程 / 第 10 章:Docker 部署
第 10 章:Docker 部署
10.1 为什么容器化部署 Dnsmasq
| 优势 | 说明 |
|---|
| 隔离性 | Dnsmasq 运行在独立环境中,不干扰宿主机 |
| 可移植性 | 配置文件随镜像打包,一键部署 |
| 版本管理 | 使用镜像标签管理不同版本 |
| 快速恢复 | 容器崩溃后秒级重启 |
| 配置管理 | Docker Compose / K8s 统一管理 |
| 挑战 | 说明 |
|---|
| 网络模式 | 需要 host 模式才能正常工作 DHCP |
| 端口占用 | 53 端口可能被其他服务占用 |
| TFTP | 文件映射需要额外配置 |
10.2 基本 Docker 部署
10.2.1 使用官方镜像
# Docker Hub 上流行的 Dnsmasq 镜像
# jpillora/dnsmasq - 最常用的镜像
docker run -d \
--name dnsmasq \
--cap-add=NET_ADMIN \
--net=host \
-v /etc/dnsmasq.conf:/etc/dnsmasq.conf \
-v /etc/dnsmasq.d:/etc/dnsmasq.d \
jpillora/dnsmasq:latest
10.2.2 自定义 Dockerfile
# Dockerfile.dnsmasq
FROM alpine:3.19
RUN apk add --no-cache dnsmasq
# 创建配置目录
RUN mkdir -p /etc/dnsmasq.d /var/lib/misc
# 复制自定义配置
COPY dnsmasq.conf /etc/dnsmasq.conf
COPY conf.d/ /etc/dnsmasq.d/
# 暴露端口
EXPOSE 53/udp 53/tcp 67/udp 69/udp
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD nslookup google.com 127.0.0.1 || exit 1
# 以前台模式运行
CMD ["dnsmasq", "--no-daemon", "--log-facility=-"]
构建并运行:
# 构建镜像
docker build -t my-dnsmasq -f Dockerfile.dnsmasq .
# 运行容器
docker run -d \
--name dnsmasq \
--cap-add=NET_ADMIN \
--net=host \
-v /path/to/config:/etc/dnsmasq.d \
-v /path/to/hosts:/etc/dnsmasq.hosts \
-v /path/to/leases:/var/lib/misc \
my-dnsmasq
10.2.3 网络模式选择
| 网络模式 | DNS | DHCP | 说明 |
|---|
| host | ✅ | ✅ | 推荐,Dnsmasq 直接使用宿主机网络 |
| bridge | ✅ | ⚠️ | DHCP 需要额外配置 |
| macvlan | ✅ | ✅ | Dnsmasq 获得独立 IP |
# host 模式(推荐)
docker run -d --name dnsmasq --net=host my-dnsmasq
# bridge 模式(仅 DNS,不推荐 DHCP)
docker run -d --name dnsmasq \
-p 53:53/udp \
-p 53:53/tcp \
my-dnsmasq
# macvlan 模式(独立 IP)
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth1 \
macvlan_net
docker run -d --name dnsmasq \
--net=macvlan_net \
--ip=192.168.1.2 \
my-dnsmasq
10.3 Docker Compose 部署
10.3.1 基本 Docker Compose 配置
# docker-compose.yml
version: '3.8'
services:
dnsmasq:
image: jpillora/dnsmasq:latest
container_name: dnsmasq
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
volumes:
- ./config/dnsmasq.conf:/etc/dnsmasq.conf:ro
- ./config/dnsmasq.d:/etc/dnsmasq.d:ro
- ./config/hosts:/etc/dnsmasq.hosts:ro
- ./data/leases:/var/lib/misc
- ./logs:/var/log/dnsmasq
environment:
- HTTP_USER=admin
- HTTP_PASS=changeme
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
# 启动
docker compose up -d
# 查看日志
docker compose logs -f dnsmasq
# 重载配置
docker compose exec dnsmasq kill -HUP 1
# 重启
docker compose restart dnsmasq
10.3.2 带 Web UI 的完整配置
# docker-compose.yml
version: '3.8'
services:
dnsmasq:
image: jpillora/dnsmasq:latest
container_name: dnsmasq
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
volumes:
- ./config/dnsmasq.conf:/etc/dnsmasq.conf:ro
- ./config/dnsmasq.d:/etc/dnsmasq.d:ro
- ./config/hosts:/etc/dnsmasq.hosts:ro
- ./data/leases:/var/lib/misc
- ./logs:/var/log/dnsmasq
environment:
# jpillora/dnsmasq 内置 Web UI
- HTTP_USER=admin
- HTTP_PASS=secure_password_here
ports:
- "8080:8080" # Web UI
networks:
default:
name: dnsmasq-net
10.3.3 生产环境 Docker Compose
# docker-compose.prod.yml
version: '3.8'
services:
dnsmasq:
image: jpillora/dnsmasq:latest
container_name: dnsmasq
restart: always
network_mode: host
cap_add:
- NET_ADMIN
- NET_RAW
volumes:
# 配置文件(只读挂载)
- ./config/dnsmasq.conf:/etc/dnsmasq.conf:ro
- ./config/dnsmasq.d:/etc/dnsmasq.d:ro
- ./config/hosts:/etc/dnsmasq.hosts:ro
# 数据目录(读写)
- dnsmasq-leases:/var/lib/misc
- dnsmasq-logs:/var/log/dnsmasq
# 系统文件(只读)
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
environment:
- TZ=Asia/Shanghai
- HTTP_USER=admin
- HTTP_PASS=${ADMIN_PASSWORD:-changeme}
# 资源限制
deploy:
resources:
limits:
cpus: '0.5'
memory: 128M
reservations:
memory: 32M
# 日志配置
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
# 健康检查
healthcheck:
test: ["CMD", "nslookup", "baidu.com", "127.0.0.1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes:
dnsmasq-leases:
dnsmasq-logs:
10.4 Dnsmasq 配置(容器内)
10.4.1 容器内配置文件
# config/dnsmasq.conf
# 适用于 Docker 容器的配置
# 监听地址
listen-address=0.0.0.0
bind-interfaces
# DNS 配置
port=53
cache-size=500
domain=home.lan
expand-hosts
# 上游 DNS
server=223.5.5.5
server=8.8.8.8
no-resolv
# hosts 文件
addn-hosts=/etc/dnsmasq.hosts
# 日志
log-queries
log-facility=/var/log/dnsmasq/dnsmasq.log
# 加载子目录配置
conf-dir=/etc/dnsmasq.d/,*.conf
# config/dnsmasq.d/dhcp.conf
# DHCP 配置(使用 host 网络模式时)
interface=eth1
dhcp-range=192.168.1.100,192.168.1.200,255.255.255.0,24h
dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,192.168.1.1
dhcp-authoritative
10.4.2 热重载配置
# 方法 1:发送 SIGHUP
docker exec dnsmasq kill -HUP 1
# 方法 2:Docker Compose exec
docker compose exec dnsmasq kill -HUP 1
# 方法 3:重建容器(配置文件变更时)
docker compose down
docker compose up -d
# 方法 4:使用 Docker 的 --watch(Docker Compose v2.22+)
# docker compose watch
10.5 容器 DNS 配置
10.5.1 为 Docker 容器提供 DNS
# 方案 1:所有容器使用 Dnsmasq 作为 DNS
# /etc/docker/daemon.json
{
"dns": ["192.168.1.1"],
"dns-search": ["home.lan"]
}
# 重启 Docker
sudo systemctl restart docker
# 方案 2:单个 Compose 项目指定 DNS
services:
webapp:
image: nginx
dns:
- 192.168.1.1 # Dnsmasq 服务器
dns_search:
- home.lan
10.5.2 Docker 内部 DNS 集成
# 使用 Docker 自定义网络,指定 DNS
version: '3.8'
services:
dnsmasq:
image: jpillora/dnsmasq:latest
container_name: dnsmasq
network_mode: host
cap_add:
- NET_ADMIN
volumes:
- ./config:/etc/dnsmasq.d:ro
# 应用容器使用自定义 DNS
webapp:
image: nginx
dns:
- 192.168.1.1
networks:
- app-net
api:
image: node:18
dns:
- 192.168.1.1
networks:
- app-net
networks:
app-net:
driver: bridge
10.5.3 容器名称解析
# Docker Compose 中容器之间自动解析服务名
# 如果需要自定义 DNS,可以在 Dnsmasq 中添加
# config/dnsmasq.d/docker-services.conf
address=/webapp.home.lan/172.17.0.2
address=/api.home.lan/172.17.0.3
address=/db.home.lan/172.17.0.4
10.6 DHCP 在 Docker 中的注意事项
10.6.1 DHCP 必须使用 host 网络模式
# DHCP 需要直接访问物理网络接口
# bridge 模式下 DHCP 请求无法正确传递
# 推荐配置
docker run -d --name dnsmasq \
--net=host \
--cap-add=NET_ADMIN \
my-dnsmasq
10.6.2 替代方案:使用 macvlan
# 如果不能使用 host 模式,使用 macvlan
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth1 \
lan-net
docker run -d --name dnsmasq \
--net=lan-net \
--ip=192.168.1.2 \
--cap-add=NET_ADMIN \
my-dnsmasq
10.7 日志与监控
10.7.1 容器日志管理
# docker-compose.yml
services:
dnsmasq:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
# 或使用外部日志驱动
# logging:
# driver: "syslog"
# options:
# syslog-address: "tcp://log-server:514"
10.7.2 Prometheus 监控集成
# 使用 Dnsmasq exporter
version: '3.8'
services:
dnsmasq:
image: jpillora/dnsmasq:latest
network_mode: host
cap_add:
- NET_ADMIN
# Prometheus Dnsmasq Exporter
dnsmasq-exporter:
image: google/dnsmasq_exporter:latest
command:
- "--dnsmasq.address=http://127.0.0.1:53"
ports:
- "9153:9153"
restart: unless-stopped
10.8 Kubernetes 部署
10.8.1 DaemonSet 部署
# k8s/dnsmasq-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: dnsmasq
namespace: kube-system
spec:
selector:
matchLabels:
app: dnsmasq
template:
metadata:
labels:
app: dnsmasq
spec:
hostNetwork: true
dnsPolicy: Default
containers:
- name: dnsmasq
image: jpillora/dnsmasq:latest
ports:
- containerPort: 53
protocol: UDP
- containerPort: 53
protocol: TCP
securityContext:
capabilities:
add:
- NET_ADMIN
volumeMounts:
- name: config
mountPath: /etc/dnsmasq.conf
subPath: dnsmasq.conf
readOnly: true
- name: config-dir
mountPath: /etc/dnsmasq.d
readOnly: true
resources:
requests:
memory: "32Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
volumes:
- name: config
configMap:
name: dnsmasq-config
- name: config-dir
configMap:
name: dnsmasq-confd
10.8.2 ConfigMap 配置
# k8s/dnsmasq-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: dnsmasq-config
namespace: kube-system
data:
dnsmasq.conf: |
listen-address=0.0.0.0
port=53
cache-size=500
server=223.5.5.5
server=8.8.8.8
no-resolv
log-queries
log-facility=-
conf-dir=/etc/dnsmasq.d/,*.conf
10.9 完整部署示例
项目目录结构
dnsmasq-docker/
├── docker-compose.yml
├── Dockerfile
├── .env
├── config/
│ ├── dnsmasq.conf
│ ├── hosts
│ └── dnsmasq.d/
│ ├── 01-upstream.conf
│ ├── 02-dhcp.conf
│ └── 03-custom.conf
├── data/
│ └── leases/
├── logs/
└── scripts/
├── backup.sh
└── update-adblock.sh
# .env
ADMIN_PASSWORD=secure_password_here
TIMEZONE=Asia/Shanghai
# 启动
docker compose up -d
# 验证
dig @127.0.0.1 www.baidu.com
# 查看日志
docker compose logs -f dnsmasq
# 更新配置后重载
docker compose exec dnsmasq kill -HUP 1
# 停止
docker compose down
10.10 小结
| 场景 | 网络模式 | DHCP | 推荐 |
|---|
| 主机 DNS 服务 | host | ✅ | ⭐ 推荐 |
| 仅 DNS 缓存 | bridge | ❌ | 简单场景 |
| 独立网络 | macvlan | ✅ | 多网段 |
| 关键配置 | 说明 |
|---|
--net=host | DHCP 必须使用 host 模式 |
--cap-add=NET_ADMIN | DHCP 需要网络管理权限 |
| 配置文件只读挂载 | :ro 防止容器内修改 |
| 日志持久化 | 挂载日志目录或使用 Docker 日志驱动 |
10.11 扩展阅读