项目地址:https://github.com/shubaocai/sbc-dnsmgr | MIT License
如果你的域名散在阿里云、腾讯云、Cloudflare、华为云好几家,改一条解析要挨个登录控制台,那 dnsmgr(彩虹聚合DNS管理系统) 就是干这个的:一个面板管所有平台的解析。
先说清楚一个容易误解的点:dnsmgr 自己不做 DNS 解析。它不是 BIND / PowerDNS 那种域名服务器,而是替你调用各家云厂商的 API 去改记录、申请和部署证书。所以它只是「管」解析,真正的解析还是在各家的 DNS 服务器上。
这篇记录一下怎么用一条命令把它跑起来,以及过程中踩到的几个坑。
它到底能干什么
| 能力 | 说白了就是 |
|---|---|
| 聚合管理 | 一个面板里管 20 多家平台:阿里云、腾讯云 DNSPod、华为云、百度云、火山引擎、京东云、青云、西部数码、宝塔、Cloudflare、AWS Route 53、Namesilo、Spaceship、PowerDNS、Technitium、HE.net、dynv6、GoEdge、DNSLA 等 |
| 多用户 | 给每个用户分配不同的域名权限,可以开 API 和免登录链接,方便 IDC 系统对接 —— 说白了能当小型的 DNS 代管服务用 |
| 容灾切换 | 支持 ping / tcp / http(s) 检测,站点挂了自动暂停或切换解析,恢复了再切回来,并推通知 |
| 定时切换 | 到点自动改 / 暂停 / 删除解析记录 |
| CF 优选 IP | 自动拉取 Cloudflare 优选 IP 并写回解析 |
| SSL 证书 | 从 Let's Encrypt 等渠道申请,再自动部署到面板 / 云厂商 / 服务器(宝塔、1Panel、K8s、群晖、FTP、SSH……几十种目标) |
| 通知 | 邮件、微信公众号、Telegram、钉钉、飞书、企业微信、QQ 机器人 |
同类面板也有几个,dnsmgr 的优势是更新勤、平台覆盖多、证书自动部署的目标特别全。
官方部署方式的两个坑
上游 README 给了 docker run 和 docker-compose 两种,但它给的卷挂法有坑:
# 上游示例(有坑)
docker run --name dnsmgr -dit -p 8081:80 -v /var/dnsmgr:/app/www netcccyun/dnsmgr
问题在这个镜像的 entrypoint:它用 cp -a /usr/src/www /app/ 把程序铺进 /app/www。而你把卷挂在 /app/www(那是已存在的挂载点),cp 会把它套一层变成 /app/www/www,结果 nginx 的 root /app/www/public 找不到入口文件,页面直接 404。
第二个坑是:面板的自动化功能(容灾切换、定时切换、CF 优选、证书自动续期)依赖常驻进程 + cron。这个镜像内部已经带了 supervisord 和 crond,用官方 docker run 其实也有,但如果你在虚拟主机 / 宝塔上手动部署,就只有 PHP-CGI,没有常驻进程,这些功能基本只能手动点。
所以我把部署过程写成了一个脚本,一次性把环境检查、Docker 安装、数据库初始化、健康检查都处理掉,也顺手避开了上面这个卷挂载的坑(改成挂 /app)。
脚本做了什么
| 步骤 | 内容 |
|---|---|
| 1/7 检查环境 | 校验 root、系统与架构、磁盘;内存不足 4GB 且没有 swap 时自动加 2GB swap;检查端口占用 |
| 2/7 安装 Docker | 依次探测 5 个 Docker 软件源(腾讯云内网 / 腾讯云公网 / 阿里云 / 中科大 / 官方),gpg 和 dists/<codename>/Release 都取得到才用;装完自动配镜像加速、限制容器日志大小 |
| 3/7 生成配置 | 随机生成两个密码(openssl rand -hex 16),写 docker-compose.yml 与 .credentials(都是 600) |
| 4/7 拉镜像 | 优先从华为云 SWR 拉(国内快),失败自动退回 Docker Hub |
| 5/7 起数据库 | MySQL 5.7 + 健康检查,自动建库建用户,并实测该账号能不能登录 |
| 6/7 起面板 | 面板容器 + 健康检查,校验程序是否真的落在 /app/www/public/index.php |
| 7/7 汇总 | 把面板地址、目录、凭据文件,以及向导里要填的数据库信息打在屏幕上 |
其中「国内网络」那一段是花时间最多的地方,和之前处理其它项目时踩的坑一样:
download.docker.com经常 TLS 握手被重置 → 改成 5 个源逐个探测,能取到 GPG 和 Release 才采用- 容器里没有 IPv6,
deb.debian.org返回 AAAA 会让 apt 卡死 → 强制 IPv4 - 镜像站首选国内(华为云 SWR 比 Docker Hub 稳得多)
三条命令跑起来
curl -fsSL -o /tmp/dnsmgr.sh https://raw.githubusercontent.com/shubaocai/sbc-dnsmgr/main/install_dnsmgr.sh && sudo bash /tmp/dnsmgr.sh
raw.githubusercontent.com 时通时不通的话,换 jsDelivr:
curl -fsSL -o /tmp/dnsmgr.sh https://cdn.jsdelivr.net/gh/shubaocai/sbc-dnsmgr@main/install_dnsmgr.sh && sudo bash /tmp/dnsmgr.sh
或者 clone 下来跑:
git clone https://github.com/shubaocai/sbc-dnsmgr.git
cd sbc-dnsmgr
sudo bash install_dnsmgr.sh
跑完屏幕上会直接把要用的信息列成两块,重点信息在最底部:
▸ 安装向导: http://<你的公网IP>:8081/
项目目录: /opt/dnsmgr
挂载目录: /opt/dnsmgr/app(程序与配置)、/opt/dnsmgr/mysql(数据库)
凭据文件: /opt/dnsmgr/.credentials(600,那串密码也在里面)
▸ 向导里这样填(其它留默认):
数据库主机:dnsmgr-mysql 端口:3306
数据库名: sbc_dnsmgr
数据库用户:sbc_dnsmgr
数据库密码:<脚本随机生成>
管理员账号 / 密码:自己设,装完立刻开二次验证(TOTP)
装完要填的字段
浏览器打开 http://<你的公网IP>:8081/,会跳到安装页。这里有个必踩的坑:
| 字段 | 填什么 |
|---|---|
| 数据库主机 | dnsmgr-mysql —— ⚠️ 不能填 localhost 或 127.0.0.1 |
| 数据库端口 | 3306 |
| 数据库名 / 用户 | sbc_dnsmgr / sbc_dnsmgr |
| 数据库密码 | 脚本最后打印的那串(也在 /opt/dnsmgr/.credentials) |
| 表前缀 | 默认 dnsmgr_,不用改 |
| 管理员 | 自己设,装完立刻开 TOTP |
为什么主机要填 dnsmgr-mysql?因为面板和数据库是两个容器,靠 Docker 内部的服务名互相找。填 localhost 时,PHP 找的是面板容器自己,那里当然没有 MySQL —— 报错就是一句干巴巴的「数据库连接失败」。我自己第一次就填错在这里。
实测数据
| 项目 | 数值 |
|---|---|
| 测试环境 | Ubuntu 22.04.5 LTS / x86_64 / 2 vCPU / 1.9GB 内存 / 50GB 磁盘 |
| 从零到面板可访问 | 约 2~3 分钟(拉镜像约 240MB 占大头) |
| 内存占用 | 面板容器约 84MB + MySQL 约 194MB,整机约 550MB |
| 磁盘占用 | 整套(Docker + 镜像 + 数据库)约 3.4GB |
| 重复执行 | 幂等:检测到已安装会复用原数据库密码,不会把密码改掉、数据不受影响 |
2GB 内存的小机器完全够用 —— 脚本还会在内存不足 4GB 且没有 swap 时自动补 2GB swap,避免 MySQL + Swoole 常驻任务把内存吃紧。
装完立刻做三件事
- 先加一个「域名账户」:选平台、填那家的 API 密钥。这一步不做的话,「域名管理」页面会报 500(
Call to a member function getDomainList() on false)—— 这是上游没做空值判断的小 bug,只要面板里还没任何账户、它就拿空账户去查域名列表。加一个账户就好了。 - 开启 TOTP 二次验证,并改掉安装时的初始密码。
- 加 HTTPS 反代 + 限制来源 IP(见下面「安全」)。
几个实测会遇到的正常现象
| 现象 | 说明 |
|---|---|
容器日志里 dmtask 一直重启(exit status 255) |
正常。安装向导走完前读不到 .env,supervisord 会一直重启它;装完自动稳定 |
| 服务器上用公网 IP 打不开自己的面板 | 云服务器常有回环限制,用 curl -I http://127.0.0.1:8081/ 自测;从外部能不能访问要用另一台机器测 |
| 浏览器打不开面板 | 先查安全组有没有放行 8081,这是最常见原因 |
| 向导提示「当前已经安装成功,如果需要重新安装,请手动删除根目录 .env 文件」 | 已经装过了。重装要删 /opt/dnsmgr/app/www/.env,或者 docker compose down -v 后重跑 |
/fpm-ping 从宿主机访问返回 403 |
设计如此,镜像只允许容器内的 127.0.0.1 访问探针 |
升级 / 备份 / 卸载
# 升级到最新镜像(自动拉新镜像、覆盖程序文件,数据库和 .env 保留)
bash install_dnsmgr.sh --upgrade
# 备份数据库
docker exec dnsmgr-mysql sh -c "exec mysqldump -uroot -p$(awk -F': ' '/^数据库 root 密码/{print $2}' /opt/dnsmgr/.credentials) --databases sbc_dnsmgr" > sbc_dnsmgr-$(date +%F).sql
# 备份程序与配置(含 .env、证书、runtime)
tar czf dnsmgr-app-$(date +%F).tar.gz -C /opt/dnsmgr app
# 停止 / 卸载
cd /opt/dnsmgr && docker compose down # 停服,数据保留
rm -rf /opt/dnsmgr # 连数据一起删
上游更新挺勤(基本几个月一个版本),建议升级前先备份数据库。
关于安全,得说重一点
这个面板里会保存各家云平台的 API 密钥 —— 那基本等于你域名的最高权限;它还能通过 SSH / FTP 往服务器上部署证书。也就是说,它本身就是一个高价值目标:
- 一定要上 HTTPS(Nginx / Caddy 反代 + Let's Encrypt),别长期裸 HTTP 暴露在公网
- 强密码 + 开启 TOTP 二次验证
- 尽量在安全组里只放行你的固定 IP,或者干脆只在内网访问
- 容器里的 MySQL 默认没有对宿主机暴露端口,这是有意的,别随手加
ports: 3306:3306
相关链接
- 部署脚本仓库(含 README、常见问题、环境变量):https://github.com/shubaocai/sbc-dnsmgr
- 上游项目 dnsmgr:https://github.com/netcccyun/dnsmgr
- 官方镜像:
swr.cn-east-3.myhuaweicloud.com/netcccyun/dnsmgr:latest(国内)/netcccyun/dnsmgr(Docker Hub)
装的过程中卡在哪一步,把屏幕上的提示原样发出来就行 —— 脚本的每一步都会把「在做什么、结果如何」打出来,失败时也会给下一步的建议(比如换哪个源、换哪个端口)。
