主题
Linux 部署(Docker)
服务器已经装有 Docker、希望统一用容器管理时使用。镜像由交付包里的 Dockerfile 在你自己的服务器上构建,不需要访问任何镜像仓库之外的外部服务。
使用交付包:linux-amd64.zip(只有 Linux 包带 Dockerfile 和 docker-compose.yml)。
1. 准备
1.1 环境要求
| 项 | 要求 |
|---|---|
| Docker | 20.10 及以上 |
| Compose | Docker Compose v2(命令是 docker compose,不是 docker-compose) |
| 网络 | 构建镜像时需要能拉取 ubuntu:24.04 并执行 apt-get;内网环境请先配置镜像加速或私有仓库 |
bash
docker version
docker compose version1.2 放置文件
bash
sudo mkdir -p /opt/apexpm
sudo tar xzf /tmp/acme-apexpm-vX.Y.Z.tar.gz -C /opt/apexpm --strip-components=1
cd /opt/apexpm
sudo chmod +x apexpm常见错误
| 现象 | 原因 | 处理 |
|---|---|---|
docker: 'compose' is not a docker command | 装的是旧版独立 docker-compose | 安装 Compose v2 插件(docker-compose-plugin),或把下文命令里的 docker compose 换成 docker-compose |
permission denied while trying to connect to the Docker daemon socket | 当前用户不在 docker 组 | 命令前加 sudo,或 sudo usermod -aG docker $USER 后重新登录 |
2. 配置
bash
cd /opt/apexpm
cp config.example.yaml config.yaml
vi config.yamlconfig.yaml 必须在启动前存在
docker-compose.yml 把 ./config.yaml 以只读方式挂载进容器。文件不存在时 Docker 会自动创建一个同名目录,程序随后读不到配置、以默认值启动。遇到这种情况先 docker compose down,rm -rf config.yaml 删掉这个目录,再复制模板。
Docker 部署时需要特别注意的字段:
| 字段 | 说明 |
|---|---|
jwt.secret | 必改,同其他部署方式 |
server.port | 容器使用 host 网络,程序直接监听宿主机的这个端口,不需要也不能配 ports 映射。改了端口的话,镜像内置的健康检查仍然检查 9000,需要在 compose 里覆盖(见下文) |
server.public_base_url | 填宿主机的内网地址 |
license.path | 保持默认 ./data/license.lic。容器内工作目录是 /app,./data 挂载自宿主机的 /opt/apexpm/data |
database.* | 连同机的数据库容器时,主机写 127.0.0.1 加映射出来的端口,不能写 compose 服务名,因为 apexpm 走的是 host 网络 |
数据库密码不想写进文件时,可以用环境变量注入(仅数据库相关键支持),在 docker-compose.yml 的 apexpm 服务下加:
yaml
environment:
APEXPM_DATABASE_DRIVER: postgres
APEXPM_DATABASE_DSN: "postgres://apexpm:密码@127.0.0.1:5432/apexpm?sslmode=disable"字段完整说明见配置文件 config.yaml。
docker-compose.yml 说明
yaml
services:
apexpm:
image: apexpm:latest
build: . # 用同目录 Dockerfile 构建
network_mode: host # 不能改,见下
volumes:
- ./data:/app/data # 数据库、附件、授权文件
- ./config.yaml:/app/config.yaml:ro
restart: unless-stopped # 崩溃和开机后自动拉起network_mode: host 不能改成 bridge
授权校验读取的是本机网卡 IP。bridge 网络下容器只能看到 172.x.x.x 的容器地址,会被直接判为「IP 未授权」。
改了 server.port(例如改成 8080)时,在 apexpm 服务下覆盖健康检查:
yaml
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"]
interval: 30s
timeout: 5s
start_period: 15s3. 启动
bash
cd /opt/apexpm
docker compose up -d --build
docker compose ps # STATUS 应在 15 秒后变为 (healthy)
docker compose logs -f验证:
bash
curl -fsS http://127.0.0.1:9000/health
curl -fsS http://127.0.0.1:9000/api/v1/license/status日常操作:
bash
docker compose restart # 改完 config.yaml 后
docker compose stop # 停止
docker compose down # 停止并删除容器(data/ 不受影响)
docker compose logs --tail 100 # 最近日志常见错误
| 现象 | 原因 | 处理 |
|---|---|---|
构建时 failed to resolve source metadata for docker.io/library/ubuntu:24.04 | 服务器拉不到 Docker Hub | 配置镜像加速(/etc/docker/daemon.json 的 registry-mirrors),或在能联网的机器上 docker pull ubuntu:24.04 后 docker save / docker load 导入 |
构建时 apt-get update 失败 | 构建阶段无法访问 Ubuntu 软件源 | 配置代理,或在 Dockerfile 的 apt-get 前把源替换为内网镜像站 |
Error response from daemon: ... not a directory / 日志显示用了默认配置 | 启动前 config.yaml 不存在,被建成了目录 | 见上文红框处理 |
docker compose ps 显示 (unhealthy) | 程序没在 9000 端口响应:启动失败,或改了端口但没覆盖健康检查 | docker compose logs --tail 50 看 fatal 日志;改过端口的按上文覆盖 healthcheck |
容器状态 Restarting | 程序启动即退出,被 restart 反复拉起 | docker compose logs --tail 50,对照故障排查总表 |
create data dir failed: permission denied | 宿主机 data/ 目录权限不对,或开启了 SELinux | sudo chown -R root:root data(容器内以 root 运行);SELinux 下把卷改成 ./data:/app/data:Z |
授权状态 IP 未授权 | 改成了 bridge 网络,或服务器 IP 与签发时不一致 | 恢复 network_mode: host;ip -4 addr 取真实 IP 联系我方 |
连数据库报 connection refused,DSN 写的是 postgres 这种服务名 | host 网络下无法解析 compose 服务名 | 改成 127.0.0.1:映射端口 |
可选:同机运行数据库
docker-compose.yml 末尾有注释掉的 PostgreSQL / MySQL 示例,取消注释并修改密码即可。数据库容器使用自己的数据卷(./data/postgres、./data/mysql),与 apexpm 的数据在同一个 data/ 目录下,备份时一起带走。
WARNING
数据库容器用的是端口映射(ports: ["5432:5432"]),会对外暴露端口。只在内网使用时,改成 "127.0.0.1:5432:5432"。
升级
bash
cd /opt/apexpm
docker compose down
cp -a data "data.bak-$(date +%Y%m%d-%H%M%S)" # 必做
unzip -o /tmp/linux-amd64.zip apexpm Dockerfile -d . # 只换二进制与 Dockerfile
chmod +x apexpm
docker compose up -d --build # 必须带 --build,否则还是旧镜像
docker compose logs -f必须带 --build
镜像是用包内二进制构建的。只替换文件不重建镜像,跑起来的仍是旧版本。升级后用 curl -fsS http://127.0.0.1:9000/health 确认返回的 version 是新版本号。
新版本的 docker-compose.yml 有变化时(看版本说明的「升级注意」),手工合并,不要直接覆盖你改过的部分。
完整说明与回滚见版本升级。
清理旧镜像
每次 --build 都会留下一个无标签的旧镜像:
bash
docker image prune -f