Skonfigurowałem aplikację Docker Django / PostgreSQL ściśle według instrukcji szybkiego startu Django na stronie Docker .
Kiedy po raz pierwszy uruchamiam migrację manage.py Django za pomocą polecenia sudo docker-compose run web python manage.py migrate
, działa to zgodnie z oczekiwaniami. Baza danych jest dobrze zbudowana wewnątrz kontenera Docker PostgreSQL.
Zmiany dokonane w samej aplikacji Django są również odzwierciedlane w kontenerze Docker Django, w momencie ich zapisywania. Wspaniale!
Ale jeśli następnie zmienię model w Django i spróbuję zaktualizować bazę danych Postgres, aby pasowała do modelu, żadne zmiany nie zostaną wykryte, więc migracja nie nastąpi, niezależnie od tego, ile razy uruchomię makemigrations
lub migrate
ponownie.
Zasadniczo za każdym razem, gdy zmieniam model Django, muszę usunąć kontenery Dockera (używając sudo docker-compose rm
) i zacząć od nowa z nową migracją.
Nadal próbuję się skupić na Dockerze i jest strasznie dużo rzeczy, których nie rozumiem, jak to działa, ale to doprowadza mnie do szału. Dlaczego migracja nie wyświetla moich zmian? Co ja robię źle?
You just have to log into your running docker container and run your commands.
ale jaki jest powód, dla którego tak się zachowuje? @LouisBarranqueiroOdpowiedzi:
Wystarczy zalogować się do uruchomionego kontenera docker i uruchomić polecenia.
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
Teraz jesteś zalogowany, a następnie przejdź do odpowiedniego folderu:
cd path/to/django_app
A teraz za każdym razem, gdy edytujesz swoje modele, uruchom w swoim kontenerze:
python manage.py makemigrations
ipython manage.py migrate
Polecam również użycie docker-entrypoint, aby Twój plik kontenera docker django działał automatycznie:
Oto przykład (
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
źródło
makemigrations
. następnym razem, gdy uruchomię mój stos,migrate
zaktualizuje bazę danych z cofniętymi ostatnimi migracjami, w przeciwnym razie aplikacja django nie będzie działać poprawnie ... To tylko skrót w dev env, aby upewnić się, że masz odpowiedni schemat bazy danych z bieżącą aplikacjąUżywam tej metody:
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
Korzystając z
docker
utworzonej przez nas hierarchii, migracja usługi przebiega po skonfigurowaniu bazy danych, a przed uruchomieniem usługi głównej. Teraz, gdy uruchomisz usługędocker
, migracje zostaną uruchomione przed uruchomieniem serwera; Wygląda na to, żemigration
serwer jest stosowany na tym samym obrazie, co serwer WWW, oznacza to, że wszystkie migracje zostaną pobrane z twojego projektu, unikając problemów.Unikniesz w ten sposób punktu wejścia lub czegokolwiek innego.
źródło
build: .
działa, gdy pojawiaimage:
się błąd, że migracja nie może pobrać nazwanego obrazubuild:
namigration
ponieważ to będzie działać, zanimweb
Uruchom stos, a następnie wyślij jednorazowe polecenie uruchamiania docker-compose. Na przykład
#assume django in container named web docker-compose run web python3 manage.py migrate
Działa to świetnie w przypadku wbudowanej (domyślnej) bazy danych SQLite, ale także w przypadku zewnętrznej dokeryzowanej bazy danych, która jest wymieniona jako zależność. Oto przykład pliku 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/
źródło
Możesz użyć
docker exec
poleceniadocker exec -it container_id python manage.py migrate
źródło
docker ps
a następnie poszukaj kolumny COMMAND dla serwera django.Jeśli masz coś takiego w swoim
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
Następnie możesz po prostu uruchomić ...
~$ docker-compose exec app python manage.py makemigrations ~$ docker-compose exec app python manage.py migrate
źródło
Wiem, że to jest stare i może czegoś mi brakuje (jeśli tak, proszę mnie oświecić!), Ale dlaczego nie dodać poleceń do swojego
start.sh
skryptu, uruchamianego przez Dockera, aby uruchomić instancję? Zajmie to tylko kilka dodatkowych sekund.NB ustawiłem
DJANGO_SETTINGS_MODULE
zmienną, aby upewnić się, że używana jest poprawna baza danych, ponieważ używam różnych baz danych do programowania i produkcji (chociaż wiem, że nie jest to „najlepsza praktyka”).To rozwiązało to dla mnie:
#!/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
źródło
Używając docker exec, otrzymywałem następujący błąd:
AppRegistryNotReady("Models aren't loaded yet.")
Więc zamiast tego użyłem tego polecenia:
docker-compose -f local.yml run django python manage.py makemigrations
źródło