4、Alembic入门与配置:Alembic安装、初始化、env.py配置、alembic.ini详解、连接到PostgreSQL/MySQL容器

Alembic 是 SQLAlchemy 官方维护的数据库迁移工具,专为 Python 项目设计。在 Docker 容器化环境中,Alembic 负责将数据库 Schema 的变更(如新增表、修改字段)以版本化脚本的形式管理,并与容器内的 PostgreSQL 或 MySQL 实例协同工作。本章将带你从零完成 Alembic 的安装、初始化、核心配置,并成功连接到运行在容器中的数据库。

4.1 Alembic 安装与项目初始化

Alembic 通过 pip 安装,建议在 Python 虚拟环境中进行。安装完成后,使用 alembic init 命令生成项目骨架。

安装步骤

  1. 创建并激活虚拟环境(推荐使用 Python 3.9+)
  2. 安装 Alembic 与数据库驱动
pip install alembic
pip install psycopg2-binary   # PostgreSQL 驱动
pip install pymysql           # MySQL 驱动

初始化 Alembic 项目

在项目根目录执行以下命令,Alembic 会创建 alembic/ 目录和 alembic.ini 配置文件。

alembic init alembic

初始化后的目录结构如下:

your_project/
├── alembic/
│   ├── versions/          # 存放迁移脚本
│   ├── env.py             # 核心环境配置
│   ├── script.py.mako     # 迁移脚本模板
│   └── README
└── alembic.ini            # 全局配置文件
提示: 如果项目使用异步框架(如 FastAPI + asyncpg),需要额外安装 alembic[async] 并调整 env.py 中的运行器。

4.2 alembic.ini 配置文件详解

alembic.ini 是 Alembic 的全局配置文件,采用 INI 格式。核心参数集中在 [alembic] 段。

参数名 默认值 说明
script_location alembic 迁移脚本目录路径
sqlalchemy.url driver://user:pass@localhost/dbname 数据库连接字符串(生产环境建议通过环境变量注入)
version_locations %(here)s/../alembic/versions 版本脚本存放路径,支持多个路径
revision_environment false 是否在生成迁移时加载 env.py 环境
file_template %(rev)s_%(slug)s 迁移脚本文件名模板

典型配置示例(连接 Docker 容器中的 PostgreSQL):

[alembic]
script_location = alembic
sqlalchemy.url = postgresql://user:password@localhost:5432/mydb

[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic
安全警告: 切勿将明文密码写入 alembic.ini 并提交到版本控制。应使用环境变量替换,例如:sqlalchemy.url = postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME},并在 env.py 中通过 os.getenv() 读取。

4.3 env.py 核心配置与数据库连接

env.py 是 Alembic 运行时的 Python 入口,负责加载 SQLAlchemy 模型元数据、配置数据库连接、以及定义迁移上下文。以下是与 Docker 容器数据库连接的关键配置。

基础 env.py 结构

from logging.config import fileConfig
from sqlalchemy import engine_from_config, pool
from alembic import context
import os

# 加载 alembic.ini 中的日志配置
config = context.config
fileConfig(config.config_file_name)

# 从环境变量读取数据库 URL(覆盖 ini 中的占位符)
DATABASE_URL = os.getenv(
    "DATABASE_URL",
    "postgresql://user:password@localhost:5432/mydb"
)
config.set_main_option("sqlalchemy.url", DATABASE_URL)

# 导入 SQLAlchemy 模型元数据
from app.models import Base  # 你的模型基类
target_metadata = Base.metadata

def run_migrations_offline():
    """离线模式:生成 SQL 脚本,不连接数据库"""
    url = config.get_main_option("sqlalchemy.url")
    context.configure(url=url, target_metadata=target_metadata, literal_binds=True)
    with context.begin_transaction():
        context.run_migrations()

def run_migrations_online():
    """在线模式:直接连接数据库执行迁移"""
    connectable = engine_from_config(
        config.get_section(config.config_ini_section),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )
    with connectable.connect() as connection:
        context.configure(connection=connection, target_metadata=target_metadata)
        with context.begin_transaction():
            context.run_migrations()

if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()

连接到 Docker 容器数据库的关键点

  • 主机地址: 如果 Alembic 在宿主机运行,容器数据库需映射端口(如 -p 5432:5432),连接地址使用 localhost 或 127.0.0.1。
  • 主机地址(容器内运行): 如果 Alembic 在另一个容器中运行,应使用 Docker Compose 服务名(如 db)作为主机名。
  • 驱动选择: PostgreSQL 使用 psycopg2,MySQL 使用 pymysql 或 mysqlclient。
  • 连接池: 迁移场景建议使用 NullPool,避免连接残留。
MySQL 连接字符串示例:
mysql+pymysql://user:password@localhost:3306/mydb?charset=utf8mb4

4.4 连接 PostgreSQL/MySQL 容器实战

以下演示如何通过 Docker Compose 启动数据库容器,并让 Alembic 成功连接。

Docker Compose 配置(docker-compose.yml)

version: '3.8'
services:
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

验证连接

启动容器后,在项目根目录执行 Alembic 的 current 命令,检查是否能获取当前数据库版本。

docker-compose up -d
alembic current

如果配置正确,输出应为 None(表示尚无迁移版本),或显示当前版本号。若出现连接错误,请检查:

  • 容器是否正常运行(docker ps)
  • 端口映射是否冲突
  • 数据库 URL 中的用户名、密码、数据库名是否匹配
  • 防火墙或 Docker 网络策略
调试技巧: 使用 alembic -c alembic.ini --raiseerr current 可以显示完整的 Python 异常堆栈,快速定位配置错误。

4.5 Alembic 配置与容器数据库连接架构图

下图展示了 Alembic 配置文件、环境变量、Docker 容器数据库之间的调用关系与数据流。

Alembic 配置与容器数据库连接架构 Alembic 配置与容器数据库连接架构 alembic.ini sqlalchemy.url 占位符 环境变量 DATABASE_URL env.py 读取配置 + 加载元数据 Docker 容器数据库 PostgreSQL / MySQL 迁移脚本 versions/*.py 说明:env.py 从 alembic.ini 读取占位符,并通过环境变量注入真实连接串,最终连接到 Docker 容器中的数据库实例。 迁移脚本通过 env.py 加载的元数据与数据库交互,生成或应用版本变更。

4.6 常见配置问题与排查

问题现象 可能原因 解决方案
sqlalchemy.exc.OperationalError 数据库容器未启动、端口错误、认证失败 检查 docker ps、端口映射、用户名密码
ModuleNotFoundError: No module named 'app.models' env.py 中模型导入路径错误 确认 Python 路径包含项目根目录,或使用相对导入
alembic.util.exc.CommandError alembic.ini 中 script_location 路径错误 使用绝对路径或 %(here)s 宏修正
迁移脚本生成空文件 target_metadata 为 None 或未正确加载 在 env.py 中打印 target_metadata.tables 调试
容器网络注意: 如果 Alembic 在宿主机运行,而数据库在容器内,请使用 localhost 而非 127.0.0.1(某些系统下 localhost 会解析为 IPv6 导致连接失败)。如果两者都在 Docker Compose 网络中,使用服务名作为主机名。

4.7 多数据库环境配置策略

在开发、测试、生产环境中,数据库连接参数通常不同。推荐使用 环境变量 + 多配置文件 的方式管理。

方案一:单一 alembic.ini + 环境变量覆盖

在 alembic.ini 中使用占位符,在 env.py 中通过 os.getenv() 动态替换。这是最简洁的方式,适合大多数项目。

方案二:多配置文件

为每个环境创建独立的配置文件,如 alembic.dev.ini、alembic.prod.ini,通过 alembic -c 参数指定。

alembic -c alembic.prod.ini upgrade head
方案 优点 缺点
环境变量覆盖 配置集中、易于 CI/CD 集成 环境变量管理需谨慎
多配置文件 环境隔离彻底、配置显式 文件增多、维护成本略高
推荐实践: 开发环境使用 alembic.ini 默认配置,生产环境通过 CI/CD 注入环境变量。避免将生产配置明文存储在代码仓库中。

4.8 本章小结