Apache Roller Docker Compose 部署指南
使用 Docker Compose 编排 Apache Roller 6.1.3 与 MariaDB 10.6 双服务,基于 tomcat:9-jre11 自建镜像注入 JDBC 配置与 JavaMail 包,MariaDB 初始化自动建表,端口映射与数据持久化,docker compose 全流程命令与回显均实测
Apache Roller Docker Compose 部署指南
目标:使用 Docker Compose 一键编排 Apache Roller 6.1.3(Tomcat 9 + 自建镜像)与 MariaDB 10.6 双服务,数据库初始化自动导入建表脚本,Roller 首页 200 可访问、可注册登录,实现从零到一的容器化博客部署。全程命令与回显均为实际执行结果(Docker Compose v5.5.1 实测)。
一、环境信息
- Docker:24.x(本指南实测环境)
- Docker Compose:v5.5.1(
docker compose子命令) - Roller 镜像:自建
roller-webapp:6.1.3(基于tomcat:9-jre11,内含 Roller 6.1.3 + MySQL Connector/J 8.0.33 + JavaMail 1.6.2) - 数据库镜像:
mariadb:10.6(实测启动版本 10.6.28-MariaDB-ubu2204) - 服务名:roller、db;容器名:roller-tomcat、roller-mariadb
- 映射端口:宿主机 8081 → roller 服务内 8080(若宿主 8080 空闲可直接用
8080:8080) - 数据目录:
./data/db→ MariaDB 数据、./data/roller→/roller-data(索引与媒体文件) - 配置目录:
./conf/createdb.sql→ MariaDB 首次初始化自动建表 - 站长账号:admin / q1w2e3r4
二、镜像选型说明
| 镜像 | 说明 |
|---|---|
tomcat:9-jre11 + 自建 | 本指南采用。官方 Tomcat 基础镜像,Dockerfile 内下载 Roller 发行包并补齐 JDBC 驱动、JavaMail,可控且离线可复现 |
mariadb:10.6 | 官方 MariaDB 镜像,兼容 MySQL 5.7 协议,支持 docker-entrypoint-initdb.d 首次初始化自动执行 SQL |
apache/roller(Docker Hub 社区镜像) | 无官方维护镜像,社区镜像版本陈旧且配置方式各异,不推荐生产使用 |
💡 Roller 发行包只有 WAR:JDBC 驱动与 JavaMail 都不在包内,无论哪种镜像方案都必须补齐这两个依赖,否则应用无法连库或菜单页报
ClassNotFoundException: javax.mail。
三、前置条件
- 装有 Docker 与 Docker Compose v2+ 的服务器,root 权限。
- 构建镜像阶段需要访问
archive.apache.org(Roller 发行包约 56MB)与 Maven 中央仓库(3 个 jar)。 - 宿主机 8080/8081 端口未被占用(被占用时改映射,见 4.3 节说明)。
四、部署步骤
4.1 创建目录结构
mkdir -p roller-compose/conf roller-compose/data/db roller-compose/data/roller
cd roller-compose
4.2 编写自建镜像的 Dockerfile
cat > Dockerfile <<'EOF'
FROM tomcat:9-jre11
# 安装下载工具
RUN apt-get update -qq && apt-get install -y -qq unzip curl && rm -rf /var/lib/apt/lists/*
# 下载并解压 Apache Roller 6.1.3,WAR 部署到 webapps
RUN cd /tmp \
&& curl -fSL -o roller.zip https://archive.apache.org/dist/roller/roller-6.1/v6.1.3/apache-roller-6.1.3-binary.zip \
&& unzip -q roller.zip \
&& cp apache-roller-6.1.3/webapp/roller.war /usr/local/tomcat/webapps/roller.war \
&& rm -rf roller.zip apache-roller-6.1.3
# JDBC 驱动与 JavaMail(Roller WAR 未捆绑,需放入 Tomcat 共享 lib)
RUN cd /usr/local/tomcat/lib \
&& curl -fSL -o mysql-connector-j-8.0.33.jar https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jar \
&& curl -fSL -o javax.mail-1.6.2.jar https://repo1.maven.org/maven2/com/sun/mail/javax.mail/1.6.2/javax.mail-1.6.2.jar \
&& curl -fSL -o javax.activation-1.2.0.jar https://repo1.maven.org/maven2/com/sun/activation/javax.activation/1.2.0/javax.activation-1.2.0.jar
# Roller 自定义配置(JDBC 指向 compose 服务名 db)与数据目录
COPY roller-custom.properties /usr/local/tomcat/lib/roller-custom.properties
RUN mkdir -p /roller-data/search-index /roller-data/mediafiles
EXPOSE 8080
EOF
💡
/usr/local/tomcat/lib是官方 Tomcat 镜像的共享类路径(等价于 Ubuntu 的/var/lib/tomcat9/lib),roller-custom.properties与 3 个 jar 放这里即可被 Roller 读到。
4.3 编写 roller-custom.properties
cat > roller-custom.properties <<'EOF'
database.configurationType=jdbc
database.jdbc.driverClass=com.mysql.cj.jdbc.Driver
database.jdbc.connectionURL=jdbc:mysql://db:3306/rollerdb?autoReconnect=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC
database.jdbc.username=roller
database.jdbc.password=q1w2e3r4
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
search.index.dir=/roller-data/search-index
mediafile.storage.dir=/roller-data/mediafiles
EOF
connectionURL 中主机名 db 是 compose 服务名,由 compose 内置 DNS 解析,不要写死 IP。
4.4 编写 docker-compose.yml
cat > docker-compose.yml <<'EOF'
version: '3.8'
services:
db:
image: mariadb:10.6
container_name: roller-mariadb
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: q1w2e3r4
MYSQL_DATABASE: rollerdb
MYSQL_USER: roller
MYSQL_PASSWORD: q1w2e3r4
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./data/db:/var/lib/mysql
- ./conf/createdb.sql:/docker-entrypoint-initdb.d/createdb.sql:ro
roller:
build: .
image: roller-webapp:6.1.3
container_name: roller-tomcat
restart: unless-stopped
depends_on:
- db
ports:
- "8081:8080"
environment:
JAVA_OPTS: "-Xms256m -Xmx512m"
volumes:
- ./data/roller:/roller-data
EOF
| 配置项 | 说明 |
|---|---|
db.environment | 首次启动自动建库 rollerdb、授权 roller 账号 |
db.volumes: ./conf/createdb.sql:/docker-entrypoint-initdb.d/createdb.sql | MariaDB 首次初始化自动导入 Roller 建表脚本(从 roller.war 内 WEB-INF/classes/dbscripts/mysql/createdb.sql 解出,共 33 张业务表) |
command: --character-set-server=utf8mb4 ... | 与 Roller 建库字符集一致,避免中文乱码 |
roller.build: . | 用 4.2 节 Dockerfile 构建 roller-webapp:6.1.3 |
roller.ports: 8081:8080 | 宿主机 8081 映射 8080;宿主 8080 空闲可改 8080:8080(实测宿主 8080 被占用故映射 8081) |
roller.environment: JAVA_OPTS | JVM 堆限定 256-512MB |
roller.volumes: ./data/roller:/roller-data | 搜索索引与媒体文件落盘宿主机 |
depends_on | 先起 db 再起 roller(仅启动顺序,不含就绪探测) |
💡
createdb.sql从 WAR 解出:unzip -o -q roller.war "WEB-INF/classes/dbscripts/mysql/*"后取WEB-INF/classes/dbscripts/mysql/createdb.sql放到./conf/。它只在数据目录为空(首次初始化)时执行,重建栈需清空./data/db才会重新导入。
4.5 启动服务
docker compose up -d --build
实测回显:
Container roller-mariadb Creating
Container roller-mariadb Created
Container roller-tomcat Creating
Container roller-tomcat Created
Container roller-mariadb Starting
Container roller-mariadb Started
Container roller-tomcat Starting
Container roller-tomcat Started
4.6 查看状态
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
roller-mariadb mariadb:10.6 "docker-entrypoint.s…" db 15 seconds ago Up 14 seconds 3306/tcp
roller-tomcat roller-webapp:6.1.3 "catalina.sh run" roller 6 seconds ago Up 5 seconds 0.0.0.0:8081->8080/tcp, [::]:8081->8080/tcp
4.7 验证服务
Roller 启动约需 10-90 秒(连接数据库并初始化),轮询探测:
for i in $(seq 1 24); do CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8081/roller/ 2>/dev/null); if [ "$CODE" = "200" ]; then echo "READY HTTP=$CODE"; break; fi; sleep 10; done
curl -s http://localhost:8081/roller/ | grep -oE "<title>[^<]+</title>"
实测回显:
READY HTTP=200
<title>Front Page: Welcome to Roller!</title>
JVM 堆参数与依赖 jar 核验:
docker exec roller-tomcat bash -c 'ps -ef | grep "[j]ava" | grep -oE "\-Xms[0-9]+m \-Xmx[0-9]+m"; ls /usr/local/tomcat/lib/ | grep -E "mysql|mail|activation"; ls /roller-data/'
实测回显:
-Xms256m -Xmx512m
javax.activation-1.2.0.jar
javax.mail-1.6.2.jar
mysql-connector-j-8.0.33.jar
search-index
4.8 初始化站长账号(curl 完成)
与常规安装一致,初始化向导三步可直接用 curl 走完(宿主机端口换成 8081):
# 1) 注册 admin 用户(先 GET 表单取会话 salt,再 POST;salt 值以实际页面返回为准)
curl -s -c /tmp/ccj.txt http://localhost:8081/roller/roller-ui/register.rol -o /tmp/creg.html
SALT=$(grep -oE "name=\"salt\" value=\"[^\"]+\"" /tmp/creg.html | sed "s/.*value=\"\([^\"]*\)\".*/\1/")
curl -s -b /tmp/ccj.txt -X POST "http://localhost:8081/roller/roller-ui/register!save.rol" \
--data-urlencode "salt=$SALT" --data-urlencode "bean.id=" \
--data-urlencode "bean.userName=admin" --data-urlencode "bean.screenName=admin" \
--data-urlencode "bean.fullName=Site Admin" --data-urlencode "bean.emailAddress=admin@example.com" \
--data-urlencode "bean.passwordText=q1w2e3r4" --data-urlencode "bean.passwordConfirm=q1w2e3r4" \
--data-urlencode "bean.locale=en_US" --data-urlencode "bean.timeZone=America/New_York" \
--data-urlencode "userRegister.button.save=Sign Up" -o /dev/null -w "register=%{http_code}\n"
实测回显:
register=200
数据库核验与登录验证:
docker exec roller-mariadb mariadb -uroot -pq1w2e3r4 rollerdb -e "SELECT username,fullname FROM roller_user;"
curl -s -b /tmp/ccj.txt -c /tmp/ccj.txt -X POST "http://localhost:8081/roller/roller_j_security_check" \
-d "j_username=admin&j_password=q1w2e3r4" -o /dev/null -w "login=%{http_code}\n"
curl -s -b /tmp/ccj.txt -L http://localhost:8081/roller/roller-ui/menu.rol | grep -oE "<title>[^<]+</title>"
实测回显:
username fullname
admin Site Admin
login=302
<title>Front Page: Your Weblogs</title>
💡 建博客与指定前台首页两步同理:
createWeblog!save.rol提交bean.handle=adminblog等,随后setup!save.rol提交frontpageBlog=adminblog;流程与《Apache Roller 安装指南》初始化一节完全一致,仅端口不同。
五、数据持久化说明
./data/db挂载到 MariaDB 的/var/lib/mysql,博客文章、用户、评论等全部数据落盘宿主机;./data/roller挂载到/roller-data,存放搜索索引search-index/与媒体文件mediafiles/;./conf/createdb.sql建表脚本随项目目录保存,重建环境可直接复用;docker compose down删除的是容器与网络,上述宿主目录不受影响;重启后数据完好。实测docker compose restart roller后再次登录会话仍有效:
Container roller-tomcat Started
after_restart=200
menu_after_restart=200
⚠️ 若要彻底重建数据库(重新导入建表脚本),必须
docker compose down后清空./data/db,否则 MariaDB 数据目录非空会跳过初始化脚本。
六、常用环境变量表
| 环境变量 | 服务 | 说明 | 本指南值 |
|---|---|---|---|
MYSQL_ROOT_PASSWORD | db | root 密码 | q1w2e3r4 |
MYSQL_DATABASE | db | 首次初始化创建的库名 | rollerdb |
MYSQL_USER / MYSQL_PASSWORD | db | 业务账号与密码 | roller / q1w2e3r4 |
JAVA_OPTS | roller | JVM 参数(堆 256-512MB) | -Xms256m -Xmx512m |
💡 Roller 自身的连接参数不走环境变量,而是读取类路径的
roller-custom.properties(见 4.3 节);改连接串需改该文件并重新构建或挂载覆盖。
七、常用配置参数说明(command)
db.command 覆盖 MariaDB 默认启动参数,常用追加项:
| command 追加参数 | 说明 |
|---|---|
--character-set-server=utf8mb4 | 服务端默认字符集,与 Roller utf8mb4 建库对齐 |
--collation-server=utf8mb4_unicode_ci | 服务端默认排序规则 |
--skip-name-resolve | 跳过域名反查,容器环境建议加上以加速连接 |
roller 服务默认 command 为镜像自带 catalina.sh run(前台运行,日志进入 docker compose logs),不建议改成 catalina.sh start(后台化后容器会立刻退出)。
八、配置文件持久化(conf 挂载)
需要把 Roller 配置也放宿主机统一管理时,把 roller-custom.properties 改为挂载方式而非打进镜像:
roller:
build: .
image: roller-webapp:6.1.3
volumes:
- ./data/roller:/roller-data
- ./conf/roller-custom.properties:/usr/local/tomcat/lib/roller-custom.properties:ro
修改宿主机 ./conf/roller-custom.properties 后 docker compose restart roller 生效,无需重新 build 镜像。
九、等价 docker run 运行方式
不写 compose 文件时的等价命令(先自建网络与数据库):
docker network create roller-net
docker run -d --name roller-mariadb --network roller-net \
-e MYSQL_ROOT_PASSWORD=q1w2e3r4 \
-e MYSQL_DATABASE=rollerdb \
-e MYSQL_USER=roller -e MYSQL_PASSWORD=q1w2e3r4 \
-v "$PWD/data/db:/var/lib/mysql" \
-v "$PWD/conf/createdb.sql:/docker-entrypoint-initdb.d/createdb.sql:ro" \
mariadb:10.6 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
docker run -d --name roller-tomcat --network roller-net \
-p 8081:8080 \
-e JAVA_OPTS='-Xms256m -Xmx512m' \
-v "$PWD/data/roller:/roller-data" \
roller-webapp:6.1.3
十、常用运维命令
docker compose up -d # 启动(栈不存在时)
docker compose up -d --build # 重新构建镜像并启动(改 Dockerfile/配置后)
docker compose ps # 查看两服务状态
docker compose logs -f roller # 跟踪 Roller 日志(catalina + roller 合流输出)
docker compose logs --tail 3 db # 查看 MariaDB 日志末尾
docker compose restart roller # 重启 Roller(配置变更后)
docker compose restart db # 重启数据库
docker compose down # 停止并删除容器与网络(保留 ./data 与 ./conf)
docker compose down -v # 额外删除命名卷(本栈未用命名卷,数据仍在 bind 目录)
docker compose logs --tail 3 db 实测回显:
roller-mariadb | 2026-10-12 0:59:31 0 [Note] mariadbd: ready for connections.
roller-mariadb | Version: '10.6.28-MariaDB-ubu2204' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
roller-mariadb | 2026-10-12 0:59:31 0 [Note] InnoDB: Buffer pool(s) load completed at 261012 0:59:31
十一、常见问题(FAQ)
11.1:启动报宿主端口占用
实测回显:
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint roller-tomcat (...): failed to bind host port 0.0.0.0:8080/tcp: address already in use
解决:把 ports 改为其他宿主端口(如 8081:8080)后 docker compose up -d 重建。
11.2:首页一直 404 或 500
排查:docker compose logs -f roller 看应用日志;常见两类原因——
- 数据库未就绪时 Roller 启动失败:
depends_on只保证顺序,MariaDB 初始化需十几秒,重启 roller 即可(docker compose restart roller); createdb.sql未导入:确认./data/db在启动前为空目录(首次初始化才会执行 initdb 脚本),必要时清空后重建。
11.3:日志报 ClassNotFoundException: javax.mail
原因:镜像内缺少 JavaMail 包。Roller WAR 不捆绑 javax.mail,登录后菜单页会 500。
解决:确认 Dockerfile 中三个 jar 的下载步骤存在且成功(docker exec roller-tomcat ls /usr/local/tomcat/lib/ 应见 mysql-connector-j、javax.mail、javax.activation),缺则补齐后重建镜像。
11.4:数据库连接失败(Communications link failure)
排查:确认 roller-custom.properties 的 connectionURL 主机名为服务名 db 而非 localhost(roller 服务内 localhost 指向自身);docker compose exec db mariadb -uroot -pq1w2e3r4 -e "SHOW DATABASES;" 确认 rollerdb 已创建。
11.5:中文内容乱码
解决:保留 command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci,且建库/建表脚本用 utf8mb4;已乱码的旧数据需重新导入。
十二、参考链接
- Apache Roller 存档下载:https://archive.apache.org/dist/roller/roller-6.1/
- Apache Roller 官网:https://roller.apache.org/
- 官方 Tomcat 镜像:https://hub.docker.com/_/tomcat
- 官方 MariaDB 镜像:https://hub.docker.com/_/mariadb
- Docker Compose 文档:https://docs.docker.com/compose/