web-dev-qa-db-fra.com

Pourquoi ne puis-je pas exécuter les migrations Django via la commande 'docker-compose run web'?

Je déploie donc des conteneurs Django, postgress et nginx via docker-compose et j'ai un problème que je n'arrive pas à comprendre.

Afin de résoudre l'erreur suivante dans mon application Django, je savais que je devais simplement exécuter une migration Django.

docker@postgres ERROR:  relation "accounts_myprofile" does not exist

Pour tenter d'exécuter des migrations, j'ai essayé:

docker-compose run web python manage.py makemigrations 
docker-compose run web python manage.py migrate

qui a renvoyé ce qui suit:

Migrations for 'accounts':
  accounts/migrations/0001_initial.py:
    - Create model Entry
    - Create model MyProfile

Running migrations:
  No migrations to apply.

Je n'ai pu migrer avec succès qu'à partir du conteneur Django, exemple:

docker exec -i -t 6dc97c6a305c /bin/bash
python manage.py makemigrations
python manage.py migrate

Bien que j'aie résolu le problème, je ne comprends toujours pas pourquoi l'exécution de la migration via l'analyse docker-compose ne fait rien migrer. J'espère que quelqu'un pourra peut-être me diriger dans la bonne direction à ce sujet.

De plus, je ne sais pas si c'est un problème connexe ou non, mais lorsque j'exécute ces commandes Web d'exécution de docker-compose, elles semblent créer de nouveaux conteneurs qui ne s'arrêteront pas sauf si je les arrête manuellement, docker-compose stop ne les supprime pas.

CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                          PORTS                    NAMES
a7bb3c7106d1        accounts_web            "python manage.py che"   4 hours ago         Restarting (0) 41 minutes ago   8000/tcp                 accounts_web_run_62
ee19ca6cdf49        accounts_web            "python manage.py mig"   4 hours ago         Restarting (0) 43 minutes ago   8000/tcp                 accounts_web_run_60
2d87ee35de3a        accounts_web            "python manage.py mak"   4 hours ago         Restarting (0) 43 minutes ago   8000/tcp                 accounts_web_run_59
1c6143c13097        accounts_web            "python manage.py mig"   4 hours ago         Restarting (1) 44 minutes ago   8000/tcp                 accounts_web_run_58
6dc97c6a305c        b1cb7debb103              "python manage.py run"   3 days ago          Up 4 hours                      8000/tcp                 accounts_web_1

Remarque: Docker-compose stop arrêtera correctement le conteneur en bas (comme il se doit), mais l'autre conteneur créé par docker-compose run web python manage.py migrate, aura besoin être arrêté manuellement.

mon docker-compose

web:    
  restart: always
  build: ./web
  expose:
    - "8000"
  links:
    - postgres:postgres

  volumes:
    - /usr/src/app
    - /usr/src/app/static

  env_file: .env
  environment:
    DEBUG: 'true'
  command: python manage.py runserver 0.0.0.0:8000


postgres:
  restart: always
  image: kartoza/postgis:9.4-2.1
  ports:
    - "5432:5432"
  volumes:
    - pgdata:/var/lib/postgresql/data/
12
david

le docker-compose run crée de nouveaux conteneurs

Vous avez déjà remarqué le problème. Lorsque vous utilisez docker-compose run, un nouveau conteneur est créé.

Lorsque vous avez exécuté la première commande (makemigrations), un nouveau conteneur a été créé, makemigrations a été exécuté et les fichiers de migration ont été écrits dans le système de fichiers du (nouveau) conteneur.

Lorsque vous avez exécuté la deuxième commande (migrer), un autre nouveau conteneur a été créé. La migration s'est déroulée, mais elle n'avait rien à voir. C'est parce que les fichiers de migration n'étaient pas disponibles - ils ont été écrits dans un conteneur différent de celui-ci.

Vous pouvez résoudre ce problème de deux manières.

Utilisation de docker-compose exec

Tout d'abord, vous pouvez faire ce que vous avez déjà fait, mais utilisez docker-compose exec au lieu de run.

docker-compose exec web python manage.py makemigrations 
docker-compose exec web python manage.py migrate

exec utilisera le conteneur déjà en cours d'exécution, plutôt que de créer de nouveaux conteneurs.

Utilisation d'un script de point d'entrée

Une autre option consiste à utiliser un script de point d'entrée et à y exécuter la migration, avant le démarrage du serveur. C'est la voie à suivre si vous préférez que les choses soient plus automatiques.

Dockerfile:

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

entrypoint.sh:

#!/bin/sh
python manage.py makemigrations
python manage.py migrate
exec "$@"

docker-compose.yml (sous 'web'):

entrypoint: /entrypoint.sh

Dans ce scénario, lorsque le conteneur démarre, le script du point d'entrée s'exécute, gère votre migration, puis transfère le command (qui dans ce cas est Django runserver).

Les nouveaux conteneurs bouclent pour toujours

Comme vous l'avez remarqué, les nouveaux conteneurs continuent de fonctionner. C'est normalement inattendu, car vous avez remplacé la commande par une qui devrait se terminer (plutôt que de continuer à fonctionner). Cependant, dans docker-compose.yml, vous avez spécifié restart: always. Ils exécuteront donc les commandes de migration encore et encore, en redémarrant à chaque fois que la commande se termine.

32
Dan Lowe

Dan Lowe a donné une réponse très agréable, mais le script du point d'entrée ne fonctionnait pas pour moi. Le problème est que certains "makemigrations" attendent votre entrée, par exemple "oui"/"non".

Vous pouvez compléter la réponse de Dan Lowe avec:

python manage.py makemigrations --noinput

au lieu de

python manage.py makemigrations

(Cela fonctionne au moins pour les questions simples "oui"/"non")

0
Rexcirus