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подвергся модификации.

Вероятно, вам понадобится крепление тома, чтобы получить возможность перезагрузки!

Это потому, что когда вы создаете контейнер, он запекает все, что у вас есть локально. Дальнейшие изменения влияют только на вашу локальную файловую систему.


Это, вероятно, не предназначено для использования (поскольку контейнер становится зависимым от внешних файлов!), Но, вероятно, полезно для более быстрого тестирования / отладки.

Вы также можете напрямую редактировать контейнер, подключившись к нему, что, возможно, вам подходит.

Другие вопросы по тегам