Почему мне не удается выполнить миграцию django с помощью команды "docker-compose run web"?

Поэтому я развертываю контейнеры django, postgress и nginx через docker-compose, и у меня есть проблема, которую я не могу понять.

Чтобы разрешить следующую ошибку в моем приложении Django, я знал, что мне просто нужно запустить миграцию Django.

[email protected] ERROR:  relation "accounts_myprofile" does not exist

В попытке выполнить миграцию я попытался:

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

который возвратил следующее:

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

Running migrations:
  No migrations to apply.

Я смог успешно выполнить миграцию из контейнера Django, например:

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

Хотя я решил проблему, я все еще не понимаю, почему запуск миграции через запуск docker-compose фактически не переносит ничего. Я надеюсь, что кто-то может, возможно, указать мне в правильном направлении.

Кроме того, я не знаю, связана ли эта проблема или нет, но когда я запускаю эти веб-команды для запуска профайлов, они, похоже, создают новые контейнеры, которые не будут закрыты, если я их не остановлю вручную, остановка докеры не удаляет их.

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

Примечание. Стоп-стоп-стоп правильно остановит контейнер внизу (как и должно быть), но другой контейнер, созданный приложением для запуска веб-python manage.py, запускается с помощью docker-comp, должен быть остановлен вручную.

мой докер-сочинитель

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/

Ответы

Ответ 1

Запуск docker-compose создает новые контейнеры

Вы уже заметили проблему. Когда вы используете docker-compose run, создается новый контейнер.

Когда вы запустили первую команду (makemigrations), был создан новый контейнер, запущены makemigrations и файлы миграции были записаны в (новую) файловую систему контейнера.

Когда вы запустили вторую команду (migrate), был создан новый новый контейнер. Миграция продолжалась, но ей нечего было делать. Это потому, что файлы миграции недоступны - они были написаны в другом контейнере, чем этот новый.

Вы можете решить это несколькими способами.

Использование команды docker-compose

Во-первых, вы можете делать то, что уже делали, но вместо run используйте docker-compose exec.

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

exec будет использовать уже запущенный контейнер, а не создавать новые контейнеры.

Использование сценария точки входа

Другим вариантом является использование сценария точки входа и запуск миграции там до запуска сервера. Это путь, если вы предпочитаете, чтобы все было более автоматическим.

Dockerfile:

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

entrypoint.sh:

#!/bin/sh
python manage.py makemigrations
python manage.py migrate
exec "[email protected]"

docker-compose.yml (под "web"):

entrypoint: /entrypoint.sh

В этом случае, когда контейнер запускается, запускается сценарий точки входа, обрабатывает вашу миграцию, а затем runserver command (которая в этом случае является runserver Django).

Новый контур контейнера навсегда

Как вы заметили, новые контейнеры остаются включенными. Это, как правило, неожиданно, потому что вы перегрузили команду тем, который должен выйти (а не оставаться в рабочем состоянии). Однако в docker-compose.yml вы указали restart: always. Поэтому они будут запускать команды миграции снова и снова, перезагружая каждый раз, когда команда завершается.

Ответ 2

Дэн Лоу дал очень хороший ответ, но сценарий входа не работал для меня. Проблема в том, что некоторые "makemigrations" ожидают вашего ввода, например "да"/"нет".

Вы можете дополнить ответ дэна Лоу:

python manage.py makemigrations --noinput

вместо

python manage.py makemigrations

(Это работает по крайней мере для простых вопросов "да"/"нет")