Why does Django recreate the DB tables on each docker-container restart?

1.3k Views Asked by At

I am running Django with PostgreSQL in a docker-compose setup for development. Each time I restart the application container, the database is empty, even though I do neither restart the DBMS container nor do I drop the DBMS's data volume. It seems that Django is dropping all tables upon restart. Why?

My setup closely follows the description here. That is, my compose file looks as follows (simplified):

version: '3.8'

services: 
    
  db:
    image: postgres
    environment:
      - POSTGRES_DB=db_dev
      - POSTGRES_USER=dev
      - POSTGRES_PASSWORD=postgres
    volumes:
      - type: volume
        source: app-data
        target: /var/lib/postgresql/data
  
  app:
    build: .
    command: python manage.py runserver 0.0.0.0:8888
    container_name: app
    environment:
      - DATABASE_URL
      - PYTHONDONTWRITEBYTECODE=1
      - PYTHONUNBUFFERED=1
    volumes:
      # Mount the local source code folder for quick iterations.
      # See: https://www.docker.com/blog/containerized-python-development-part-3/
      - type: bind
        source: .
        target: /code
    ports:
      - target: 8888
        published: 8888
    depends_on:
      - db
    env_file:
      - ./dev.env

volumes:
    app-data:
      external: true

The Django application is started by means of an entrypoint.sh:

#! /bin/sh

if [ "$DATABASE" = "postgresql" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

doMigrate=${DB_MIGRATE:-false}
if [ "$doMigrate" = true ] ;
then
  python manage.py flush --no-input
  python manage.py migrate
fi

exec "$@"

In the development setup, I set DB_MIGRATE=true and DEBUG=1.

1

There are 1 best solutions below

0
On BEST ANSWER

The Django flush command removes all data from the database, as explained in the documentation.

Hence, to solve my problem above, I only need to remove the line

  python manage.py flush --no-input

from my entrypoint.sh script.

Explanation: I thought - incorrectly - that flush would commit any pending transactions that might still be open from other applications that might potentially use the DB. This is not the case. Instead, flush simply removes all data.