【问题标题】:Activate conda environment in docker在 docker 中激活 conda 环境
【发布时间】:2019-08-03 01:15:57
【问题描述】:

我需要在 docker 中激活环境并在此环境中运行命令。 我创建了环境,然后我尝试激活这个环境并以这种方式运行命令:

CMD [ "source activate mro_env && ipython kernel install --user --name=mro_env" ]

但是当我运行 docker 时出现错误:

[FATAL tini (8)] exec source activate mro_env && ipython kernel install 
--user --name=mro_env failed: No such file or directory

这是整个 Dockerfile:

FROM continuumio/miniconda3

ADD /src/mro_env.yml /src/mro_env.yml
RUN conda env create -f /src/mro_env.yml

# Pull the environment name out of the mro_env.yml
RUN echo "source activate $(head -1 /src/mro_env.yml | cut -d' ' -f2)" > ~/.bashrc
ENV PATH /opt/conda/envs/$(head -1 /src/mro_env.yml | cut -d' ' -f2)/bin:$PATH

CMD [ "source activate mro_env && ipython kernel install --user --name=mro_env" ]

【问题讨论】:

  • 请向我们展示您的 Dockerfile;看起来您实际上并没有最终创建 mro_env 环境。也请查看official documentation 以获取 CMD 指令。
  • @JordanSinger 我添加了 Dockerfile
  • 你确定你的环境创建成功了吗?
  • @FabienP 是的。环境安装成功。问题是与 jupyter notebook 的集成。我的目标是在 jupyter 上安装环境,并用这个环境启动 jupyter。你知道我该怎么做吗?
  • 我这样做的方式通常是在环境中安装 Jupyter,然后从那里启动它。否则,您可以查看 nb_conda_kernels 以从您的 Jupyter 服务器访问此环境。

标签: python docker anaconda conda


【解决方案1】:

关注了tutorial,它成功了。示例 Dockerfile:

FROM continuumio/miniconda
WORKDIR /usr/src/app
COPY ./ ./
RUN conda env create -f environment.yml

# Make RUN commands use the new environment:
SHELL ["conda", "run", "-n", "myenv", "/bin/bash", "-c"]

EXPOSE 5003
# The code to run when container is started:
ENTRYPOINT ["conda", "run", "-n", "myenv", "python3", "src/server.py"]

更新:

如果您使用 4.9 版本的 conda,您可以使用“conda run --no-capture-output”来不缓冲 IO。更新 Dockerfile:

FROM continuumio/miniconda
WORKDIR /usr/src/app
COPY ./ ./
RUN conda env create -f environment.yml

# Make RUN commands use the new environment:
SHELL ["conda", "run", "--no-capture-output", "-n", "myenv", "/bin/bash", "-c"]

EXPOSE 5003
# The code to run when container is started:
ENTRYPOINT ["conda", "run", "--no-capture-output", "-n", "myenv", "python3", "src/server.py"]

【讨论】:

  • 您在此处提到的教程(以及整个网站)值得花每一分钟阅读。谢谢。
  • SHELL 命令不起作用并使我的其余代码认为它在引号中
  • 最后我知道,conda run 缓冲所有标准输出/错误,直到该过程完成,因此这不是通过标准 I/O 交互的应用程序的选项。我想它仍然可以运行服务器,但不要指望在运行时监视任何 stderr 消息。此外,该“教程”存在问题,例如第一个示例仅失败,因为作者没有在单个 RUN 中正确链接他们的命令(即使用&&),并且在the base image 已经有不必要的情况下运行conda init完成设置。
  • Docker 是如此短暂以至于命令需要像那样链接起来
  • @merv 如果您使用 4.9 版本的 conda,您可以使用“conda run --no-capture-output”不缓冲 IO
【解决方案2】:

您可以设置 CONDA_DEFAULT_ENV

像这样:

FROM continuumio/miniconda3

ARG conda_env=mro_env

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

ENV PATH /opt/conda/envs/$conda_env/bin:$PATH
ENV CONDA_DEFAULT_ENV $conda_env

CMD [ "python", "test.py" ]

更新:

更好地使用激活。为我工作:

FROM continuumio/miniconda3

ADD /src/environment.yml /src/environment.yml

RUN conda env create -f /src/environment.yml
ENV PATH /opt/conda/envs/mro_env/bin:$PATH
RUN /bin/bash -c "source activate mro_env"

CMD [ "python", "test.py" ]

【讨论】:

  • 它是在 conda env 的 bin 前面加上可以工作的,不知道 CONDA_DEFAULt_ENV 的作用在这里。这可能会使conda activate 混乱,因为您没有将其他变量定义为CONDA_SHLVL 等...
  • 我的问题是在这个环境下启动 jupyter。您知道如何在 jupyter 上安装环境并使用环境启动它吗?
  • 指定/bin/bash -c "source activate mro_env" 似乎完全没有意义,因为后面的ENTRYPOINT 和/或CMD 的活动shell 不是bash;显然是sh。设置CONDA_DEFAULT_ENV 似乎也同样没有意义。在这两种情况下,真正的工作都是由ENV PATH 完成的。
  • 在使用 docker 时,我们每次创建容器时是否总是需要创建一个新的 conda 环境?还是在创建 docker 镜像时只做一次?
【解决方案3】:

对我来说,here 介绍的解决方案工作得很好:

FROM continuumio/miniconda3
RUN conda create -n env python=3.6
RUN echo "source activate env" > ~/.bashrc
ENV PATH /opt/conda/envs/env/bin:$PATH

【讨论】:

    【解决方案4】:

    正如用户 merv 在上面的其中一个 cmets 中指出的那样(抱歉没有足够的代表来投票赞成评论)conda run 缓冲所有 stdout/stderr,从而使其不适用于交互甚至只是显示的应用程序通过 I/O 登录。

    我注意到没有可接受的答案,所以我只发布了对我来说非常有效的答案:

    您可以使用入口点脚本来激活 conda 环境并让它接管 Dockerfile 的进一步输入,以便可以在激活的 conda 环境中执行 python 脚本

    示例 Dockerfile:

    FROM continuumio/miniconda3
    
    # make docker use bash instead of sh
    SHELL ["/bin/bash", "--login", "-c"]
    
    # copy all necessary files
    COPY environment.yml .
    COPY ownchain/mypyscript.py .
    COPY entrypoint.sh /usr/local/bin/
    
    # make entrypoint script executable
    RUN chmod u+x /usr/local/bin/entrypoint.sh
    # create environment
    RUN conda env create -f environment.yml
    
    ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
    CMD ["python", "mypyscript.py"]
    

    entrypoint.sh 如下所示:

    #!/bin/bash --login
    set -e
    
    # activate conda environment and let the following process take over
    conda activate myenv
    exec "$@"
    

    感谢 this post 的 David R. Pugh 提供了更多详细信息,尤其是关于 Jupyter。

    【讨论】:

    • 在使用 docker 时,我们每次创建容器时是否总是需要创建一个新的 conda env?还是在创建 docker 镜像时只做一次?
    【解决方案5】:

    下面是如何在 conda 环境中运行脚本不缓冲所有标准输入/输出。

    --no-capture-output 选项自 conda 4.9 版起可用。

    FROM continuumio/miniconda3
    
    COPY ./environment.yml ./environment.yml
    
    RUN conda env create && conda clean --all -f --yes
    
    ENTRYPOINT ["conda", "run", "--no-capture-output", "-n", "the_environment_name", "python", "myscript.py"]
    

    【讨论】:

      【解决方案6】:

      对我来说,问题是安装后在 docker 内运行命令 conda activate env 导致 conda 要求我使用 conda init bash 命令。但是,此命令要求您重新启动 shell,而我们不想在 docker 内部执行此操作。所以解决的办法是意识到conda要求你重新启动shell的原因是因为它已经修改并且想要重新加载~/.bashrc的内容。我们可以手动执行此操作,而无需使用以下方法重新启动 shell:

      . ~/.bashrc
      

      这里有完整的 dockerfile 供需要的人使用:

      FROM ubuntu:18.04
      # update apt and get miniconda
      RUN apt-get update \
          && apt-get install -y wget \
          && wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
      
      
      # install miniconda
      ENV PATH="/root/miniconda3/bin:$PATH"
      RUN mkdir /root/.conda && bash Miniconda3-latest-Linux-x86_64.sh -b
      
      # create conda environment
      RUN conda init bash \
          && . ~/.bashrc \
          && conda create --name test-env python=3.7 \
          && conda activate test-env \
          && pip install ipython
      
      

      编辑 - 处理评论

      评论者是正确的,因为上面的示例不适用于在 docker 中切换 conda 环境。最近,我发现要让它工作,你应该以conda init bash && .~/.bashrc && conda activate env 开始每个RUN 命令。

      这是另一个例子:

      
      FROM quay.io/pypa/manylinux2014_x86_64
      
      RUN yum install -y wget
      RUN wget https://repo.anaconda.com/miniconda/Miniconda3-py39_4.9.2-Linux-x86_64.sh
      RUN bash Miniconda3-py39_4.9.2-Linux-x86_64.sh -b -p /Miniconda3
      
      RUN /Miniconda3/bin/conda create -y --name py37 python=3.7 pytest
      RUN /Miniconda3/bin/conda create -y --name py38 python=3.8 pytest
      RUN /Miniconda3/bin/conda create -y --name py39 python=3.9 pytest
      
      RUN /Miniconda3/bin/conda init && bash ~/.bashrc && . ~/.bashrc
      
      ENV conda /Miniconda3/bin/conda
      ENV bashrc /root/.bashrc
      
      # install numpy in each env
      RUN $conda init && . $bashrc && conda activate py37 && pip install numpy 
      RUN $conda init && . $bashrc && conda activate py38 && pip install numpy
      RUN $conda init && . $bashrc && conda activate py39 && pip install numpy
      
      

      【讨论】:

      • 将最后一个复合命令放在不同的 RUN 行上,它会完全中断。如果您需要在容器中的不同环境之间切换,这不是一个可行的解决方案。
      • @Jeremy Leipzig 是正确的。为了在后续的 RUN 命令中切换 conda 环境,您需要以 conda init && . ~/.bashrc && conda activate py38 开始每个 RUN 命令(例如)。
      【解决方案7】:

      我知道没有一种解决方案适合所有人,但这是我在 Flask 应用程序中一直使用的解决方案:

      FROM continuumio/miniconda3
      
      COPY environment.yml .
      RUN conda env create -f environment.yml
      
      COPY app /app
      WORKDIR /app
      
      CMD ["conda", "run", "-n", "my_env", "python", "app.py"]
      

      逻辑很简单。首先,复制环境文件,然后创建环境。接下来,复制应用程序文件(这是我所有的 Flask 应用程序文件所在的位置)。最后,使用 CMD 通过指向环境启动应用程序。

      这是我在 Dockerfile 中使用的项目目录结构:

      -- project
          -- app
              -- app.py
          -- environment.yaml
          -- Dockerfile
      

      请注意,这不会激活环境本身,而是在运行时在 CMD 命令中指向它

      【讨论】:

        【解决方案8】:

        我在尝试激活环境然后在其中安装一些软件包时偶然发现了这个问题。 SHELL 解决方案对我不起作用(可能是因为我在旧版本的 conda 上尝试这样做 - 准确地说是 4.5.4)。

        解决方案是激活环境并在新外壳中运行所有必需的命令。另外,请记住,每次 RUN 都会启动一个新的 shell,它不会记住前一次 RUN 的任何内容。

        FROM continuumio/miniconda3
        
        ADD /src/environment.yml /src/environment.yml
        
        RUN conda env create -f /src/environment.yml
        ENV PATH /opt/conda/envs/mro_env/bin:$PATH
        RUN /bin/bash -c "source activate mro_env \
            && conda config --add channels conda-forge \
            && conda install Jupiter \
            && conda env list"
        
        CMD [ "python", "test.py" ]
        

        注意每个命令都在同一个 /bin/bash -c 的 "" 内。

        【讨论】:

          【解决方案9】:

          与其他答案类似,但 SHELL 看起来更干净

          RUN wget \
          https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \
          && mkdir /root/.conda \
          && bash Miniconda3-latest-Linux-x86_64.sh -b \
          && rm -f Miniconda3-latest-Linux-x86_64.sh \
          && echo "source activate base" > ~/.bashrc
          
          SHELL ["/bin/bash", "-c"]
          ARG CONDA_ENV=env_name 
          # Create env
          RUN conda --version \
            && conda create -n ${CONDA_ENV} python=3.7 \
            && source activate ${CONDA_ENV}
          

          【讨论】:

            【解决方案10】:

            如果您不需要改变基地以外的环境,您也可以这样做:

            COPY conda.yaml /
            RUN { echo "name: base"; tail +2 /conda.yaml; } > /base.yaml
            RUN conda env update --file /base.yaml --prune
            

            conda.yaml 中的环境可以有任何名称,因为我们将其替换为 base。

            【讨论】:

              【解决方案11】:

              因为 conda run 是一项实验性功能,所以正确的方法是将此行添加到 Dockerfile 中

              SHELL [ "/bin/bash", "--login", "-c" ]
              

              之后你可以继续

              RUN conda init bash
              

              然后继续使用

              激活您的环境
              RUN conda activate <env_name>
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-06-08
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多