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、云安全組和日誌監控。