簡體   English   中英

在 docker 中激活 conda 環境

[英]Activate conda environment in docker

我需要在 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:

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"]

您可以設置 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" ]

對我來說, 這里介紹的解決方案運行順暢:

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

正如用戶 merv 在上面的評論之一中指出的那樣(對不起,沒有足夠的代表來投票贊成評論) 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 "$@"

這篇文章的所有功勞歸功於 David R. Pugh,其中包含更多細節,尤其是關於 Jupyter。

以下是如何在 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"]

對我來說,問題是安裝后在 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

我知道沒有一種解決方案適合所有人,但這是我在 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 命令中指向它

我在嘗試激活環境然后在其中安裝一些軟件包時偶然發現了這個問題。 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 的 "" 內。

與其他答案類似,但使用 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}

讓它可靠地工作是非常沒有希望的。 有時,解決方案在系統上運行了一段時間,然后突然停止工作。 continuum/minicoda3的創建者現在也很少支持這一點。 我猜是因為他們打算以不同的方式使用容器。 我嘗試了以下操作,但是,當嘗試使用docker-compose運行容器時,它會在一個奇怪的位置/opt/conda/envs/而不是/root/miniconda3/envs/

FROM ubuntu:22.04
ENV PATH="/root/miniconda3/bin:${PATH}"
ARG PATH="/root/miniconda3/bin:${PATH}"
RUN apt-get update

RUN apt-get install -y wget build-essential time && rm -rf /var/lib/apt/lists/*

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 

RUN conda --version

RUN conda init bash

RUN conda create -n myenv -c conda-forge -c bioconda python==3.10 pip

SHELL ["conda", "run", "-n", "myenv", "/bin/bash", "-c"]

COPY requirements.txt requirements.txt

RUN pip install -r requirements.txt

我在運行容器時使用它來激活環境。 為了將軟件包安裝到該環境中,我只使用“-n myenv”。

ENV PATH /opt/miniconda/bin:${PATH}

RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-4.5.11-Linux-x86_64.sh -O ~/miniconda.sh --no-check-certificate && /bin/bash ~/miniconda.sh -b -p /opt/miniconda
RUN rm ~/miniconda.sh
RUN conda clean -ya

RUN conda update -n base -c defaults conda
RUN conda create --name detic python=3.8 -y

RUN echo ". /opt/miniconda/etc/profile.d/conda.sh" >> ~/.bashrc
RUN echo "conda activate detic" >> ~/.bashrc

RUN conda install -n detic ipython

我不喜歡更改入口點

如果您不需要改變遠離基地的環境,您也可以這樣做:

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

conda.yaml中的環境可以有任何名稱,因為我們將其替換為 base。

由於 conda run 是一項實驗性功能,因此正確的方法是將此行添加到 Dockerfile

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

在此之后你可以繼續

RUN conda init bash

然后繼續激活你的環境

RUN conda activate <env_name>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM