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 运行.
传递命令行参数
Command line arguments to docker run will be appended after all elements in an exec form ENTRYPOINT
就上下文而言,此问题与 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 运行.
传递命令行参数Command line arguments to docker run will be appended after all elements in an exec form ENTRYPOINT