J'ai configuré une application Docker Django/PostgreSQL en suivant de près le Instructions de démarrage rapide de Django sur le site Docker .
La première fois que j'exécute manage.py migrate de Django à l'aide de la commande Sudo docker-compose run web python manage.py migrate
, cela fonctionne comme prévu. La base de données est construite parfaitement dans le conteneur Docker PostgreSQL.
Les modifications apportées à l'application Django elle-même sont également reflétées dans le conteneur Docker Django, au moment où je les enregistre. C'est génial!
Mais si je modifie ensuite un modèle dans Django et que je tente de mettre à jour la base de données Postgres pour qu'elle corresponde au modèle, aucune modification n'est détectée. Par conséquent, aucune migration n'a lieu, peu importe le nombre de fois où j'ai exécuté makemigrations
ou migrate
. encore.
Fondamentalement, chaque fois que je modifie le modèle Django, je dois supprimer les conteneurs Docker (à l'aide de Sudo docker-compose rm
) et recommencez avec une nouvelle migration.
J'essaie encore de comprendre Docker, et je ne comprends pas très bien comment cela fonctionne, mais celui-ci me rend dingue. Pourquoi ne pas migrer voir mes modifications? Qu'est-ce que je fais mal?
Vous devez simplement vous connecter à votre conteneur docker en cours d'exécution et exécuter vos commandes.
docker-compose build -f path/to/docker-compose.yml
docker-compose up -f path/to/docker-compose.yml
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 ...
docker exec -t -i 66175bfd6ae6 bash
Maintenant que vous êtes connecté, allez dans le bon dossier: cd path/to/Django_app
Et maintenant, chaque fois que vous modifiez vos modèles, exécutez-les dans votre conteneur: python manage.py makemigrations
et python manage.py migrate
Je vous recommande également d’utiliser un docker-entrypoint pour votre fichier conteneur docker Django) à exécuter automatiquement:
Voici un exemple (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
J'utilise ces méthodes:
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
En utilisant la hiérarchie docker
que nous avons créée, la migration du service s’exécute après la configuration de la base de données et avant l’exécution du service principal. Désormais, lorsque vous exécuterez votre service, docker
exécutera les migrations avant d'exécuter le serveur. Si le serveur migration
est appliqué sur la même image que le serveur Web, cela signifie que toutes les migrations seront prises à partir de votre projet, évitant ainsi les problèmes.
Vous évitez de faire un point d'entrée ou quoi que ce soit d'autre avec ce moyen.
Faites fonctionner votre pile, puis lancez une commande d'exécution docker-compos one-shot. Par exemple
#assume Django in container named web
docker-compose run web python3 manage.py migrate
Vous pouvez utiliser docker exec
commande
docker exec -it container_id python manage.py migrate
Je sais que c'est vieux et qu'il me manque peut-être quelque chose ici (si c'est le cas, veuillez m'éclairer!), Mais pourquoi ne pas ajouter simplement les commandes à votre start.sh
script, exécuté par Docker pour lancer votre instance? Cela ne prendra que quelques secondes supplémentaires.
N.B. Je règle le Django_SETTINGS_MODULE
variable pour vérifier que la base de données correcte est utilisée, car j’utilise différentes bases de données pour le développement et la production (bien que je sache que ce n’est pas une "pratique exemplaire").
Cela l'a résolu pour moi:
#!/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