Docker run python скрипт не может найти локально установленный модуль - PullRequest
0 голосов
/ 10 марта 2020

Для контекста эта проблема относится к docker образу, который будет запущен с использованием azure пакета.

Вот Dockerfile, полностью:

FROM continuumio/miniconda3

ADD . /pipegen

ADD environment.yml /tmp/environment.yml
RUN conda env create -f /tmp/environment.yml

RUN echo "conda activate $(head -1 /tmp/environment.yml | cut -d' ' -f2)" >> ~/.bashrc

ENV PATH /opt/conda/envs/$(head -1 /tmp/environment.yml | cut -d' ' -f2)/bin:$PATH
ENV CONDA_DEFAULT_ENV $(head -1 /tmp/environment.yml | cut -d' ' -f2)

ADD classify.py /classify.py
RUN rm -rf /pipegen

pipgen - это локальный модуль (где расположен Dockerfile), который устанавливается с использованием файла environment.yml , Вот файл environment.yml полностью:

name: pointcloudz

channels:
  - conda-forge
  - defaults

dependencies:
  - python=3.7
  - python-pdal
  - entwine
  - matplotlib
  - geopandas
  - notebook
  - azure-storage-blob==1.4.0
  - pip:
    - /pipegen
    - azure-batch==6.0.0

Для ясности структура каталогов выглядит следующим образом:

Dockerfile
pipegen
  \__ __init__.py
  \__ pipegen.py
  \__ utils.py
classify.py
batch_containers.py
environment.yml
setup.py

Dockerfile устанавливает среду, созданную с помощью environment.yml файл в качестве среды по умолчанию (conda) python при запуске контейнера. Поэтому я могу запустить контейнер в интерактивном режиме следующим образом:

docker run -it pdalcontainers.azurecr.io/pdalcontainers/pdal-pipelines

и изнутри контейнера выполнить сценарий classify.py с некоторыми аргументами командной строки, как показано ниже:

python classify.py in.las out.las --defaults

и сценарий выполняется должным образом. Однако, когда я запускаю следующую команду, пытаясь выполнить тот же сценарий «извне» контейнера,

docker run -it pdalcontainers.azurecr.io/pdalcontainers/pdal-pipelines python classify.py in.las out.las --defualts

я получаю следующую ошибку:

File "classify.py", line 2, in <module>
    from pipegen.pipegen import build_pipeline, write_las
ModuleNotFoundError: No module named 'pipegen'

Для ясности, скрипт classify.py импортирует pipegen, локальный модуль, который теперь установлен в среде conda, созданной в Dockerfile. Мне нужно иметь возможность выполнить скрипт с помощью команды docker run, указанной выше, из-за ограничений в том, как пакетные задания Azure запускают задания. Я пробовал несколько исправлений, но сейчас застрял. Любая мудрость будет принята с благодарностью!

1 Ответ

1 голос
/ 10 марта 2020

Проблема, с которой вы сталкиваетесь, заключается в том, что вы добавили conda activate в сценарий .bashrc, который активируется только для оболочек входа в систему. Когда вы запускаете контейнер в интерактивном режиме, это то, что вы получаете. Однако, когда вы просто пытаетесь вызвать скрипт python напрямую, вы не получаете оболочку входа в систему, поэтому ваша среда conda не активирована.

Одна мысль, которую вы могли бы сделать, это не использовать Конда активировать и вместо этого запустить скрипт с conda run. Чтобы упростить командную строку, добавьте эту точку входа в ваш Dockerfile:

ENTRYPOINT ["conda", "run", "-n", "$CONDA_DEFAULT_ENV", "python", "classify.py"]

Использование этого в точке входа также позволяет вызывающей стороне передавать аргументы командной строки через docker run.

Из ссылки Dockerfile

Аргументы командной строки для docker run будут добавлены после всех элементов в exe c форме ENTRYPOINT

Более подробное объяснение см. Активация среды Conda в вашем Dockerfile

...