I have a django docker image and using docker-compose to start it along with postgresql.
# docker-compose -p torsha-single -f ./github/docker-compose.yml --project-directory ./FINAL up --build --force-recreate --remove-orphans
# docker-compose -p torsha-single -f ./github/docker-compose.yml --project-directory ./FINAL exec fastapi /bin/bash
# My version of docker = 18.09.4-ce
# Compose file format supported till version 18.06.0 is 3.7
version: "3.7"
services:
postgresql:
image: "postgres:13-alpine"
restart: always
volumes:
- type: bind
source: ./DO_NOT_DELETE_postgres_data
target: /var/lib/postgresql/data
environment:
POSTGRES_DB: project
POSTGRES_USER: postgres
POSTGRES_PASSWORD: abc123
PGDATA: "/var/lib/postgresql/data/pgdata"
networks:
- postgresql_network
webapp:
image: "django_image"
depends_on:
- postgresql
ports:
- 8000:8000
networks:
- postgresql_network
networks:
postgresql_network:
driver: bridge
Now when after I do docker-compose up
for first time I have to create dummy data using
docker-compose exec webapp sh -c 'python manage.py migrate';
docker-compose exec webapp sh -c 'python manage.py shell < useful_scripts/intialize_dummy_data.py'
After this anytime later I dont need to do the above.
Where to place this script so it checks if its first time then run these commands.
CodePudding user response:
docker-compose run is designed for this type of problem. Pair it with the -rm flag to remove the container when the command is complete. Common examples are doing the sort of migrations and initialization you are trying to accomplish.
This is right out of the manual page for the docker-compose run command:
docker-compose run --rm web python manage.py db upgrade
You can think of this as a sort of disposable container, that does one job, and exits. This technique can also be used for scheduled jobs with cron.
CodePudding user response:
One of the Django documentation's suggestions for Providing initial data for models is to write it as a data migration. That will automatically load the data when you run manage.py migrate
. Like other migrations, Django records the fact that it has run in the database itself, so it won't re-run it a second time.
This then reduces the problem to needing to run migrations when your application starts. You can write a shell script that first runs migrations, then runs some other command that's passed as arguments:
#!/bin/sh
python manage.py migrate
exec "$@"
This is exactly the form required for a Docker ENTRYPOINT
script. In your Dockerfile, COPY
this script in with the rest of your application, set the ENTRYPOINT
to run this script, and set the CMD
to run the application as before.
COPY . . # probably already there
ENTRYPOINT ["./entrypoint.sh"] # must be JSON-array form
CMD python manage.py runserver 0.0.0.0:8000 # unchanged
(If you already have an entrypoint wrapper script, add the migration line there. If your Dockerfile somehow splits ENTRYPOINT
and CMD
, combine them into a single CMD
.)
Having done this, the container will run migrations itself whenever it starts. If this is the first time the container runs, it will also load the seed data. You don't need any manual intervention.