我有一个带有Docker的Django应用
我想在运行docker-compose up时基于init.sql文件初始化数据库
正确构建了2个容器,并且db_container中提供了init.sql文件
但是'a'
显示一个错误,指示数据库尚未迁移:
错误:关系table1不存在
执行entrypoint.sh文件时创建数据库(命令python manage.py migration)
我不明白何时执行init.db?
Dockerfile
POINTS
entrypoint.sh
docker logs db_container
docker-compose.yml
FROM python:3.8.3-alpine
WORKDIR /usr/src/app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN apk update && apk add postgresql-dev gcc python3-dev musl-dev
RUN apk --update add libxml2-dev libxslt-dev libffi-dev gcc musl-dev libgcc openssl-dev curl
RUN apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev
RUN pip3 install psycopg2 psycopg2-binary
COPY requirements/ requirements/
RUN pip install --upgrade pip && pip install -r requirements/dev.txt
COPY ./entrypoint.sh .
COPY . .
# Run entrypoint.sh
ENTRYPOINT [ "/usr/src/app/entrypoint.sh" ]
init.sql
#!/bin/sh
if [ "$DATABASE" = "postgres" ]
then
echo "Waiting for postgres..."
# nc = netcap -z = scanning
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done
echo "PostgreSQL started"
fi
python manage.py flush --no-input
python manage.py migrate
exec "$@"
答案 0 :(得分:0)
/docker-entrypoint-initdb.d/init.sql
在数据库容器开始运行时执行,而entrypoint.sh
在Web容器开始运行时执行。由于您的Web容器取决于数据库容器,因此SQL脚本将始终在入口点之前执行。
换句话说,想要什么是不可能的。
您需要在init.sql
中创建数据库和table1,并告诉Django不要尝试创建它们(如果它们已经存在),或者以某种方式将您的INSERT..
添加到要运行的迁移列表中。
我从没使用过Django,所以我不知道以上两种方法是否可行。
答案 1 :(得分:0)
事物通常按以下顺序运行:
web
build:
块和Dockerfile
执行。这将永远无法访问数据库。db
容器已创建。web
容器已创建。nc -z
循环,并在此处有效地暂停。postgres
映像的入口点脚本将启动一个临时PostgreSQL实例。postgres
图像的入口点脚本创建db_dev
环境变量中命名的POSTGRES_DB
数据库。postgres
图像的入口点脚本运行/docker-entrypoint-initdb.d
中的所有文件(包括您显示的init.sql
脚本)。postgres
映像的入口点脚本将停止临时PostgreSQL实例,并启动真正的可通过网络访问的实例。nc
循环。python manage.py migrate
。exec "$@"
用于运行主容器命令。采用另一种方式:Django迁移命令要等到PostgreSQL容器完全完成其首次启动(包括运行docker-entrypoint-initdb.d
脚本)后才能运行。这意味着在迁移中创建的表将永远不存在。
需要在初始化时加载到数据库中的数据(例如,运行测试或为知名的“ admin”用户运行)通常称为“种子数据”。 How to seed Django project ? - insert a bunch of data into the project for initialization包含添加自定义manage.py
命令或fixtures
文件以加载种子数据的示例。在显示的入口点脚本中,您将在运行迁移之后但在最后启动主服务器之前添加python manage.py seed
或load data
命令。
答案 2 :(得分:0)
感谢双方。
我使用数据迁移https://docs.djangoproject.com/en/3.1/howto/writing-migrations/
我取消了docker-entrypoint-initdb.d脚本 执行入口点时,我的数据库已初始化(manage.py migration应用所有迁移)