Skip to content

容器启动与环境协调

init_db.py 是 Docker 容器生命周期的起点。它确保了在复杂的微服务拓扑中,应用进程仅在基础设施(PostgreSQL)完全就绪后启动,并自动完成数据库表结构的最新映射。


在分布式部署中,数据库容器的启动往往慢于应用容器。该脚本通过以下流程建立服务的自愈能力

  1. 健康探测 (wait_for_db): 使用 psycopg2 建立低开销的轮询连接。如果数据库未初始化完成,脚本将阻塞并每隔 2 秒重试,防止应用因连接失败而频繁崩溃重启(Crash Loop)。
  2. Schema 同步 (sync_db)
    • 迁移模式:若检测到 migrations 文件夹,执行 flask db upgrade 以应用版本化变更。
    • 初始化模式:若为新部署,执行 db.create_all() 建立基础表结构。
  3. 进程交管 (os.execvp): 使用系统调用替换当前脚本进程,将控制权交给最终指令(如 gunicorncelery),确保容器能正确接收操作系统发出的停止信号(SIGTERM)。

环境变量驱动

通过 DB_HOSTDB_PORT 等变量动态构建 URI,支持在本地、Docker Compose 或 Kubernetes 之间无缝迁移。

角色分工逻辑

引入 SKIP_DB_SYNC 变量。确保在多副本部署时,只有主后端容器执行数据库同步,防止 Celery Worker 容器产生竞态冲突。

平滑进程替换

采用 os.execvp 而非 subprocess。这使得应用进程成为容器内的 PID 1,能够完美处理 Docker Stop 时的优雅关闭请求。


while True:
try:
# 尝试通过环境变量构建的连接串进行拨测
conn = psycopg2.connect(uri)
conn.close()
break # 连接成功,跳出循环
except Exception:
# 连接失败时不抛出异常,而是等待重试
time.sleep(2)
def sync_db():
if os.path.exists("migrations"):
# 优先使用版本化迁移工具 Alembic
subprocess.run(["flask", "db", "upgrade"])
else:
# 兜底方案:根据 SQLAlchemy 模型创建全量表
with app.app_context():
db.create_all()