Django AWS Elastic Beanstalk数据库迁移

10

我正在使用Elastic Beanstalk将Django项目部署到AWS上,但在迁移数据库时遇到了问题。

目前情况:我能够成功部署django项目,并通过mysubdomain.elasticbeanstalk.com加载页面。在需要进行数据库调用的页面之前,页面加载没有错误。但是当我进入这些页面时,就会收到类似于relation "accounts_user" does not exist LINE 1: SELECT COUNT(*) FROM "accounts_user"的错误提示,因为我的数据库还没有被迁移。

我尝试过的:我尝试了许多不同的方法。幸运的是,有很多stackoverflow帖子和一些教程。不幸的是,它们似乎都在使用不同版本,而他们所建议的方法并不适用于我的项目。

很明显,我需要在.ebextensions/文件夹中的foobar.config文件中运行迁移。以下是我想要做的基本内容:

container_commands:
  01_migrate:
    command: "python manage.py migrate --noinput"
    leader_only: true

在日志中,我看到发布后脚本尝试运行但失败了。我没有收到任何其他有关错误的信息,我只看到类似于“ERROR:01_migrate post deployment script failed”的信息。

我发现我需要为该命令激活虚拟环境,这很有道理。从asdf中,我尝试了这个:

container_commands:
  01_migrate:
    command: "source /opt/python/run/venv/bin/activate && python rlg/manage.py migrate --noinput"
    leader_only: true

但它不起作用。实际上,通过SSH,我发现我甚至没有/opt/python/文件夹,只有/opt/aws/和/opt/elasticbeanstalk/。所有的教程和SO问题都涉及到这个文件夹,但我没有它?

版本: Python 3.4.1,Django 1.7.7,AWS CLI 3.2.1,Postgres 9.3


1
我卡在同一个地方了。我发现:container_commands不会在docker容器内执行,而是在ec2实例本身上执行。我猜我们需要使用类似于“docker exec [container_name] /var/app/bin/python manage.py migrate --noinput”的东西来执行迁移。不幸的是,我仍然在努力找到正确的[container_name]。 - Sebastian Annies
@SebastianAnnies 很棒,很高兴找到和我处于同一位置的人!谢谢你的提示,我也会继续努力,并让你知道我发现的任何东西。 - awwester
不确定这个教程是什么时候写的,但它有一个专门介绍Django迁移的部分。https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-django.html - Josh
4个回答

15

我知道这是一个旧帖子,但我想在这里发布我的答案,因为我花了很长时间才找到答案。

Sebastian 在某种程度上指引了我正确的方向,但是这种方法的问题是它在部署之前运行(所以你迁移旧代码)

您还可以在 ebextensions 中使用 files 命令,并编写一个文件到 /opt/elasticbeanstalk/hooks/appdeploy/post,但这将在每个实例上运行。

你可以把这两件事结合起来:

container_commands:
  01migrate:
    command: "mkdir -p /opt/elasticbeanstalk/hooks/appdeploy/post/ && echo -e '#!/bin/bash\ndocker exec `docker ps -a -q | head -n 1` python <path_to_code> migrate' > /opt/elasticbeanstalk/hooks/appdeploy/post/99_migrate.sh && chmod +x /opt/elasticbeanstalk/hooks/appdeploy/post/99_migrate.sh"
    leader_only: true

这将在正确的目录中创建一个发布后脚本,并且仅在主节点上运行。

对我来说,这非常有效,但请注意,hooks目录是未经记录的功能。


10

container_commands不在Docker容器内执行,而是直接在EC2实例上执行。目前,我正在使用 docker exec 进行迁移。由于相关的Docker容器是最后一个启动的,因此我使用 docker ps -a --no-trunc -q | head -n 1 获取容器ID。

最终,我的setup.config看起来像这样

container_commands:
  01syncdb:
    command: "docker exec `docker ps -a --no-trunc -q | head -n 1` /var/app/bin/python /var/app/manage.py syncdb --noinput  &>> /tmp/deploy.log"
    leader_only: true
  02migrate:
    command: "docker exec `docker ps -a --no-trunc -q | head -n 1` /var/app/bin/python /var/app/manage.py migrate --noinput  &>> /tmp/deploy.log"
    leader_only: true

希望这也能解决你的问题。


仅供阅读:https://forums.aws.amazon.com/ann.jspa?annID=2982 我们本可以避免这些麻烦... - Sebastian Annies
1
我尝试过这个,但是我注意到它获取的是我的旧容器而不是新的!有其他人遇到过这个问题吗?我正在尝试一个稍微修改但等价的命令:"CONTAINER=\docker ps -a --no-trunc | grep aws_beanstalk | cut -d' ' -f1 | head -1` && docker exec $CONTAINER python3 manage.py migrate"` - MrColes
1
这个可以运行,但是会在当前版本上执行命令,而不是正在部署的暂存版本(正如@MrCols所说)。nkhumphreys提供的解决方案似乎可以在新部署的版本上解决问题。 - Hugo Briand

0

从所有实例运行迁移(简单且经过测试)

Amazon Linux 2平台引入了钩子来处理这类问题。在项目的<PROJECT_ROOT>/.platform/hooks/postdeploy/migrate.sh中添加以下文件:

#!/bin/bash

docker exec `docker ps -a -q | head -n 1` python manage.py migrate

这里是文档:https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/platforms-linux-extend.html

仅从领导者运行迁移(未经测试)

要仅从领导者运行迁移,请尝试以下操作:

.ebextensions/migrate.config

container_commands:
  touch_the_leader:
    command: touch /tmp/migrate
    leader_only: true

.platform/hooks/postdeploy/migrate.sh

#!/bin/bash

if [ -f /tmp/migrate ]; then
    docker exec `docker ps -a -q | head -n 1` python manage.py migrate
    rm /tmp/migrate
fi

-3

更新有关最新 Elastic Beanstalk 版本的信息。

我正在使用 64 位 Amazon Linux 2016.09 v2.3.3 运行 Python 3.4

以下命令适用于我,无需激活 virtualenv 或创建后应用程序部署钩子。

container_commands:
  01_migrate_db:
    command: "python manage.py db upgrade" <-- insert your migration command here
    leader_only: true

为了证明容器命令将在发布后执行,我对我的模型进行了更改,生成了更新的迁移脚本,部署了新版本,并检查数据库是否成功迁移:成功!

2
那是因为你没有在Docker容器中运行你的Django应用程序,而是在Python 3.4镜像上运行。在使用Docker的设置中,情况不同(请参见有关在最新的Docker容器中运行命令的注释)。这是Docker环境特定的问题。 - yellowcap

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接