【发布时间】:2019-09-18 06:14:48
【问题描述】:
对于 Docker 来说还很新,我正在尝试将自定义 sql 脚本(触发器和函数)的执行添加到 Django 的迁移过程中,我开始感到有点失落。总体而言,我想要实现的目标遵循这个漂亮的clear tutorial。在本教程中,迁移是通过执行入口点脚本来实现的。在 Dockerfile 中:
# run entrypoint.sh
ENTRYPOINT ["/usr/src/my_app/entrypoint.sh"]
这里是 entrypoint.sh:
#!/bin/sh
if [ "$DATABASE" = "postgres" ]
then
echo "Waiting for postgres..."
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done
echo "PostgreSQL started"
fi
# tried several with and without combinations
python manage.py flush --no-input
python manage.py makemigrations my_app
python manage.py migrate
exec "$@"
到目前为止一切顺利。关于在迁移过程中集成自定义sql脚本的执行的问题,我看的大部分文章(例如this one)都建议创建一个空迁移来添加sql语句的执行。这是我所拥有的
my_app/migrations/0001_initial_data.py
import os
from django.db import migrations, connection
def load_data_from_sql(filename):
file_path = os.path.join(os.path.dirname(__file__), '../sql/', filename)
sql_statement = open(file_path).read()
with connection.cursor() as cursor:
cursor.execute(sql_statement)
class Migration(migrations.Migration):
dependencies = [
('my_app', '0001_initial'),
]
operations = [
migrations.RunPython(load_data_from_sql('my_app_base.sql'))
]
如 dependencies 所述,此步骤取决于初始步骤 (0001_initial.py):
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Unpayed',
fields=[
etc etc
[问题] 但是,即使我尝试手动迁移 (docker-compose exec web python manage.py makemigrations my_app),我也会收到以下错误,因为 postgresql 容器中的 db 是 empty:
File "/usr/src/my_app/my_app/migrations/0001_initial_data.py", line 21, in Migration
migrations.RunPython(load_data_from_sql('my_app_base.sql'))
File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 82, in _execute
....
return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "auth_user" does not exist
[我不明白的地方] 但是,当我登录容器时,删除0001_initial_data.py 并运行./entrypoint.sh,一切都像魅力一样工作并创建了表格。我可以稍后手动添加0001_initial_data.py,再次运行entrypoint.sh 并拥有我的功能。当我在运行docker-compose up -d --build 之前删除此文件时也是如此:已创建表。
我觉得我错过了一些明显的方法,并且在尝试以这种规范方式集成 sql 脚本迁移时更容易。我只需要在 0001_initial 迁移结束后运行这个脚本。你会怎么做?
[编辑] docker-compose.yml:
version: '3.7'
services:
web:
build:
context: ./my_app
dockerfile: Dockerfile
command: python /usr/src/my_app/manage.py runserver 0.0.0.0:8000
volumes:
- ./my_app/:/usr/src/my_app/
ports:
- 8000:8000
environment:
- SECRET_KEY='o@@xO=jrd=p0^17svmYpw!22-bnm3zz*%y(7=j+p*t%ei-4pi!'
- SQL_ENGINE=django.db.backends.postgresql
- SQL_DATABASE=postgres
- SQL_USER=postgres
- SQL_PASSWORD=N0tTh3D3favlTpAssw0rd
- SQL_HOST=db
- SQL_PORT=5432
depends_on:
- db
db:
image: postgres:10.5-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
volumes:
postgres_data:
django:2.2 蟒蛇:3.7
【问题讨论】:
-
为什么在 Docker 文件中运行
makemigrations?my_app/migrations/0001_initial.py签到了吗? -
“签到”?你的意思是,在我
docker-compose up之后的容器中?是的。以及为什么makemigrations在入口点?老实说,因为我发现这个“创建一个空的迁移以在迁移期间执行自定义 sql”的技巧非常令人困惑,只是为了弄清楚它是否改变了一些东西。我认为makemigrations必须在migrate之前运行 -
“签入”就像在“签入到版本控制”中一样。或者换句话说,迁移
0001_initial是否存在在你docker-compose up之前? -
是的。它在我
docker-compose up之前的源文件中(如果我理解正确的话) -
请分享您的撰写文件。还有什么版本的python和django?
标签: django postgresql docker database-migration devops