phpList 3.6.17 Docker Compose 部署指南
使用 Docker Compose 编排部署 phpList 3.6.17 官方镜像:一键启动与自动初始化、MariaDB 数据持久化重建验证、环境变量表、等价 docker run 命令与 SMTP 发送配置要点。
phpList 3.6.17 Docker Compose 部署指南
目标:使用 Docker Compose 编排部署 phpList 3.6.17 官方镜像,组合 MariaDB 10.11 数据库与 MailHog 邮件测试捕获器,完成一键启动、自动数据库初始化、管理员登录验证、数据持久化重建验证与等价
docker run命令对照,并给出环境变量表与 SMTP 发送配置要点。
一、环境信息
| 项目 | 内容 |
|---|---|
| Docker / Compose 版本 | Docker 29.9.2 / Docker Compose v5.6.1(docker --version、docker compose version 实测) |
| phpList 版本 | 3.6.17(官方最新稳定版,2026-10-26 实查 GitHub Releases) |
| phpList 镜像 | phplist/phplist:3.6.17(Docker Hub 官方镜像,累计拉取 393,258 次,镜像最后更新 2026-10-24) |
| 数据库镜像 | mariadb:10.11 |
| 邮件测试捕获器 | mailhog/mailhog:v1.0.1(仅用于开发验证收信,生产环境替换为真实 SMTP 服务器) |
| 端口规划 | Web 管理后台 8128,MailHog Web 界面 8129(示例值,按宿主机空闲端口调整) |
| 容器网段 | 10.89.58.0/24(显式指定,避免与既有内网网段冲突) |
| 演示账号 | 管理员 admin / q1w2e3r4,数据库 phplist / q1w2e3r4 |
phpList 官方镜像的特点:镜像启动脚本会自动完成「等待数据库就绪 → 初始化数据库结构(建表)→ 初始化多语言包 → 创建管理员 → 启动 cron 与 Apache」的全流程,无需手工执行安装向导。
二、镜像选型
2.1 phpList 官方镜像
phpList 官方在 Docker Hub 维护 phplist/phplist 镜像(2026-10-26 查询 Docker Hub API:累计拉取 393,258 次,最后更新 2026-10-24),tag 列表覆盖 3.6.x 与 3.7.0 预发布线。生产部署建议锁定小版本号 tag(本例 3.6.17),不要使用 latest,以便版本可追溯、可回滚。
镜像内部约定(来源官方仓库 docker/ 目录与启动日志实测):
- 应用代码位于
/var/www/phpList3/public_html/lists/(与源码包手工部署的/var/www/lists不同,注意路径差异); - 配置文件为
/etc/phplist/config.php,由镜像内置模板生成,核心取值来自环境变量(模板关键代码实测):
$database_host = getenv('DB_HOST');
$database_name = getenv('DB_NAME');
$database_user = getenv('DB_USER');
$database_password = getenv('DB_PASSWORD');
$mailhost = getenv('MAILHOST');
define('PHPMAILERHOST', $mailhost);
define('TEST', 0);
define('MANUALLY_PROCESS_QUEUE', 0);
可见镜像版默认 TEST=0(真实发送)且 MANUALLY_PROCESS_QUEUE=0(队列由内置 cron 自动处理),与源码包手工安装的默认值不同。
- 启动时动态生成命令行工具
/usr/bin/phplist,并把容器环境变量注入其中,后续命令行操作与《phpList 3.6.17 常用 CLI 命令详解》一致。
2.2 数据库与邮件捕获器镜像
- MariaDB 10.11:phpList 官方兼容 MySQL / MariaDB,10.11 为成熟 LTS 分支,实测建表与全功能无兼容问题;
- MailHog v1.0.1:轻量 SMTP 测试捕获器,提供 1025 端口收信与 8025 端口 Web 界面查看邮件,适合部署验证阶段使用。生产环境务必把
MAILHOST指向真实邮件服务器或专业 ESP,MailHog 只收不发。
三、部署步骤
3.1 编写 docker-compose.yml
创建部署目录并写入编排文件(本例完整文件,实测可用):
mkdir -p /opt/phplist && cd /opt/phplist
vim docker-compose.yml
name: phplist-3-6-17-stack
services:
phplist-db:
image: mariadb:10.11
container_name: phplist-3-6-17-db
restart: always
environment:
MYSQL_ROOT_PASSWORD: q1w2e3r4
MYSQL_DATABASE: phplistdb
MYSQL_USER: phplist
MYSQL_PASSWORD: q1w2e3r4
volumes:
- db_data:/var/lib/mysql
networks:
- phplist-net
mailhog:
image: mailhog/mailhog:v1.0.1
container_name: phplist-3-6-17-mailhog
restart: always
ports:
- "8129:8025"
environment:
MH_SMTP_BIND_ADDR: 0.0.0.0:25
networks:
- phplist-net
phplist:
image: phplist/phplist:3.6.17
container_name: phplist-3-6-17-web
depends_on:
- phplist-db
- mailhog
restart: always
volumes:
- upload_images:/var/www/phpList3/public_html/images
ports:
- "8128:80"
environment:
DB_HOST: phplist-db
DB_USER: phplist
DB_PASSWORD: q1w2e3r4
DB_NAME: phplistdb
ADMIN_NAME: admin
ADMIN_PASSWORD: q1w2e3r4
ADMIN_EMAIL: admin@example.com
HOSTNAME: localhost
PORT: 80
MAILHOST: mailhog
networks:
- phplist-net
volumes:
db_data:
upload_images:
networks:
phplist-net:
driver: bridge
ipam:
config:
- subnet: 10.89.58.0/24
配置要点:
name: phplist-3-6-17-stack显式声明项目名,多套部署并存时避免项目名冲突;db_data卷持久化数据库文件,upload_images卷持久化后台上传的图片与模板资源;MAILHOST直接写服务名mailhog(同一 Docker 网络内置 DNS 解析);接真实 SMTP 时改为对应主机名或 IP;- MailHog 通过
MH_SMTP_BIND_ADDR=0.0.0.0:25把内部 SMTP 端口对齐 25(phpList 侧不配置端口变量时默认按 25 连接),宿主机 8129 端口映射的是其 8025 Web 界面。
3.2 启动编排
docker compose up -d
查看栈状态(实测回显):
docker compose ps
NAME IMAGE STATUS PORTS
phplist-3-6-17-db mariadb:10.11 Up About a minute 3306/tcp
phplist-3-6-17-mailhog mailhog/mailhog:v1.0.1 Up About a minute 1025/tcp, 0.0.0.0:8129->8025/tcp
phplist-3-6-17-web phplist/phplist:3.6.17 Up About a minute 0.0.0.0:8128->80/tcp
3.3 自动初始化过程
首次启动时,phpList 容器日志完整记录初始化流程(docker logs phplist-3-6-17-web 实测回显,节选):
Initialising phpList, Please wait
Waiting for the Database to be available - 1/10
phpList - phpList version 3.6.17 (c) 2000-2026 phpList Ltd, https://www.phplist.com
phpList - Initialising phpList database structure.
Creating tables
Initialising table attribute
... ok
Initialising table user_attribute
... ok
Initialising table user
... ok
Initialising table list
... ok
Initialising table message
... ok
...(依次初始化共 60 余张 phplist_* 表,此处节选)
Initialising table i18n
... ok
Setting default configuration
Admin = admin
Admin Email = admin@example.com
phpList - uk
phpList - Initialising language uk
phpList - tr
phpList - Initialising language tr
...(依次初始化 30 余种语言包,此处节选)
流程说明:先最多等待数据库 10 轮(每轮 10 秒),建表后写入默认配置,ADMIN_NAME/ADMIN_EMAIL 环境变量在此环节自动登记为管理员,最后初始化多语言包并启动服务。日志尾部出现 READY 字样即初始化完成。
3.4 访问与登录验证
浏览器访问 http://<服务器IP>:8128/lists/admin/,用 admin / q1w2e3r4 登录。命令行验证(实测回显):
curl -s -c /tmp/ck.txt -d "login=admin&password=q1w2e3r4" \
"http://127.0.0.1:8128/lists/admin/?page=login" \
-o /dev/null -w "login POST http_code: %{http_code}\n"
curl -s -b /tmp/ck.txt "http://127.0.0.1:8128/lists/admin/?page=main" | grep -oE "<title>[^<]*</title>"
login POST http_code: 200
<title>phpList :: phpList :: main</title>
登录成功即部署完成。MailHog 收信界面在 http://<服务器IP>:8129(仅测试用途)。
四、数据持久化
4.1 持久化范围
| 数据 | 载体 | 说明 |
|---|---|---|
| 全部业务数据 | 具名卷 db_data → /var/lib/mysql | 订阅者、列表、活动、统计、配置全在数据库内 |
| 上传图片/模板资源 | 具名卷 upload_images → /var/www/phpList3/public_html/images | 后台上传的附件图片 |
| 应用代码 | 镜像层 | 升级版本即换镜像 tag |
phpList 的业务数据全部落库,因此持久化的核心是数据库卷。
4.2 重建验证(实测)
对栈执行完整重建(容器删除重建、卷保留),验证数据不丢失:
docker compose down
docker compose up -d
等待约 30 秒初始化跑完后再次登录(实测回显):
NAME IMAGE STATUS
phplist-3-6-17-db mariadb:10.11 Up 28 seconds
phplist-3-6-17-mailhog mailhog/mailhog:v1.0.1 Up 28 seconds
phplist-3-6-17-web phplist/phplist:3.6.17 Up 28 seconds
login POST http_code: 200
<title>phpList :: phpList :: main</title>
重建后管理员账号可直接登录、既有数据完整,持久化验证通过。注意:执行 docker compose down -v 会连卷一起删除,数据将不可恢复,生产操作务必区分 down 与 down -v。
五、环境变量表
phpList 镜像可识别的环境变量(来源:镜像内配置模板与初始化行为实测):
| 环境变量 | 作用 | 示例值 |
|---|---|---|
DB_HOST | 数据库主机名 | phplist-db |
DB_NAME | 数据库名 | phplistdb |
DB_USER | 数据库用户 | phplist |
DB_PASSWORD | 数据库密码 | q1w2e3r4 |
MAILHOST | SMTP 发送服务器(写入 PHPMAILERHOST) | mailhog(生产填真实 SMTP 主机) |
ADMIN_NAME | 初始化时创建的管理员登录名 | admin |
ADMIN_PASSWORD | 初始化时创建的管理员密码 | q1w2e3r4 |
ADMIN_EMAIL | 初始化时创建的管理员邮箱 | admin@example.com |
HOSTNAME / PORT | 由启动脚本导出到命令行环境(镜像配置模板未直接消费,保留于官方编排示例) | localhost / 80 |
说明:镜像模板还固定了 TEST=0(真实发送)、MANUALLY_PROCESS_QUEUE=0(cron 自动处理队列)、PHPMAILER_SECURE=0(明文 SMTP,可按需在自定义配置中调整)等默认值;如需覆盖更多参数(发件人地址、批量发送、退信处理等),可挂载自定义 config.php 覆盖 /etc/phplist/config.php,参数详解见《phpList 3.6.17 配置参数详解》。
六、等价 docker run 命令
不用 Compose 时,以下三条命令等价复现上述编排(先建网络,再按依赖顺序启动):
docker network create --subnet 10.89.58.0/24 phplist-net
docker run -d --name phplist-3-6-17-db --network phplist-net --restart always \
-e MYSQL_ROOT_PASSWORD=q1w2e3r4 \
-e MYSQL_DATABASE=phplistdb \
-e MYSQL_USER=phplist \
-e MYSQL_PASSWORD=q1w2e3r4 \
-v db_data:/var/lib/mysql \
mariadb:10.11
docker run -d --name phplist-3-6-17-mailhog --network phplist-net --restart always \
-p 8129:8025 \
-e MH_SMTP_BIND_ADDR=0.0.0.0:25 \
mailhog/mailhog:v1.0.1
docker run -d --name phplist-3-6-17-web --network phplist-net --restart always \
-p 8128:80 \
-e DB_HOST=phplist-db -e DB_NAME=phplistdb \
-e DB_USER=phplist -e DB_PASSWORD=q1w2e3r4 \
-e ADMIN_NAME=admin -e ADMIN_PASSWORD=q1w2e3r4 \
-e ADMIN_EMAIL=admin@example.com \
-e HOSTNAME=localhost -e PORT=80 \
-e MAILHOST=phplist-3-6-17-mailhog \
phplist/phplist:3.6.17
生产建议仍使用 Compose:编排文件即文档,depends_on 保证启动顺序,升级回滚只需改 tag 后 docker compose up -d。
七、SMTP 发送配置要点
镜像部署下发送链路的三个关键点:
- SMTP 主机:
MAILHOST环境变量直接写入PHPMAILERHOST。开发验证用 MailHog;生产填真实邮件服务器,若非 25 端口或需 TLS 认证,需通过自定义 config.php 追加PHPMAILERPORT、PHPMAILER_SECURE及 SMTP 认证配置。 - 发件人默认值:初始化时数据库默认发件人为
noreply@[DOMAIN],[DOMAIN]取自初始化上下文的主机名。若主机名含端口等非法成分,发送会因 Sender 地址校验失败而全部退队(完整排障实录见《Ubuntu 22.04 安装 phpList 3.6.17 指南》第七节)。镜像部署下建议初始化完成后在后台「设置」中把默认发件人改为合法地址,或在自定义配置中显式设置$message_envelope与活动默认发件人。 - 队列处理:镜像默认
MANUALLY_PROCESS_QUEUE=0,内置 cron 自动跑队列,无需手工触发;修改队列节奏可调整镜像内/etc/phplist/crontab或改回手动模式。
八、常见问题
Q1:phpList 容器反复重启或日志停在 Waiting for the Database?
数据库未就绪。启动脚本最多等待 100 秒(10 轮 × 10 秒)后放弃。检查 DB_HOST 服务名拼写、数据库容器健康状态与 MYSQL_USER/MYSQL_PASSWORD 是否与 DB_USER/DB_PASSWORD 一致,修复后 docker compose restart phplist。
Q2:MailHog 容器意外退出(实测事件)
本次实测中 MailHog 容器曾以退出码 2 无日志异常地退出(最后一次日志为正常收信记录),重新启动后恢复正常、收信数据保留。该现象属于测试捕获器的偶发行为,编排中已配置 restart: always 自动拉起;生产环境本就不应依赖 MailHog,请使用真实 SMTP 服务器或专业 ESP。
Q3:后台上传图片 404 或丢失?
upload_images 卷未挂载或路径写错。必须挂载到镜像内应用路径 /var/www/phpList3/public_html/images(注意不是源码包部署的 /var/www/lists/ 路径)。
Q4:端口 8128/8129 被占用?
改宿主机侧映射端口即可(ports: "8228:80"),容器内 80/8025 不动;若需固定容器网段避免与内网冲突,保留 ipam 显式 subnet 配置并避开既有网段。
Q5:如何从手工安装迁移到镜像部署?
数据库整体导出导入(mysqldump)是唯一关键步骤:phpList 业务数据全在库中,导入后在新环境核对 config 表中的域名相关项(domain、网站地址等)即可。部署方式与版本背景可先阅读 《phpList 3.6.17 介绍与选型指南》。