创建数据库后如何执行docker-entrypoint-initdb.d/init.sql文件



我有一个带有Docker 的Django应用程序

我想在运行docker compose-up 时基于init.sql文件初始化我的数据库

2个容器已正确构建,init.sql文件在db_container 中可用

但CCD_ 1显示了一个错误,表明数据库尚未迁移:

错误:关系表1不存在

执行entrypoint.sh文件时创建数据库(命令python manage.py migrate(

我不明白init.db是什么时候执行的?

Dockerfile

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" ]

入口点.sh

#!/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 "$@"

docker compose.yml

version: '3.7'
services:
web:
...
depends_on: 
- db
db:
image: postgres:12.0-alpine
restart: always
volumes:
- postgres_data:/var/lib/postgres/data/
- ./imports/init.sql:/docker-entrypoint-initdb.d/init.sql
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=user
- POSTGRES_DB=db_dev
volumes:
postgres_data:

init.sql

c db_dev
INSERT INTO table1 (field1,field2,field3) VALUES ('value1','value2','value3');
...

/docker-entrypoint-initdb.d/init.sql在数据库容器开始运行的那一刻执行,而entrypoint.sh在web容器开始运行时执行。由于web容器依赖于数据库容器,SQL脚本将始终在入口点之前执行。

换句话说,你想要的是不可能的。

您需要在init.sql中创建数据库和表1,并告诉Django如果它们已经存在,就不要尝试创建它们,或者以某种方式将INSERT..添加到要运行的迁移列表中。

我从来没有使用过Django,所以我不知道以上任何一种是否可行。

事情通常会按照以下顺序运行:

  1. 显示的webbuild:块和Dockerfile执行。这将永远无法访问数据库
  2. 创建db容器
  3. 创建docker logs db_container0容器
  4. 应用程序映像的入口点脚本进入nc -z循环,并在此处有效地暂停
  5. postgres映像的入口点脚本启动一个临时PostgreSQL实例
  6. postgres映像的入口点脚本创建db_dev数据库,该数据库在POSTGRES_DB环境变量中命名
  7. postgres映像的入口点脚本运行/docker-entrypoint-initdb.d中的所有文件(包括您显示的init.sql脚本(
  8. postgres镜像的入口点脚本停止临时PostgreSQL实例,并启动真正的网络可访问实例
  9. 应用程序映像的入口点脚本成功连接到PostgreSQL,并通过nc循环
  10. 应用程序映像的入口点脚本运行python manage.py migrate
  11. 应用程序映像的入口点脚本exec "$@"以运行主容器命令

换句话说:Django迁移命令要等到PostgreSQL容器完全完成首次启动(包括运行docker-entrypoint-initdb.d脚本(后才能运行。这意味着在迁移中创建的表永远不存在。

需要在初始化时加载到数据库中的数据,例如运行测试或用于众所周知的";管理员";用户通常被称为"用户";种子数据";。如何种子Django项目?-将一堆数据插入到项目中进行初始化。例如,添加自定义manage.py命令或fixtures文件来加载种子数据。在您显示的入口点脚本中,您将在运行迁移之后,但在最后启动主服务器之前添加python manage.py seedload data命令。

感谢两者。

我使用数据迁移https://docs.djangoproject.com/en/3.1/howto/writing-migrations/

并且我抑制docker入口点initdb.d脚本我的数据库在执行入口点时初始化(manage.py migrate应用所有迁移(

这对您的案例有效吗?

1(首先,在文件夹db 中创建一个init脚本

db1-init.sh

init脚本用于创建数据库(如果不存在(。您也可以在此处添加数据插入

#!/bin/bash
set -e
export PGPASSWORD=$POSTGRES_PASSWORD;
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER $APP_DB_USER WITH PASSWORD '$APP_DB_PASS';
CREATE DATABASE $APP_DB_NAME;
GRANT ALL PRIVILEGES ON DATABASE $APP_DB_NAME TO $APP_DB_USER;
connect $APP_DB_NAME $APP_DB_USER
BEGIN;
CREATE TABLE IF NOT EXISTS event (
id CHAR(26) NOT NULL CHECK (CHAR_LENGTH(id) = 26) PRIMARY KEY,
xxx INT,
yyy JSON NOT NULL,
UNIQUE(xxx)
);
COMMIT;
EOSQL

2(然后在docker compose文件中,卷将主机db文件夹映射到容器docker入口点initdb.d以共享db init脚本

version: '3'
services:
sql_app:
... ## Other settings
depends_on:
- postgres
networks:
- postgres-network
postgres:
image: postgres:13.1
... ## Other settings
restart: always
environment:
- POSTGRES_USER=foooooo
- POSTGRES_PASSWORD=foooooo
- APP_DB_USER=foooooo
- APP_DB_PASS=foooooo
- APP_DB_NAME=foooooo
volumes:
- ./db:/docker-entrypoint-initdb.d/
ports:
- 5432:5432
networks:
- postgres-network
networks:
postgres-network:
driver: bridge

3(删除Dockerfile 中的迁移脚本

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 . .

最新更新