Docker 运行 python 脚本找不到本地安装的模块

Docker run python script cant find locally installed module

就上下文而言,此问题与 docker 图像有关,该图像将 运行 使用 azure batch。

这是 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 是使用environment.yml 文件安装的本地模块(Dockerfile 所在的位置)。这是完整的 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

并且脚本按预期执行。但是,当我 运行 以下命令试图从 "outside" 容器执行完全相同的脚本时,

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,现在安装在 Dockerfile 中创建的 conda 环境中的本地模块。由于 Azure 批处理 运行 作业的限制,我需要能够使用上面的 docker run 命令执行脚本。我已经尝试了多个修复程序,但现在很卡住了。任何智慧将不胜感激!

您遇到的问题是因为您将 conda activate 添加到 .bashrc 脚本,该脚本仅在登录 shell 时激活。当您以交互方式 运行 容器时,这就是您得到的。但是,当您只是尝试直接调用 python 脚本时,您不会获得登录 shell 因此您的 conda 环境 激活。

有人认为您可以不使用 conda 激活,而是 运行 使用 conda run 的脚本。要简化命令行,请将此入口点添加到您的 Dockerfile:

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

在入口点使用它还允许调用者通过 docker 运行.

传递命令行参数

来自Dockerfile reference

Command line arguments to docker run will be appended after all elements in an exec form ENTRYPOINT

更详细的解释见Activating a Conda environment in your Dockerfile