为什么要把 AdGuard Home 和 Nginx Proxy Manager 放在一起聊?
很多玩 Docker 的朋友,最终都会走向一条“自建全家桶”的路。折腾过一阵子你就会发现,DNS 解析和反向代理是无论如何都绕不开的两个核心环节。AdGuard Home 负责在源头拦截广告和恶意域名,Nginx Proxy Manager(下文简称 NPM)则负责把家里或 VPS 上乱七八糟的端口服务,统一收敛到 80/443 上,配上 HTTPS 证书,干净又安全。
这两者搭配起来,一个管“入口”的纯净度,一个管“出口”的统一性。今天笔者就把这两套服务的 Docker 部署配置、初始化细节以及常见坑位一次讲透。如果你对服务器基础配置还有疑问,建议先看看我们之前写的云服务器网卡带宽到底怎么选?全网拉测性能指标的一次深度拆解,别让带宽瓶颈拖了后腿。
环境准备与网络规划
在敲命令之前,我们建议先理清网络拓扑。假设你有一台云服务器或者家里的小主机(Debian/Ubuntu),Docker 和 Docker Compose 已经装好。我们需要规划两个关键点:
- IP 与端口:AdGuard Home 默认监听 53(DNS)、80(初始化面板)、3000(安装向导)。NPM 默认监听 80、443、81(管理面板)。强烈建议把 AdGuard 的 80 端口映射到宿主机的其他端口(如 8080),避免与 NPM 的 80 冲突。
- Bridge 网络:为了让两个容器能通过内部域名互相访问,我们创建一个自定义 Docker 网络。
docker network create webnet
第一步:部署 AdGuard Home(DNS 拦截核心)
AdGuard Home 的部署本身不复杂,但映射端口时要注意。我们用 docker-compose.yml 来定义服务,方便后续维护。
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguardhome
restart: unless-stopped
networks:
- webnet
ports:
- "53:53/tcp"
- "53:53/udp"
- "3000:3000/tcp" # 初始化向导端口
- "8080:80/tcp" # 将面板映射到宿主机的 8080
volumes:
- ./adguard/work:/opt/adguardhome/work
- ./adguard/conf:/opt/adguardhome/conf
networks:
webnet:
external: true
执行 docker compose up -d 后,访问 http://服务器IP:3000 进行初始化。这里有个细节:初始化向导里填写的“Web 管理界面端口”和“DNS 服务端口”要填写容器内部的端口,即 80 和 53,不要填宿主机映射后的 8080 和 53(53 没变,但 80 一定要填 80)。否则你会发现面板打不开。
初始化完成后,管理界面地址就变成了 http://服务器IP:8080。进入面板后,在“设置 – DNS 设置”里,建议勾选“速度限制”并设置一个合理的值,防止被恶意利用做 DNS 放大攻击。在“过滤器 – DNS 拦截清单”里,添加几个知名的广告规则列表,这里就不一一列举地址了,网上搜“AdGuard Home 规则”一大把,挑维护活跃的加即可。
第二步:部署 Nginx Proxy Manager(反向代理与 SSL 终结)
NPM 的存在就是为了让我们告别手写 Nginx 配置的繁琐。它提供 Web 界面,点点鼠标就能完成域名转发和 Let’s Encrypt 证书申请。同样,我们用 Compose 部署:
services:
npm:
image: jc21/nginx-proxy-manager:latest
container_name: npm
restart: unless-stopped
networks:
- webnet
ports:
- "80:80"
- "443:443"
- "81:81" # 管理面板端口
environment:
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm_pass"
DB_MYSQL_NAME: "npm"
volumes:
- ./npm/data:/data
- ./npm/letsencrypt:/etc/letsencrypt
depends_on:
- db
db:
image: mariadb:10.8
container_name: npm-db
restart: unless-stopped
networks:
- webnet
environment:
MYSQL_ROOT_PASSWORD: "root_pass"
MYSQL_DATABASE: "npm"
MYSQL_USER: "npm"
MYSQL_PASSWORD: "npm_pass"
volumes:
- ./npm/mysql:/var/lib/mysql
networks:
webnet:
external: true
登录 http://服务器IP:81,默认账号 admin@example.com,密码 changeme。首次登录会强制修改密码。
关键配置:让 NPM 反代 AdGuard Home 面板
我们以“把 AdGuard Home 面板绑定到 ad.yourdomain.com”为例。在 NPM 中点击 “Add Proxy Host”:
- Domain Names:填
ad.yourdomain.com。 - Forward Hostname / IP:这里填容器内部名称
adguardhome(因为我们用了同一个网络 webnet)。 - Forward Port:填
80(注意是容器端口,不是宿主机的 8080)。 - Block Common Exploits:勾选。
- SSL 选项卡:选择 “Request a new SSL Certificate”,勾选 “Force SSL” 和 “HTTP/2”。
保存后,访问 https://ad.yourdomain.com 就能看到 AdGuard 面板,且自动跳转 HTTPS。这套逻辑同样适用于反代你部署的其他任何 Web 服务,比如后续想折腾 WordPress,可以参考我们之前写的网站慢如蜗牛?用Redis缓存加静态资源优化,让你的WordPress飞起来,通过 NPM 反代后配合 Redis 缓存,速度会有质的飞跃。
进阶:让 AdGuard Home 作为上游 DNS
如果你希望 NPM 所在的主机或内网设备都通过 AdGuard 过滤,需要修改宿主机的 DNS 指向。但这里要注意,AdGuard 的 53 端口映射在宿主机上,如果你把宿主机的 DNS 也指向 127.0.0.1,会导致 Docker 容器内 DNS 解析死循环。这是一个非常经典的坑。
正确的做法是:在 AdGuard 的设置里,将 “Upstream DNS Servers” 设置为公共 DNS(如 1.1.1.1 或 223.5.5.5),然后在宿主机防火墙规则中,只允许内网网段访问 53 端口。对于 Docker 容器本身,我们更推荐在 NPM 的 Compose 文件里,给每个容器单独指定 dns 配置,指向 AdGuard 的容器 IP。
services:
npm:
...
dns:
- 172.18.0.2 # 替换为 adguardhome 容器的实际 IP,可用 docker inspect 查看
这样既能让容器流量经过广告过滤,又不会干扰宿主机的网络栈。
常见问题与排查思路
| 症状 | 原因 | 解决方案 |
|---|---|---|
| AdGuard 初始化后 80 端口无法访问面板 | 向导中填了宿主机映射端口 | 重新初始化或修改 conf 文件中的端口为 80 |
| NPM 申请证书失败 | 域名 DNS 未解析到本机,或 80 端口被占用 | 确认 A 记录指向,检查宿主机的 80 端口是否被其他进程占用 |
| 容器间无法通过服务名互通 | 未加入同一外部网络 | 确保两个 Compose 文件都声明了 external: true 的 webnet |
| DNS 解析延迟高 | 上游 DNS 选择不当 | 国内建议使用 223.5.5.5 或 119.29.29.29 |
安全加固与一点延伸建议
服务跑起来后,安全这根弦不能松。AdGuard Home 的管理面板和 NPM 的管理面板千万不要直接暴露在公网,只监听内网或通过防火墙限制来源 IP。如果你对防火墙配置不熟悉,强烈推荐阅读我们这篇实战踩坑记录:别再裸奔了!Linux服务器安全加固与UFW防火墙配置,这些坑我替你踩过了。另外,如果你用的是云服务器,建议在安全组层面就把 81 端口(NPM 管理)和 3000 端口(AdGuard 初始化)封锁掉,只保留 80、443 和 53 的对外访问。
至于服务器选择,如果你打算长期跑这两个服务,加上后续可能折腾其他容器,内存最好在 2GB 以上。带宽方面,DNS 请求虽然占用极小,但如果你用 NPM 反代大流量应用,务必关注月流量包是否够用。之前我们深度拆解过云服务器网卡带宽到底怎么选?全网拉测性能指标的一次深度拆解,选购前不妨参考一下。
最后提醒一句,SSH 登录千万别再用密码,赶紧换成密钥对登录,这是底线。具体操作可以看这篇:黑客天天扫你的服务器?关掉密码登录,用 SSH 密钥对一把锁死暴力破解。
这套组合拳打下来,你的服务器基本就具备了广告拦截、统一入口、自动 HTTPS 三大能力。剩下的,就是慢慢往里面加服务了。祝折腾愉快。