Come si eseguono le migrazioni del database Django quando si utilizza Docker-Compose?


99

Ho configurato un'app Docker Django / PostgreSQL seguendo da vicino le istruzioni Django Quick Start sul sito Docker .

La prima volta che eseguo il manage.py migrate di Django, usando il comando sudo docker-compose run web python manage.py migrate, funziona come previsto. Il database è costruito all'interno del contenitore Docker PostgreSQL perfettamente.

Le modifiche apportate all'app Django stessa si riflettono allo stesso modo nel contenitore Docker Django, nel momento in cui le salvo. È ottimo!

Ma se poi cambio un modello in Django e provo ad aggiornare il database Postgres in modo che corrisponda al modello, non vengono rilevate modifiche, quindi non viene eseguita alcuna migrazione, indipendentemente da quante volte eseguo makemigrationso di migratenuovo.

In sostanza, ogni volta che cambio il modello Django, devo eliminare i container Docker (utilizzando sudo docker-compose rm) e ricominciare da capo con una nuova migrazione.

Sto ancora cercando di capire bene Docker, e ci sono molte cose che non capisco su come funziona, ma questo mi sta facendo impazzire. Perché la migrazione non vede le mie modifiche? Che cosa sto facendo di sbagliato?


Hai capito perché? Ricevo la risposta di seguito e funziona: You just have to log into your running docker container and run your commands.ma qual è il motivo per cui si comporta in questo modo? @LouisBarranqueiro
lukik

Risposte:


104

Devi solo accedere al tuo container Docker in esecuzione ed eseguire i tuoi comandi.

  1. Costruisci il tuo stack: docker-compose build -f path/to/docker-compose.yml
  2. Avvia il tuo stack: docker-compose up -f path/to/docker-compose.yml
  3. Visualizza docker in esecuzione contenitori: 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. Ottieni l' ID CONTAINER della tua app django e accedi a:
docker exec -t -i 66175bfd6ae6 bash
  1. Ora sei loggato, quindi vai alla cartella giusta: cd path/to/django_app

  2. E ora, ogni volta che modifichi i tuoi modelli, esegui nel tuo contenitore: python manage.py makemigrationsepython manage.py migrate

Ti consiglio anche di utilizzare un punto di ingresso docker per l'esecuzione automatica del file contenitore docker django:

  • collezionistico
  • migrare
  • runerver o avviarlo con gunicorn o uWSGI

Ecco un esempio ( 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

16
Ti consiglio anche di utilizzare un punto di ingresso docker per eseguire automaticamente il tuo file contenitore docker django - tali operazioni non dovrebbero mai essere eseguite automaticamente - intendo soprattutto migrare .
Opal

7
Non importa in quale ambiente ti trovi: la distribuzione dovrebbe sempre avere lo stesso aspetto. Se le migrazioni sono automatizzate, potrebbero essere eseguite contemporaneamente, il che è altamente sconsigliato. Ad esempio, su heroku: le migrazioni non vengono mai eseguite come parte della distribuzione.
Opal

5
contemporaneamente? Qui siamo in un dev env. Io corro makemigrations. la prossima volta che avvierò il mio stack, migrateaggiornerò il database con le ultime migrazioni annullate, altrimenti l'app django non funzionerà correttamente ... È solo una scorciatoia in dev env per essere sicuro di avere lo schema di database corretto con l'app corrente
Louis Barranqueiro

2
@LouisBarranqueiro, intendevo più istanze, singolo DB.
Opal

1
Per il passaggio 4, consiglierei: docker exec -ti $ CONTAINER_ID / bin / sh
Santiago Magariños

52

Uso questi metodi:

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

Utilizzando la dockergerarchia che abbiamo creato, la migrazione del servizio viene eseguita dopo aver configurato il database e prima di eseguire il servizio principale. Ora, quando si esegue il servizio, dockerverranno eseguite le migrazioni prima di eseguire il server; guarda che il migrationserver è applicato sopra la stessa immagine che il web server, significa che tutte le migrazioni saranno prese dal tuo progetto, evitando problemi.

Eviti il ​​punto di ingresso o qualsiasi altra cosa in questo modo.


2
Come build: .funziona image: ottengo l'errore che la migrazione non può estrarre l'immagine denominata
Aaron McMillin,

2
L'ho risolto mettendomi build:su migrationdato che verrà eseguito primaweb
Aaron McMillin

4
Questo non mantiene l'immagine uzman in esecuzione e consuma RAM per sempre? Inoltre, qual è l'immagine uzman?
mlissner

È la mia immagine docker personalizzata. Non ho ancora testato la RAM.
SalahAdDin

32

Fai in modo che il tuo stack funzioni, quindi attiva un comando di esecuzione docker-compose in un colpo. Per esempio

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

Funziona alla grande per il database SQLite integrato (predefinito), ma anche per un database dockerizzato esterno elencato come dipendenza. Ecco un esempio di file 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/


12

Puoi usare docker execcommand

docker exec -it container_id python manage.py migrate

1
Questa dovrebbe essere la risposta.
tolga

Per ottenere il container_id menzionato, fai docker pse poi cerca la colonna COMMAND per django server.
Jai Sharma il

5

Se hai qualcosa di simile nel tuo file 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

Quindi puoi semplicemente correre ...

~$ docker-compose exec app python manage.py makemigrations
~$ docker-compose exec app python manage.py migrate

2

So che questo è vecchio e forse mi manca qualcosa qui (se è così, per favore illuminami!), Ma perché non aggiungere semplicemente i comandi al tuo start.shscript, eseguito da Docker per avviare la tua istanza? Ci vorranno solo pochi secondi in più.

NB Ho impostato la DJANGO_SETTINGS_MODULEvariabile per assicurarmi che venga utilizzato il database corretto, poiché utilizzo database diversi per lo sviluppo e la produzione (anche se so che questa non è "best practice").

Questo ha risolto per me:

#!/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

1

Utilizzando docker exec, stavo ottenendo il seguente errore:

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

Quindi ho usato questo comando invece:

docker-compose -f local.yml run django python manage.py makemigrations
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.