fix(avatar): 杜绝发布后继续运行旧镜像 #24
@@ -12,14 +12,15 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: sqlite:////app/avatar.db
|
DATABASE_URL: sqlite:////data/db/avatar.db
|
||||||
UPLOAD_DIR: /app/uploads
|
UPLOAD_DIR: /data/uploads
|
||||||
CHAT_MODEL_CONFIG_URL: http://host.docker.internal:8000/api/ai-models/runtime/digital-avatar
|
CHAT_MODEL_CONFIG_URL: http://host.docker.internal:8000/api/ai-models/runtime/digital-avatar
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.docker.internal:host-gateway"
|
- "host.docker.internal:host-gateway"
|
||||||
volumes:
|
volumes:
|
||||||
- ${AVATAR_DB_PATH:?AVATAR_DB_PATH must point to the persistent avatar.db}:/app/avatar.db
|
# Mount the directory, not only avatar.db: SQLite WAL/SHM files must survive recreation.
|
||||||
- ${AVATAR_UPLOAD_DIR:?AVATAR_UPLOAD_DIR must point to persistent uploads}:/app/uploads
|
- ${AVATAR_DB_DIR:?AVATAR_DB_DIR must contain the persistent avatar.db}:/data/db
|
||||||
|
- ${AVATAR_UPLOAD_DIR:?AVATAR_UPLOAD_DIR must point to persistent uploads}:/data/uploads
|
||||||
expose:
|
expose:
|
||||||
- "8000"
|
- "8000"
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -61,10 +61,10 @@ WECHAT_VIRTUAL_PRODUCT_2=<100元套餐商品ID>
|
|||||||
WECHAT_VIRTUAL_PRODUCT_3=<1000元套餐商品ID>
|
WECHAT_VIRTUAL_PRODUCT_3=<1000元套餐商品ID>
|
||||||
WECHAT_VIRTUAL_PRODUCT_4=<10000元套餐商品ID>
|
WECHAT_VIRTUAL_PRODUCT_4=<10000元套餐商品ID>
|
||||||
|
|
||||||
AVATAR_DB_PATH=/srv/digital-avatar/data/avatar.db
|
AVATAR_DB_DIR=/srv/digital-avatar/data/db
|
||||||
AVATAR_UPLOAD_DIR=/srv/digital-avatar/data/uploads
|
AVATAR_UPLOAD_DIR=/srv/digital-avatar/data/uploads
|
||||||
DATABASE_URL=sqlite:////app/avatar.db
|
DATABASE_URL=sqlite:////data/db/avatar.db
|
||||||
UPLOAD_DIR=/app/uploads
|
UPLOAD_DIR=/data/uploads
|
||||||
CHAT_MODEL_CONFIG_URL=http://<huihuisquare-api>/api/ai-models/runtime/digital-avatar
|
CHAT_MODEL_CONFIG_URL=http://<huihuisquare-api>/api/ai-models/runtime/digital-avatar
|
||||||
EMBEDDING_API_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
|
EMBEDDING_API_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
|
||||||
EMBEDDING_API_KEY=<production-embedding-api-key>
|
EMBEDDING_API_KEY=<production-embedding-api-key>
|
||||||
@@ -86,7 +86,7 @@ CHAT_ATTACHMENT_CLEANUP_MINUTES=60
|
|||||||
|
|
||||||
如生产 AI 配置中心不可用,还应提供当前项目支持的 `OPENAI_API_KEY`、`OPENAI_BASE_URL`、`CHAT_MODEL` 等兜底配置。数据库文件与上传目录必须从宿主机显式挂载,不能存放在容器临时层。
|
如生产 AI 配置中心不可用,还应提供当前项目支持的 `OPENAI_API_KEY`、`OPENAI_BASE_URL`、`CHAT_MODEL` 等兜底配置。数据库文件与上传目录必须从宿主机显式挂载,不能存放在容器临时层。
|
||||||
|
|
||||||
`AVATAR_DB_PATH` 和 `AVATAR_UPLOAD_DIR` 必须是已备份的宿主机绝对路径,编排缺少任一变量都会直接拒绝构建或启动,防止误挂空卷造成用户、分身或知识库“丢失”的假象。
|
`AVATAR_DB_DIR` 和 `AVATAR_UPLOAD_DIR` 必须是已备份的宿主机绝对路径,编排缺少任一变量都会直接拒绝构建或启动,防止误挂空卷造成用户、分身或知识库“丢失”的假象。SQLite 必须挂载整个数据库目录,不能只挂载 `avatar.db` 单文件,否则 `avatar.db-wal` 和 `avatar.db-shm` 会留在容器临时层,换容器后可能出现数据状态回退。
|
||||||
|
|
||||||
`EMBEDDING_API_URL` 同时支持 OpenAI 兼容基础地址(如上面的 `/v1`)和完整的 `/v1/embeddings` 地址,后端会统一请求 `/embeddings`。发布后必须在后端容器内执行一次最小向量探针,确认返回向量数量和维度,而不能只检查 `/api/health`。
|
`EMBEDDING_API_URL` 同时支持 OpenAI 兼容基础地址(如上面的 `/v1`)和完整的 `/v1/embeddings` 地址,后端会统一请求 `/embeddings`。发布后必须在后端容器内执行一次最小向量探针,确认返回向量数量和维度,而不能只检查 `/api/health`。
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ App 与 H5 积分充值使用会会支付体系的 `payment-v3/payment/pay`,
|
|||||||
```bash
|
```bash
|
||||||
BACKUP_DIR="backups/$(date +%Y%m%d-%H%M%S)"
|
BACKUP_DIR="backups/$(date +%Y%m%d-%H%M%S)"
|
||||||
mkdir -p "$BACKUP_DIR"
|
mkdir -p "$BACKUP_DIR"
|
||||||
cp /srv/digital-avatar/data/avatar.db "$BACKUP_DIR/"
|
cp /srv/digital-avatar/data/db/avatar.db "$BACKUP_DIR/"
|
||||||
tar -C /srv/digital-avatar/data -czf "$BACKUP_DIR/uploads.tgz" uploads
|
tar -C /srv/digital-avatar/data -czf "$BACKUP_DIR/uploads.tgz" uploads
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ python3 scripts/verify-deployment.py \
|
|||||||
https://digital.99hui.com "$APP_GIT_SHA" \
|
https://digital.99hui.com "$APP_GIT_SHA" \
|
||||||
--backend-container avatar-backend \
|
--backend-container avatar-backend \
|
||||||
--frontend-container avatar-frontend \
|
--frontend-container avatar-frontend \
|
||||||
--expected-db-source /srv/digital-avatar/data/avatar.db \
|
--expected-db-source /srv/digital-avatar/data/db \
|
||||||
--expected-upload-source /srv/digital-avatar/data/uploads
|
--expected-upload-source /srv/digital-avatar/data/uploads
|
||||||
docker compose exec avatar-backend python -c 'import embeddings; v=embeddings.embed(["部署向量探针"]); print(len(v), len(v[0]))'
|
docker compose exec avatar-backend python -c 'import embeddings; v=embeddings.embed(["部署向量探针"]); print(len(v), len(v[0]))'
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ def main():
|
|||||||
parser.add_argument("expected_sha", help="Full Git commit SHA being deployed")
|
parser.add_argument("expected_sha", help="Full Git commit SHA being deployed")
|
||||||
parser.add_argument("--backend-container", help="Backend container name for image and mount checks")
|
parser.add_argument("--backend-container", help="Backend container name for image and mount checks")
|
||||||
parser.add_argument("--frontend-container", help="Frontend container name for image checks")
|
parser.add_argument("--frontend-container", help="Frontend container name for image checks")
|
||||||
parser.add_argument("--expected-db-source", help="Required host source mounted as the SQLite database")
|
parser.add_argument("--expected-db-source", help="Required host directory mounted for SQLite and its WAL files")
|
||||||
parser.add_argument("--expected-upload-source", help="Required host source mounted as the upload directory")
|
parser.add_argument("--expected-upload-source", help="Required host source mounted as the upload directory")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user