Apache Archiva 2.2.10 Docker Compose 部署指南
Apache Archiva 2.2.10 Docker Compose 部署指南:基于 eclipse-temurin:8-jdk 自建 archiva:2.2.10 镜像(COPY 发行包完全离线构建,wrapper.conf 内置 256-512MB 堆),Compose 编排单服务,挂载 data/repositories/logs 三个目录持久化,端口 8080 映射,REST 初始化管理员并验证重启持久化,全程命令与回显实测
Apache Archiva 2.2.10 Docker Compose 部署指南
目标:使用 Docker Compose 编排 Apache Archiva 2.2.10 仓库管理服务:基于
eclipse-temurin:8-jdk自建archiva:2.2.10镜像(COPY 方式注入官方发行包,构建完全离线),挂载 data / repositories / logs 三个目录落盘持久化,端口 8080 映射,JVM 堆限定 256-512MB,重启后账号与仓库数据不丢。全程命令与回显均为实际执行结果。
一、环境信息
- Docker:29.8.1(实测环境,
docker versionServer Version) - Docker Compose:v2.5.1(
docker compose子命令) - Archiva 镜像:自建
archiva:2.2.10(基于eclipse-temurin:8-jdk,内含 Archiva 2.2.10 独立发行包,构建后镜像 461MB) - 服务:archiva(Web 控制台 + REST API + 仓库代理下载,单服务单进程)
- 映射端口:8080(HTTP)
- 挂载目录:
./data→/opt/archiva/data(Derby 元数据)、./repositories→/opt/archiva/repositories(制品存储)、./logs→/opt/archiva/logs - 管理账号:admin / q1w2e3r4(REST 初始化)
💡 说明:Archiva 项目没有官方维护的镜像;
archive.apache.org归档站只有 tar.gz/war 制品。自建镜像的价值在于版本固定、可离线分发,且与《安装指南》的二进制部署使用同一份发行包,行为完全一致。
二、镜像选型说明
| 镜像 | 基础 | 说明 |
|---|---|---|
archiva:2.2.10(自建) | eclipse-temurin:8-jdk | 本指南采用:官方 tar.gz 打进镜像,wrapper.conf 出厂即改好 256-512MB 堆,开箱可用 |
仅用 eclipse-temurin:8-jdk + 挂载发行包 | 官方基础镜像 | 不做镜像,把 tar.gz 解压目录整体挂进运行命令;适合快速试用,但配置改动都在宿主机命令里,不易留档 |
关键差异:两者运行时行为相同(都是同一发行包 + JSW wrapper console 前台启动)。自建镜像把「解压、改堆」固化进构建,交付物就是一个镜像文件,推荐主线方案。
三、前置条件
- 装有 Docker 与 Docker Compose v2 的服务器,root 权限。
- 已从归档站取得
apache-archiva-2.2.10-bin.tar.gz(约 68MB,下载与 SHA256 校验方式见《Apache Archiva 2.2.10 安装指南》4.2 节,本文不再重复校验输出)。 - 宿主机 8080 端口空闲(
ss -tlnp | grep 8080应无输出)。
四、部署步骤
4.1 创建目录结构
mkdir -p archiva-compose && cd archiva-compose
cp /opt/apache-archiva-2.2.10-bin.tar.gz .
ls -l
-rw-r--r-- 1 root root 68419100 Mar 16 2023 apache-archiva-2.2.10-bin.tar.gz
💡 发行包与 Dockerfile 放同一目录,后面用 COPY 注入镜像:构建期不访问外网,秒级完成,也规避了在构建步骤里直连归档站下载(实测该方式长时间无进展,见 9.1)。
4.2 编写自建镜像的 Dockerfile
cat > Dockerfile <<'EOF'
FROM eclipse-temurin:8-jdk
# Apache Archiva 2.2.10 发行包(与 Dockerfile 同目录提前放好,构建完全离线)
COPY apache-archiva-2.2.10-bin.tar.gz /tmp/
RUN cd /tmp \
&& tar -xzf apache-archiva-2.2.10-bin.tar.gz \
&& mv apache-archiva-2.2.10 archiva \
&& rm -f apache-archiva-2.2.10-bin.tar.gz \
&& mv /tmp/archiva /opt/archiva \
&& sed -i "s/^wrapper.java.initmemory=.*/wrapper.java.initmemory=256/" /opt/archiva/conf/wrapper.conf \
&& sed -i "s/^wrapper.java.maxmemory=.*/wrapper.java.maxmemory=512/" /opt/archiva/conf/wrapper.conf
WORKDIR /opt/archiva
EXPOSE 8080
CMD ["./bin/archiva", "console"]
EOF
| 指令 | 说明 |
|---|---|
FROM eclipse-temurin:8-jdk | Archiva 2.2.10 基于 Jetty 8 + 老版 JSP 栈,需 JDK 8(JDK 11+ 未适配);选 8-jdk,镜像内自带 jps |
COPY ... /tmp/ | 把已下载校验好的发行包带进构建,构建过程零外网依赖 |
sed wrapper.conf | 出厂堆 512/512,构建期固化为 256/512(生效验证见 4.6) |
CMD ./bin/archiva console | wrapper console 模式前台运行,日志输出交给 docker,进程退出即服务退出 |
构建镜像:
docker build -t archiva:2.2.10 .
#8 [4/4] WORKDIR /opt/archiva
#8 DONE 0.9s
#9 exporting to image
#9 exporting layers 0.5s done
#9 writing image sha256:2cededdfbd5807599905c3c7a9d10de3716a54c985a6f9468c176c3e1bdc5a08 done
#9 naming to docker.io/library/archiva:2.2.10 done
#9 DONE 0.6s
docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | grep archiva
archiva:2.2.10 461MB
解读:461MB = temurin JDK 基础(约 400MB)+ Archiva 发行包解压(约 260MB,与基础层有去重);镜像 ID 每次构建不同,以本机输出为准。
4.3 编写 docker-compose.yml
cat > docker-compose.yml <<'EOF'
version: "3.8"
services:
archiva:
image: archiva:2.2.10
container_name: archiva-server
restart: unless-stopped
mem_limit: 1g
ports:
- "8080:8080"
volumes:
- ./data:/opt/archiva/data
- ./repositories:/opt/archiva/repositories
- ./logs:/opt/archiva/logs
EOF
| 配置项 | 说明 |
|---|---|
container_name: archiva-server | 固定实例名,方便 docker exec / docker logs 操作 |
ports | Web 控制台、REST 与仓库下载共用 8080,一并映射 |
volumes | 三个目录挂载:Derby 元数据、制品存储、日志全部落盘宿主机 |
mem_limit: 1g | 实例内存上限;堆 256/512 + 永久代 128MB 的稳态占用约 430MB,1g 余量充足 |
restart: unless-stopped | 宿主机重启后自动拉起(docker 服务在运行时) |
💡 v2 的 compose 会提示
the attribute version is obsolete, it will be ignored——仅提示,可删掉version: "3.8"行消除;本文保留与实测文件一致。
4.4 启动与状态确认
docker compose up -d
[+] Running 2/2
✔ Network archiva-compose_default Created
✔ Container archiva-server Started
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
archiva-server archiva:2.2.10 "/__cacert_entrypoin…" archiva 3 seconds ago Up Less than a second 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp
解读:COMMAND 显示
"/__cacert_entrypoin…"是 temurin 基础镜像入口脚本,它再 exec 我们的./bin/archiva console。
启动日志(wrapper console 模式输出,节选):
docker logs archiva-server 2>&1 | tail -3
Running Apache Archiva...
Running Apache Archiva...
Removed stale pid file: /opt/archiva/logs/archiva.pid
首次启动含 Derby 建库,约 20-30 秒就绪。三个挂载目录随之生成:
ls data repositories logs
data:
databases jcr remotes
logs:
archiva-audit.log archiva.log archiva.pid request-20261013.log wrapper-20261013.log
repositories:
internal repositories snapshots
⚠️
repositories/下除internal、snapshots外还冒出一个嵌套的repositories/repositories/(内含同名空目录):Archiva 首启用相对路径./repositories/internal建仓,部分组件按错误基准目录解析产生的空目录,不影响使用;介意的话可删空目录,或经 REST 把仓库 location 改为绝对路径(见《安装指南》8.5 同款怪癖)。
4.5 初始化管理员
首次部署没有管理员账号,经 REST 初始化(Origin 头的地址端口要与访问 URL 一致,否则静默 403,见 9.2):
curl -s -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' \
-H 'Origin: http://localhost:8080' \
-d '{"username":"admin","password":"q1w2e3r4","confirmPassword":"q1w2e3r4","fullName":"Archiva Administrator","email":"admin@example.org","validated":true,"permanent":true}' \
http://localhost:8080/restServices/redbackServices/userService/createAdminUser
true
curl -s -H 'Origin: http://localhost:8080' \
http://localhost:8080/restServices/redbackServices/userService/isAdminUserExists
true
登录拿会话并列出内置仓库:
curl -s -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' \
-H 'Origin: http://localhost:8080' -c /tmp/archiva-cookie.txt \
-d '{"username":"admin","password":"q1w2e3r4"}' \
http://localhost:8080/restServices/redbackServices/loginService/logIn | head -c 100
{"username":"admin","fullName":"Archiva Administrator","email":"admin@example.org","validated":true,"locked":false,"pass...
TOKEN=$(grep -oP '(?<="validationToken":")[^"]+' /tmp/login.json)
curl -s -b /tmp/archiva-cookie.txt -H 'Origin: http://localhost:8080' -H "X-XSRF-TOKEN: $TOKEN" \
http://localhost:8080/restServices/archivaServices/managedRepositoriesService/getManagedRepositories \
| python3 -c 'import json,sys; [print(r["id"],"->",r["location"]) for r in json.load(sys.stdin)]'
internal -> ./repositories/internal
snapshots -> ./repositories/snapshots
4.6 服务验证
Web 控制台:浏览器访问 http://<宿主机IP>:8080/,用 admin / q1w2e3r4 登录。命令行侧验证首页与免登录 ping 接口:
curl -s -o /dev/null -w "index:%{http_code}\n" http://localhost:8080/
curl -s http://localhost:8080/ | grep -oE '<title>[^<]*</title>'
curl -s -H 'Origin: http://localhost:8080' \
http://localhost:8080/restServices/archivaServices/pingService/ping
index:200
<title>Apache Archiva</title>
Yeah Baby It rocks!
确认容器内 JVM 堆实际生效值(验证 4.2 的 wrapper.conf 固化已生效):
docker exec archiva-server jps -v | grep WrapperSimpleApp | grep -oE '\-Xms[0-9]+m \-Xmx[0-9]+m'
-Xms256m -Xmx512m
五、数据持久化说明
| 数据 | 落盘位置 | 说明 |
|---|---|---|
| Derby 元数据 | 宿主机 ./data/databases/ | 仓库定义、用户、审计等,重启不丢 |
| 内容索引 | 宿主机 ./data/jcr/、./data/remotes/ | jcr 会话工厂索引与远程下载缓存 |
| 制品存储 | 宿主机 ./repositories/ | Maven 布局制品,重建实例不丢 |
| 运行日志 | 宿主机 ./logs/ | archiva.log、wrapper-日期.log、request-日期.log、archiva-audit.log |
| 配置 | 镜像内 /opt/archiva/conf/ | 未挂载;需定制见下方提示 |
验证持久化:重启后管理员与元数据依旧可用:
docker compose restart
sleep 25
docker compose ps
curl -s -H 'Origin: http://localhost:8080' \
http://localhost:8080/restServices/redbackServices/userService/isAdminUserExists
Container archiva-server Restarting
Container archiva-server Started
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
archiva-server archiva:2.2.10 "/__cacert_entrypoin…" archiva About a minute ago Up 25 seconds 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp
true
💡 说明:wrapper.conf 等配置已固化进镜像。若需在宿主机定制配置(如改端口),在
volumes:中追加- ./conf/wrapper.conf:/opt/archiva/conf/wrapper.conf单文件挂载(先docker exec archiva-server cat /opt/archiva/conf/wrapper.conf取出厂底稿),改完docker compose restart生效。
六、环境变量表
Archiva 发行包没有业务语义的环境变量,行为全部由配置文件驱动。与运行相关的环境层面项如下:
| 环境变量/等价配置 | 默认值 | 说明 |
|---|---|---|
appserver.home / appserver.base(wrapper.conf 内置) | . | 安装根;镜像内 WORKDIR 即 /opt/archiva,无需改动 |
jetty.port(系统属性,出厂未设) | 8080 | 需改端口时往 wrapper.conf 加 -Djetty.port=nnnn(见《配置参数详解》5.1) |
| JVM 堆 | 出厂 512/512 | 本文构建期固化为 256/512 |
💡 说明:Archiva 的 JVM 参数不走
JAVA_OPTS/JAVA_TOOL_OPTIONS约定,而是读conf/wrapper.conf的initmemory/maxmemory,所以 Compose 场景下改堆要么构建期 sed 固化(本文方式),要么单文件挂载覆盖 wrapper.conf。
七、配置参数说明
镜像内 /opt/archiva/conf/ 关键配置(出厂值与本文取值):
| 配置 | 文件 | 出厂值 | 本文取值 |
|---|---|---|---|
| JVM 初始/最大堆 | wrapper.conf 的 initmemory/maxmemory | 512 / 512 | 256 / 512 |
| 监听端口 | jetty.xml(jetty.port 默认) | 8080 | 8080(映射即对外端口) |
| 启动方式 | Dockerfile CMD | — | bin/archiva console(前台) |
| 元数据库 | 内嵌 Derby | data/databases | 挂载 ./data 持久化 |
| 本地仓库 | REST/控制台管理 | internal、snapshots | 挂载 ./repositories 持久化 |
| 实例内存上限 | compose mem_limit | 无 | 1g |
各配置项的完整含义、仓库调度与代理参数,见《Apache Archiva 2.2.10 配置参数详解》。
八、配置文件挂载
本方案默认不挂载配置(配置已固化进镜像),两种定制方式按需选择:
- 单文件挂载(推荐):只挂
wrapper.conf或jetty.xml,保留镜像内其余出厂配置。挂载路径必须与镜像内路径一字不差:/opt/archiva/conf/wrapper.conf。 - 重建镜像:团队内统一配置基线时,改 Dockerfile 里的 sed 步骤重新构建,交付物版本化。
修改宿主机文件后需 docker compose restart 生效;确认生效用:
docker exec archiva-server grep -E 'initmemory|maxmemory' /opt/archiva/conf/wrapper.conf
wrapper.java.initmemory=256
wrapper.java.maxmemory=512
九、常见问题
9.1 构建期 RUN wget 下载发行包长时间无进展
现象:Dockerfile 用 RUN wget ... https://archive.apache.org/... 方式构建,docker build 长时间停在下载步骤无输出(实测 18 分钟未完成),构建进程仍在。
定位:构建容器内直连归档站,受网络策略与归档站限速影响,wget -q 静默无进度反馈。
解决:按本文 4.2 的 COPY 方式——先在宿主机下载并校验好 tar.gz 放进构建目录,构建过程完全离线,实测数秒完成。
9.2 REST 请求静默 403(空响应体)
现象:curl http://127.0.0.1:8080/restServices/... 带 Origin: http://localhost:8080 仍返回空、状态 403;首页却正常 200。
定位:Redback 的 CSRF 校验同时看 Origin 头与请求主机是否匹配——用 127.0.0.1 访问但 Origin 写 localhost(或端口对不上)即被拒(实测复现)。
解决:Origin 与访问 URL 的主机端口保持一致;改用 http://localhost:8080 访问 + 同值 Origin 后,ping 正常返回 Yeah Baby It rocks!。改了 compose 对外端口(如 "18080:8080")时,Origin 同步写外部地址(如 http://localhost:18080)。
9.3 启动即退出或反复重启
排查顺序(命令均在宿主机执行):
docker compose ps # 看 STATUS 是否 Restarting
docker logs --tail 30 archiva-server # wrapper console 输出
docker exec archiva-server tail -30 /opt/archiva/logs/archiva.log
docker inspect archiva-server --format '{{.State.OOMKilled}}'
常见根因:挂载目录属主不对(Archiva 以 root 运行,挂载目录 root 可写即可);mem_limit 低于实际需求(堆 256/512 + PermGen 128MB 稳态约 430MB,上限至少 768MB);8080 被宿主机其他进程占用(docker compose up 时直接报 bind failed,换端口映射)。
9.4 制品存储误挂成嵌套目录
现象:想把仓库直接落在宿主机某路径,挂载 ./repositories/internal:/opt/archiva/repositories/internal 后 Archiva 启动报错或目录混乱。
定位:首启要用 ./repositories/internal 相对基准创建内置仓库,把仓库子目录本身挂死会与该逻辑冲突(另见 4.4 的嵌套目录怪癖)。
解决:挂 ./repositories 父目录(本文方式),首启完成后再按需把自建仓库 location 指到挂载目录内的子路径(绝对路径)。
十、参考链接
- 归档下载目录(2.2.10 binaries):https://archive.apache.org/dist/archiva/2.2.10/binaries/
- 官方管理指南(2.2.10):https://archiva.apache.org/docs/2.2.10/adminguide/
- Compose 文件参考:https://docs.docker.com/compose/
- eclipse-temurin 镜像:https://hub.docker.com/_/eclipse-temurin
- Apache Attic 项目页:https://attic.apache.org/projects/archiva.html