¿Cómo se realizan las migraciones de bases de datos de Django cuando se usa Docker-Compose?

99

He configurado una aplicación Docker Django / PostgreSQL siguiendo de cerca las instrucciones de inicio rápido de Django en el sitio de Docker .

La primera vez que ejecuto manage.py migrate de Django, usando el comando sudo docker-compose run web python manage.py migrate, funciona como se esperaba. La base de datos está construida dentro del contenedor Docker PostgreSQL muy bien.

Los cambios realizados en la propia aplicación Django también se reflejan en el contenedor Docker Django, en el momento en que los guardo. ¡Es genial!

Pero si luego cambio un modelo en Django e intento actualizar la base de datos de Postgres para que coincida con el modelo, no se detectan cambios, por lo que no se produce ninguna migración, sin importar cuántas veces lo ejecute makemigrationso de migratenuevo.

Básicamente, cada vez que cambio el modelo de Django, tengo que eliminar los contenedores de Docker (usando sudo docker-compose rm) y comenzar de nuevo con una nueva migración.

Todavía estoy tratando de entender a Docker, y hay muchas cosas que no entiendo sobre cómo funciona, pero este me está volviendo loco. ¿Por qué migrar no ve mis cambios? ¿Qué estoy haciendo mal?

Juan
fuente
¿Descubriste por qué? Recibo la respuesta a continuación y funciona: You just have to log into your running docker container and run your commands.pero ¿cuál es la razón por la que se comporta de esa manera? @LouisBarranqueiro
lukik

Respuestas:

104

Solo tiene que iniciar sesión en su contenedor docker en ejecución y ejecutar sus comandos.

  1. Construye tu pila: docker-compose build -f path/to/docker-compose.yml
  2. Lanza tu pila: docker-compose up -f path/to/docker-compose.yml
  3. Mostrar contenedores en ejecución de Docker: docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
3fcc49196a84        ex_nginx          "nginx -g 'daemon off"   3 days ago          Up 32 seconds       0.0.0.0:80->80/tcp, 443/tcp   ex_nginx_1
66175bfd6ae6        ex_webapp         "/docker-entrypoint.s"   3 days ago          Up 32 seconds       0.0.0.0:32768->8000/tcp       ex_webapp_1
# postgres docker container ...
  1. Obtenga el ID DE CONTENEDOR de su aplicación django e inicie sesión en:
docker exec -t -i 66175bfd6ae6 bash
  1. Ahora ha iniciado sesión, luego vaya a la carpeta correcta: cd path/to/django_app

  2. Y ahora, cada vez que edite sus modelos, ejecute en su contenedor: python manage.py makemigrationsypython manage.py migrate

También le recomiendo que use un punto de entrada de docker para que su archivo contenedor de docker de django se ejecute automáticamente:

  • colecstatic
  • emigrar
  • runserver o inícielo con gunicorn o uWSGI

Aquí hay un ejemplo ( docker-entrypoint.sh):

#!/bin/bash

# Collect static files
echo "Collect static files"
python manage.py collectstatic --noinput

# Apply database migrations
echo "Apply database migrations"
python manage.py migrate

# Start server
echo "Starting server"
python manage.py runserver 0.0.0.0:8000
Luis Barranqueiro
fuente
16
También le recomiendo que use un punto de entrada de docker para que su archivo contenedor de docker de django se ejecute automáticamente ; tales operaciones nunca deben ejecutarse automáticamente; me refiero a migrar especialmente.
Opal
7
No importa en qué entorno se encuentre, la implementación siempre debe tener el mismo aspecto. Si las migraciones están automatizadas, es posible que se ejecuten al mismo tiempo, lo cual no se recomienda. Por ejemplo, en heroku: las migraciones nunca se ejecutan como parte del despliegue.
Opal
5
concurentemente? Aquí estamos en un entorno de desarrollo. Yo corro makemigrations. la próxima vez que lance mi pila, migrateactualizaré la base de datos con las últimas migraciones deshechas, de lo contrario, la aplicación django no funcionará correctamente ... Es solo un acceso directo en dev env para asegurarse de que tiene el esquema de base de datos correcto con la aplicación actual
Louis Barranqueiro
2
@LouisBarranqueiro, me refiero a varias instancias, una sola base de datos.
Opal
1
Para el paso 4, recomendaría: docker exec -ti $ CONTAINER_ID / bin / sh
Santiago Magariños
52

Yo uso estos métodos:

services:
  web:
    build: .
    image: uzman
    command: python manage.py runserver 0.0.0.0:8000
    ports:
      - "3000:3000"
      - "8000:8000"
    volumes:
      - .:/code
    depends_on:
      - migration
      - db
  migration:
    image: uzman
    command: python manage.py migrate --noinput
    volumes:
      - .:/code
    depends_on:
      - db

Usando la dockerjerarquía que hicimos, la migración del servicio se ejecuta después de configurar la base de datos y antes de ejecutar el servicio principal. Ahora, cuando ejecute su servicio, dockerse ejecutarán las migraciones antes de ejecutar el servidor; Mira que el migrationservidor se aplica sobre la misma imagen que el servidor web, significa que todas las migraciones serán tomadas de tu proyecto, evitando problemas.

De esta forma evitas hacer punto de entrada o cualquier otra cosa.

SalahAdDin
fuente
2
¿Cómo build: .funciona? image: Recibo el error de que la migración no puede extraer la imagen nombrada
Aaron McMillin
2
Resolví que al poner el build:sobre migration, ya que se ejecutará antesweb
Aaron McMillin
4
¿No mantiene esto funcionando la imagen de Uzman y consumiendo RAM para siempre? Además, ¿qué es la imagen de Uzman?
mlissner
Es mi imagen personalizada de la ventana acoplable. Todavía no he probado la RAM.
SalahAdDin
32

Haga que su pila se ejecute y luego ejecute un comando de ejecución de docker-compose de un solo disparo. P.ej

#assume django in container named web
docker-compose run web python3 manage.py migrate

Esto funciona muy bien para la base de datos SQLite incorporada (predeterminada), pero también para una base de datos externa acoplada que aparece como dependencia. Aquí hay un ejemplo de archivo docker-compose.yaml

version: '3'

services:
  db:
    image: postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db

https://docs.docker.com/compose/reference/run/

Oliver Shaw
fuente
12

Puedes usar el docker execcomando

docker exec -it container_id python manage.py migrate
SuperNova
fuente
1
Esta debería ser la respuesta.
Tolga
Para obtener el container_id mencionado, hazlo docker psy luego busca la columna COMMAND para el servidor django.
Jai Sharma
5

Si tienes algo como esto en tu docker-compose.yml

version: "3.7"

services:

  app:
    build:
      context: .
      dockerfile: docker/app/Dockerfile
    ports:
    - 8000:8000
    volumes:
        - ./:/usr/src/app
    depends_on:
      - db

  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_USER: docker
      POSTGRES_PASSWORD: docker
      POSTGRES_DB: docker

Entonces puedes simplemente ejecutar ...

~$ docker-compose exec app python manage.py makemigrations
~$ docker-compose exec app python manage.py migrate
Robert Johnstone
fuente
2

Sé que esto es antiguo, y tal vez me falta algo aquí (si es así, ¡ilumíneme!), Pero ¿por qué no agregar los comandos a su start.shscript, ejecutado por Docker para iniciar su instancia? Solo le llevará unos segundos más.

Nota : configuro la DJANGO_SETTINGS_MODULEvariable para asegurarme de que se utiliza la base de datos correcta, ya que utilizo diferentes bases de datos para el desarrollo y la producción (aunque sé que esto no es la "mejor práctica").

Esto me lo resolvió:

#!/bin/bash
# Migrate the database first
echo "Migrating the database before starting the server"
export DJANGO_SETTINGS_MODULE="edatool.settings.production"
python manage.py makemigrations
python manage.py migrate
# Start Gunicorn processes
echo "Starting Gunicorn."
exec gunicorn edatool.wsgi:application \
    --bind 0.0.0.0:8000 \
    --workers 3
TBZ92
fuente
1

Al usar Docker Exec, recibí el siguiente error:

AppRegistryNotReady("Models aren't loaded yet.")

Entonces usé este comando en su lugar:

docker-compose -f local.yml run django python manage.py makemigrations
Santiago Magariños
fuente