#!/bin/sh # ═══════════════════════════════════════════════════════════════ # 容器启动脚本 # 职责:等待数据库就绪 → 初始化表结构 → 启动 Gunicorn # ═══════════════════════════════════════════════════════════════ set -e # ── 颜色输出 ────────────────────────────────────────────────── log() { echo "[entrypoint] $*"; } info() { echo "\033[0;36m[entrypoint] $*\033[0m"; } ok() { echo "\033[0;32m[entrypoint] ✓ $*\033[0m"; } warn() { echo "\033[0;33m[entrypoint] ⚠ $*\033[0m"; } err() { echo "\033[0;31m[entrypoint] ✗ $*\033[0m" >&2; } # ── 等待数据库就绪(最多 60 秒)──────────────────────────────── wait_for_db() { info "等待数据库连接就绪…" MAX_WAIT=${DB_WAIT_SECONDS:-60} elapsed=0 until python - <<'PYEOF' import os, sys, pymysql url = os.environ.get('DATABASE_URL', '') # 从 DATABASE_URL 解析连接参数 # 格式: mysql+pymysql://user:pass@host:port/db import re m = re.match(r'mysql\+pymysql://([^:]+):([^@]+)@([^:/]+):?(\d+)?/(\S+)', url) if not m: sys.exit(1) user, pwd, host, port, db = m.groups() port = int(port or 3306) try: conn = pymysql.connect(host=host, port=port, user=user, password=pwd, database=db, connect_timeout=3) conn.close() sys.exit(0) except Exception as e: print(f" 未就绪: {e}", file=sys.stderr) sys.exit(1) PYEOF do if [ "$elapsed" -ge "$MAX_WAIT" ]; then err "数据库在 ${MAX_WAIT}s 内未就绪,退出" exit 1 fi elapsed=$((elapsed + 3)) sleep 3 done ok "数据库连接成功" } # ── 数据库初始化(幂等)──────────────────────────────────────── init_db() { info "执行数据库初始化…" python init_db.py \ --admin-user "${ADMIN_USERNAME:-admin}" \ --admin-pass "${ADMIN_PASSWORD:-Admin@123456}" \ --admin-email "${ADMIN_EMAIL:-admin@example.com}" ok "数据库初始化完成" } # ── 创建上传目录 ─────────────────────────────────────────────── prepare_dirs() { mkdir -p app/static/uploads/{text,image,audio,video,temp} ok "上传目录就绪" } # ── 主流程 ──────────────────────────────────────────────────── info "启动个人资料库…" info "Python: $(python --version)" info "Flask env: ${FLASK_ENV:-development}" prepare_dirs wait_for_db init_db # ── 启动 Gunicorn ───────────────────────────────────────────── WORKERS=${GUNICORN_WORKERS:-4} TIMEOUT=${GUNICORN_TIMEOUT:-120} BIND=${GUNICORN_BIND:-0.0.0.0:5000} ok "启动 Gunicorn (workers=${WORKERS}, bind=${BIND})" exec gunicorn \ --workers "$WORKERS" \ --worker-class sync \ --timeout "$TIMEOUT" \ --bind "$BIND" \ --access-logfile - \ --error-logfile - \ --log-level "${LOG_LEVEL:-info}" \ "run:app"