Files
order_site/.env.server.example
T
yml2213 56ca479c6b chore(deploy): 基础镜像源改为可配置 BASE_REGISTRY,并提前补齐 FROM 基础镜像
## 修的是什么

线上部署卡死过一次:daocloud 加速源返回 502 Bad Gateway,整轮构建在 load metadata
阶段就失败,而服务器 daemon.json 里另外两个 registry-mirrors 完全帮不上忙。

原因是**显式写死的 registry 会绕过 daemon.json 的 registry-mirrors**:
Dockerfile 里 `FROM docker.m.daocloud.io/library/node:...` 属于显式指定 registry,
镜像列表对它就失效了,于是这个源成了构建的单点故障。

## 修法

1. 四个 Dockerfile(backend / frontend / backend-dev / dev-caddy)的 `FROM` 改用
   `${BASE_REGISTRY}`(registry 前缀语义),默认值 docker.m.daocloud.io 保持不变;
2. docker-compose.yml / docker-compose.dev.yml 的 `build.args` 接上
   `${BASE_REGISTRY:-docker.m.daocloud.io}`,并把 postgres / minio / node / caddy
   这几处 `image:` 也改成同一变量,整套编排只有一个换源开关;
3. 部署脚本:新增 resolve_base_registry()(读 .env 的 BASE_REGISTRY,缺省同 compose),
   --dry-run 的基础镜像 digest 预检沿用同一变量;
   新增 ensure_dockerfile_base_images(),在 pull_base_images 阶段把 Dockerfile 里
   `FROM` 用到的基础镜像提前补齐 —— 这类镜像不归 `docker compose pull` 管,
   本地缺失要拖到构建阶段才报错,且报错信息晦涩,看不出来是"源挂了"还是"代码写错了";
   现在缺失时明确提示并给出换源/离线搬运两条排障路径;
4. .env.server.example 增加 BASE_REGISTRY 说明(推荐多源容灾时设 docker.io,
   走 daemon 的 registry-mirrors 列表自动故障转移)。

## 验证

- docker compose config:默认值下所有镜像引用与改动前逐字一致(不会触发重新下载);
  BASE_REGISTRY=docker.1panel.live / docker.io 时全部引用正确替换;
- docker buildx build --call=check -f deploy/docker/backend.Dockerfile:Check complete, no warnings;
- deploy/ubuntu-deploy.sh bash -n 通过;
- 生产实测:预拉三个基础镜像后,buildkit 解析基础镜像 1s 命中本地镜像、不再访问远端。
2026-10-12 16:33:45 +08:00

137 lines
6.0 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 生产部署模板。复制为 .env 后替换所有 change-me 值。
# 真实密钥不要提交到 git。
# App / Caddy
APP_DOMAIN=order.khhao.com
CADDY_SITE_ADDR=https://order.khhao.com
WORKER_SITE_ADDR=https://worker.khhao.com
TZ=Asia/Shanghai
BACKEND_PORT=3000
# 反向代理层数:Caddy 后保持 1(默认),后端直连暴露时设为 false
HTTP_TRUST_PROXY=1
# 构建镜像源(可选,默认阿里云公共源)
# 阿里云 ECS 同地域内网可改为 mirrors.cloud.aliyuncs.com 加速 apt/apk
# DEBIAN_MIRROR=mirrors.aliyun.com
# ALPINE_MIRROR=mirrors.aliyun.com
# NPM_REGISTRY=https://registry.npmmirror.com
#
# 基础镜像源(registry 前缀,node / caddy / postgres 都从这里拉)。
# 默认 docker.m.daocloud.io。加速源会抽风(daocloud 出现过 502 Bad Gateway,
# 而显式写死的 registry 会绕过 daemon.json 的 registry-mirrors,其它源帮不上忙)。
# 想要多源容灾就设为 docker.io:走 daemon.json 的 registry-mirrors 列表自动故障转移。
# BASE_REGISTRY=docker.m.daocloud.io
# Claim Links
CLAIM_BASE_URL=https://order.khhao.com/#/claim
CLAIM_TOKEN_TTL_HOURS=0
# Database
POSTGRES_DB=order_site
POSTGRES_USER=postgres
POSTGRES_PASSWORD=change-me-postgres-password
DATABASE_URL=postgres://postgres:change-me-postgres-password@postgres:5432/order_site
DATABASE_MAX_CONNECTIONS=8
DATABASE_IDLE_TIMEOUT_MS=30000
DATABASE_CONNECTION_TIMEOUT_MS=5000
DATABASE_STATEMENT_TIMEOUT_MS=15000
# 慢查询告警阈值;超过该时长的 SQL 只记录指纹和耗时,不记录参数值
DATABASE_SLOW_QUERY_THRESHOLD_MS=500
# PostgreSQL 原生慢查询日志阈值(毫秒);-1 关闭
POSTGRES_LOG_MIN_DURATION_STATEMENT_MS=500
# PostgreSQL 容器资源与性能参数。默认值按 4 核 8G 且与其他服务共用的
# 服务器设置;数据库独占或内存更足时可上调 shared_buffers 与
# effective_cache_size(后者只是规划器提示,不实际占用内存):
POSTGRES_MEM_LIMIT=1.5g
# 4 核共用机器上的推荐值:postgres 是最大单一消耗者,2 核会被突发打满并触发
# cgroup 节流(生产实测累计被节流 2.6 小时);同机其它容器实测只用 0.2–0.4 核。
POSTGRES_CPUS=3
POSTGRES_SHARED_BUFFERS=384MB
POSTGRES_EFFECTIVE_CACHE_SIZE=4GB
POSTGRES_WORK_MEM=16MB
POSTGRES_MAINTENANCE_WORK_MEM=256MB
# 单条查询并行度:>1 时一条查询要 leader + 2 worker = 3 核,容易撞容器配额被节流
POSTGRES_MAX_PARALLEL_WORKERS_PER_GATHER=1
# 检查点频率与 WAL 上限:放宽后写突发从「5 分钟一轮」变成「15 分钟一轮」
POSTGRES_CHECKPOINT_TIMEOUT=900
POSTGRES_MAX_WAL_SIZE=4GB
# 超过该毫秒数的自动清理会打日志(600000=只有 >10 分钟的才记,等于看不到)
POSTGRES_LOG_AUTOVACUUM_MIN_DURATION_MS=5000
# 后端与 Web 容器限额(内存紧张的小机器可相应收紧)
BACKEND_MEM_LIMIT=768m
BACKEND_CPUS=1.5
WEB_MEM_LIMIT=256m
WEB_CPUS=0.5
# Logging
LOG_LEVEL=info
# integration-*.log:对接日志级别(debug|info|warn|error),默认 warn 只记异常
LOG_INTEGRATION_LEVEL=warn
LOG_RETENTION_DAYS=30
# 单个 app/integration 日志文件达到 20MB 后轮转,单日最多保留 5 个分片
LOG_MAX_FILE_SIZE_MB=20
LOG_MAX_FILES=5
# 数据库敏感报文/事件保留策略(天)。清理任务每天执行一次。
RAW_PAYLOAD_RETENTION_DAYS=180
TASK_EVENT_RETENTION_DAYS=180
WEBHOOK_EVENT_RETENTION_DAYS=180
AUDIT_LOG_RETENTION_DAYS=365
WORK_ORDER_EVENT_RETENTION_DAYS=180
# 文件存储:生产使用阿里云 OSS(生产编排已移除 MinIO,仅本地开发使用)。
# STORAGE_MODE 取值 minio | dual | oss;dual 仅在 MinIO→OSS 迁移/回滚期间使用。
STORAGE_MODE=oss
# 以下 MinIO 配置仅在 STORAGE_MODE=dual/minio(迁移回滚场景)时使用。
STORAGE_ENDPOINT=http://minio:9000
STORAGE_BUCKET=order-site
STORAGE_ACCESS_KEY_ID=change-me-storage-access-key
STORAGE_SECRET_ACCESS_KEY=change-me-storage-secret-key
STORAGE_REGION=us-east-1
STORAGE_MAX_UPLOAD_SIZE_MB=10
# 阿里云 OSS S3 兼容端点:ECS 与桶同地域时用内网地址(免流量费、低延迟)
STORAGE_OSS_ENDPOINT=https://oss-cn-hangzhou-internal.aliyuncs.com
STORAGE_OSS_BUCKET=change-me-oss-bucket
STORAGE_OSS_ACCESS_KEY_ID=change-me-oss-access-key
STORAGE_OSS_SECRET_ACCESS_KEY=change-me-oss-secret-key
STORAGE_OSS_REGION=oss-cn-hangzhou
# 数据库备份 → OSS(deploy/backup-db.sh 与 dist/db-backup.js 使用)。
# 默认复用上面的 STORAGE_OSS_* 上传到同桶 backups/ 前缀,以下仅需按需调整。
DB_BACKUP_OSS_PREFIX=backups/postgres
# 服务器本地保留的备份份数(OSS 端过期请配置桶生命周期规则)
# 本地只是断网应急用,OSS 已有完整备份;而 deploy 脚本的磁盘预检要求
# 可用 >= 备份目录x2,本地留太多会把部署卡死(49G 盘建议不超过 2~3 份)。
DB_BACKUP_KEEP=2
# 建议为备份单独创建 RAM 用户、只授予 backups/ 前缀权限(策略见 docs/数据库备份与恢复.md);
# 使用独立桶/密钥时取消注释覆盖:
# DB_BACKUP_OSS_ENDPOINT=https://oss-cn-hangzhou-internal.aliyuncs.com
# DB_BACKUP_OSS_BUCKET=change-me-backup-bucket
# DB_BACKUP_OSS_ACCESS_KEY_ID=change-me-backup-access-key
# DB_BACKUP_OSS_SECRET_ACCESS_KEY=change-me-backup-secret-key
# DB_BACKUP_OSS_REGION=oss-cn-hangzhou
# Admin
ADMIN_SESSION_SECRET=change-me-long-random-session-secret
ADMIN_DEFAULT_USERS_JSON=[{"username":"admin","password":"change-me-admin-password","role":"admin"},{"username":"operator","password":"change-me-operator-password","role":"operator"}]
# 生产环境必须使用显式来源白名单,多个来源用逗号分隔。
CORS_ALLOWED_ORIGINS=https://order.khhao.com,https://worker.khhao.com
# 91Kaquan
KAQUAN91_USER_ID=
KAQUAN91_SECRET=
# 快手行业电子凭证
KUASHOU_INDUSTRY_APP_KEY=
KUASHOU_INDUSTRY_APP_SECRET=
KUASHOU_INDUSTRY_SIGN_SECRET=
KUASHOU_INDUSTRY_MESSAGE_SECRET=
# 接单平台短信验证码(打手注册)
WORKER_SMS_PROVIDER=mock
WORKER_SMS_ACCESS_KEY_ID=
WORKER_SMS_ACCESS_KEY_SECRET=
WORKER_SMS_SIGN_NAME=
WORKER_SMS_TEMPLATE_CODE=