You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在构建Docker镜像时如何通过Alembic自动生成并应用数据库迁移

在构建Docker镜像时如何通过Alembic自动生成并应用数据库迁移

我懂你这种痛点——每次改完模型还要手动敲Alembic命令、重新构建镜像,在开发环境里确实有点折腾人。针对你的需求,我给你梳理了一套适合个人开发的方案,能自动处理迁移,不用再手动重复操作:

核心思路说明

首先得明确两个关键逻辑:

  • Alembic的revision --autogenerate只需要对比模型定义和现有迁移脚本,不需要连接数据库,所以可以在构建镜像阶段或者容器启动阶段执行;
  • 而upgrade head需要连接到可用的数据库,所以只能在容器启动阶段执行(毕竟构建镜像时你的数据库大概率还没跑起来)。

下面给你具体的实现步骤:


方案一:用启动脚本处理(推荐,灵活度高)

直接在Dockerfile里写复杂命令不够灵活,不如写个shell脚本,让容器启动时先处理迁移,再启动FastAPI服务。

步骤1:创建启动脚本

在项目根目录新建start.sh文件,内容如下:

#!/bin/bash

# 生成自动迁移脚本(如果模型有变化)
echo "检查模型变化,生成迁移脚本..."
alembic revision --autogenerate -m "Auto-generated migration on container start"

# 应用最新迁移到数据库
echo "应用数据库迁移到最新版本..."
alembic upgrade head

# 启动FastAPI服务
echo "启动FastAPI应用..."
uvicorn app.main:app --host 0.0.0.0 --port 8000

步骤2:修改Dockerfile

把原来的CMD替换成执行这个脚本,还要给脚本加执行权限:

# Use official Python image
FROM python:3.11-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Set work directory
WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy project files
COPY . .

# 给启动脚本添加执行权限
RUN chmod +x start.sh

# Expose port
EXPOSE 8000

# 替换原来的CMD,执行启动脚本
CMD ["./start.sh"]

步骤3:确保Alembic能正确加载模型和环境变量

打开alembic/env.py,在顶部添加加载.env和导入模型基类的代码,不然Alembic找不到你的模型变化:

from dotenv import load_dotenv
import os
from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context
# 这里替换成你项目中模型的基类路径,比如所有模型都继承自app.models.base.Base
from app.models.base import Base 

# 加载.env文件里的数据库配置
load_dotenv()

# 读取.env里的DB_URL,覆盖alembic.ini里的配置
config = context.config
config.set_main_option("sqlalchemy.url", os.getenv("DB_URL"))

# 下面保留原来的alembic env.py代码...
# 还要确保target_metadata指向你的模型基类的metadata
target_metadata = Base.metadata

另外,把python-dotenv加到requirements.txt里,不然加载不了.env文件。


方案二:构建阶段生成迁移脚本(镜像包含迁移文件)

如果你希望迁移脚本被直接打包到镜像里,而不是容器启动时临时生成,可以在Dockerfile的构建阶段执行迁移生成命令:

修改后的Dockerfile片段:

# Copy project files
COPY . .

# 构建阶段生成迁移脚本(如果模型有变化)
RUN alembic revision --autogenerate -m "Auto-generated migration during image build"

# 给启动脚本加执行权限
RUN chmod +x start.sh

# Expose port
EXPOSE 8000

# 启动脚本只做迁移应用和服务启动
CMD ["./start.sh"]

对应的start.sh可以简化,去掉生成迁移的步骤:

#!/bin/bash

echo "应用数据库迁移..."
alembic upgrade head

echo "启动FastAPI服务..."
uvicorn app.main:app --host 0.0.0.0 --port 8000

这个方案的好处是,迁移脚本会被包含在镜像里,你可以从镜像里把迁移文件拷出来备份;缺点是每次构建镜像都会执行一次生成命令,不过如果模型没变化,Alembic会输出No changes in schema detected,不会生成多余的文件。


关键注意事项(一定要看!)

  1. 只适合开发环境:我必须强调,这种自动生成+应用迁移的方式绝对不能用在生产环境!生产环境的迁移需要手动生成、仔细检查、测试后再应用,自动生成的迁移可能漏了索引、约束的变化,甚至会破坏数据。
  2. 数据库连接要正常:容器启动时,数据库必须是可访问的(比如用Docker Compose把app和DB容器放在同一个网络里),不然alembic upgrade head会失败。
  3. 优化.dockerignore:把myenv/、__pycache__/这些不需要的文件加到.dockerignore里,减少镜像体积:
myenv/
__pycache__/
*.pyc
*.pyo
*.pyd
.env.local

测试方法

  1. 修改一个模型(比如给某个模型加个新字段);
  2. 构建镜像:docker build -t my-fastapi-app .;
  3. 运行容器:docker run -p 8000:8000 --env-file .env my-fastapi-app;
  4. 查看容器日志,你会看到Alembic生成迁移、应用迁移,然后启动FastAPI的过程。如果模型没变化,生成迁移的步骤会提示没有变化,直接跳过,然后启动服务。

这样你就不用每次改模型都手动敲命令啦,开发效率能提不少~

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 03:09:50