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/
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.
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.
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
).
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.
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")