文档中心 / OntiCards Docker Compose 部署指南

OntiCards Docker Compose 部署指南

本文档适用于仓库根目录的 compose.yaml。生产环境推荐部署在 x86_64(amd64)Linux 服务器;项目 API 镜像包含 amd64 版的 Microsoft ODBC 与 Oracle Instant Client 依赖,ARM 服务器需要另行适配。

1. 部署前准备

1.1 资源与网络要求

项目最低配置生产建议
操作系统Ubuntu 22.04 / 24.04 x86_64Ubuntu 24.04 x86_64
CPU2 核4 核或以上
内存4 GB8 GB 或以上
磁盘30 GB50 GB 或以上 SSD
DockerDocker Engine 当前稳定版Docker Engine 当前稳定版
ComposeDocker Compose v2.24.0+ 插件Docker Compose 当前稳定版插件

请确保服务器可以访问所需的镜像仓库、软件源和模型服务。首次构建 API 与 Web 除了拉取容器镜像,还可能访问 Debian APT、PyPI、Yarn/NPM、Microsoft 软件源和 Oracle 下载站;只配置 Docker 镜像加速器并不能解决这些构建依赖的网络问题。

仅 Nginx 会向宿主机暴露端口,默认是 9107。PostgreSQL、Weaviate、API 与 Web 仅在 Docker 内部网络中通信,不需要、也不应单独暴露到公网。

Docker 发布的端口可能绕过 UFW/firewalld 的常规规则。生产环境应同时限制云安全组和主机防火墙,并只开放实际需要的 Nginx 主机端口。参见 Docker 的防火墙说明

1.2 当前服务拓扑

onticards-db + onticards-weaviate
              ↓
      onticards_api + onticards_web
              ↓
        onticards_nginx :9107
              ↓
          浏览器 / 外层反向代理

Compose 会自动创建名为 onticards 的 bridge 网络,不需要预先执行 docker network create。启动顺序是"数据库与向量库容器先启动 → API 与 Web 容器启动 → Nginx 容器启动"。

本项目没有 Docker healthcheck,因此不会定时请求 /healthz 并刷应用日志。service_started 只保证容器启动顺序,不代表数据库或 API 已完成初始化;请以 docker compose ps 与服务日志判断实际状态。

2. 安装 Docker 与 Docker Compose

2.1 已有 Docker 的服务器

先检查版本:

docker --version
docker compose version

若命令正常且 Compose 为 v2.24.0 或更高版本,跳过安装步骤。当前编排使用了 env_file.required 长语法,该字段要求 Docker Compose 2.24.0+。不要在正在运行其他 Docker 工作负载的服务器上,为了安装而直接卸载 dockercontainerd 或修改 /etc/docker/daemon.json;先评估现有容器与运维窗口。

2.2 Ubuntu 22.04 / 24.04:使用 Docker 官方 APT 仓库

以下步骤适用于全新 Ubuntu 服务器。命令来自 Docker Engine 官方 Ubuntu 安装文档

sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker

验证安装:

sudo docker run --rm hello-world
docker compose version

Docker 官方安装包已经包含 docker-compose-plugin,日常命令请使用 docker compose,不要使用已归为 legacy 的独立版 docker-compose。参见 Compose 安装说明

如需让非 root 用户执行 Docker 命令,可执行:

sudo usermod -aG docker "$USER"
newgrp docker

docker 用户组等同于获得主机 root 级能力;生产服务器应按最小权限原则授权。详见 Docker Linux post-installation

2.3 RHEL / Rocky / AlmaLinux

请使用对应发行版的 Docker 官方安装流程,不要套用 Ubuntu 的 APT 命令。RHEL 8/9/10 可参考 Docker Engine on RHEL;安装完成后同样应确认:

docker --version
docker compose version
sudo systemctl enable --now docker

2.4 Windows 开发机

Windows 本地开发建议安装 Docker Desktop for Windows,选择 Linux containers 与 WSL 2 后端。Docker Desktop 已自带 Docker Engine、CLI 与 Compose;安装后在 PowerShell 中验证:

docker version
docker compose version

Windows Docker Desktop 与 Linux 服务器的镜像加速配置位置不同,见下文"国内/企业镜像仓库"章节。

3. 国内或企业镜像仓库

3.1 先判断是哪一类拉取失败

资源当前来源Docker Hub 加速器是否通常覆盖
PostgreSQLpostgres:15-alpine
Nginxnginx:1.27-alpine
API 基础镜像python:3.10-slim-bookworm
Web 基础镜像node:20.11-alpine3.19
BuildKit Dockerfile 前端docker/dockerfile:1
Weaviatecr.weaviate.io/semitechnologies/weaviate:1.36.0否,需单独同步或代理
APT / pip / Yarn / Oracle 等构建依赖各自的软件源

Docker 的 registry-mirrors 是 Docker Hub 的镜像加速机制,不能自动代理 cr.weaviate.io 等其他 Registry。不要使用来源不明的公共镜像站;镜像可能过期、失效或带来供应链风险。

3.2 开发/测试:配置云厂商专属 Docker Hub 加速器

在阿里云等云厂商控制台获取自己账号对应的加速地址。以 阿里云 ACR 镜像加速器 为例,控制台会生成专属地址;该服务的官方说明将其定位为个人开发场景,生产环境应使用镜像同步或私有仓库。

在 Linux Docker Engine 上,先备份已有配置;若 /etc/docker/daemon.json 已存在,必须将下列字段合并到原有 JSON 中,不能覆盖其他配置:

sudo install -d -m 0755 /etc/docker
sudo test ! -f /etc/docker/daemon.json || \
  sudo cp -a /etc/docker/daemon.json "/etc/docker/daemon.json.bak.$(date +%Y%m%d%H%M%S)"
sudoedit /etc/docker/daemon.json

填写从云厂商控制台获得的真实地址:

{
  "registry-mirrors": [
    "https://<云厂商或企业分配的加速地址>"
  ]
}

在维护窗口重启 Docker 并验证。重启 Docker 可能中断正在运行的容器:

sudo systemctl daemon-reload
sudo systemctl restart docker
docker info | sed -n '/Registry Mirrors:/,/Live Restore:/p'
docker pull nginx:1.27-alpine

Docker 的 registry-mirrors 配置格式见 dockerd 官方参考Docker Hub mirror 说明

在 Docker Desktop 中,不要修改 Linux 的 /etc/docker/daemon.json。打开 Settings → Docker Engine,将同一 JSON 字段合并进去,再点击 Apply & Restart

3.3 生产环境:同步到受控的国内/企业私有仓库

推荐在可访问海外镜像的 CI 或构建机中,先验证并同步所需镜像到企业 ACR/TCR/SWR/Harbor,再让生产服务器只访问受控的国内或内网仓库。请固定版本或 digest,不要将 latest 用于生产。

以 Weaviate 为例,以下命令必须在能访问 cr.weaviate.io 的机器执行:

docker pull cr.weaviate.io/semitechnologies/weaviate:1.36.0
docker tag cr.weaviate.io/semitechnologies/weaviate:1.36.0 \
  registry.example.com/onticards/weaviate:1.36.0
docker login registry.example.com
docker push registry.example.com/onticards/weaviate:1.36.0

同样同步 postgres:15-alpinenginx:1.27-alpinepython:3.10-slim-bookwormnode:20.11-alpine3.19docker/dockerfile:1。不要随意改变 Weaviate 的版本;当前 Compose 版本与项目依赖的 Weaviate client 相匹配。

为避免直接修改仓库的主编排文件,可在根目录创建仅供本环境使用的 compose.images.override.yaml

services:
  onticards-db:
    image: registry.example.com/onticards/postgres:15-alpine

  onticards-weaviate:
    image: registry.example.com/onticards/weaviate:1.36.0

  onticards_nginx:
    image: registry.example.com/onticards/nginx:1.27-alpine

使用覆盖文件启动:

docker compose -f compose.yaml -f compose.images.override.yaml config -q
docker compose -f compose.yaml -f compose.images.override.yaml up -d --build

生产服务器从私有仓库拉取镜像前,同样需要登录(或由企业凭据系统提供凭据):

docker login registry.example.com

建议使用只具备拉取权限的机器人账号或凭据助手;不要把用户名、密码、AccessKey 或 token 写进 Git、.env.prod、Compose 文件或覆盖文件。

API 和 Web 会从源码构建;若 Docker Hub 完全不可达,还需把两个 Dockerfile 的基础镜像改为企业仓库地址:

# OntiCards_Api/Dockerfile
FROM registry.example.com/onticards/python:3.10-slim-bookworm AS base

# OntiCards_Web/Dockerfile
FROM registry.example.com/onticards/node:20.11-alpine3.19 AS base

API Dockerfile 首行的 # syntax=docker/dockerfile:1 也依赖 Docker Hub 的 BuildKit 前端。完全离线时,应将该镜像同步到企业仓库并改为对应的私有仓库地址,或者在联网构建机上预构建 API/Web 镜像后推送到企业仓库。

3.4 无外网环境

最可靠的方式是在联网构建机执行镜像构建与导出,在离线服务器导入:

# 联网构建机:先完成 docker compose build 和所需 docker pull
docker save -o onticards-images.tar \
  onticards-api:local onticards-web:local \
  postgres:15-alpine nginx:1.27-alpine \
  cr.weaviate.io/semitechnologies/weaviate:1.36.0

# 离线服务器
docker load -i onticards-images.tar

# 已导入 API/Web 镜像时,禁止 Compose 再次触发源码构建
docker compose up -d --no-build --pull never

离线服务器还需拥有与构建机相同的项目源码、镜像标签和运行配置。长期生产使用仍推荐企业私有仓库,而不是手工传输镜像 tar 包。

4. 获取代码与配置环境变量

git clone https://github.com/stepll2026/OntiCards.git
cd OntiCards

根目录的 .env.prod 是可直接启动的开发/测试默认配置。生产部署请创建未提交的 .env 覆盖文件:

cp .env.prod .env
chmod 600 .env

编辑 .env 时,至少替换下列敏感配置:

类别需要处理的配置
PostgreSQLDB_PASSWORD;首次启动前确认 DB_USERNAMEDB_DATABASE
应用与 SSOSECRET_KEYSSO_SECRET_KEY
数据源连接信息加密CONNECT_INFO_MASTER_KEY
对外访问PUBLIC_BASE_URLALLOWED_ORIGINSNGINX_SERVER_NAMENGINX_HOST_PORT
资源与日志GUNICORN_WORKER_MEMORY_LIMIT_MBLOG_

Docker Compose 会强制 API 使用 Docker 服务名:

DB_HOST=onticards-db
WEAVIATE_URL=http://onticards-weaviate:8080

不要把它们改成宿主机 IP 或外部 IP。API 与数据库/向量库在 onticards 网络内通过服务名解析;外部访问应始终经过 Nginx。

首次初始化后,./volumes/postgresql/data 已经存在时,再修改 DB_USERNAMEDB_PASSWORDDB_DATABASE 不会自动修改已有 PostgreSQL 的账号、密码或数据库名称。变更前先备份并按 PostgreSQL 迁移流程操作。

域名与端口示例

NGINX_SERVER_NAME=onticards.example.com
NGINX_HOST_PORT=9107
PUBLIC_BASE_URL=https://onticards.example.com
ALLOWED_ORIGINS=https://onticards.example.com

NGINX_SERVER_NAME 只是 Nginx 的 server_name 槽位;它不会自动签发 HTTPS 证书,也不是访问白名单。ALLOWED_ORIGINS 是浏览器 CORS 来源列表,不是 IP 访问控制。

5. 启动与验证

5.1 首次启动

docker compose config -q
docker compose up -d --build
docker compose ps

docker compose config -q 只校验配置,不会启动容器。首次执行 up -d --build 会构建 API 和 Web 镜像,并启动五个服务。

查看日志时按服务筛选,避免无关日志淹没问题:

docker compose logs --tail=200 onticards_api
docker compose logs --tail=200 onticards_web
docker compose logs --tail=200 onticards_nginx

访问入口:

http://<服务器 IP 或域名>:9107/

可以只检查 Nginx 首页连通性,不要使用 /healthz

curl -I http://127.0.0.1:9107/

5.2 端口 9107 被占用

检查端口:

sudo ss -lntp | grep ':9107'

在根目录 .env 中换一个宿主机端口,例如:

NGINX_HOST_PORT=19107

然后重新应用配置:

docker compose up -d

容器内 Nginx 始终监听 9107,只改变宿主机映射端口。此时对外地址、PUBLIC_BASE_URLALLOWED_ORIGINS 也应改成实际公开地址。

5.3 域名与 HTTPS

建议让云负载均衡或宿主机已有的 Nginx/Caddy 负责证书与 443,再反向代理到 OntiCards 的宿主机端口:

server {
    listen 80;
    server_name onticards.example.com;

    location / {
        proxy_pass http://127.0.0.1:9107;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

配置证书后,将 PUBLIC_BASE_URLALLOWED_ORIGINS 改为 https://onticards.example.com。不要在未配置证书的情况下把 HTTPS 地址写入这两个变量。

6. 数据持久化、备份与升级

本项目使用宿主机绑定挂载,而不是 Docker named volumes。需要纳入备份的目录是:

volumes/postgresql/data/
volumes/weaviate/data/
volumes/governance/reports/
.env

PostgreSQL 运行中时,使用逻辑导出以保证一致性:

mkdir -p backups
docker compose exec -T onticards-db \
  sh -c 'pg_dumpall -U "$POSTGRES_USER"' \
  > backups/postgresql-$(date +%F).sql

Weaviate 的文件级备份应在服务停止后执行,避免得到不一致的数据文件:

docker compose stop onticards_api onticards_web onticards_nginx onticards-weaviate
tar -C volumes/weaviate -czf backups/weaviate-$(date +%F).tar.gz data
docker compose up -d

治理报告可按文件备份;若业务正在生成报告,为获得时间点一致性也应在低峰期或停写窗口执行:

tar -C volumes/governance -czf backups/governance-reports-$(date +%F).tar.gz reports

如必须做 PostgreSQL 数据目录的物理文件级备份,应先停止数据库及其依赖服务,或使用经过验证的存储快照方案;不要对运行中的 volumes/postgresql/data 直接执行 tar

docker compose down 会停止并删除容器与网络,但不会删除上述宿主机数据目录。不要在未备份的情况下手工删除这些目录。

升级应用:

git pull --ff-only
# 手工对比 .env.prod 的新增项,不要覆盖已有 .env 中的生产密钥。
docker compose config -q
docker compose up -d --build
docker compose ps

7. 常用运维与故障排查

场景命令或处理方式
查看状态docker compose ps
查看全部日志docker compose logs -f
查看 API 日志docker compose logs -f onticards_api
查看 Web 日志docker compose logs -f onticards_web
重启单个服务docker compose restart onticards_api
停止整套服务docker compose down
重新创建容器docker compose up -d --force-recreate
配置渲染检查docker compose config -q

常见问题:

  1. 镜像拉取超时或 i/o timeout:先按第 3 章配置受控镜像加速器或私有仓库;Weaviate 与构建软件源需要单独处理。
  2. API 容器反复重启:执行 docker compose logs --tail=300 onticards_api,检查数据库初始化、配置项、外部模型服务或可用内存。当前编排没有健康检查,因此没有 /healthz 轮询日志。
  3. 刚启动时短暂 502:由于仅保证容器启动顺序,数据库/API 初次初始化期间可能尚未接受请求;等待日志完成后再访问。
  4. 域名能解析但浏览器请求失败:核对 PUBLIC_BASE_URLALLOWED_ORIGINS、外层反向代理的 Host/X-Forwarded-* 头及云安全组规则。
  5. 磁盘空间不足:先用 docker system df 查看 Docker 占用,再制定保留镜像与构建缓存的清理方案;不要在不了解影响的情况下执行全局清理命令。

8. 上线前检查清单

  • [ ] 已使用 Docker Engine 与 Compose v2,并通过 docker compose version 验证。
  • [ ] .env 已创建且权限受限,生产密码与密钥均已替换。
  • [ ] DB_HOST=onticards-dbWEAVIATE_URL=http://onticards-weaviate:8080 保持 Docker 服务名。
  • [ ] 只开放 Nginx 对应的宿主机端口;数据库、API、Web、Weaviate 未直接暴露公网。
  • [ ] 已为生产环境准备可信的私有镜像仓库或经过验证的镜像加速方案。
  • [ ] 已验证 APT、PyPI、Yarn/NPM、Microsoft/Oracle 等构建依赖的网络策略。
  • [ ] 已备份 volumes/ 目录与 .env,并验证恢复流程。
  • [ ] 已配置域名、HTTPS、云安全组和日志监控。