Hypercorn с «--reload» и томами Docker
Я запускаю Hypercorn внутри контейнера Docker. Файл, который я запускаю, хранится в томе, управляемом Docker Compose.
Когда я меняю файл в своей системе, я вижу, что это изменение отражается в томе, например, с помощью
docker compose exec myapp /bin/cat /app/runtime/service.py
.
Однако, когда я изменяю файл таким образом, Hypercorn не перезапускается, как я ожидал. Есть ли какое-то неблагоприятное взаимодействие между Hypercorn и томом Docker? Или я чего-то жду от
--reload
вариант, которого я не должен ожидать?
Примеры файлов ниже. Я ожидал, что изменение извне контейнера заставит Hypercorn перезапустить сервер с измененной версией файла. Но этого не происходит.
Изменить: я должен добавить, что использую Docker 20.10.5 через Docker Desktop для Mac на MacOS 10.14.6.
Изменить 2: это может быть ошибка Hypercorn. Если я добавлю
uvicorn[standard]
в
requirements.txt
и беги
python -m uvicorn --reload --host 0.0.0.0 --port 8001 service:app
, перезагрузка работает нормально. Возможно, связано: https://gitlab.com/pgjones/hypercorn/-/issues/185
entrypoint.sh
:
#!/bin/sh
cd /app/runtime
/opt/venv/bin/python -m hypercorn --reload --bind 0.0.0.0:8001 service:app
Dockerfile
:
FROM $REDACTED
RUN /opt/venv/bin/python -m pip install -U pip
RUN /opt/venv/bin/pip install -U setuptools wheel
COPY requirements.txt /app/requirements.txt
RUN /opt/venv/bin/pip install -r /app/requirements.txt
COPY requirements-dev.txt /app/requirements-dev.txt
RUN /opt/venv/bin/pip install -r /app/requirements-dev.txt
COPY entrypoint.sh /app/entrypoint.sh
EXPOSE 8001/tcp
CMD ["/app/entrypoint.sh"]
docker-compose.yml
:
version: "3.8"
services:
api:
container_name: api
hostname: myapp
build:
context: .
ports:
- 8001:8001
volumes:
- ./runtime:/app/runtime
runtime/service.py
:
import logging
import quart
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
app = quart.Quart(__name__)
@app.route('/')
async def handle_hello():
logger.info('Handling request.')
return 'Hello, world!\n'
@app.route('/bad')
async def handle_bad():
logger.critical('Bad request.........')
raise RuntimeError('Oh no!!!')
2 ответа
Вот минимальный, полностью рабочий пример, который выполняет автоматическую перезагрузку с помощью:
docker-compose.yaml
services:
app:
build: .
# Here --reload is used which works as intended!
command: hypercorn --bind 0.0.0.0:8080 --reload src:app
ports:
- 8080:8080
volumes:
- ./src:/app/src
Dockerfile
FROM python:3.10-slim-bullseye
WORKDIR /app
RUN pip install hypercorn==0.14.3 quart==0.18.0
COPY src ./src
EXPOSE 8080
ENV QUART_APP=src:app
# This is the production command; docker-compose.yaml overwrites it for local development
CMD hypercorn --bind 0.0.0.0:8080 src:app
src/__init__.py
from quart import Quart
app=Quart(__name__)
@app.route('/', methods=['GET'])
def get_root():
return "Hello world!"
Выполнить черезdocker-compose up
и обратите внимание, какhypercorn
перезагружается один раз__init__.py
подвергся модификации.
Вероятно, вам понадобится крепление тома, чтобы получить возможность перезагрузки!
Это потому, что когда вы создаете контейнер, он запекает все, что у вас есть локально. Дальнейшие изменения влияют только на вашу локальную файловую систему.
Это, вероятно, не предназначено для использования (поскольку контейнер становится зависимым от внешних файлов!), Но, вероятно, полезно для более быстрого тестирования / отладки.
Вы также можете напрямую редактировать контейнер, подключившись к нему, что, возможно, вам подходит.