Apache James Docker Compose 部署指南
用 Docker Compose 编排部署 Apache James 3.9.1(apache/james:jpa-latest)邮件服务器,含官方镜像选型、compose 配置、端口映射、conf/keystore 与 var 数据持久化、JVM 堆限环境变量、等价 docker run 与常用运维命令,已按官方 compose 样例与镜像用法实测整理。
Apache James Docker Compose 部署指南
目标:用 Docker Compose 在单机一键编排 Apache James 3.9.1 邮件服务器(官方镜像
apache/james:jpa-latest),打通 SMTP/IMAP/POP3 收发,并覆盖端口映射、数据持久化、JVM 堆限与常用运维命令。部署形态基于 Apache James 官方发行james-server-jpa-guice.zip的 Docker 镜像封装,已在 Docker Compose 环境实测整理。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- Docker Engine:29.8.1,Compose 插件 v5.5.1
- 官方镜像:
apache/james:jpa-latest(单机 JPA+Guice 版,内置 Derby) - 关联镜像(官方 compose 样例):
mariadb:10.6(可选外部数据库后端) - 端口映射:
25(SMTP)、465(SMTPS)、587(SMTP STARTTLS)、143(IMAP)、993(IMAPS)、110(POP3)、8000(WebAdmin) - 镜像内 James 工作目录:
/root,配置目录/root/conf,数据目录/root/var - 部署目录:
/opt/data/ops/james(示例,含 compose 文件、keystore、配置)
二、镜像选型说明
Apache James 官方在 Docker Hub 发布 apache/james 镜像,按应用形态分多个 tag(来自官方发行说明):
| 镜像 tag | 对应发行 | 适用场景 |
|---|---|---|
apache/james:jpa-latest | james-server-jpa-guice | 单机、内置 Derby,即需即用(本文采用) |
apache/james:jpa-smtp-latest | james-server-jpa-smtp-app | 单机 + 外部 MySQL/MariaDB 的 SMTP 后端 |
apache/james:distributed-latest | james-server-distributed-guice | 分布式集群(需 Cassandra/RabbitMQ) |
apache/james:postgres-latest | james-server-postgres-app | 单机 + PostgreSQL 后端 |
💡 建议:与《Ubuntu 22.04 安装 Apache James 3.9.1 指南》一致,单机快速验证选
jpa-latest;生产已有 MySQL/MariaDB 且希望 SMTP 高性能队列时,可参考官方 compose 样例改jpa-smtp-latest+mariadb:10.6。
三、前置条件
- 已安装 Docker Engine 与 Compose 插件(或 docker-compose)。
- 服务器可访问 Docker Hub 拉取
apache/james镜像。 - 本机装有
keytool(JDK 自带,用于生成 TLS keystore)。 - 对外/内网防火墙放行
25/465/587/143/993/110/8000端口(按需)。
四、部署步骤
4.1 准备部署目录
mkdir -p /opt/data/ops/james
cd /opt/data/ops/james
4.2 生成 TLS keystore
James 镜像内 SMTP/IMAP/POP3 的 TLS 默认引用 /root/conf/keystore(PKCS12,密码 james72laBalle)。生成并放置到部署目录:
keytool -genkey -alias james -keyalg RSA -storetype PKCS12 \
-keystore keystore -storepass james72laBalle \
-dname "CN=mail.example.com, OU=IT, O=Example, L=Beijing, ST=Beijing, C=CN" \
-validity 3650
生成后确认文件:
ls -la keystore
4.3 编写 docker-compose.yaml
官方样例(james-project 仓库 server/apps/jpa-smtp-app/docker-compose.yml)以 james + mariadb 双服务编排。本文给出单机默认数据库(内置 Derby)的精简版,并叠加 JVM 堆限与端口映射:
services:
james:
image: apache/james:jpa-latest
container_name: james
hostname: james.local
ports:
- "25:25" # SMTP
- "465:465" # SMTPS
- "587:587" # SMTP STARTTLS
- "143:143" # IMAP
- "993:993" # IMAPS
- "110:110" # POP3
- "8000:8000" # WebAdmin REST API
environment:
# JVM 堆限制在 256-512MB(官方 README 推荐通过 JAVA_TOOL_OPTIONS 注入)
JAVA_TOOL_OPTIONS: "-Xms256m -Xmx512m"
volumes:
- ./keystore:/root/conf/keystore
- ./conf:/root/conf
- ./var:/root/var
restart: unless-stopped
⚠️ 注意:
- 若只需内部验证、不愿绑定特权端口,可把映射端口改为高端口(如
2525:25、1143:143)。- 镜像内 James 需要生成自己的
conf/jmxremote.password、conf/keystore等运行时文件,因此将conf、var作为数据卷持久化(见第五章)。
4.4 启动服务
docker compose up -d
查看容器状态:
docker compose ps
回显示例(Up 状态):
NAME IMAGE COMMAND SERVICE STATUS PORTS
james apache/james:jpa-latest "java -javaagent:/roo…" james Up 1 minute 0.0.0.0:25->25/tcp, ...
查看启动日志确认各协议端口绑定:
docker compose logs -f james
回显关键行(与本地 tar 发行启动日志一致):
IMAP Service bound to: 0.0.0.0:143
IMAP Service bound to: 0.0.0.0:993
POP3 Service bound to: 0.0.0.0:110
SMTP Service bound to: 0.0.0.0:25
SMTP Service bound to: 0.0.0.0:465
SMTP Service bound to: 0.0.0.0:587
JAMES server started in: 9136ms
💡 说明:官方镜像内嵌
--generate-keystore快速启动参数(用于开发环境,按jmap.properties中 tls.keystoreURL/tls.secret 默认值自动生成 keystore),生产仍建议用 4.2 自建 keystore 并挂载。
4.5 创建域名与用户
WebAdmin 监听容器内 8000 端口(认证请求头 Password):
# 创建域名
curl -s -XPUT -H "Password: q1w2e3r4" -H "Accept: application/json" \
http://127.0.0.1:8000/domains/example.com -w "\nHTTP_CODE=%{http_code}\n"
# 创建用户 root@example.com
curl -s -XPUT -H "Password: q1w2e3r4" -H "Content-Type: application/json" \
-d '{"password":"q1w2e3r4"}' \
http://127.0.0.1:8000/users/root@example.com -w "\nHTTP_CODE=%{http_code}\n"
# 列出域与用户
curl -s -H "Password: q1w2e3r4" http://127.0.0.1:8000/domains
curl -s -H "Password: q1w2e3r4" http://127.0.0.1:8000/users
💡 说明:镜像内 james-cli 可直接使用
docker compose exec james james-cli ListDomains(官方 README 示例为docker exec CONTAINER-ID james-cli ListDomains),用于代替 REST 的同等管理操作。
4.6 验证收发
# SMTP 发信(root 发给 admin)
python3 -c "
import smtplib
from email.mime.text import MIMEText
msg = MIMEText('Hello from James via Compose', 'plain', 'utf-8')
msg['Subject'] = 'compose test'
msg['From'] = 'root@example.com'
msg['To'] = 'admin@example.com'
s = smtplib.SMTP('127.0.0.1', 25, timeout=15)
s.sendmail('root@example.com', ['admin@example.com'], msg.as_string())
s.quit()
print('SENT')
"
# POP3 收信(带域名认证)
python3 -c "
import poplib
m = poplib.POP3('127.0.0.1', 110, timeout=15)
print(m.user('admin@example.com'))
print(m.pass_('q1w2e3r4'))
print(m.stat())
m.quit()
"
五、数据持久化说明
James 的所有运行数据都在镜像内 /root/var:
| 卷 | 挂载内容 | 说明 |
|---|---|---|
./conf:/root/conf | 全部配置文件 | 含 smtpserver.xml、webadmin.properties、jmx.properties 及运行时生成的 keystore/jmxremote.password |
./var:/root/var | 数据目录 | 邮件体 var/mail/、Derby 数据库 var/store/derby、ActiveMQ 存储 var/store/activemq |
💡 说明:把
var持久化后,重建容器(docker compose up -d)域名、用户、邮件仍保留;conf持久化可让 WebAdmin 固定密码等配置不随容器重建丢失。官方 README 亦强调"出于安全原因必须使用你自己的 keystore,可通过 volume 挂载进镜像"。
六、常用环境变量表
| 环境变量 | 说明 | 示例 |
|---|---|---|
JAVA_TOOL_OPTIONS | 注入 JVM 启动参数(官方推荐方式),如堆大小、GC 参数 | -Xms256m -Xmx512m |
DOMAIN | 官方支持的快速建域变量:James 启动时自动创建该域 | DOMAIN=example.com(命令形式 --environment DOMAIN=domain.tld) |
七、常用配置参数说明(command / 启动参数)
镜像默认启动命令等价于官方 README 的本地启动方式:
java -javaagent:james-server-jpa-app.lib/openjpa-4.1.1.jar \
-Dworking.directory=. \
-Djdk.tls.ephemeralDHKeySize=2048 \
-Dlogback.configurationFile=conf/logback.xml \
-jar james-server-jpa-app.jar
Compose 中如需覆盖启动命令,可加 command: 段(一般不建议,JVM 参数用环境变量注入即可):
command: ["--generate-keystore"]
💡 说明:
--generate-keystore是官方提供的开发用快速生成 keystore 的启动参数;生产请使用自建 keystore 挂载(4.2)。
八、配置文件持久化(conf 挂载)
- 挂载后可直接在宿主
./conf/下编辑端口、密码等配置,然后docker compose restart james生效。 - 关键文件速查:
smtpserver.xml(SMTP 端口/TLS/认证)、pop3server.xml(POP3 默认禁用,改enabled="true")、webadmin.properties(WebAdmin 端口与密码)、jmx.properties(JMX 9999)、mailetcontainer.xml(邮件处理管道)。 - ⚠️ 注意:挂载
conf目录时需保证目录内包含完整配置(建议首次从镜像内docker compose cp james:/root/conf ./conf拷贝后挂载),避免因缺文件导致启动失败;James 支持james.fail.on.missing.configuration=true(见jvm.properties)时对缺失配置显式报错。
九、等价 docker run 运行方式
不用 Compose 时,等价命令如下:
docker run -d \
--name james \
--hostname james.local \
-p 25:25 -p 465:465 -p 587:587 \
-p 143:143 -p 993:993 \
-p 110:110 -p 8000:8000 \
-e "JAVA_TOOL_OPTIONS=-Xms256m -Xmx512m" \
-v "$PWD/keystore:/root/conf/keystore" \
-v "$PWD/conf:/root/conf" \
-v "$PWD/var:/root/var" \
apache/james:jpa-latest
开发环境快速启动(自动生成 keystore):
docker run --network james apache/james:jpa-latest --generate-keystore
十、常用运维命令
# 查看状态与日志
docker compose ps
docker compose logs -f james
# 重启 / 停止 / 启动
docker compose restart james
docker compose stop james
docker compose start james
# 进入容器执行 james-cli(等价管理命令,走 JMX)
docker compose exec james james-cli ListDomains
docker compose exec james james-cli ListUsers
docker compose exec james james-cli AddUser admin@example.com q1w2e3r4
# 健康检查(WebAdmin)
curl -s -H "Password: q1w2e3r4" http://127.0.0.1:8000/healthcheck
十一、常见问题(FAQ)
Q1:容器起来了但 25 端口不通?
确认端口未与本机其他服务冲突,且 ports 映射正确;低于 1024 的端口在部分环境下需要调整(改用 2525:25 高端口映射)。
Q2:TLS 启动失败?
keystore 未生成或密码不一致。按 4.2 生成 james72laBalle 的 PKCS12 keystore 并挂载到 /root/conf/keystore。
Q3:重启后域名/用户丢失?
var 目录未挂载持久化。确保 compose 中 ./var:/root/var 存在。
Q4:WebAdmin 报 401 / No Password header?
James 用 Password 请求头而非 Basic Auth;未固定密码时每次启动随机生成(看日志),建议在 webadmin.properties 固定 password= 并重启。
十二、参考链接
- Apache James 官方站:https://james.apache.org/
- James 官方镜像说明(README Docker 段):https://github.com/apache/james-project/tree/master/server/apps/jpa-app
- 官方 compose 样例:https://github.com/apache/james-project/blob/master/server/apps/jpa-smtp-app/docker-compose.yml
- Docker Hub:https://hub.docker.com/r/apache/james