您的位置:首页 > 运维架构 > Docker

在docker中使用alembic管理数据库的问题

2017-08-17 17:05 381 查看
alembic是配合SQLAlchemy的一个工具,可以方便的upgrade或downgrade数据库,而不用每次修改都进行reset操作导致数据丢失。

安装和初始化

pip install alembic


安装之后在project的目录下面执行初始化命令:

alembic init APP/NAME


这里APP是我Flask的APP名称,NAME是存放alembic初始化文件的文件夹名称,我这里用的是migrations。

初始化后,进入migrations文件夹,会有versions文件夹,每次生成的revision file会在这儿,env.py环境文件,根据项目设置,以及script.py.mako产生revision file的模板文件,如果需要可以自定义,这里我是将常用的sqlalchemy及时间相关的包导入放在了这里,不用每次都去添加。

在project文件夹下还有一个alembic.ini的文件,也是初始化生成的。

首次使用

docker-compose up # 启动image


假设现在我们要添加一个foo table,执行下面的命令创建一个revision file:

docker-compose exec --user "$(id -d):$(id -g)" website alembic revision -m "create foo table"


其实除开docker的命令,这个和git的使用是很像的,–user “(id−d):(id -g)”这个地方是使用native docker的用户需要的,保证生成的文件归属于用户否则是属于root的,如果是下OSX或Windows下用docker machine可以忽略。

生成的文件在versions文件夹下,文件名为HASH_注释的信息.py,upgrade和downgrade本应为pass,这里我已经手动修改了:

import sqlalchemy as sa

from alembic import op

from lib.util_datetime import tzware_datetime
from lib.util_sqlalchemy import AwareDateTime

"""
create foo table

Revision ID: 934098c9f899
Revises:
Create Date: 2017-08-16 01:34:43.895131
"""

# Revision identifiers, used by Alembic.
revision = '934098c9f899'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
op.create_table('foos',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('created_on', AwareDateTime(),
default=tzware_datetime),
sa.Column('updated_on', AwareDateTime(),
default=tzware_datetime,
onupdate=tzware_datetime),
sa.Column('bar', sa.String(128), index=True))

def downgrade():
op.drop_table('foos')


手动修改了upgrade和downgrade方法后,就可以去terminal中运行了:

docker-compose exec website alembic upgrade head


这里head始终表示revision的最新文件,即使你多次降级后,执行upgrade head仍然是执行的最新的revision file。

升级成功后,会提示已经指向了这次升级的revision的hash。同理,降级:

docker-compose exec website alembic downgrade -1


降级一次,升级也能用+1,这里也可以用其他数字。

写到这里,大家可能觉得不好用,因为这还没有结合SQLAlchemy来使用。

与SQLAlchemy一起用

加减个新表不是使用alembic的真正价值所在,这次我们需要在users的表中增加一列foobar。

首先,我们找到users models.py,在User下直接添加一列foobar,这时再升级就需要使用–autogenerate这个flag了,他能帮我们自动的生成相应的revision file,而不是生成空白的自己去填写,我们需要做的就是检查是否正确,做修改后执行升级操作:

docker-compose exec --user "$(id -u):$(id -g)" website alembic revision --autogenerate -m "add foobar column to users"


这里会生成一个新的revision file,但是你会发现这里有对foo table的操作,比如会在升级的时候drop foo table,因为自动生成是根据ORM的关系来构建的,而foo是我们通过修改revision file生成的,不存在于model中,所以,这里如果要保留foo就应该将其中对foo的操作去掉,去掉后结果如下:

import sqlalchemy as sa

from alembic import op

from lib.util_datetime import tzware_datetime
from lib.util_sqlalchemy import AwareDateTime
from sqlalchemy.dialects import postgresql

"""
add foobar column to users

Revision ID: d7676576f4ef
Revises: 73428a75ef16
Create Date: 2017-08-16 15:16:10.539365
"""

# Revision identifiers, used by Alembic.
revision = 'd7676576f4ef'
down_revision = '73428a75ef16'
branch_labels = None
depends_on = None

def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('foobar', sa.String(length=128), nullable=True))
op.create_index(op.f('ix_users_foobar'), 'users', ['foobar'], unique=False)
### end Alembic commands ###

def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_users_foobar'), table_name='users')
op.drop_column('users', 'foobar')
### end Alembic commands ###


这时我们再去执行一次升级操作就能完成对users这个表添加foobar列的操作。

补充命令行

docker-compose exec website alembic current # 查询当前所在的revision
docker-compose exec website alembic history --verbose # revision的详细历史记录


其他不清楚的都能用 –help这个flag查询。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据库