Home > other >  docker-compose and docker: need to intialize with dummy data only first time. whats the best way to
docker-compose and docker: need to intialize with dummy data only first time. whats the best way to

Time:10-10

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.

  • Related