condas `source activate virtualenv` 在 Dockerfile 中不起作用
condas `source activate virtualenv` does not work within Dockerfile
场景
我正在尝试设置一个简单的 docker 图片(我对 docker 很陌生,所以请纠正我可能的误解)基于在 public continuumio/anaconda3 容器上。
Dockerfile
:
FROM continuumio/anaconda3:latest
# update conda and setup environment
RUN conda update conda -y \
&& conda env list \
&& conda create -n testenv pip -y \
&& source activate testenv \
&& conda env list
docker build -t test .
的构建和图像以错误结束:
/bin/sh: 1: source: not found
激活新的虚拟环境时。
建议 1:
以下 this answer 我试过:
FROM continuumio/anaconda3:latest
# update conda and setup environment
RUN conda update conda -y \
&& conda env list \
&& conda create -y -n testenv pip \
&& /bin/bash -c "source activate testenv" \
&& conda env list
这似乎一开始有效,因为它输出:prepending /opt/conda/envs/testenv/bin to PATH
,但是 conda env list
以及屁股 echo $PATH
清楚地表明它没有:
[...]
# conda environments:
#
testenv /opt/conda/envs/testenv
root * /opt/conda
---> 80a77e55a11f
Removing intermediate container 33982c006f94
Step 3 : RUN echo $PATH
---> Running in a30bb3706731
/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
docker 文件作为 MWE 开箱即用。
我很欣赏任何想法。谢谢!
使用docker ENV
指令可以将虚拟环境路径永久添加到PATH
。 虽然这并不能解决conda env list
下列出的所选环境。
查看 MWE:
FROM continuumio/anaconda3:latest
# update conda and setup environment
RUN conda update conda -y \
&& conda create -y -n testenv pip
ENV PATH /opt/conda/envs/testenv/bin:$PATH
RUN echo $PATH
RUN conda env list
借用 ccauet 的回答(我没法开始工作),以及 Charles Duffey 的评论说它不仅仅是 PATH
,下面是解决这个问题的方法。
激活环境时,conda 会设置以下变量,以及一些在停用环境时可以引用的备份默认值。这些变量已从 Dockerfile 中省略,因为永远不需要再次使用根 conda 环境。作为参考,它们是 CONDA_PATH_BACKUP
、CONDA_PS1_BACKUP
和 _CONDA_SET_PROJ_LIB
。它还设置 PS1
以便在终端提示行的左侧显示 (testenv)
,这也被省略了。以下语句将执行您想要的操作。
ENV PATH /opt/conda/envs/testenv/bin:$PATH
ENV CONDA_DEFAULT_ENV testenv
ENV CONDA_PREFIX /opt/conda/envs/testenv
为了减少创建的层数,您可以将这些命令组合成一个 ENV 命令,同时设置所有变量。
根据包的不同,可能还需要设置一些其他变量。例如,
ENV GDAL_DATA /opt/conda/envs/testenv/share/gdal
ENV CPL_ZIP_ENCODING UTF-8
ENV PROJ_LIB /opt/conda/envs/testenv/share/proj
获取此信息的简单方法是在根环境中调用 printenv > root_env.txt
,激活 testenv
,然后调用 printenv > test_env.txt
,然后检查
diff root_env.txt test_env.txt
.
方法 1:使用 SHELL 和自定义入口点脚本
编辑:我开发了一种 新的、改进的 方法,它比 "conda", "run"
语法更好。
Sample dockerfile available at this gist。它通过利用自定义入口点脚本在 exec
ing RUN
节的参数之前设置环境来工作。
为什么这样做有效?
A shell 是(简单地说)一个可以充当任意程序入口点的进程。 exec "$@"
允许我们启动一个新进程,继承父进程的所有环境。在这种情况下,这意味着我们激活 conda(它基本上破坏了一堆环境变量),然后 运行 /bin/bash -c CONTENTS_OF_DOCKER_RUN
.
方法 2:SHELL 带参数
这是我以前的方法,由 Itamar Turner-Trauring 提供;非常感谢他们!
# Create the environment:
COPY environment.yml .
RUN conda env create -f environment.yml
# Set the default docker build shell to run as the conda wrapped process
SHELL ["conda", "run", "-n", "vigilant_detect", "/bin/bash", "-c"]
# Set your entrypoint to use the conda environment as well
ENTRYPOINT ["conda", "run", "-n", "myenv", "python", "run.py"]
修改 ENV
可能不是最好的方法,因为 conda 喜欢自己控制环境变量。此外,您的自定义 conda env 可能会激活其他脚本以进一步调节环境。
为什么这样做有效?
这利用 conda run 在启动新的 bash shell 之前“为环境和 运行 环境可能包含的任何激活脚本添加条目” .
使用 conda 可能是一种令人沮丧的体验,因为这两种工具实际上都想独占环境,并且从理论上讲,您永远不需要在容器中使用 conda。但最后期限和技术债务是一回事,有时你只需要完成它,有时 conda 是提供依赖项的最简单方法(看着你,GDAL)。
场景
我正在尝试设置一个简单的 docker 图片(我对 docker 很陌生,所以请纠正我可能的误解)基于在 public continuumio/anaconda3 容器上。
Dockerfile
:
FROM continuumio/anaconda3:latest
# update conda and setup environment
RUN conda update conda -y \
&& conda env list \
&& conda create -n testenv pip -y \
&& source activate testenv \
&& conda env list
docker build -t test .
的构建和图像以错误结束:
/bin/sh: 1: source: not found
激活新的虚拟环境时。
建议 1:
以下 this answer 我试过:
FROM continuumio/anaconda3:latest
# update conda and setup environment
RUN conda update conda -y \
&& conda env list \
&& conda create -y -n testenv pip \
&& /bin/bash -c "source activate testenv" \
&& conda env list
这似乎一开始有效,因为它输出:prepending /opt/conda/envs/testenv/bin to PATH
,但是 conda env list
以及屁股 echo $PATH
清楚地表明它没有:
[...]
# conda environments:
#
testenv /opt/conda/envs/testenv
root * /opt/conda
---> 80a77e55a11f
Removing intermediate container 33982c006f94
Step 3 : RUN echo $PATH
---> Running in a30bb3706731
/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
docker 文件作为 MWE 开箱即用。 我很欣赏任何想法。谢谢!
使用docker ENV
指令可以将虚拟环境路径永久添加到PATH
。 虽然这并不能解决conda env list
下列出的所选环境。
查看 MWE:
FROM continuumio/anaconda3:latest
# update conda and setup environment
RUN conda update conda -y \
&& conda create -y -n testenv pip
ENV PATH /opt/conda/envs/testenv/bin:$PATH
RUN echo $PATH
RUN conda env list
借用 ccauet 的回答(我没法开始工作),以及 Charles Duffey 的评论说它不仅仅是 PATH
,下面是解决这个问题的方法。
激活环境时,conda 会设置以下变量,以及一些在停用环境时可以引用的备份默认值。这些变量已从 Dockerfile 中省略,因为永远不需要再次使用根 conda 环境。作为参考,它们是 CONDA_PATH_BACKUP
、CONDA_PS1_BACKUP
和 _CONDA_SET_PROJ_LIB
。它还设置 PS1
以便在终端提示行的左侧显示 (testenv)
,这也被省略了。以下语句将执行您想要的操作。
ENV PATH /opt/conda/envs/testenv/bin:$PATH
ENV CONDA_DEFAULT_ENV testenv
ENV CONDA_PREFIX /opt/conda/envs/testenv
为了减少创建的层数,您可以将这些命令组合成一个 ENV 命令,同时设置所有变量。
根据包的不同,可能还需要设置一些其他变量。例如,
ENV GDAL_DATA /opt/conda/envs/testenv/share/gdal
ENV CPL_ZIP_ENCODING UTF-8
ENV PROJ_LIB /opt/conda/envs/testenv/share/proj
获取此信息的简单方法是在根环境中调用 printenv > root_env.txt
,激活 testenv
,然后调用 printenv > test_env.txt
,然后检查
diff root_env.txt test_env.txt
.
方法 1:使用 SHELL 和自定义入口点脚本
编辑:我开发了一种 新的、改进的 方法,它比 "conda", "run"
语法更好。
Sample dockerfile available at this gist。它通过利用自定义入口点脚本在 exec
ing RUN
节的参数之前设置环境来工作。
为什么这样做有效?
A shell 是(简单地说)一个可以充当任意程序入口点的进程。 exec "$@"
允许我们启动一个新进程,继承父进程的所有环境。在这种情况下,这意味着我们激活 conda(它基本上破坏了一堆环境变量),然后 运行 /bin/bash -c CONTENTS_OF_DOCKER_RUN
.
方法 2:SHELL 带参数
这是我以前的方法,由 Itamar Turner-Trauring 提供;非常感谢他们!
# Create the environment:
COPY environment.yml .
RUN conda env create -f environment.yml
# Set the default docker build shell to run as the conda wrapped process
SHELL ["conda", "run", "-n", "vigilant_detect", "/bin/bash", "-c"]
# Set your entrypoint to use the conda environment as well
ENTRYPOINT ["conda", "run", "-n", "myenv", "python", "run.py"]
修改 ENV
可能不是最好的方法,因为 conda 喜欢自己控制环境变量。此外,您的自定义 conda env 可能会激活其他脚本以进一步调节环境。
为什么这样做有效?
这利用 conda run 在启动新的 bash shell 之前“为环境和 运行 环境可能包含的任何激活脚本添加条目” .
使用 conda 可能是一种令人沮丧的体验,因为这两种工具实际上都想独占环境,并且从理论上讲,您永远不需要在容器中使用 conda。但最后期限和技术债务是一回事,有时你只需要完成它,有时 conda 是提供依赖项的最简单方法(看着你,GDAL)。