从Dockerfile在Singularity容器中激活conda环境

3

我正在尝试从现有的Docker镜像中设置一个Singularity容器,在其中运行名为“tensorflow”的conda环境。当我运行容器时,该环境将被激活。我在这个主题上找到了一些答案 (链接)。不幸的是,在这篇文章中,他们只解释了如何设置singularity.def文件以默认激活conda环境。但是,我想仅修改我的现有Dockerfile,然后从中构建Singularity镜像。

我目前尝试的是按以下方式设置Dockerfile:

FROM opensuse/tumbleweed

ENV PATH /opt/conda/bin:$PATH
ENV PATH /opt/conda/envs/tensorflow/bin:$PATH

# Add conda environment files (.yml)
COPY ["./conda_environments/", "."]

# Install with zypper
RUN zypper install -y sudo wget bzip2 vim tree which util-linux

# Get installation file
RUN wget --quiet https://repo.anaconda.com/archive/Anaconda3-2019.07-Linux-x86_64.sh -O ~/anaconda.sh

# Install anaconda at /opt/conda
RUN /bin/bash ~/anaconda.sh -b -p "/opt/conda"

# Remove installation file
RUN rm ~/anaconda.sh

# Make conda command available to all users
RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh

# Create tensorflow environment
RUN conda env create -f tensorflow.yml

# Activate conda environment with interactive bash session
RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc
RUN echo "conda activate tensorflow" >> ~/.bashrc

# Default command
CMD ["/bin/bash"]

构建Docker镜像后,可以使用以下命令运行Docker容器:

docker run -t -d --rm --name=my_container opensuse_conda:latest

使用以下命令进入容器:

docker exec -it my_container bash

结果正如预期。 shell 会话直接启动 "tensorflow" 环境,这由 (tensorflow) 前缀表示。

要从此 Docker 镜像构建 Singularity 镜像,我使用:

sudo singularity build opensuse_conda.sif docker-daemon://opensuse_conda:latest

并使用以下命令来运行容器:

sudo singularity run opensuse_conda.sif

这就是问题所在。默认情况下会激活“base”环境,而不是“tensorflow”环境。然而,当我运行singularity容器时,我希望激活“tensorflow”环境。
请问如何修改Dockerfile,使得无论是运行docker容器还是singularity容器,默认环境都是“tensorflow”?
非常感谢您的帮助!
1个回答

2
你的问题在于只有在启动交互式 shell 时才会读取 .bashrc,但是当容器使用默认命令运行时不会读取。请参考这个答案获取背景信息。
有一堆bash 启动文件可以用来代替,在其中放置 conda activate tensorflow 命令。我建议定义自己的文件,并将文件名放入 BASH_ENV 环境变量中。这两个步骤都可以轻松地在 Dockerfile 中完成。最初的回答:您的问题在于 .bashrc 文件只有在启动交互式 shell 时才会被读取,但是当容器使用默认命令运行时不会读取。请参考此答案了解背景信息。有多个 bash 启动文件可供选择,您可以在其中任何一个文件中添加 conda activate tensorflow 命令。建议创建自己的文件,并将文件名添加到 BASH_ENV 环境变量中,这两个步骤都可以通过 Dockerfile 轻松完成。

非常感谢您的回答。我还有两个后续问题: 1.) 当我采用您推荐的BASH_ENV解决方案并尝试从singularity容器内执行python脚本时,我是否必须运行singularity run opensuse_conda.sif bash -c“python test.py”以确保激活“tensorflow”环境?对我来说这很有效,但我想知道是否真的必须使用bash -c命令。 - Constih
你说过,只有在启动交互式 shell 时才会读取 .bashrc 文件。当我运行 docker run -it <image> /bin/bash 时,这是正确的。正如预期的那样,我可以获得一个交互式会话,并且 "tensorflow" 环境处于活动状态。然而,运行 singularity run <image>.sif /bin/bash 会产生一个交互式会话,但没有任何环境处于活动状态。我必须首先输入 conda activate tensorflow 才能进入我的自定义环境。为什么会这样呢?看起来像是我在 Dockerfile 中创建的 .bashrc 文件在启动交互式 singularity 容器会话时没有被读取。 - Constih
默认情况下,Singularity 运行时使用 --norc 和自定义的 $PS1,以便您知道您正在使用 Singularity 镜像而不是主机。当您使用 bash -c ... 作为运行命令时,您将绕过通常使用 --norc 的位置,这就是为什么您的运行环境与您期望的一样的原因。 - tsnowlan
嗨@Constih,我想知道你是否找到了一种不使用bash -c ...自动激活环境的方法? - web

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接