Mailcow Docker Compose 部署指南

Mailcow Docker Compose 部署指南:官方 mailcow-dockerized(2026-09a)从 clone、generate_config.sh 配置生成、mailcow.conf 关键变量(端口/降配/子网)到 compose 拉起与验收的完整实测记录,含 SKIP_SOLR 改名、非标端口重定向等真实坑位与回显。

Mailcow邮件服务器2026/10/19

Mailcow Docker Compose 部署指南

目标:在一台 Ubuntu 服务器上以官方 mailcow-dockerized(tag 2026-09a,2026-10-19 实查的最新稳定版)完成 Mailcow 部署:clone → 配置生成 → 降配与端口/子网定制 → 拉起 → 验收。全部命令与回显为 Ubuntu 22.04 + Docker 29.8.1(Compose 插件 v2.x)实测,安装目录 /opt/data/mailcow-dockerized/。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64)
  • Docker:29.8.1,含 compose 插件(docker compose version 通过;Mailcow 生成脚本要求 Docker ≥ 24.0,低于此版本会拒绝生成配置)
  • Mailcow:2026-09a(GitHub Releases 实查最新稳定 tag)
  • 安装目录:/opt/data/mailcow-dockerized/
  • 邮件主机名:mail.example.com,邮件域:example.com(内网环境用 /etc/hosts 解析,公网环境用 DNS A 记录)
  • Web 端口:HTTP 8126、HTTPS 8130(本机 80/443 与部分高位端口已被同宿主机其他服务占用,故用非标端口,见 4.2)
  • 部署前内存复核(本机内存吃紧,必须先看):
$ free -h
               total        used        free      shared  buff/cache   available
Mem:            31Gi        23Gi       4.4Gi       333Mi       3.2Gi       6.7Gi
Swap:          2.0Gi       2.0Gi       9.0Mi

Mailcow 官方建议 ≥ 6 GiB 内存,本机 available 约 6.7 GiB,因此按第五章全量关闭 ClamAV/SOGo/全文检索降配部署。

二、获取代码

固定 tag 克隆(走代理时通过环境变量注入):

$ export https_proxy=http://<proxy-host>:<proxy-port> http_proxy=http://<proxy-host>:<proxy-port>
$ git clone --depth 1 -b 2026-09a https://github.com/mailcow/mailcow-dockerized.git /opt/data/mailcow-dockerized
$ cd /opt/data/mailcow-dockerized
$ ls
CODE_OF_CONDUCT.md  CONTRIBUTING.md     create_cold_standby.sh  data
docker-compose.yml  generate_config.sh  helper-scripts          LICENSE
_modules            README.md           SECURITY.md             update.sh

坑位记录:不要用 git clone -b master 之后靠脚本切分支——generate_config.sh 默认会 git checkout -f master 把代码切到主线。固定版本 tag 部署时务必用 -d(dev mode)运行生成脚本,脚本将跳过分支切换保持当前 tag(本文采用)。

三、生成配置(generate_config.sh 实测)

3.1 前置依赖

$ apt-get install -y jq

2026-09a 的生成脚本强依赖 jq,缺失时直接退出(实测回显):

Error: Cannot find command 'jq'. Cannot proceed.
Solution: Please review system requirements and install requirements. Then, re-run the script.

3.2 运行生成

.env 软链已随仓库提供(指向 mailcow.conf)。以 -d 模式运行并按提示输入主机名:

$ ./generate_config.sh -d
Detecting if your IP is listed on Spamhaus Bad ASN List...
Check completed! Your IP is clean
Press enter to confirm the detected value '[value]' where applicable or enter a custom value.
Enabled Dev Mode.
Not checking out a different branch!
IPv6 not detected on host – disabling IPv6 support.
Skipping Docker IPv6 configuration because host does not support IPv6.
Make sure to check if your docker daemon.json does not include "enable_ipv6": true if you do not want IPv6.
IPv6 configuration complete: ENABLE_IPV6=false
Generating snake-oil certificate...

脚本做了四件事:Spamhaus Bad ASN 检测(无公网 IP 也会快速通过)、主机名/时区交互(时区自动检测为 Asia/Shanghai)、IPv6 探测(本机无 IPv6 默认路由,自动置 ENABLE_IPV6=false 并跳过 Docker IPv6 配置)、生成自签 snake-oil 证书(供无公网证书场景使用)。

3.3 mailcow.conf 关键变量(生成后修改)

$ grep -E '^(MAILCOW_HOSTNAME|HTTP_PORT|HTTPS_PORT|SKIP_CLAMD|SKIP_SOGO|SKIP_FTS|SKIP_LETS_ENCRYPT|IPV4_NETWORK|ENABLE_IPV6|TZ)=' mailcow.conf
MAILCOW_HOSTNAME=mail.example.com
HTTP_PORT=8126
HTTPS_PORT=8130
TZ=Asia/Shanghai
SKIP_LETS_ENCRYPT=y
SKIP_CLAMD=y
SKIP_SOGO=y
SKIP_FTS=y
IPV4_NETWORK=10.89.54
ENABLE_IPV6=false

逐项说明:

变量取值理由
MAILCOW_HOSTNAMEmail.example.com邮件服务器 FQDN(非邮件域),证书与 HELO 均用它
HTTP_PORT / HTTPS_PORT8126 / 8130默认 80/443 已被占用;见 4.2 端口规划
HTTP_REDIRECTn(默认 y)见 4.3 非标端口重定向坑位
SKIP_LETS_ENCRYPTy无公网域名,ACME 无法验证,关闭避免空转
SKIP_CLAMD / SKIP_SOGO / SKIP_FTSy / y / y内存紧张全量降配,见第五章
IPV4_NETWORK10.89.54自定义内部网络网段(生成 10.89.54.0/24),避免与默认 172.22.1.0/24 及宿主其他网络冲突
ENABLE_IPV6false脚本自动探测写入

坑位记录(版本改名):老教程里的 SKIP_SOLR=y 在 2026-09a 已改为 SKIP_FTS=y(全文检索后端由 Solr 换成 Dovecot 内置 Flatcurve/Xapian),写错变量不会报错,只会让降配不生效。

3.4 数据库与随机密钥

生成的 mailcow.conf 内含自动生成的 DBPASS、DBROOT、REDISPASS(28 位随机串),部署后请连同整个文件妥善备份(权限已是 600)。

四、端口与网络规划

4.1 邮件协议端口(宿主直绑)

25/110/143/465/587/993/995/4190 全部空闲,保持默认直绑;内部端口(SQL 13306、Redis 7654、Doveadm 19991)默认仅绑 127.0.0.1。部署后实测监听:

$ ss -ltn | grep -E ':(8126|8130|25|110|143|465|587|993|995|4190)\s'
LISTEN 0      4096         0.0.0.0:8126      0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8130      0.0.0.0:*
LISTEN 0      4096         0.0.0.0:25        0.0.0.0:*
LISTEN 0      4096         0.0.0.0:110       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:143       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:4190      0.0.0.0:*
LISTEN 0      4096         0.0.0.0:465       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:587       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:993       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:995       0.0.0.0:*

4.2 Web 端口选择

本机 80/443 被占用,且 8125、8127–8129 等高位端口亦被同宿主机其他服务监听(部署前 ss -ltn 复核为部署纪律)。故 Web 入口选 HTTP_PORT=8126、HTTPS_PORT=8130(两者实测空闲)。若你的 8127 空闲,用 HTTPS_PORT=8127 亦完全等价——这只是两个普通变量。

4.3 坑位记录:非标端口下 HTTP 301 丢端口

HTTP_REDIRECT=y(默认)时,访问 http://mail.example.com:8126/ 会被 301 到 https://mail.example.com/(丢失 8130,落在 443 上)。官方模板按标准端口假设生成重定向。两种处理:

  • 保持 HTTP_REDIRECT=n:8126 直接吐 UI(本地/内网场景实测选择);
  • 或改用标准 80/443 绑定。

本机改法与验证:

$ sed -i 's/^HTTP_REDIRECT=y$/HTTP_REDIRECT=n/' mailcow.conf
$ docker compose up -d
 Container mailcowdockerized-nginx-mailcow-1 Started
$ curl -s -o /dev/null -w '%{http_code}\n' http://mail.example.com:8126/
200

4.4 内部网络子网

Mailcow 内部网络由 IPV4_NETWORK 控制(compose 网络段定义为 ${IPV4_NETWORK:-172.22.1}.0/24)。设为 10.89.54 后实测:

$ docker network inspect mailcowdockerized_mailcow-network --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
10.89.54.0/24

网桥名 br-mailcow(compose driver_opts 固定),宿主路由不受影响。

五、降配部署(低内存场景)

本机可用内存约 6.7 GiB,mailcow.conf 三开关全开:

SKIP_CLAMD=y    # 关闭 ClamAV 病毒扫描
SKIP_SOGO=y     # 关闭 SOGo(Webmail/CalDAV/CardDAV/ActiveSync)
SKIP_FTS=y      # 关闭 Dovecot 全文检索(Flatcurve)

拉起后验证降配的真实形态——被跳过的服务容器并不消失,而是只跑保活进程(实测容器内进程为 /bin/bash /clamd.sh + sleep 365d),日志明确打印跳过原因:

$ docker logs mailcowdockerized-clamd-mailcow-1
SKIP_CLAMD=y, skipping ClamAV...
$ docker logs mailcowdockerized-sogo-mailcow-1
SKIP_SOGO=y, skipping SOGo...

Rspamd 会自动探测 ClamAV 缺位并降级,实测外域入站信的 X-Spamd-Result 出现:

CLAM_VIRUS_FAIL(0.00)[failed to scan and retransmits exceed];

即病毒检查记 0 分放行、不阻塞投递。恢复某组件:把对应变量改回 n 后 docker compose up -d 重建即可。

六、拉起与验收

6.1 启动

$ docker compose up -d

首次会拉取 15 个官方构建镜像(ghcr.io/mailcow/*,总下载量约 1.5 GB),随后按依赖顺序启动。

6.2 实测最终状态

$ docker compose ps --format '{{.Name}}\t{{.Status}}'
mailcowdockerized-acme-mailcow-1        Up ...
mailcowdockerized-clamd-mailcow-1       Up ... (healthy)      # 降配保活
mailcowdockerized-dockerapi-mailcow-1   Up ...
mailcowdockerized-dovecot-mailcow-1     Up ...
mailcowdockerized-memcached-mailcow-1   Up ...
mailcowdockerized-mysql-mailcow-1       Up ...
mailcowdockerized-netfilter-mailcow-1   Up ...
mailcowdockerized-nginx-mailcow-1       Up ...
mailcowdockerized-ofelia-mailcow-1      Up ...
mailcowdockerized-olefy-mailcow-1       Up ...
mailcowdockerized-php-fpm-mailcow-1     Up ...
mailcowdockerized-postfix-mailcow-1     Up ...
mailcowdockerized-postfix-tlspol-mailcow-1      Up ...
mailcowdockerized-redis-mailcow-1       Up ...
mailcowdockerized-rspamd-mailcow-1      Up ...
mailcowdockerized-sogo-mailcow-1        Up ...                # 降配保活
mailcowdockerized-unbound-mailcow-1     Up ... (healthy)
mailcowdockerized-watchdog-mailcow-1    Up ...

6.3 Web 入口验收

$ curl -s -o /dev/null -w '%{http_code}\n' http://mail.example.com:8126/
200
$ curl -s http://mail.example.com:8126/ | grep -oE '<title>[^<]+</title>'
<title>mail.example.com - mail UI</title>

首次登录用户名 admin、密码 moohoo(生成脚本注释原文:# Default password is "moohoo"),登录后立即改强密码——流程见快速入门篇。

6.4 主机名解析准备

内网无 DNS 时把主机名与自动发现名指到本机(公网环境应为 A 记录):

$ echo '127.0.0.1 mail.example.com autodiscover.example.com autoconfig.example.com' >> /etc/hosts
$ getent hosts mail.example.com
127.0.0.1       mail.example.com

七、常见问题(部署期实测)

  1. jq 缺失:按 3.1 安装后重跑。
  2. 固定 tag 被切分支:用 ./generate_config.sh -d,不要交互选 master/nightly。
  3. SKIP_SOLR 无效:2026-09a 已改名 SKIP_FTS(3.3 节)。
  4. HTTP 301 丢端口:非标端口下设 HTTP_REDIRECT=n(4.3 节)。
  5. 修改 mailcow.conf 后未生效:compose 不会自动重建已存在容器,需 docker compose up -d(必要时对目标服务 --force-recreate,如开启 API 后重建 php-fpm-mailcow/nginx-mailcow)。
  6. 降配后 ClamAV 报 CLAM_VIRUS_FAIL:属预期降级行为(第五章),非故障。
  7. fatal: HEAD does not point to a branch:-d 模式下 detached HEAD 查询 upstream 的无害提示,可忽略。

八、卸载与清理

$ cd /opt/data/mailcow-dockerized
$ docker compose down -v    # 移除容器、网络与命名卷(邮件数据全清,慎重)
$ rm -rf /opt/data/mailcow-dockerized

仅停机保留数据用 docker compose down(不带 -v);升级/迁移请走 update.sh 或冷备脚本(见运维手册篇)。

九、参考链接

  1. 官方部署文档:https://docs.mailcow.email/getstarted/install/
  2. 官方仓库:https://github.com/mailcow/mailcow-dockerized(tag 2026-09a)
  3. IP 绑定与反代:https://docs.mailcow.email/post_installation/firststeps-ip_bindings/
  4. 站内同族部署实测:《docker-mailserver Docker Compose 部署指南》、《Postal Docker Compose 部署指南》