Як виконувати міграцію бази даних Django під час використання Docker-Compose?


99

Я створив програму Docker Django / PostgreSQL, уважно дотримуючись інструкцій із швидкого запуску Django на сайті Docker .

Перший раз, коли я запускаю міграцію Django manage.py, використовуючи команду sudo docker-compose run web python manage.py migrate, вона працює належним чином . База даних побудована всередині контейнера Docker PostgreSQL просто чудово.

Зміни, внесені в саму програму Django, також відображаються в контейнері Docker Django, як тільки я їх збережу. Це чудово!

Але якщо після цього я зміню модель у Django та спробую оновити базу даних Postgres, щоб вона відповідала моделі, ніяких змін не виявлено, тому жодної міграції не відбувається, скільки б разів я не запускався makemigrationsчи migrateзнову.

В основному, кожного разу, коли я змінюю модель Django, мені доводиться видаляти контейнери Docker (за допомогою sudo docker-compose rm) і починати спочатку з новою міграцією.

Я все ще намагаюся розібратися з Докером, і я страшенно багато не розумію, як це працює, але цей зводить мене з розуму. Чому міграція не бачить мої зміни? Що я роблю не так?


Ви зрозуміли чому? Я отримую відповідь нижче, і вона працює: You just have to log into your running docker container and run your commands.але в чому причина, що вона поводиться так? @LouisBarranqueiro
lukik

Відповіді:


104

Вам просто потрібно увійти у ваш запущений контейнер докера і запустити свої команди.

  1. Створіть свій стек: docker-compose build -f path/to/docker-compose.yml
  2. Запустіть свій стек: docker-compose up -f path/to/docker-compose.yml
  3. Відобразити запущені контейнери докера: 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 ...
  1. Отримайте ІДЕНТИФІК КОНТЕЙНЕРУ вашої програми django та увійдіть до:
docker exec -t -i 66175bfd6ae6 bash
  1. Тепер ви ввійшли в систему, а потім перейдіть до правої папки: cd path/to/django_app

  2. А тепер кожного разу, коли ви редагуєте свої моделі, запускайте у своєму контейнері: python manage.py makemigrationsіpython manage.py migrate

Я також рекомендую вам використовувати точку входу docker для вашого файлу контейнера django docker для автоматичного запуску:

  • колекстатичний
  • мігрувати
  • runserver або запустіть його за допомогою ганікорна або uWSGI

Ось приклад ( 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

16
Я також рекомендую вам використовувати докер-точку входу для вашого файлу контейнера django docker для автоматичного запуску - такі операції ніколи не повинні запускатися автоматично - я маю на увазі особливо перенести .
Опал

7
Не має значення, в якому середовищі ви знаходитесь - розгортання завжди має виглядати однаково. Якщо міграція автоматизована, це може виконуватися одночасно, що вкрай не рекомендується. Наприклад, на героку - міграції ніколи не запускаються як частина розгортання.
Опал,

5
спокійно? Ось ми в розробнику. Я біжу makemigrations. наступного разу, коли я запущу свій стек, я оновлю migrateбазу даних з останніми скасованими міграціями, інакше програма django не працюватиме належним чином ... Це просто ярлик у dev env, щоб переконатися, що ви отримали правильну схему бази даних з поточною програмою
Louis Barranqueiro

2
@LouisBarranqueiro, я мав на увазі кілька екземплярів, одну БД.
Опал,

1
Для кроку 4 я б рекомендував: docker exec -ti $ CONTAINER_ID / bin / sh
Santiago

52

Я використовую такі методи:

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

Використовуючи dockerстворену нами ієрархію, міграція служби запускається після налаштування бази даних та перед запуском основної служби. Тепер під час запуску ваша служба dockerбуде запускати міграції перед запуском сервера; Подивіться, що migrationсервер застосовано до того самого зображення, що і веб-сервер, це означає, що всі міграції будуть взяті з вашого проекту, уникаючи проблем.

Таким чином ви уникаєте зробленої точки входу чи чогось іншого.


2
Як це build: .працює, image: я отримую помилку, що міграція не може витягнути назване зображення
Аарон Макміллін,

2
Я вирішив це, поставивши build:на, migrationоскільки він буде працювати ранішеweb
Аарон Макміллін

4
Хіба це не змушує образ uzman працювати і споживати оперативну пам’ять назавжди? Крім того, що таке образ узману?
mlissner

Це мій власний образ докера. Я ще не тестував оперативну пам’ять.
СалахАдДін

32

Запустіть свій стек, а потім запустіть команду запуску докеру, складіть один постріл. Напр

#assume django in container named web
docker-compose run web python3 manage.py migrate

Це чудово працює для вбудованої (за замовчуванням) бази даних SQLite, а також для зовнішньої докеризованої бази даних, яка вказана як залежність. Ось приклад файлу 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/


12

Ви можете використовувати docker execкоманду

docker exec -it container_id python manage.py migrate

1
Це має бути відповіддю.
tolga

Щоб отримати згаданий container_id, виконайте, docker psа потім знайдіть стовпець COMMAND для сервера django.
Джай Шарма

5

Якщо у вас є щось подібне у вашому 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

Тоді ви можете просто запустити ...

~$ docker-compose exec app python manage.py makemigrations
~$ docker-compose exec app python manage.py migrate

2

Я знаю, що це старе, і, можливо, мені чогось тут не вистачає (якщо так, то просвітіть мене!), Але чому б просто не додати команди до вашого start.shсценарію, запущеного Docker для запуску вашого екземпляра? Це займе лише кілька додаткових секунд.

NB Я встановивDJANGO_SETTINGS_MODULE змінну, щоб переконатися, що використовується правильна база даних, оскільки я використовую різні бази даних для розробки та виробництва (хоча я знаю, що це не найкраща практика).

Це вирішило це для мене:

#!/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

1

Використовуючи docker exec, я отримав таку помилку:

AppRegistryNotReady("Models aren't loaded yet.")

Тому я використав замість цього команду:

docker-compose -f local.yml run django python manage.py makemigrations
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.