Автоматическая перезагрузка изменений кода с развитием Django в Docker с Gunicorn
Я использую контейнер Docker для разработки Django, и контейнер запускает Gunicorn с Nginx. Я бы хотел, чтобы изменения кода были загружены автоматически, но единственный способ загрузить их - это перестроить с помощью docker-compose (docker-compose build
). Проблема с "сборкой" заключается в том, что она повторно запускает все мои установки папок.
Я использую флаг Gunicorn --reload
, который, по-видимому, должен делать то, что я хочу. Вот мои конфигурационные файлы Docker:
## Dockerfile:
FROM python:3.4.3
RUN mkdir /code
WORKDIR /code
ADD . /code/
RUN pip install -r /code/requirements/docker.txt
## docker-compose.yml:
web:
restart: always
build: .
expose:
- "8000"
links:
- postgres:postgres
volumes:
- /usr/src/app/static
env_file: .env
command: /usr/local/bin/gunicorn myapp.wsgi:application -w 2 -b :8000 --reload
nginx:
restart: always
build: ./config/nginx
ports:
- "80:80"
volumes:
- /www/static
volumes_from:
- web
links:
- web:web
postgres:
restart: always
image: postgres:latest
volumes:
- /var/lib/postgresql
ports:
- "5432:5432"
Я пробовал некоторые другие команды Docker (docker-compose restart
, docker-compose up
), но код не обновляется.
Что мне не хватает?
Ответы
Ответ 1
Благодаря kikicarbonell я заглянул в объем для моего кода и после просмотра Docker Compose рекомендовал настройку Django, я добавил volumes: - .:/code
в мой веб-контейнер в docker-compose.yml, и теперь любые изменения кода, которые я делаю, автоматически применяются.
## docker-compose.yml:
web:
restart: always
build: .
expose:
- "8000"
links:
- postgres:postgres
volumes:
- /usr/src/app/static
- .:/code
env_file: .env
command: /usr/local/bin/gunicorn myapp.wsgi:application -w 2 -b :8000 --reload
Обновление: для подробного примера использования Gunicorn и Django с Docker, посмотрите этот пример проекта из Rackspace, в котором также показано, как использовать докеры -machine для запуска установки на удаленных серверах, таких как Rackspace Cloud.
Предостережение:, этот метод не работает, когда ваш код локально, а хост докера удален (например, у облачного провайдера, такого как Digital Ocean или Rackspace). Это также относится к виртуальным машинам, если ваша локальная файловая система не установлена на виртуальной машине. Обратите внимание, что есть отдельные драйверы томов (например, flocker), и может быть что-то там, чтобы удовлетворить эту потребность. На данный момент "fix" - это rsync/scp ваши файлы до каталога на удаленном узле докера. Затем флаг --reload
будет автоматически перезагружать бункер после любого scp/rsync. Обновление:. Если вы нажимаете код для удаления узла докеров, мне гораздо проще просто перестроить контейнер докера (например, docker-compose build web && docker-compose up -d
). Это может быть медленнее, чем подход rsync, если ваша папка src большая.
Ответ 2
У вас еще одна проблема - Docker кэширует каждый слой, который он создает. Вам не нужно повторно запускать установку pip каждый раз!
ADD . /code/
RUN pip install -r /code/requirements/docker.txt
Это ваша проблема. Docker проверяет каждый оператор ADD, чтобы увидеть, изменились ли какие-либо файлы и недействительность кэша для него и каждый последующий шаг, если он есть. Правильный способ сделать это...
ADD ./requirements/docker.txt /code/requirements/
RUN pip install -r /code/requirements/docker.txt
ADD ./code/
Это приведет к недействительности вашей линии установки пакета, если ваш файл требований изменится!
Ответ 3
Поскольку я так и не нашел желаемого решения, рассмотрим этот интересный взлом. Публикуя здесь, я хотел посмотреть, есть ли у кого-нибудь подобные/хорошие/плохие опыты с этим "обходным путем".
Чтобы сделать перезагрузку кода локально для разработки, я просто создал View, который немедленно вызывает exit()
. Выход завершится сбоем Django, и перезагрузка произойдет, когда изменения кода доступны. Перезагрузка занимает доли секунды и может быть выполнена с помощью вкладки в браузере, вызовом requests.get
или любым другим подобным вызовом. Перезагрузка не автоматическая, но она пропускает любые задержки Docker, такие как перезапуск.
Когда будет вызван выход, вы увидите приращение PID (если следите за журналами):
web | [2019-07-15 18:29:52 +0000] [22] [INFO] Worker exiting (pid: 22)
web | [2019-07-15 18:29:52 +0000] [24] [INFO] Booting worker with pid: 24
Я надеюсь, что это поможет другим и/или получит обратную связь от этого подхода.