构建期间在 Dockerfile 中激活和切换 Anaconda 环境

Posted

技术标签:

【中文标题】构建期间在 Dockerfile 中激活和切换 Anaconda 环境【英文标题】:Activate and switch Anaconda environment in Dockerfile during build 【发布时间】:2019-10-23 22:05:40 【问题描述】:

我已经尝试了几个小时,但无法弄清楚如何在构建过程中在 Dockerfile 中激活和切换 anaconda 环境

这是初始代码:

FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu16.04

# Set user
ENV SETUSER myuser

RUN useradd -m $SETUSER
USER $SETUSER
WORKDIR /home/$SETUSER

# Install Anaconda
RUN wget https://repo.anaconda.com/archive/Anaconda3-2019.03-Linux-x86_64.sh
RUN bash Anaconda3-2019.03-Linux-x86_64.sh -b
RUN rm Anaconda3-2019.03-Linux-x86_64.sh

# Set path to conda
ENV CONDA_ENV_NAME mynewenv
RUN /home/$SETUSER/anaconda3/condabin/conda create -q --name $CONDA_ENV_NAME python=3.6 && \
    /home/$SETUSER/anaconda3/condabin/conda clean --yes --all
RUN /home/$SETUSER/anaconda3/condabin/conda activate base #Just for testing anaconda environment

一开始Docker中的anaconda会抱怨shell设置不正确,所以在conda create命令后我添加了:

RUN /home/$SETUSER/anaconda3/condabin/conda init bash
RUN /bin/bash -c "source /home/$SETUSER/.bashrc"
RUN /home/$SETUSER/anaconda3/condabin/conda activate base

在构建 docker 镜像后运行 3 个命令有效(即在调用 docker run container-name 后以交互方式运行),但由于某种原因,它在 构建 容器时不起作用。我发现 $PATH 变量在构建期间没有被更新,所以在构建时和构建后比较我的 $PATH。

ENV PATH /home/$SETUSER/anaconda3/envs/$CONDA_ENV_NAME/bin:$PATH
ENV PATH /home/$SETUSER/anaconda3/condabin:$PATH
ENV PATH /home/$SETUSER/anaconda3/bin:$PATH
RUN conda init bash
RUN /bin/bash -c "source /home/$SETUSER/.bashrc"
RUN conda activate base

现在,构建时的 Docker $PATH 和构建后运行容器时交互修改时的 $PATH 是相同的,但我仍然收到 shell 未正确设置错误。

CommandNotFoundError:您的 shell 未正确配置为使用“conda activate”。 要初始化你的 shell,运行 $ 康达初始化 目前支持的 shell 有: - 重击 - 鱼 -tcsh - xonsh -zsh - 电源外壳 有关更多信息和选项,请参阅“conda init --help”。 重要提示:运行“conda init”后,您可能需要关闭并重新启动 shell。

为什么这不起作用???

我已经看到可能有使用 miniconda docker 模板的解决方法,但我不能使用它。 Docker搭建过程中如何创建和切换anaconda环境?谢谢!

【问题讨论】:

通常在 Docker 中,您不需要像 Conda 这样可以管理多个并发隔离软件安装的工具:Docker 本身提供了这种隔离。对于 Python 包,只需在 Dockerfile 中运行 pip install 即可将内容安装到“系统”Python 中(与您正在构建的映像隔离)。 没关系,但我需要运行特定版本的python。所以我需要为此创建一个新的 anaconda 环境。 Same problem here with solution 你试过把RUN conda activate base改成RUN bash -c "conda activate base"吗? @DavidMaze 一些包仅通过 Anaconda 分发,在 PyPI 上不可用 【参考方案1】:

你的 Dockerfile 中有太多的 RUN 命令。不仅仅是每个 RUN 在图像中创建一个新层。也就是每个 RUN 命令都会启动一个新的 shell,conda activate 只适用于当前的 shell。

您应该将操作的逻辑组组合成一个 RUN 命令。使用&& 组合命令,使用\ 换行以提高可读性:

RUN conda activate <myenv> \
 && conda install <whatever> \
 && ...

请记住:在该 RUN 命令结束时,shell 将消失。因此,如果您想在之后对该 conda 环境执行其他操作,则必须再次运行 conda activate,或者使用 -n &lt;myenv&gt; 将某些内容放入环境中而不先激活它。

当您从镜像启动容器时,您还必须在容器内调用conda activate

【讨论】:

【参考方案2】:

假设您要安装 conda 环境并在其中运行某些东西,这种方法使用 ENV PATH 在该 conda 环境中间接启动 python。人们可能会怀疑这种方法是否真的激活了环境,但只要后续命令有效,而且确实有效,这可能并不重要。

FROM continuumio/miniconda3:latest
WORKDIR myappdir
COPY environment.yml .
RUN set -x && \
#   apt-get update && apt-get -y install gcc && \
    conda install -n base -c defaults conda=4.* && \
    conda env create -n condaenv  # Installs environment.yml && \
    conda clean -a
COPY myapppkg myapppkg
ENV PATH /opt/conda/envs/condaenv/bin:$PATH
ENTRYPOINT ["python", "-m", "myapppkg"]

我建议不要使用conda run,因为它是实验性的,因为有严重错误的历史,例如影响它的this one。尽管这个特定的错误现在已经修复,但它持续的“实验性”性质(如 conda run -h 所示)意味着它可能再次破坏上游,从而限制了人们对其的信任。

供参考:

List of Miniconda Docker tags 按频道列出的 conda 更新列表:defaults、conda-forge

【讨论】:

【参考方案3】:

我还没有使用 nvidia 图像对其进行测试,但 multi-stage Docker builds 应该可以帮助您,它可能看起来像:

# get Miniconda docker image to get a installed conda env; WARNING: That image is Debian based
FROM continuumio/miniconda3:latest AS miniconda


# your Docker commands
FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu16.04

# Set user
ENV SETUSER myuser

RUN useradd -m $SETUSER
USER $SETUSER
WORKDIR /home/$SETUSER


# Miniconda: get necessary files from build
COPY --from=miniconda /opt/conda /opt/conda
# Set correct permissions
RUN chown -R $SETUSER: /opt/conda
#   New terminals will have conda active
# If nvidia's Docker image has no .bashrc
# COPY --from=miniconda /home/$SETUSER/.bashrc
# else
RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
    echo "conda activate base" >> ~/.bashrc

# switch shell sh (default in Linux) to bash
SHELL ["/bin/bash", "-c"]

# give bash access to Anaconda, then normal anaconda commands, e.g. (-q: quiet, -y: answer yes)
RUN source /home/$SETUSER/.bashrc \
 && conda create -q --name testy \
 && conda activate testy \
 && conda install -y your_package

来自这个 GitHub 问题的灵感:https://github.com/ContinuumIO/docker-images/issues/89

【讨论】:

以上是关于构建期间在 Dockerfile 中激活和切换 Anaconda 环境的主要内容,如果未能解决你的问题,请参考以下文章

如何在 docker 构建期间指定和使用证书文件

从dockerfile构建的docker容器运行时无法连接到Rabbit MQ实例

在 Dockerfile 中激活 python virtualenv

Docker 命令在构建期间失败,但在正在运行的容器中执行时成功

在公司网络上构建映像期间网络调用失败

06-docker系列-使用dockerfile构建nginxredis镜像