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_64 | Ubuntu 24.04 x86_64 |
| CPU | 2 核 | 4 核或以上 |
| 内存 | 4 GB | 8 GB 或以上 |
| 磁盘 | 30 GB | 50 GB 或以上 SSD |
| Docker | Docker Engine 当前稳定版 | Docker Engine 当前稳定版 |
| Compose | Docker 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 工作负载的服务器上,为了安装而直接卸载 docker、containerd 或修改 /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 加速器是否通常覆盖 |
|---|---|---|
| PostgreSQL | postgres:15-alpine | 是 |
| Nginx | nginx:1.27-alpine | 是 |
| API 基础镜像 | python:3.10-slim-bookworm | 是 |
| Web 基础镜像 | node:20.11-alpine3.19 | 是 |
| BuildKit Dockerfile 前端 | docker/dockerfile:1 | 是 |
| Weaviate | cr.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-alpine、nginx:1.27-alpine、python:3.10-slim-bookworm、node:20.11-alpine3.19 与 docker/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 时,至少替换下列敏感配置:
| 类别 | 需要处理的配置 |
|---|---|
| PostgreSQL | DB_PASSWORD;首次启动前确认 DB_USERNAME、DB_DATABASE |
| 应用与 SSO | SECRET_KEY、SSO_SECRET_KEY |
| 数据源连接信息加密 | CONNECT_INFO_MASTER_KEY |
| 对外访问 | PUBLIC_BASE_URL、ALLOWED_ORIGINS、NGINX_SERVER_NAME、NGINX_HOST_PORT |
| 资源与日志 | GUNICORN_、WORKER_MEMORY_LIMIT_MB、LOG_ |
Docker Compose 会强制 API 使用 Docker 服务名:
DB_HOST=onticards-db
WEAVIATE_URL=http://onticards-weaviate:8080
不要把它们改成宿主机 IP 或外部 IP。API 与数据库/向量库在 onticards 网络内通过服务名解析;外部访问应始终经过 Nginx。
首次初始化后,./volumes/postgresql/data 已经存在时,再修改 DB_USERNAME、DB_PASSWORD 或 DB_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_URL 和 ALLOWED_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_URL 和 ALLOWED_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 |
常见问题:
- 镜像拉取超时或
i/o timeout:先按第 3 章配置受控镜像加速器或私有仓库;Weaviate 与构建软件源需要单独处理。 - API 容器反复重启:执行
docker compose logs --tail=300 onticards_api,检查数据库初始化、配置项、外部模型服务或可用内存。当前编排没有健康检查,因此没有/healthz轮询日志。 - 刚启动时短暂 502:由于仅保证容器启动顺序,数据库/API 初次初始化期间可能尚未接受请求;等待日志完成后再访问。
- 域名能解析但浏览器请求失败:核对
PUBLIC_BASE_URL、ALLOWED_ORIGINS、外层反向代理的Host/X-Forwarded-*头及云安全组规则。 - 磁盘空间不足:先用
docker system df查看 Docker 占用,再制定保留镜像与构建缓存的清理方案;不要在不了解影响的情况下执行全局清理命令。
8. 上线前检查清单
- [ ] 已使用 Docker Engine 与 Compose v2,并通过
docker compose version验证。 - [ ]
.env已创建且权限受限,生产密码与密钥均已替换。 - [ ]
DB_HOST=onticards-db和WEAVIATE_URL=http://onticards-weaviate:8080保持 Docker 服务名。 - [ ] 只开放 Nginx 对应的宿主机端口;数据库、API、Web、Weaviate 未直接暴露公网。
- [ ] 已为生产环境准备可信的私有镜像仓库或经过验证的镜像加速方案。
- [ ] 已验证 APT、PyPI、Yarn/NPM、Microsoft/Oracle 等构建依赖的网络策略。
- [ ] 已备份
volumes/目录与.env,并验证恢复流程。 - [ ] 已配置域名、HTTPS、云安全组和日志监控。