Poweradmin v4.4.3 Docker Compose 部署指南
Docker Compose 三服务栈部署 Poweradmin v4.4.3 + PowerDNS 4.9.18 gmysql + MariaDB 10.11 的完整实录:编排文件全文、部署与解析验证闭环、8 个真实排障坑速查。
Poweradmin v4.4.3 Docker Compose 部署指南
目标:在一台 Ubuntu 22.04 服务器上,用 Docker Compose 部署「Poweradmin v4.4.3 + PowerDNS Authoritative 4.9.18(gmysql 后端)+ MariaDB 10.11」三服务栈,跑通「服务启动 → 管理员登录 → 建 master zone → 记录增/删/改 → dig 验证解析生效」的完整闭环,并沉淀全程踩到的 8 个真实故障点。本文全部命令与回显已在 Docker Engine 29.9.2(Compose v5.6.1)环境实测通过。
一、环境信息
| 项目 | 取值 |
|---|---|
| 操作系统 | Ubuntu 22.04(root 用户) |
| Docker Engine | 29.9.2 |
| Docker Compose | v5.6.1 |
| Poweradmin | v4.4.3(官方镜像 poweradmin/poweradmin:4.4.3,解压后 761MB) |
| PowerDNS Authoritative | 4.9.18(官方镜像 powerdns/pdns-auth-49:4.9.18,解压后 378MB) |
| 数据库 | MariaDB 10.11(官方镜像 mariadb:10.11,解压后 459MB) |
| 网络隔离 | 自定义 bridge 网络,子网 10.89.60.0/24 |
| 端口规划 | Web 界面 8131(映射容器 80);DNS 服务 5311(映射容器 53,TCP+UDP) |
| 示例账号 | 管理员 admin / q1w2e3r4;数据库 root q1w2e3r4 |
| 部署形态 | 三服务同一栈、同一网络:Poweradmin 经 SQL 直连模式读写 PowerDNS 的 gmysql 库 |
💡 技术拓展:本篇采用 Poweradmin 的 SQL 直连模式(
dns.backend='sql')——Poweradmin 与 PowerDNS 共用同一个 MariaDB 库,Poweradmin 直接读写其中的 domains/records 表,DNSSEC rectify 场景下 Poweradmin 另行调用 PowerDNS 的 HTTP API(见 compose 中的PA_PDNS_API_URL/PA_PDNS_API_KEY)。若采用 API 后端模式(dns.backend='api'),Poweradmin 不需要数据库权限,全部变更经 PowerDNS REST API 下发,两种模式的取舍见《Poweradmin v4.4.3 介绍与选型指南》 3.1 节。
1.1 版本依据
- Poweradmin v4.4.3 是 GitHub Releases 页当前标记「Latest」的版本(4.4 LTS 维护线补丁,发布说明确认从 v4.4.2 原地替换无需数据库迁移);
- PowerDNS 4.9.18 与 MariaDB 10.11 是 Poweradmin 官方 README「Tested on」矩阵中 4.4.x 线的实测组合;
- 镜像标签约定:
stable当前指向 4.4.x 线,latest指向 4.5.x,4.4跟踪 4.4 线最新补丁,生产建议固定精确版本标签(本文用4.4.3)。
二、编排文件
2.1 目录结构
/opt/poweradmin/
├── docker-compose.yml # 三服务编排
└── pdns.conf # PowerDNS Authoritative 配置(必须挂载覆盖镜像默认值,见 3.2)
2.2 docker-compose.yml 全文
name: poweradmin-4.4.3-stack
networks:
pa-net:
driver: bridge
ipam:
config:
- subnet: 10.89.60.0/24
services:
db:
image: mariadb:10.11
container_name: poweradmin-4.4.3-db
hostname: db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: q1w2e3r4
MARIADB_DATABASE: powerdns
MARIADB_USER: poweradmin
MARIADB_PASSWORD: q1w2e3r4
volumes:
- db-data:/var/lib/mysql
networks: [pa-net]
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 5s
timeout: 5s
retries: 20
app:
image: poweradmin/poweradmin:4.4.3
container_name: poweradmin-4.4.3-app
hostname: app
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "8131:80"
environment:
# 数据库连接(Poweradmin 自身表与 PowerDNS gmysql 表共用一个库)
DB_TYPE: mysql
DB_HOST: db
DB_PORT: "3306"
DB_USER: poweradmin
DB_PASS: q1w2e3r4
DB_NAME: powerdns
PA_INIT_PDNS_SCHEMA: "true"
# DNS 默认值(新建 zone 时自动带入 SOA 字段)
DNS_NS1: ns1.example.com
DNS_NS2: ns2.example.com
DNS_HOSTMASTER: hostmaster.example.com
# PowerDNS API 集成(SQL 后端模式下用于签名 zone rectify)
PA_PDNS_API_URL: http://pdns:8081
PA_PDNS_API_KEY: pa-pdns-api-key-4.4.3
# Poweradmin REST API 与文档页
PA_API_ENABLED: "true"
PA_API_DOCS_ENABLED: "true"
# 会话与其他
PA_SESSION_KEY: pa-4.4.3-session-key-0123456789abcdefXYZ
PA_TIMEZONE: Asia/Shanghai
# 管理员账号(无 PA_CREATE_ADMIN 时镜像不建任何用户)
PA_CREATE_ADMIN: "true"
PA_ADMIN_USERNAME: admin
PA_ADMIN_PASSWORD: q1w2e3r4
networks: [pa-net]
pdns:
image: powerdns/pdns-auth-49:4.9.18
container_name: poweradmin-4.4.3-pdns
hostname: pdns
restart: unless-stopped
depends_on:
db:
condition: service_healthy
volumes:
- ./pdns.conf:/etc/powerdns/pdns.conf:ro
ports:
- "5311:53"
- "5311:53/udp"
networks: [pa-net]
volumes:
db-data:
要点说明:
name: poweradmin-4.4.3-stack:显式指定项目名。注意 Compose 会把名称中的点替换掉,实际生成的网络名是poweradmin-443-stack_pa-net,docker network ls时按这个名字找;db的healthcheck用 MariaDB 官方镜像自带的healthcheck.sh --connect --innodb_initialized,app与pdns通过depends_on: condition: service_healthy等库就绪后再启动;- Web 端口映射为
8131:80:生产环境若 80 空闲可改回80:80,或在前置 Nginx/Caddy 上做反向代理与 HTTPS 终结; - DNS 端口映射为
5311:53:服务器 53 端口常被系统解析服务占用,这里用高位端口演示,生产环境对外服务时改回53:53并放行 TCP/UDP。
2.3 pdns.conf 全文
local-address=0.0.0.0,::
launch=gmysql
gmysql-host=db
gmysql-port=3306
gmysql-user=poweradmin
gmysql-password=q1w2e3r4
gmysql-dbname=powerdns
gmysql-dnssec=yes
api=yes
webserver=yes
webserver-address=0.0.0.0
webserver-port=8081
api-key=pa-pdns-api-key-4.4.3
daemon=no
api-key 的值与 compose 中 PA_PDNS_API_KEY 保持一致——SQL 直连模式下 Poweradmin 在每次修改 DNSSEC 签名 zone 后要调用这个 API 触发 rectify,两边不一致时签名 zone 的 DNSSEC 维护会失败。
三、部署步骤
3.1 准备文件并启动
mkdir -p /opt/poweradmin && cd /opt/poweradmin
# 将 2.2、2.3 两节内容分别保存为 docker-compose.yml 与 pdns.conf 后:
docker compose up -d db app
app 首次启动会完成两件事:把 PowerDNS 的 gmysql 库结构灌入 powerdns 库(PA_INIT_PDNS_SCHEMA=true 触发),随后执行 Poweradmin 自身的数据迁移并创建管理员账号。启动日志(节选实测):
poweradmin-4.4.3-app | {"level":"info","ts":...,"msg":"Poweradmin v4.4.3 starting..."}
poweradmin-4.4.3-app | {"level":"info","ts":...,"msg":"Timezone set to: Asia/Shanghai"}
poweradmin-4.4.3-app | {"level":"info","ts":...,"msg":"FrankenPHP handler started"}
poweradmin-4.4.3-app | {"level":"info","ts":...,"msg":"Caddy server initialising"}
poweradmin-4.4.3-app | {"level":"info","ts":...,"msg":"serving initial configuration"}
验证库结构初始化结果(实测回显):
docker exec poweradmin-4.4.3-db mariadb -upoweradmin -pq1w2e3r4 powerdns -e "SHOW TABLES;"
api_keys
comments
cryptokeys
domain_metadata
domains
groups
groups_perm_templ
log_api
log_groups
log_users
log_zones
login_attempts
migrations_user_group
perm_items
perm_templ
perm_templ_items
record_log
records
settings
supermasters
tsigkeys
user_agreements
user_groups
users
zones
其中 domains、records、cryptokeys 等 7 张表属于 PowerDNS gmysql 后端(由 PA_INIT_PDNS_SCHEMA 创建),其余 17 张属于 Poweradmin 自身(用户、权限模板、API key、各类审计日志等)。两套表同库但互不冲突,这正是 SQL 直连模式的库形态。
3.2 启动 PowerDNS 并确认健康
docker compose up -d pdns && sleep 5
docker compose ps --format '{{.Name}} {{.Status}}'
poweradmin-4.4.3-db Up 2 minutes (healthy)
poweradmin-4.4.3-app Up 2 minutes (healthy)
poweradmin-4.4.3-pdns Up 8 seconds
PowerDNS 启动日志确认 gmysql 后端加载成功(实测节选):
poweradmin-4.4.3-pdns | PowerDNS Authoritative Server 4.9.18 (C) 2001-2026 PowerDNS.COM BV
poweradmin-4.4.3-pdns | gmysql Connection successful. Replication-based recursor is disabled.
poweradmin-4.4.3-pdns | [webserver] Added & secured 'webserver' on 0.0.0.0:8081
poweradmin-4.4.3-pdns | gmysql Backend launch complete: Launching gmysql backend
poweradmin-4.4.3-pdns | Creating backend connection for TCP
poweradmin-4.4.3-pdns | About to create 3 backend threads
⚠️ 排障实录(坑 1):若不挂载
pdns.conf,直接用命令行参数启动 pdns 服务,容器会崩溃重启,日志报错:Fatal error: Trying to set unknown setting 'gsqlite3-dnssec'根因:
powerdns/pdns-auth-49:4.9.18镜像自带一份/etc/powerdns/pdns.conf,内容是 gsqlite3 示例配置且含一行无效的gsqlite3-dnssec标志位;命令行参数与配置文件会合并生效,配置文件里的非法行直接导致启动失败。解法就是本文做法——挂载一份干净的pdns.conf覆盖镜像默认配置文件。
3.3 首次登录
浏览器访问 http://<服务器IP>:8131/,会重定向到 /login 登录页,用 PA_ADMIN_USERNAME/PA_ADMIN_PASSWORD 设定的账号登录(本文示例:admin / q1w2e3r4)。登录成功后进入仪表盘。
⚠️ 排障实录(坑 2):镜像默认不创建任何管理员(
docker logs启动时会打印Admin User Creation: false),不设PA_CREATE_ADMIN: "true"时 users 表为空,登录页永远提示凭据错误。这正是官方为避免「镜像一启动就有默认弱口令」做的设计:管理员账号必须显式声明创建。PA_CREATE_ADMIN=1且未指定PA_ADMIN_PASSWORD时,镜像会生成随机密码并打印到日志。
四、功能验证:建 zone 与记录增删改
以下操作全部通过 Web 界面完成,辅以数据库与 dig 回显验证。
4.1 创建 master zone
登录后进入 Forward Zones → Add master zone,表单填写:
- Zone name:
example.com - Zone type:
MASTER(下拉仅有MASTER/NATIVE两项) - Owner:勾选
admin - Zone template:
none
提交后跳转 Forward Zones 列表,zone 出现在列表中。数据库侧验证(实测回显):
docker exec poweradmin-4.4.3-db mariadb -upoweradmin -pq1w2e3r4 powerdns -e \
"SELECT id,name,type,master FROM domains; SELECT id,domain_id,name,type,ttl,content FROM records;"
id name type master
1 example.com MASTER NULL
id domain_id name type ttl content
1 1 example.com SOA 86400 ns1.example.com hostmaster.example.com 2026102600 28800 7200 604800 86400
SOA 记录由 Poweradmin 按 DNS_NS1/DNS_NS2/DNS_HOSTMASTER 环境变量自动生成,serial 为创建当日日期格式 2026102600。
4.2 添加记录(A / MX / TXT)
进入 zone 编辑页(Forward Zones → example.com),在记录添加表单中依次提交三条记录,每次提交后 SOA serial 自动加 1:
| Name | Type | Content | Prio | TTL |
|---|---|---|---|---|
www | A | 198.51.100.10 | 0 | 86400 |
| (空 = 本域) | MX | mail.example.com | 10 | 86400 |
| (空 = 本域) | TXT | "v=spf1 -all" | 0 | 86400 |
⚠️ 排障实录(坑 3):TXT 记录内容必须自带引号。填
v=spf1 -all(不带引号)提交会被表单校验拒绝,页面提示:TXT record content must be enclosed in quotes.这是 Poweradmin 的显式校验而非 PowerDNS 的行为——引号是 zone 文件语法的一部分,面板要求录入者直接按 zone 文件格式书写。
添加完成后的库内状态(实测回显):
id name type content
1 example.com SOA ns1.example.com hostmaster.example.com 2026102602 28800 7200 604800 86400
2 www.example.com A 198.51.100.10
3 example.com MX mail.example.com
4.3 修改记录
在 zone 编辑页把 www.example.com 的 A 记录内容从 198.51.100.10 改为 198.51.100.11,点 Save changes 提交。保存后库内即变为新值,SOA serial 同步递增。
4.4 删除记录
勾选 TXT 记录行,点 Delete selected。
⚠️ 排障实录(坑 4):删除是两步确认流——第一次提交后进入「Are you sure you want to delete the selected records?」确认页,必须再点一次确认按钮(
confirm=1)才真正删除,直接丢弃确认页会导致记录仍在。这是防误删设计,脚本化操作时容易在第一步就以为已删完。
删除成功后跳回编辑页,TXT 行消失,SOA serial 继续递增。
4.5 dig 验证生效闭环
在服务器上对映射端口 5311 发起查询(实测回显):
dig @127.0.0.1 -p 5311 www.example.com A +noedns
; <<>> DiG 9.20.30 <<>> @127.0.0.1 -p 5311 www.example.com A +noedns
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48740
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;www.example.com. IN A
;; ANSWER SECTION:
www.example.com. 86400 IN A 198.51.100.11
;; Query time: 2 msec
;; SERVER: 127.0.0.1#5311(127.0.0.1) (UDP)
;; WHEN: Sun Oct 26 06:45:31 UTC 2026
;; MSG SIZE rcvd: 49
注意 ANSWER 里的 198.51.100.11——正是 4.3 节修改后的值,说明面板改动实时生效、无缓存延迟(PowerDNS 每次查询直读数据库)。再验证 MX、SOA 与已删除的 TXT:
dig @127.0.0.1 -p 5311 example.com MX +noedns | grep -A3 "ANSWER SECTION"
dig @127.0.0.1 -p 5311 example.com SOA +noedns | grep -A2 "ANSWER SECTION"
dig @127.0.0.1 -p 5311 example.com TXT +noedns | grep -E "status:|ANSWER"
;; ANSWER SECTION:
example.com. 86400 IN MX 10 mail.example.com.
;; ANSWER SECTION:
example.com. 86400 IN SOA ns1.example.com. hostmaster.example.com. 2026102605 28800 7200 604800 86400
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26734
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
SOA serial 2026102605 是四次修改累计递增的结果;TXT 查询 ANSWER: 0 证明删除已生效。flags: qr aa rd 中的 aa(Authoritative Answer)确认这是权威应答。
4.6 健全性检查:apex NS 记录
⚠️ 排障实录(坑 5):Poweradmin 创建 master zone 时只生成 SOA,不自动创建 apex NS 记录。用 PowerDNS 自带的
pdnsutil check-zone检查(实测回显):docker exec poweradmin-4.4.3-pdns pdnsutil check-zone example.com[Error] No NS record at zone apex in zone 'example.com' Checked 3 records of 'example.com', 1 errors, 0 warnings.缺少 apex NS 时 DNS 查询仍能应答,但授权链不完整(从父域 delegation 过来的查询会被部分解析器拒绝)。解法:在 zone 编辑页为
example.com本域补两条 NS 记录(ns1.example.com、ns2.example.com),补齐后复查:Checked 5 records of 'example.com', 0 errors, 0 warnings.生产部署建议把「建 zone 后立即补 apex NS」写进操作清单,或改用 zone template(
DNS_NS1/DNS_NS2环境变量只影响 SOA,不生成 NS)。
五、安装向导说明
Poweradmin 传统源码部署(tarball 解压 + PHP 运行时)带一个 8 步 Web 安装向导,官方文档(docs.poweradmin.org → Installation → Web installer wizard)描述的流程为:
- Prerequisites:文件/目录权限自检(config 目录可写等);
- Configuration check:PHP 扩展与版本检查;
- Language:选择界面语言;
- Database:填写数据库主机、库名、账号,并设置管理员账号密码(用户名固定
admin); - DNS defaults:hostmaster 邮箱、ns1/ns2 默认 NS,并生成受限数据库用户的创建 SQL;
- Create limited user:展示第 4 步生成的 SQL,提示手动在数据库执行(向导刻意不用高权限账号直接建用户);
- Generate config:生成
config/settings.php内容,提示手动复制到 config 目录; - Remove installer:删除
install/目录后进入登录页。
本文的 Docker 镜像部署没有这个向导——实测把运行中实例的 config/settings.php 移除后访问首页只会得到「No configuration file found at config/settings.php」错误页,错误页里的 installer 超链接是遗留文案,点开仍是同一错误页;/install 与 /install/ 均不返回向导界面。官方 Docker 镜像的初始化完全由环境变量驱动(DB_TYPE 必填,缺了连启动都会被 entrypoint 拒绝),表结构与账号自动创建。两种路径的选择建议:生产/可重复部署用环境变量方式(本篇做法);追求「逐步确认」的一次性手工部署再考虑源码 + 向导方式。
六、等价 docker run 命令
不用 Compose 时,以下三条命令与 2.2 节编排等价(同一网络,先建网络):
docker network create -d bridge --subnet 10.89.60.0/24 pa-net
docker run -d --name poweradmin-4.4.3-db --network pa-net \
-e MARIADB_ROOT_PASSWORD=q1w2e3r4 \
-e MARIADB_DATABASE=powerdns \
-e MARIADB_USER=poweradmin \
-e MARIADB_PASSWORD=q1w2e3r4 \
-v poweradmin-db-data:/var/lib/mysql \
mariadb:10.11
docker run -d --name poweradmin-4.4.3-app --network pa-net \
-p 8131:80 \
-e DB_TYPE=mysql -e DB_HOST=poweradmin-4.4.3-db -e DB_PORT=3306 \
-e DB_USER=poweradmin -e DB_PASS=q1w2e3r4 -e DB_NAME=powerdns \
-e PA_INIT_PDNS_SCHEMA=true \
-e DNS_NS1=ns1.example.com -e DNS_NS2=ns2.example.com \
-e DNS_HOSTMASTER=hostmaster.example.com \
-e PA_PDNS_API_URL=http://poweradmin-4.4.3-pdns:8081 \
-e PA_PDNS_API_KEY=pa-pdns-api-key-4.4.3 \
-e PA_API_ENABLED=true -e PA_API_DOCS_ENABLED=true \
-e PA_SESSION_KEY=pa-4.4.3-session-key-0123456789abcdefXYZ \
-e PA_TIMEZONE=Asia/Shanghai \
-e PA_CREATE_ADMIN=true -e PA_ADMIN_USERNAME=admin -e PA_ADMIN_PASSWORD=q1w2e3r4 \
poweradmin/poweradmin:4.4.3
docker run -d --name poweradmin-4.4.3-pdns --network pa-net \
-p 5311:53 -p 5311:53/udp \
-v /opt/poweradmin/pdns.conf:/etc/powerdns/pdns.conf:ro \
powerdns/pdns-auth-49:4.9.18
注意两点差异:直连 docker run 没有 Compose 的健康检查等待,app/pdns 需等数据库完全就绪后启动(建议库先起、间隔 10 秒以上再起其余两个);pdns.conf 里的 gmysql-host 要相应改成 poweradmin-4.4.3-db 这个容器名(Compose 内服务名是 db)。
七、常用运维命令
# 栈状态与日志
docker compose ps
docker compose logs -f app pdns
# zone 健全性检查与查看(PowerDNS 侧权威工具)
docker exec poweradmin-4.4.3-pdns pdnsutil check-zone example.com
docker exec poweradmin-4.4.3-pdns pdnsutil list-zone example.com
docker exec poweradmin-4.4.3-pdns pdnsutil show-zone example.com
list-zone 输出为 zone 文件格式(实测节选),可直接用于核对记录:
$ORIGIN .
example.com 86400 IN MX 10 mail.example.com.
example.com 86400 IN SOA ns1.example.com hostmaster.example.com 2026102610 28800 7200 604800 86400
www.example.com 86400 IN A 198.51.100.11
show-zone 可看 zone 角色与 DNSSEC 状态:
This is a Master zone
Last SOA serial number we notified: 0 != 2026102610 (serial in the database)
Zone is not actively secured
Metadata items: None
No keys for zone 'example.com'.
数据备份(整库导出即可覆盖两套表):
docker exec poweradmin-4.4.3-db sh -c \
'mariadb-dump -upoweradmin -pq1w2e3r4 powerdns' > powerdns-$(date +%F).sql
升级:4.4 LTS 线内的补丁升级(如 4.4.2 → 4.4.3)无需数据库迁移,改 compose 中镜像 tag 后 docker compose up -d app 重建即可;跨大版本(如 4.4 → 4.5)前先看官方发布说明中的迁移提示。
八、常见问题速查
| 现象 | 根因与解法 | 本文位置 |
|---|---|---|
pdns 反复重启,报 Trying to set unknown setting 'gsqlite3-dnssec' | 镜像自带 gsqlite3 示例配置非法;挂载干净 pdns.conf 覆盖 | 2.3 / 3.2 |
| 登录页凭据永远错误 | 未设 PA_CREATE_ADMIN,users 表为空 | 3.3 |
页面报 Session encryption key is too short, please set a longer one in your configuration file. | PA_SESSION_KEY 少于 32 字符(实测 29 字符被拒),换 ≥32 字符随机串 | 2.2 |
TXT 记录提交被拒 TXT record content must be enclosed in quotes. | TXT 内容需自带英文双引号 | 4.2 |
脚本直 POST 建 zone 报 Invalid or unexpected input given. | dom_type 必须用大写 MASTER/NATIVE(与 UI 下拉一致),小写被拒 | 4.1 |
pdnsutil check-zone 报 No NS record at zone apex | 建 zone 不自动生成 apex NS,手动补 NS 记录 | 4.6 |
| 删除记录后列表里还在 | 两步确认流,需在确认页再提交一次 | 4.4 |
docker pull 官方镜像缓慢 | 国内环境可为镜像名加加速前缀(如 hub.rat.dev/poweradmin/poweradmin:4.4.3) | 一 |
九、参考链接
- Poweradmin 官方 Docker 文档(仓库 DOCKER.md):
https://github.com/poweradmin/poweradmin/blob/master/DOCKER.md - 官方安装文档(含 8 步向导说明):
https://docs.poweradmin.org/installation/ - PowerDNS Authoritative 官方文档:
https://doc.powerdns.com/authoritative/ - 同专栏认知篇:《Poweradmin v4.4.3 介绍与选型指南》