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 命令生成项目骨架。
安装步骤
- 创建并激活虚拟环境(推荐使用 Python 3.9+)
- 安装 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 # 全局配置文件
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+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 容器数据库之间的调用关系与数据流。
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 调试 |
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 注入环境变量。避免将生产配置明文存储在代码仓库中。