How to execute docker-entrypoint-initdb.d/init.sql files AFTER database is created?
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.
更多推荐
所有评论(0)