Compare commits
2
Commits
v1.0.0-rc1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d0ae4d7d1 | ||
|
|
9cfd515b8f |
@@ -28,3 +28,9 @@ package-lock.json
|
||||
# local vendor for agent test env (not shipped)
|
||||
.vendor/
|
||||
vendor_wheels/
|
||||
|
||||
# 正式环境部署产物(证书私钥、备份)
|
||||
deploy/tls/certs/
|
||||
backups/
|
||||
ALERT.log
|
||||
backup.log
|
||||
|
||||
@@ -16,3 +16,16 @@ APP_BOOTSTRAP_ADMIN_PASSWORD=change-me-in-local-env
|
||||
|
||||
# 内网测试可暂时关闭登录失败锁定;正式环境不得开启
|
||||
# APP_LOGIN_RATE_LIMIT_DISABLED=1
|
||||
|
||||
# ---- 同宿主机第二套环境(正式)必须设置的隔离参数 ----
|
||||
# compose 项目名(默认 deploy;正式环境改为 caiwuzongzhang-prod)
|
||||
# COMPOSE_PROJECT_NAME=caiwuzongzhang-prod
|
||||
# 应用容器名与宿主机端口映射(正式默认只绑本机回环,由反代对外)
|
||||
# APP_CONTAINER_NAME=caiwuzongzhang-prod-app
|
||||
# APP_PORT_MAP=127.0.0.1:4174:4173
|
||||
|
||||
# ---- 正式 HTTPS 反代(COMPOSE_PROFILES=tls 启用 proxy 服务)----
|
||||
# COMPOSE_PROFILES=tls
|
||||
# PROXY_CONTAINER_NAME=caiwuzongzhang-proxy
|
||||
# PROXY_PORT_MAP=8443:8443
|
||||
# 首次启用前先执行 ./tls/gen-cert.sh 生成证书
|
||||
|
||||
@@ -46,6 +46,45 @@ docker exec caiwuzongzhang-app python -c "import sqlite3; s=sqlite3.connect('/ap
|
||||
docker cp caiwuzongzhang-app:/tmp/b.db ../backups/app.db.$STAMP
|
||||
```
|
||||
|
||||
## 3.1 正式环境部署(同宿主机隔离,2026-08-30 首次上线采用)
|
||||
|
||||
测试与正式同宿主机并行,靠 compose 项目名/容器名/端口三隔离:
|
||||
|
||||
| 项 | 测试环境 | 正式环境 |
|
||||
|---|---|---|
|
||||
| 目录 | `/home/leefer/caiwuzongzhang-test` | `/home/leefer/caiwuzongzhang-prod` |
|
||||
| compose 项目 | `deploy`(默认) | `COMPOSE_PROJECT_NAME=caiwuzongzhang-prod` |
|
||||
| 应用容器 | `caiwuzongzhang-app` | `caiwuzongzhang-prod-app` |
|
||||
| 端口 | `4173`(对外) | `127.0.0.1:4174`(仅本机,反代上游) |
|
||||
| HTTPS | 无 | nginx 反代 `8443`(`COMPOSE_PROFILES=tls`) |
|
||||
| 访问 | http://192.168.200.36:4173/ | https://192.168.200.36:8443/ |
|
||||
|
||||
首次部署顺序:
|
||||
|
||||
```bash
|
||||
git clone <repo> /home/leefer/caiwuzongzhang-prod && cd /home/leefer/caiwuzongzhang-prod
|
||||
git checkout release/prod
|
||||
mkdir -p data/files backups && chown -R 10001:10001 data # 容器内 app uid
|
||||
cd deploy
|
||||
cp .env.example .env # 按下述差异填写
|
||||
./tls/gen-cert.sh # 生成内部 CA + 服务器证书(SAN 含对外 IP)
|
||||
TAG=<发布镜像tag> docker compose up -d # 不带 --build,直接用已验收镜像
|
||||
docker logs <应用容器> 2>&1 | grep "shown once" # 首启一次性初始口令,只出现一次
|
||||
```
|
||||
|
||||
正式 `.env` 与测试的差异(铁律):
|
||||
|
||||
- `COMPOSE_PROJECT_NAME=caiwuzongzhang-prod`、`APP_CONTAINER_NAME=caiwuzongzhang-prod-app`、`APP_PORT_MAP=127.0.0.1:4174:4173`
|
||||
- `COMPOSE_PROFILES=tls`、`PROXY_CONTAINER_NAME=caiwuzongzhang-proxy`、`PROXY_PORT_MAP=8443:8443`
|
||||
- `APP_UID=10001` / `APP_GID=10001`(data/ 已 chown 10001)
|
||||
- 管理员用户名自定(如 `jinniu-admin`);**不设** `APP_BOOTSTRAP_ADMIN_PASSWORD`(首启控制台取随机一次性口令,首登立即改密)
|
||||
- **不设** `APP_LOGIN_RATE_LIMIT_DISABLED`(限流默认开启)
|
||||
|
||||
证书与信任分发:
|
||||
|
||||
- `tls/certs/ca.crt` 发给各公司电脑安装到「受信任的根证书颁发机构」(安装指引见交接文档);`ca.key`/`server.key` 永不离开宿主机。
|
||||
- 服务器证书有效期 5 年,到期前用 `./tls/gen-cert.sh` 重签并 `docker compose restart proxy`。
|
||||
|
||||
## 4. 回滚(应用层,5 分钟内)
|
||||
|
||||
```bash
|
||||
@@ -68,6 +107,16 @@ cd deploy && ./rollback.sh <上一个镜像tag>
|
||||
|
||||
cron `*/5 * * * *` 运行 `deploy/monitor.sh`;连续失败或磁盘 ≥80% 时查看 `deploy/ALERT.log` 并按需扩容/清理。容器重启策略 `unless-stopped`。
|
||||
|
||||
宿主机 crontab(leefer,2026-08-30 起,正式环境):
|
||||
|
||||
```cron
|
||||
15 2 * * * cd /home/leefer/caiwuzongzhang-prod/deploy && CONTAINER=caiwuzongzhang-prod-app ./backup.sh >> backup.log 2>&1
|
||||
*/5 * * * * cd /home/leefer/caiwuzongzhang-prod/deploy && CONTAINER=caiwuzongzhang-prod-app HEALTH_URL=http://127.0.0.1:4174/ ./monitor.sh >/dev/null 2>&1
|
||||
01 3 1 * * rsync -a /home/leefer/caiwuzongzhang-prod/backups/monthly/ /vol1/caiwuzongzhang-backups/monthly/
|
||||
```
|
||||
|
||||
(第三行为月度异盘副本:`/vol1` 是与系统盘不同的物理卷;如后续提供真正的异机目标,改为该目标。)
|
||||
|
||||
## 7. 升级数据库
|
||||
|
||||
应用启动时自动执行迁移(`MIGRATIONS`,当前版本 10)。迁移只前不改写历史;回退 schema 用对应 down 迁移,先备份后操作。
|
||||
|
||||
+55
-2
@@ -1,10 +1,16 @@
|
||||
# 测试/正式环境部署编排(正式口令不得写入本文件)。
|
||||
# 使用:复制 .env.example 为 .env 填写;TAG 指定镜像标签(默认取当前提交 sha)。
|
||||
# 例:TAG=v1.0.0-rc1 docker compose -f compose.yaml up -d --build
|
||||
#
|
||||
# 同宿主机多套环境(测试 + 正式)必须各自设置:
|
||||
# COMPOSE_PROJECT_NAME / APP_CONTAINER_NAME / APP_PORT_MAP 互不相同。
|
||||
# 正式环境启用 HTTPS 反代:.env 中设 COMPOSE_PROFILES=tls(先跑 tls/gen-cert.sh)。
|
||||
|
||||
name: ${COMPOSE_PROJECT_NAME:-deploy}
|
||||
|
||||
services:
|
||||
app:
|
||||
container_name: caiwuzongzhang-app
|
||||
container_name: ${APP_CONTAINER_NAME:-caiwuzongzhang-app}
|
||||
image: caiwuzongzhang:${TAG:-latest}
|
||||
build:
|
||||
context: ..
|
||||
@@ -15,7 +21,7 @@ services:
|
||||
# APP_UID/APP_GID,正式与测试环境各自填写,默认镜像内 app=10001)
|
||||
user: "${APP_UID:-10001}:${APP_GID:-10001}"
|
||||
ports:
|
||||
- "4173:4173"
|
||||
- "${APP_PORT_MAP:-4173:4173}"
|
||||
volumes:
|
||||
- ../data:/app/data
|
||||
init: true
|
||||
@@ -30,9 +36,56 @@ services:
|
||||
pids_limit: 128
|
||||
mem_limit: 512m
|
||||
cpus: 1.0
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:4173/', timeout=2)"]
|
||||
interval: 15s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
# 可选 HTTPS 反向代理(正式环境用):COMPOSE_PROFILES=tls 启用。
|
||||
# 证书由 tls/gen-cert.sh 生成的内部 CA 签发(内网自受管信任),公司电脑
|
||||
# 安装 tls/certs/ca.crt 一次即可无告警访问。
|
||||
proxy:
|
||||
container_name: ${PROXY_CONTAINER_NAME:-caiwuzongzhang-proxy}
|
||||
image: nginx:1.27-alpine
|
||||
profiles: ["tls"]
|
||||
ports:
|
||||
- "${PROXY_PORT_MAP:-8443:8443}"
|
||||
volumes:
|
||||
- ./tls/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./tls/certs/server.crt:/etc/nginx/tls/server.crt:ro
|
||||
- ./tls/certs/server.key:/etc/nginx/tls/server.key:ro
|
||||
# 与证书文件属主一致的 uid/gid(默认 101=镜像 nginx 用户;宿主机生成证书时
|
||||
# 设为属主 uid/gid,保持 server.key 0600 不放宽)
|
||||
user: "${PROXY_UID:-101}:${PROXY_GID:-101}"
|
||||
depends_on:
|
||||
- app
|
||||
restart: unless-stopped
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /var/cache/nginx:size=16m
|
||||
- /var/run:size=1m
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
pids_limit: 64
|
||||
mem_limit: 64m
|
||||
cpus: 0.5
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--no-check-certificate", "-O", "/dev/null", "https://127.0.0.1:8443/"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
# 生成内网专用 CA 与服务器证书(自受管内部信任,不涉及公网域名)。
|
||||
# 用法:在正式环境 deploy/ 目录执行 ./tls/gen-cert.sh
|
||||
# 可用环境变量覆盖:
|
||||
# CERT_IP 对外访问 IP(默认 192.168.200.36)
|
||||
# CERT_DNS 额外 DNS 名称(空格分隔,默认 caiwuzongzhang.jinniu.internal)
|
||||
# 输出:tls/certs/{ca.crt,ca.key,server.crt,server.key}(key 永不入库、不分发)
|
||||
# 分发:仅把 ca.crt 发给公司电脑安装(受信任的根证书颁发机构)。
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
||||
CERTS="$ROOT/certs"
|
||||
mkdir -p "$CERTS"
|
||||
cd "$CERTS"
|
||||
|
||||
CERT_IP="${CERT_IP:-192.168.200.36}"
|
||||
CERT_DNS="${CERT_DNS:-caiwuzongzhang.jinniu.internal}"
|
||||
|
||||
SAN="IP:${CERT_IP}"
|
||||
for d in $CERT_DNS; do SAN="$SAN,DNS:$d"; done
|
||||
|
||||
if [[ ! -f ca.key ]]; then
|
||||
# 内部根 CA:10 年,仅本系统使用
|
||||
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
|
||||
-keyout ca.key -out ca.crt -days 3650 -nodes -subj "/CN=Jinniu Ledger Internal CA" \
|
||||
-addext "basicConstraints=critical,CA:TRUE" \
|
||||
-addext "keyUsage=critical,keyCertSign,cRLSign"
|
||||
chmod 600 ca.key
|
||||
echo "ca 已生成"
|
||||
fi
|
||||
|
||||
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
|
||||
-keyout server.key -out server.csr -nodes \
|
||||
-subj "/CN=${CERT_DNS%% *}" >/dev/null 2>&1
|
||||
cat > server.ext <<EXT
|
||||
subjectAltName=${SAN}
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage=digitalSignature,keyEncipherment
|
||||
extendedKeyUsage=serverAuth
|
||||
EXT
|
||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
|
||||
-out server.crt -days 1825 -sha256 -extfile server.ext >/dev/null 2>&1
|
||||
chmod 600 server.key
|
||||
rm -f server.csr server.ext ca.srl
|
||||
echo "server 证书已生成(SAN: ${SAN}),有效期 5 年"
|
||||
echo "分发文件:${CERTS}/ca.crt(其余文件不得离开本机)"
|
||||
@@ -0,0 +1,31 @@
|
||||
# 正式环境 HTTPS 反代(nginx)。证书挂载自 deploy/tls/certs/(gen-cert.sh 生成)。
|
||||
# 上游为同 compose 网络内的 app:4173;对外仅暴露本代理的 8443。
|
||||
server {
|
||||
listen 8443 ssl;
|
||||
listen [::]:8443 ssl;
|
||||
http2 on;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/nginx/tls/server.crt;
|
||||
ssl_certificate_key /etc/nginx/tls/server.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:2m;
|
||||
ssl_session_timeout 1h;
|
||||
|
||||
# 银行流水 Excel 上传上限
|
||||
client_max_body_size 25m;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_send_timeout 120s;
|
||||
|
||||
location / {
|
||||
proxy_pass http://app:4173;
|
||||
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 https;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user