Answer a question

I have a Django app with Docker

I want to initialize my database based on init.sql file when running docker-compose up

2 containers are correctly built and init.sql file is available in db_container

but docker logs db_container show an error indicating that database has not been migrated yet:

ERROR: relation table1 does not exist

Database is created when entrypoint.sh files is executed (command python manage.py migrate)

I do not understand when init.db is executed?

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

entrypoint.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');
...

Answers

/docker-entrypoint-initdb.d/init.sql is executed the moment your database container starts running, while your entrypoint.sh is executed the moment your web container starts running. Since your web container depends on your database container, the SQL script will always be executed ahead of your entrypoint.

In other words, what you want is impossible.

You need to either create the database and table1 in init.sql and tell Django not to attempt creating them if they already exists or somehow add your INSERT.. to the list of migrations to be run.

I've never used Django, so I do not know if either of the above is possible.

Logo

云原生社区为您提供最前沿的新闻资讯和知识内容

更多推荐