Wie führen Sie Django-Datenbankmigrationen durch, wenn Sie Docker-Compose verwenden?

97

Ich habe eine Docker Django / PostgreSQL-App eingerichtet, die den Anweisungen für den Django-Schnellstart auf der Docker-Site genau folgt .

Das erste Mal, wenn ich Djangos management.py migrate mit dem Befehl ausführe sudo docker-compose run web python manage.py migrate, funktioniert es wie erwartet. Die Datenbank ist in den Docker PostgreSQL-Container integriert.

Änderungen an der Django-App selbst werden ebenfalls im Docker Django-Container angezeigt, sobald ich sie speichere. Es ist toll!

Wenn ich dann ein Modell in Django ändere und versuche, die Postgres-Datenbank so zu aktualisieren, dass sie mit dem Modell übereinstimmt, werden keine Änderungen erkannt, sodass keine Migration stattfindet, egal wie oft ich sie ausführe makemigrationsoder migrateerneut.

Grundsätzlich muss ich jedes Mal, wenn ich das Django-Modell ändere, die Docker-Container löschen (mit sudo docker-compose rm) und mit einer neuen Migration neu beginnen.

Ich versuche immer noch, mich mit Docker zu beschäftigen, und es gibt eine Menge, die ich nicht verstehe, wie es funktioniert, aber diese macht mich verrückt. Warum werden meine Änderungen bei der Migration nicht angezeigt? Was mache ich falsch?

John
quelle
Hast du herausgefunden warum? Ich bekomme die Antwort unten und es funktioniert: You just have to log into your running docker container and run your commands.Aber was ist der Grund, warum es sich so verhält? @ LouisBarranqueiro
lukik

Antworten:

101

Sie müssen sich nur in Ihren laufenden Docker-Container einloggen und Ihre Befehle ausführen.

  1. Bauen Sie Ihren Stack: docker-compose build -f path/to/docker-compose.yml
  2. Starten Sie Ihren Stack: docker-compose up -f path/to/docker-compose.yml
  3. Docker-Laufcontainer anzeigen: 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. Holen Sie sich die CONTAINER ID Ihrer Django App und melden Sie sich an:
docker exec -t -i 66175bfd6ae6 bash
  1. Jetzt sind Sie angemeldet und gehen in den richtigen Ordner: cd path/to/django_app

  2. Und jetzt führen Sie jedes Mal, wenn Sie Ihre Modelle bearbeiten, in Ihrem Container aus: python manage.py makemigrationsundpython manage.py migrate

Ich empfehle Ihnen außerdem, einen Docker-Einstiegspunkt zu verwenden, damit Ihre Django-Docker-Container-Datei automatisch ausgeführt wird:

  • kollektiv
  • Wandern
  • runserver oder starte es mit gunicorn oder uWSGI

Hier ist ein Beispiel ( 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
Louis Barranqueiro
quelle
15
Ich empfehle Ihnen auch, einen Docker-Einstiegspunkt zu verwenden, damit Ihre Django-Docker-Container-Datei automatisch ausgeführt wird. Solche Vorgänge sollten niemals automatisch ausgeführt werden. Ich meine, insbesondere migrieren .
Opal
7
Es spielt keine Rolle, in welcher Umgebung Sie sich befinden - die Bereitstellung sollte immer gleich aussehen. Wenn Migrationen automatisiert sind, werden sie möglicherweise gleichzeitig ausgeführt, was dringend empfohlen wird. ZB auf Heroku - Migrationen werden niemals als Teil der Bereitstellung ausgeführt.
Opal
4
gleichzeitig? Hier sind wir in einer Entwicklungsumgebung. Ich renne makemigrations. migrateWenn ich das nächste Mal meinen Stack starte , wird die Datenbank mit den letzten rückgängig gemachten Migrationen aktualisiert, andernfalls funktioniert die Django-App nicht richtig ... Es ist nur eine Verknüpfung in dev env, um sicherzustellen, dass Sie das richtige Datenbankschema mit der aktuellen App haben
Louis Barranqueiro
2
@ LouisBarranqueiro, ich meinte mehrere Instanzen, einzelne DB.
Opal
1
Für Schritt 4 würde ich empfehlen: docker exec -ti $ CONTAINER_ID / bin / sh
Santiago Magariños
52

Ich benutze diese Methode:

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

Unter Verwendung der von dockeruns erstellten Hierarchie wird die Dienstmigration nach dem Einrichten der Datenbank und vor dem Ausführen des Hauptdienstes ausgeführt. Wenn Sie jetzt Ihren Dienst dockerausführen, werden Migrationen ausgeführt, bevor der Server ausgeführt wird. Wenn der migrationServer auf dasselbe Image wie der Webserver angewendet wird, bedeutet dies, dass alle Migrationen aus Ihrem Projekt übernommen werden, um Probleme zu vermeiden.

Auf diese Weise vermeiden Sie den Einstiegspunkt oder was auch immer.

SalahAdDin
quelle
1
Wie funktioniert das build: .? image: Ich erhalte die Fehlermeldung, dass die Migration das genannte Bild nicht abrufen kann
Aaron McMillin
2
Ich beschloss , es durch die Umsetzung build:auf , migrationda es vor laufenweb
Aaron McMillin
4
Hält das Uzum-Image nicht für immer am Laufen und verbraucht RAM? Was ist das Uzman-Bild?
mlissner
Es ist mein benutzerdefiniertes Docker-Image. Ich habe den RAM noch nicht getestet.
SalahAdDin
32

Lassen Sie Ihren Stack laufen und starten Sie dann einen One-Shot-Docker-Compose-Run-Befehl. Z.B

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

Dies funktioniert hervorragend für die integrierte (Standard-) SQLite-Datenbank, aber auch für eine externe Docker-Datenbank, die als Abhängigkeit aufgeführt ist. Hier ist ein Beispiel für die Datei 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
quelle
11

Sie können den docker execBefehl verwenden

docker exec -it container_id python manage.py migrate
SuperNova
quelle
1
Dies sollte die Antwort sein.
Tolga
Um die erwähnte container_id zu erhalten, führen Sie docker psdie Spalte COMMAND for django server aus.
Jai Sharma
5

Wenn Sie so etwas in Ihrem haben 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

Dann können Sie einfach laufen ...

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

Ich weiß, dass dies alt ist, und vielleicht fehlt mir hier etwas (wenn ja, klären Sie mich bitte auf!), Aber warum nicht einfach die Befehle zu Ihrem start.shSkript hinzufügen , das von Docker ausgeführt wird, um Ihre Instanz zu starten? Es dauert nur ein paar zusätzliche Sekunden.

NB Ich habe die DJANGO_SETTINGS_MODULEVariable festgelegt, um sicherzustellen, dass die richtige Datenbank verwendet wird, da ich für die Entwicklung und Produktion unterschiedliche Datenbanken verwende (obwohl ich weiß, dass dies keine bewährte Methode ist).

Das hat es für mich gelöst:

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

Bei Verwendung von Docker Exec wurde folgende Fehlermeldung angezeigt:

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

Also habe ich stattdessen diesen Befehl verwendet:

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