148 lines
4.7 KiB
YAML
148 lines
4.7 KiB
YAML
|
|
# 只部署工资系统及其 MySQL/Redis;T+ 为客户现场的外部只读 SQL Server。
|
|||
|
|
# 从仓库根目录执行,显式传 --env-file docker/.env.prod.local。
|
|||
|
|
name: ys-payroll-prod
|
|||
|
|
|
|||
|
|
x-app-environment: &app-environment
|
|||
|
|
TZ: Asia/Shanghai
|
|||
|
|
APP_ENV: prod
|
|||
|
|
APP_SECRET_KEY: ${APP_SECRET_KEY:?请设置应用密钥}
|
|||
|
|
MYSQL_HOST: mysql
|
|||
|
|
MYSQL_PORT: "3306"
|
|||
|
|
MYSQL_DATABASE: ${MYSQL_DATABASE:-payroll}
|
|||
|
|
MYSQL_USER: ${MYSQL_USER:-payroll}
|
|||
|
|
MYSQL_PASSWORD: ${MYSQL_PASSWORD:?请设置业务库密码}
|
|||
|
|
REDIS_HOST: redis
|
|||
|
|
REDIS_PORT: "6379"
|
|||
|
|
REDIS_PASSWORD: ${REDIS_PASSWORD:?请设置Redis密码}
|
|||
|
|
REDIS_DB: "0"
|
|||
|
|
T_PLUS_ENABLED: "true"
|
|||
|
|
T_PLUS_CONNECTION_FILE: ""
|
|||
|
|
T_PLUS_HOST: ${T_PLUS_HOST:?请填写客户现场T+服务器DNS名}
|
|||
|
|
T_PLUS_PORT: ${T_PLUS_PORT:-1433}
|
|||
|
|
T_PLUS_DATABASE: ${T_PLUS_DATABASE:?请确认客户账套数据库名}
|
|||
|
|
T_PLUS_USER: ${T_PLUS_USER:?请填写T+连接账号}
|
|||
|
|
T_PLUS_ALLOW_ADMIN_ACCOUNT: ${T_PLUS_ALLOW_ADMIN_ACCOUNT:-false}
|
|||
|
|
T_PLUS_PASSWORD: ${T_PLUS_PASSWORD:?请设置T+只读账号密码}
|
|||
|
|
T_PLUS_ODBC_DRIVER: "ODBC Driver 18 for SQL Server"
|
|||
|
|
T_PLUS_ENCRYPT: "true"
|
|||
|
|
T_PLUS_TRUST_SERVER_CERTIFICATE: "false"
|
|||
|
|
T_PLUS_AUTOMATION_ENABLED: ${T_PLUS_AUTOMATION_ENABLED:-false}
|
|||
|
|
T_PLUS_SCHEDULE_WEEKDAY: ${T_PLUS_SCHEDULE_WEEKDAY:-0}
|
|||
|
|
T_PLUS_SCHEDULE_TIME: ${T_PLUS_SCHEDULE_TIME:-02:00}
|
|||
|
|
PAYROLL_APPROVAL_ENABLED: ${PAYROLL_APPROVAL_ENABLED:-false}
|
|||
|
|
PAYROLL_ALLOW_LEGACY_CALCULATION: "false"
|
|||
|
|
|
|||
|
|
x-app: &app
|
|||
|
|
image: ys-payroll-backend:${PAYROLL_VERSION:?请填写本次发布版本}
|
|||
|
|
build:
|
|||
|
|
context: ..
|
|||
|
|
dockerfile: backend/Dockerfile
|
|||
|
|
environment: *app-environment
|
|||
|
|
init: true
|
|||
|
|
restart: unless-stopped
|
|||
|
|
stop_grace_period: 15m
|
|||
|
|
depends_on:
|
|||
|
|
mysql:
|
|||
|
|
condition: service_healthy
|
|||
|
|
redis:
|
|||
|
|
condition: service_healthy
|
|||
|
|
logging: &bounded-logging
|
|||
|
|
driver: json-file
|
|||
|
|
options:
|
|||
|
|
max-size: "10m"
|
|||
|
|
max-file: "3"
|
|||
|
|
|
|||
|
|
services:
|
|||
|
|
mysql:
|
|||
|
|
image: mysql:8.0
|
|||
|
|
restart: unless-stopped
|
|||
|
|
environment:
|
|||
|
|
TZ: Asia/Shanghai
|
|||
|
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?请设置数据库管理密码}
|
|||
|
|
MYSQL_DATABASE: ${MYSQL_DATABASE:-payroll}
|
|||
|
|
MYSQL_USER: ${MYSQL_USER:-payroll}
|
|||
|
|
MYSQL_PASSWORD: ${MYSQL_PASSWORD:?请设置业务库密码}
|
|||
|
|
command: ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_general_ci"]
|
|||
|
|
volumes:
|
|||
|
|
- mysql-data:/var/lib/mysql
|
|||
|
|
healthcheck:
|
|||
|
|
test: ["CMD-SHELL", "MYSQL_PWD=\"$$MYSQL_PASSWORD\" mysql --host=127.0.0.1 --user=\"$$MYSQL_USER\" --database=\"$$MYSQL_DATABASE\" --execute='SELECT 1' >/dev/null"]
|
|||
|
|
interval: 10s
|
|||
|
|
timeout: 5s
|
|||
|
|
retries: 12
|
|||
|
|
start_period: 60s
|
|||
|
|
logging: *bounded-logging
|
|||
|
|
|
|||
|
|
redis:
|
|||
|
|
image: redis:7.4-alpine
|
|||
|
|
restart: unless-stopped
|
|||
|
|
user: redis
|
|||
|
|
environment:
|
|||
|
|
REDIS_PASSWORD: ${REDIS_PASSWORD:?请设置Redis密码}
|
|||
|
|
# 仅将口令的 SHA-256 放入 Redis ACL,避免口令进入服务进程参数。
|
|||
|
|
command:
|
|||
|
|
- /bin/sh
|
|||
|
|
- -ec
|
|||
|
|
- |
|
|||
|
|
password_hash=$$(printf '%s' "$$REDIS_PASSWORD" | sha256sum | cut -d ' ' -f 1)
|
|||
|
|
umask 077
|
|||
|
|
printf 'appendonly yes\nuser default reset on #%s ~* &* +@all\n' "$$password_hash" > /tmp/payroll-redis.conf
|
|||
|
|
exec redis-server /tmp/payroll-redis.conf
|
|||
|
|
init: true
|
|||
|
|
volumes:
|
|||
|
|
- redis-data:/data
|
|||
|
|
healthcheck:
|
|||
|
|
test: ["CMD-SHELL", "REDISCLI_AUTH=\"$$REDIS_PASSWORD\" redis-cli --no-auth-warning ping | grep -qx PONG"]
|
|||
|
|
interval: 10s
|
|||
|
|
timeout: 5s
|
|||
|
|
retries: 12
|
|||
|
|
logging: *bounded-logging
|
|||
|
|
|
|||
|
|
api:
|
|||
|
|
<<: *app
|
|||
|
|
volumes:
|
|||
|
|
- uploads:/app/backend/uploads
|
|||
|
|
- api-logs:/app/backend/logs
|
|||
|
|
healthcheck:
|
|||
|
|
# /api/health 的 HTTP 200 不代表依赖正常,需要检查 data 三项。
|
|||
|
|
test: ["CMD", "python", "-c", "import json, urllib.request; d=json.load(urllib.request.urlopen('http://127.0.0.1:8000/api/health', timeout=5))['data']; raise SystemExit(0 if all(d.get(k) is True for k in ('app','db','redis')) else 1)"]
|
|||
|
|
interval: 30s
|
|||
|
|
timeout: 10s
|
|||
|
|
retries: 3
|
|||
|
|
start_period: 30s
|
|||
|
|
|
|||
|
|
supervisor:
|
|||
|
|
<<: *app
|
|||
|
|
command: ["python", "-m", "app.cli", "tplus-supervisor"]
|
|||
|
|
network_mode: "service:api"
|
|||
|
|
volumes:
|
|||
|
|
- uploads:/app/backend/uploads
|
|||
|
|
depends_on:
|
|||
|
|
api:
|
|||
|
|
condition: service_healthy
|
|||
|
|
|
|||
|
|
web:
|
|||
|
|
image: ys-payroll-web:${PAYROLL_VERSION:?请填写本次发布版本}
|
|||
|
|
build:
|
|||
|
|
context: ..
|
|||
|
|
dockerfile: frontend/Dockerfile
|
|||
|
|
restart: unless-stopped
|
|||
|
|
ports:
|
|||
|
|
- "127.0.0.1:${PAYROLL_HTTP_PORT:-8080}:80"
|
|||
|
|
depends_on:
|
|||
|
|
api:
|
|||
|
|
condition: service_healthy
|
|||
|
|
logging: *bounded-logging
|
|||
|
|
|
|||
|
|
migrate:
|
|||
|
|
<<: *app
|
|||
|
|
profiles: ["tools"]
|
|||
|
|
restart: "no"
|
|||
|
|
command: ["alembic", "upgrade", "head"]
|
|||
|
|
|
|||
|
|
volumes:
|
|||
|
|
mysql-data:
|
|||
|
|
redis-data:
|
|||
|
|
uploads:
|
|||
|
|
api-logs:
|