Как сделать пакеты, установленные с помощью Poetry, доступными в Docker?

У меня есть Django REST framework API, который я пытаюсь запустить в Docker. Проект использует Poetry 1.1.12. При запуске я вижу, что Poetry установлен правильно, и что Poetry устанавливает пакеты в моем pyproject.toml, включая Django. Я использую супервизор для запуска API с помощью Daphne, а также для некоторых других задач (например, сбора статических файлов).

Однако, когда супервизор запускает приложение, я получаю:

Traceback (most recent call last):
  File "/home/docker/api/manage.py", line 22, in <module>
    main()
  File "/home/docker/api/manage.py", line 13, in main
    raise ImportError(
ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?
Traceback (most recent call last):
  File "/home/docker/api/manage.py", line 11, in main
    from django.core.management import execute_from_command_line
ModuleNotFoundError: No module named 'django'

Обратите внимание, как я установил POETRY_VIRTUALENVS_CREATE=false и ENV PATH="/root/.local/bin:${PATH}". Согласно сценарию установки стихов, именно этот путь необходимо добавить в PATH.

Вот сокращенная версия моего Dockerfile:

FROM python:3.9-slim-buster
ENV PATH="/root/.local/bin:${PATH}"

RUN apt-get update && apt-get install -y --no-install-recommends \
    ... \
    curl \
    supervisor \
    && curl -sSL 'https://install.python-poetry.org' | python - && poetry --version \
    && apt-get remove -y curl \
    && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
    && apt-get clean -y && rm -rf /var/lib/apt/lists/* \
    && rm -rf /var/lib/apt/lists/*

COPY poetry.lock pyproject.toml /home/docker/api/

WORKDIR /home/docker/api

RUN if [ "$DEBUG" = "false" ] \
    ; then POETRY_VIRTUALENVS_CREATE=false poetry install --no-dev --no-interaction --no-ansi -vvv --extras "production" \
    ; else POETRY_VIRTUALENVS_CREATE=false poetry install --no-interaction --no-ansi -vvv --extras "production" \
    ; fi

COPY . /home/docker/api/
COPY .docker/services/api/files/supervisor.conf /etc/supervisor/conf.d/

CMD ["supervisord", "-n"]

Почти так же я вижу, как это делают другие. Есть идеи?

Может ли это быть из-за отсутствия переменной окружения DJANGO_SETTINGS_MODULE?

Poetry documents itself as trying very very hard to always run inside a virtual environment. Однако контейнер Docker сам по себе изолирован от других Python, и это нормально (и проще всего) устанавливать пакеты в "системном" Python.

Существует команда poetry export, которая может преобразовать файлы Poetry в обычный файл pip requirements.txt, и оттуда вы можете RUN pip install в свой Dockerfile. Вы можете использовать многоступенчатый Dockerfile для создания этого файла без включения Poetry в основной образ.

FROM python:3.9-slim-buster AS poetry
RUN pip install poetry
WORKDIR /app
COPY pyproject.toml poetry.lock .
RUN poetry export -f requirements.txt --output requirements.txt

FROM python:3.9-slim-buster
WORKDIR /app
COPY --from=poetry /app/requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["./manage.py", "runserver", "0.0.0.0:8000"]

django должен появиться в сгенерированном requirements.txt файле, и поскольку pip install устанавливает его как "обычный" "системный" пакет Python, ваше приложение должно увидеть его нормально, без изменения переменных окружения или других настроек.

Вернуться на верх