SquirrelMail 1.4.22 Docker Compose 部署指南
SquirrelMail 1.4.22 Docker Compose 双服务栈部署实测:自建 webmail(php:7.4-apache)与 Postfix/Dovecot 后端镜像、栈内协同机制、display_errors 打断登录的排障实录与生产化改造建议。
SquirrelMail 1.4.22 Docker Compose 部署指南
目标:用 Docker Compose 一键部署 SquirrelMail 1.4.22 + Postfix/Dovecot 邮件后端的双服务栈,完成登录与收信端到端验证。官方未提供任何官方镜像,本篇使用自建 Dockerfile(应用本体来自官方发布包,构建上下文内自带,离线可复现),并在文中明确标注;全部命令与回显来自 2026-10-27 在 Ubuntu 22.04 + Docker 实测。
一、环境信息
- 宿主机:Ubuntu 22.04(jammy),x86_64
- Docker:Compose v2(
docker compose子命令,项目名规范化为squirrelmail-1422-stack) - 栈内镜像(均为自建,非官方镜像):
squirrelmail-1.4.22-webmail:local(基座php:7.4-apache,实测构建后 657 MB)squirrelmail-1.4.22-mail:local(基座debian:12-slim,实测构建后 207 MB)
- 应用本体:SquirrelMail 1.4.22 官方发布包(sha256 校验值同系列安装篇:
286453c7aac6...b2d0b847) - 对外端口:宿主
8130→ webmail 服务80(2026-10-27 实测宿主 8128–8152 段中 8130 空闲) - 栈内网络:
squirrelmail-1422-stack_smnet,子网10.89.61.0/24(实测已验证连通的槽位复用) - 演示账号:
admin/q1w2e3r4(由 mail 服务入口脚本创建) - 目录约定:部署目录
squirrelmail-compose/,结构如下(本篇第二节逐一给出全部文件):
squirrelmail-compose/
├── docker-compose.yml
├── webmail/
│ ├── Dockerfile
│ └── squirrelmail-webmail-1.4.22.tar.gz # 官方发布包
└── mail/
├── Dockerfile
└── entrypoint.sh
二、部署文件详解(自建镜像标注)
2.1 docker-compose.yml
name: squirrelmail-1.4.22-stack
services:
mail:
build: ./mail
image: squirrelmail-1.4.22-mail:local
container_name: squirrelmail-1.4.22-mail
hostname: mail.example.com
restart: unless-stopped
networks: [smnet]
webmail:
build: ./webmail
image: squirrelmail-1.4.22-webmail:local
container_name: squirrelmail-1.4.22-webmail
depends_on: [mail]
ports:
- "8130:80"
restart: unless-stopped
networks: [smnet]
networks:
smnet:
driver: bridge
ipam:
config:
- subnet: 10.89.61.0/24
要点说明:
name:显式声明 Compose 项目名为squirrelmail-1.4.22-stack(Compose v2 会把项目名规范化为squirrelmail-1422-stack,网络名即squirrelmail-1422-stack_smnet,实测回显见第四章)。- 两个服务均为 自建镜像:SquirrelMail 官方从未发布 Docker 镜像(官网与 SourceForge 均无容器产物,2026-10-27 实查),
image:只是给本地构建结果命名;build:才是镜像的真实来源。 - 子网显式固定为
10.89.61.0/24,避免与其他在跑环境网段冲突;8130为宿主 Web 入口。
2.2 webmail/Dockerfile(SquirrelMail 应用服务)
FROM php:7.4-apache
# 启用生产级 php.ini(镜像默认无 php.ini,display_errors=On 的 Warning 会打断 SquirrelMail 重定向流程)
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# 应用本体:SquirrelMail 1.4.22 官方发布包(构建上下文内自带,离线可复现)
ADD squirrelmail-webmail-1.4.22.tar.gz /usr/share/
# 数据与附件缓存目录(config.php 默认即指向 /var/local/squirrelmail/,无需改路径)
RUN mkdir -p /var/local/squirrelmail/data /var/local/squirrelmail/attach \
&& chown -R www-data:www-data /var/local/squirrelmail
# 生成 config.php:仅把 IMAP/SMTP 服务器从 localhost 指到栈内 mail 服务
RUN cp /usr/share/squirrelmail-webmail-1.4.22/config/config_default.php \
/usr/share/squirrelmail-webmail-1.4.22/config/config.php \
&& sed -i "s/\$smtpServerAddress = 'localhost';/\$smtpServerAddress = 'mail';/" \
/usr/share/squirrelmail-webmail-1.4.22/config/config.php \
&& sed -i "s/\$imapServerAddress = 'localhost';/\$imapServerAddress = 'mail';/" \
/usr/share/squirrelmail-webmail-1.4.22/config/config.php \
&& chown -R www-data:www-data /usr/share/squirrelmail-webmail-1.4.22
# Apache:站点根直接指向 SquirrelMail 应用目录
ENV APACHE_DOCUMENT_ROOT=/usr/share/squirrelmail-webmail-1.4.22
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \
&& sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
EXPOSE 80
⚠️ 自建镜像标注与 PHP 版本依据:
php:7.4-apache基座是刻意选择——1.4.22 是 PHP 5 时代代码,实测在 PHP 8.x 下 Fatal error 不可运行(一票否决取证见《SquirrelMail 1.4.22 介绍与选型指南》第五章),PHP 7.4 为可用上限。官方发布包以ADD方式进入镜像,整个构建过程不需要访问外网(离线可复现)。
2.3 mail/Dockerfile 与 entrypoint.sh(Postfix + Dovecot 后端)
mail 服务 Dockerfile:
FROM debian:12-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends postfix dovecot-imapd \
&& rm -rf /var/lib/apt/lists/*
# SquirrelMail 1.4.22 走明文 PLAIN 认证,放开 Dovecot 明文限制(内网栈)
RUN sed -i 's/^#disable_plaintext_auth = yes/disable_plaintext_auth = no/' \
/etc/dovecot/conf.d/10-auth.conf
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 25 143
CMD ["/entrypoint.sh"]
entrypoint.sh:
#!/bin/sh
set -e
# 演示邮箱账号(与文档演示口径一致)
id admin >/dev/null 2>&1 || useradd -m -s /bin/bash admin
echo 'admin:q1w2e3r4' | chpasswd
# Postfix 本域投递配置
postconf -e "myhostname=mail.example.com"
postconf -e "mydestination=example.com, mail.example.com, localhost.localdomain, localhost"
postconf -e "mynetworks=127.0.0.0/8 [::1]/128"
service postfix start
service dovecot start
# 栈启动即投递一封验证邮件,便于首次登录即可见
printf "Subject: Welcome from compose stack\nFrom: root@example.com\nTo: admin@example.com\n\nThis is a smoke-test mail delivered inside the compose stack.\n" \
| sendmail admin@example.com || true
exec tail -F /var/log/mail.log 2>/dev/null || tail -f /dev/null
要点说明:disable_plaintext_auth = no 与系列安装篇第八章同理(SquirrelMail 1.4.22 默认明文 PLAIN 认证,内网栈放开限制);演示账号与测试邮件在入口脚本一次性就位,栈起即用;末行 tail -F 让服务保持前台。
三、一键部署与验证步骤
3.1 准备文件与构建
把 2.1–2.3 的文件按第一章目录树落盘,并将官方发布包放入 webmail/ 目录(下载与校验方式见系列安装篇 10.1)。然后构建:
cd squirrelmail-compose
docker compose build
实测输出(节选,两个镜像均构建成功):
[+] Building 1.4s (12/12) FINISHED
=> => naming to docker.io/library/squirrelmail-1.4.22-webmail:local
[+] Building 41.4s (13/13) FINISHED
=> => naming to docker.io/library/squirrelmail-1.4.22-mail:local
构建后的镜像清单(实测):
docker images 'squirrelmail-1.4.22*' --format '{{.Repository}}:{{.Tag}} {{.Size}}'
实测输出:
squirrelmail-1.4.22-webmail:local 657MB
squirrelmail-1.4.22-mail:local 207MB
3.2 启动栈
docker compose up -d
实测输出:
[+] Running 3/3
✔ Network squirrelmail-1422-stack_smnet Created
✔ Container squirrelmail-1.4.22-mail Started
✔ Container squirrelmail-1.4.22-webmail Started
核对运行状态与网络(注意网络名是项目名规范化后的 squirrelmail-1422-stack_smnet):
docker compose ps --format '{{.Name}} {{.Image}} {{.Status}}'
docker network inspect squirrelmail-1422-stack_smnet --format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}}'
实测输出:
squirrelmail-1.4.22-mail squirrelmail-1.4.22-mail:local Up 2 minutes
squirrelmail-1.4.22-webmail squirrelmail-1.4.22-webmail:local Up 14 seconds
squirrelmail-1422-stack_smnet 10.89.61.0/24
3.3 登录与收信端到端验证
入口:http://<宿主地址>:8130/src/login.php。命令行验证(与浏览器路径一致):
rm -f /tmp/sm_cookie
curl -s -c /tmp/sm_cookie -o /tmp/rd.html -w 'login POST HTTP:%{http_code}\n' \
-d 'login_username=admin' -d 'secretkey=q1w2e3r4' \
-d 'js_autodetect_results=0' -d 'just_logged_in=1' \
http://127.0.0.1:8130/src/redirect.php
curl -s -b /tmp/sm_cookie -o /tmp/in.html -w 'right_main HTTP:%{http_code} SIZE:%{size_download}\n' \
http://127.0.0.1:8130/src/right_main.php
grep -oE '<title>[^<]*</title>' /tmp/in.html
实测输出(302 为登录成功跳转;收件箱 200 且标题带版本号):
login POST HTTP:302
right_main HTTP:200 SIZE:5741
<title>SquirrelMail 1.4.22</title>
确认入口脚本投递的验证邮件出现在收件箱(主题 Welcome from compose stack,页面内空格转义为  ):
grep -oE 'Welcome( |\s)from( |\s)compose( |\s)stack' /tmp/in.html
实测输出:
Welcome from compose stack
至此栈级端到端打通:webmail 服务(Apache+PHP+SquirrelMail)经栈内网络调用 mail 服务的 IMAP 认证成功、SMTP 收件正常。
四、栈内服务协同机制说明
- 服务发现:webmail 的
config.php把 IMAP/SMTP 服务器指向mail(Compose 服务名),栈内网络自动提供 DNS 解析(实测从 webmail 侧getent hosts mail可解析到栈内地址,fsockopen('mail',143)直接 LOGIN 成功)。 - 依赖顺序:
depends_on: [mail]只保证启动顺序,不等待 mail 服务内 Postfix/Dovecot 就绪;mail 服务入口脚本在数秒内完成配置与启动,实测无竞态问题(webmail 首次登录即成功)。若后端就绪过慢出现登录失败,等几秒重试即可。 - 配置生效方式:SquirrelMail 配置在 webmail 镜像构建时固化(
config.php写死栈内服务名);mail 侧配置在入口脚本启动时执行(postconf -e、dovecot明文开关)。改配置 = 改文件 →docker compose up -d --build重建对应服务。 - 数据持久化:本栈为演示形态,用户偏好(
.pref/.abook)与邮箱数据都落在服务实例内部,未挂数据卷;销毁栈即丢数据。生产化改造见第五章。
五、生产化改造建议
- 挂载数据卷:mail 服务把
/var/mail(邮箱)与/var/lib/postfix挂 named volume;webmail 服务把/var/local/squirrelmail(偏好与附件缓存)挂 named volume,避免栈重建丢数据。 - 改密码与账号管理:演示账号在 entrypoint.sh 内明文建号,生产应改为 IMAP 虚拟域(SQL/LDAP 用户库)或至少把凭据移出镜像(环境变量/挂载文件注入)。
- TLS:SquirrelMail 1.4.22 与明文 IMAP/PLAIN 均应置于反向代理(TLS 终止)之后,Dovecot 若对外暴露需启用 STARTTLS 并恢复
disable_plaintext_auth = yes。 - 升级路径:无官方镜像意味着升级即换发布包重 build;但 1.4.22 之后上游再无版本(2011-07 至今),"升级"实际不存在,应把精力放在边界防护与迁移评估(迁移选型见《SquirrelMail 1.4.22 介绍与选型指南》第七章)。
六、常见问题(FAQ)
Q1:登录后浏览器显示 "Unknown user or password incorrect.",但凭据正确?
先看 Apache 响应/页面顶部是否有多行 Warning: session_set_cookie_params(): Cannot change session cookie parameters...。本篇实测时即遇到该问题:php:7.4-apache 基座默认未放置 php.ini(只有 development/production 模板),display_errors 为 On,SquirrelMail 1.4.22 的 functions/global.php:472 在 PHP 7.4 下触发该 Warning 并输出到页面,随后 "headers already sent" 打断 src/redirect.php 的重定向,登录失败。修复即在 webmail Dockerfile 构建阶段启用生产级 php.ini(见 2.2 第一段 RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"),重建后实测登录 302 恢复正常。
Q2:docker compose up 报网段子网冲突?
把 docker-compose.yml 中 10.89.61.0/24 换成宿主上未占用且不与其他 Compose 网络重叠的私有网段(用 docker network ls -q | xargs docker network inspect --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 排查既有占用)。
Q3:webmail 页面能开,但登录一直转圈后失败?
用栈内直连分段定位:在 webmail 服务侧实测 fsockopen('mail',143) 是否 LOGIN 成功(本篇实测该路径正常),再测 mail 侧 doveadm auth test admin q1w2e3r4;两端通过而页面失败时,多半是 webmail config.php 的 imapServerAddress 未指向 mail(构建时 sed 未生效,回看 build 日志)。
Q4:宿主 8130 端口被占用想换端口?
只改 docker-compose.yml 的 "8130:80" 左侧宿主端口即可,栈内不变;改后 docker compose up -d 增量生效。
七、卸载与清理
cd squirrelmail-compose
docker compose down -v # 移除栈与网络
docker rmi squirrelmail-1.4.22-webmail:local squirrelmail-1.4.22-mail:local # 移除自建镜像
实测输出(down 阶段):
[+] Running 3/3
✔ Container squirrelmail-1.4.22-webmail Removed
✔ Container squirrelmail-1.4.22-mail Removed
✔ Network squirrelmail-1422-stack_smnet Removed
清理后核对(应无输出):
docker images 'squirrelmail-1.4.22*' --format '{{.Repository}}'
docker ps -a --format '{{.Names}}' | grep squirrelmail
八、参考链接
- SourceForge 发布文件列表(1.4.22,应用本体来源):https://sourceforge.net/projects/squirrelmail/files/stable/1.4.22/
- php:7.4-apache 基座镜像说明(php.ini 模板与 APACHE_DOCUMENT_ROOT 机制):https://hub.docker.com/_/php
- Dovecot 认证配置文档(disable_plaintext_auth):https://doc.dovecot.org/configuration_manual/authentication/
- 本平台系列文档:《SquirrelMail 1.4.22 介绍与选型指南》、《Ubuntu 22.04 安装 SquirrelMail 1.4.22 指南》