«Нет модуля с именем x» для пользовательских модулей в развертывании Python с использованием Dockerfile и docker-compose

#python #docker #docker-compose #dockerfile

#python #docker #docker-compose #dockerfile

Вопрос:

Я пытаюсь развернуть приложение Python в качестве контейнера Docker, используя Dockerfile и docker-compose.

Структура проекта такова:

 ms-request
    - src
        __init__.py
        - exceptions
            __init__.py
            ms_request_exceptions.py
        - messaging
            __init__.py
            receive_rabbit.py
            send_rabbit.py
        - request
            __init__.py
            bsrequest.py
    - test
        __init__.py
        test_bsrequest.py
    Dockerfile
    requirements.txt
  

В моем receive_rabbit.py скрипте я импортирую функции из пакетов запросов и сообщений следующим образом:

 from src.request import bsrequest
from src.messaging.send_rabbit import send_message
  

Выполнение этого с помощью PyCharm работает нормально. Запуск его из командной строки изначально не работал, пока я не обновил PYTHONPATH с помощью export PYTHONPATH=${PYTHONPATH}:. .

Я хотел бы развернуть это как контейнер Docker, поэтому я создал Dockerfile и запись в моем docker-compose.yml для проекта.

Dockerfile:

 FROM python:3
WORKDIR /bsreq
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY src/ ./src
COPY test/ ./test
RUN export PYTHONPATH=${PYTHONPATH}:.
CMD [ "python", "/bsreq/src/messaging/receive_rabbit.py" ]
  

docker-compose.yml:

 version: "3.3"

services:
        rabbitmq: [...]
        bs-request:
                build: ./ms-request/
                depends_on:
                        - rabbitmq
                env_file:
                        - rabbit.env
        [...]
  

Запуск этого использования docker-compose up bs-request всегда заканчивается сбоем с ошибкой No module named 'src' .

Я пробовал несколько вариантов ввода для строк WORKDIR, COPY, PYTHONPATH и CMD в Dockerfile. Все это приводит к одной и той же ошибке. Я пробовал относительный импорт, который выдает Attempted relative import with no known parent package .

Я надеюсь, что это проблема, с которой другие сталкивались раньше. Что мне нужно сделать, чтобы это развертывание заработало?

Ответ №1:

docker layers-способ построения образа делает export его непригодным для использования сразу после соответствующей RUN команды.

 FROM python:3
WORKDIR /bsreq
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY src/ ./src
COPY test/ ./test
RUN export PYTHONPATH=${PYTHONPATH}:.  #--> exporting
CMD [ "python", "/bsreq/src/messaging/receive_rabbit.py" ]  #--> last export is not persistent 
  

в качестве обходного пути вы устанавливаете переменные среды, которые будут сохраняться при сборке И в конечном образе с ENV PYTHONPATH=${PYTHONPATH}:. помощью command .
дополнительное чтение: https://vsupalov.com/docker-build-time-env-values /

в любом случае, предлагаемый метод заключается в записи setup.py файла и установке вашего пакета, python setup.py install чтобы он был установлен как пакет, и импорт будет работать.

P.S лучшим, более обновленным способом было бы использовать такие инструменты, poetry которые используют pyproject.toml (согласно PEP 518, 517), которые являются будущим способом python!
бонусное чтение: https://python-poetry.org /

удачи!

Комментарии:

1. Большое вам спасибо! Это почти как три ответа в одном. Я буду обновлять проект, чтобы использовать Poetry!