Singularity(八)| conda实战

Singularity(八)| conda实战

8.1 conda 和容器的区别

Conda和容器技术(如Docker)都是现代软件开发和数据科学中常用的工具,用于解决环境依赖和应用部署的问题。尽管它们有着相似的目标,即确保应用可以在不同的环境中以一致的方式运行,但它们在设计和工作方式上有着根本的不同。

  • Conda 的主要目的是管理不同版本的软件包和创建虚拟环境,以便在同一计算机上安装和运行不同的软件包和库。它主要用于 Python 环境。
  • 容器的主要目的是将整个应用程序及其依赖项打包成容器,以确保应用程序在不同环境中的一致性和可移植性

隔离级别:

  • Conda:Conda 提供虚拟环境,通过创建独立的环境来隔离不同软件包的依赖关系,但它仍运行于操作系统之上,依赖于宿主机的操作系统和库(尽管通过环境可以实现一定程度的隔离)。
  • 容器:与宿主机共享内核,在操作系统级别提供隔离,每个容器都有自己的文件系统、网络配置和隔离的进程空间。

8.2 在 Singularity 容器中配置 conda

实例1:构建 qiime1 容器

首先在容器中安装 miniconda

shell 复制代码
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
chmod u+x Miniconda3-latest-Linux-x86_64.sh
./Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda3
chmod --recursive a+rw /opt/miniconda3

必须注意的是,Singularity 容器内的进程默认以用户 root 的身份运行。这意味着 $HOME 被设置为 /root,此时,Miniconda 在默认情况下会被安装到 /root/miniconda3。

然而,root 目录只有 root 账号才能访问,即使里面的文件有 a+rx 权限。即如果我们将 conda 默认装到了容器内 root 目录下,我们将无法以非 root 账户使用容器内的 conda,因此,conda 一定不能被安装在 /root 目录下

针对这一问题,我们在使用 shell 修改容器时,最好添加 --no-home 参数。

安装 qiime1 及其依赖:

bash 复制代码
# source .bashrc
. ~/.bashrc

# 1 创建新的 conda 环境 qiime1
conda create -n qiime1 python=2.7
conda activate qiime1

# 2 安装matplotlib==1.4.3的时候,出现错误 "The following required packages can
# not be built: * freetype", pip 不能安装系统依赖,手动安装系统依赖后然后安装
apt-get install libfreetype6-dev libxft-dev
pip install matplotlib==1.4.3

# 3 qiime中要求biom-format>=2.1.4,<2.2.0,但是目前版本不支持python 2.7
# 手动安装2.1.4版本
pip install biom-format==2.1.4

# 4 最后安装qiime
pip install qiime

# 5 检测安装是否成功
print_qiime_config.py -t

实例2:构建 qiime2 容器

下面还展示了一种直接利用 dockerfile 构建 qiime2 容器的方式:

dockerfile 复制代码
FROM ubuntu:20.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && \
    apt-get install -y \
    apt-utils \
    wget=1.20.3-1ubuntu1 \
    git=1:2.25.1-1ubuntu3 && \
    apt-get clean && \
    rm -rf rm -rf /var/lib/apt/lists/* && \
    wget https://repo.anaconda.com/miniconda/Miniconda3-py38_4.8.3-Linux-x86_64.sh && \
    chmod +x Miniconda3-py38_4.8.3-Linux-x86_64.sh && \
    ./Miniconda3-py38_4.8.3-Linux-x86_64.sh -b -p /opt/miniconda3 && \
    ln -s /opt/miniconda3/bin/conda /usr/bin/conda && \
    wget https://data.qiime2.org/distro/core/qiime2-2020.8-py36-linux-conda.yml && \
    conda env create -n qiime2-2020.8 --file qiime2-2020.8-py36-linux-conda.yml && \
    conda install -y -n qiime2-2020.8 -c conda-forge -c bioconda -c qiime2 -c defaults q2cli q2templates q2-types q2-feature-table q2-metadata vsearch snakemake && \
    chmod --recursive a+rw /opt/miniconda3 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm /qiime2-2020.8-py36-linux-conda.yml && \
    rm /Miniconda3-py38_4.8.3-Linux-x86_64.sh

CMD ["/bin/bash"]

参考前面的方法,创建 docker 容器后转为 singularity。或是按上文中的方法直接从 dockerfile 到 singularity。

这样,singularity exec ~/dockerimage.sif conda 就能正常运行,并显示 conda 的使用情况。然而,如果尝试执行其他一些命令,例如 singularity exec ~/dockerimage.sif conda run python -v,我们会得到类似以下的错误信息:

OSError: [Errno 30] Read-only file system: '/opt/miniconda3/.tmp58csqy_a'

这是因为除了挂载的目录外,容器是不可变的。此外,运行 singularity exec ~/dockerimage.sif conda activate qiime2-2020.8 也会失败:

CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'. To initialize your shell, run

swift 复制代码
$ conda init <SHELL_NAME>

Currently supported shells are:

  • bash
  • fish
  • tcsh
  • xonsh
  • zsh
  • powershell

See 'conda init --help' for more information and options.

IMPORTANT: You may need to close and restart your shell after running 'conda init'.

即使我们已经正确修改设置了 shell,我们仍然会得到以上结果。

8.3 使用 Singularity 容器中的 conda

针对以上问题,我们可以提供两种可能的解决方案,然而,这两个都存在很强的限制,目前来看,我们还无法完美的解决这一问题:

方式1:在容器内部运行

首先进入容器:

bash 复制代码
singularity shell ~/dockerimage.sif

然后在容器内部运行:

ini 复制代码
conda init # Modifies .bashrc on your host machine
source .bashrc # Loads modified .bashrc
export LC_ALL=C.UTF-8 # Sets locale to UTF-8
export LANG=C.UTF-8 # Sets locale to UTF-8
conda activate qiime2-2020.8 # Activates the environment

这一方法在我们具有 root 权限且只需要在本地运行程序时的体验很好。然而,在我们需要搭配 HPC 使用时非常困难。

方式 2:直接调用特定 conda 环境中的程序执行

例如,我们可以使用 def 文件创建一个包含 conda 的容器后,将参数直接传递给 conda 环境中的程序:

First, you'll want to

shell 复制代码
# get the environment YML
conda activate your_env
conda env export > environment.yml
shell 复制代码
Bootstrap: docker

From: continuumio/miniconda3

%files
    environment.yml

%post
    /opt/conda/bin/conda env create -f environment.yml

%runscript
    exec /opt/conda/envs/$(head -n 1 environment.yml | cut -f 2 -d ' ')/bin/"$@"

构建容器:

shell 复制代码
singularity build conda.sif

此时,我们可以直接调用容器内 conda 环境中的 ipython 解释器:

shell 复制代码
singularity run conda.sif ipython
# 或者使用conda环境中的绝对路径
singularity exec conda.sif /opt/conda/envs/.../bin/app

然而,这种方法无法激活 conda 环境,在某些情况下会遇到环境变量问题。

方式3:手动处理 conda 环境变量

较多情况下,激活 conda 环境的作用在于重新配置环境变量。

例如我们在 base conda 环境下安装某个应用,其软件依赖的可执行程序一般会被放置在 /opt/conda/bin 目录下,在 activate conda 环境后,/opt/conda/bin 目录就会被添加到环境变量中。

因此,在不激活 conda 环境的条件下,我们可以使用三种方式实现环境变量的配置:

  1. (推荐)在调用容器前,添加需要的环境变量:

    shell 复制代码
    export PATH="/opt/conda/bin:$PATH"
  2. 在现存环境变量的路径下(例如:/usr/local/bin)为调用的软件依赖创建软链接:

    shell 复制代码
    ln -s /opt/conda/bin/curl /usr/local/bin/curl
  3. 直接修改源代码中的依赖路径为绝对路径。

8.1 conda 和容器的区别

Conda和容器技术(如Docker)都是现代软件开发和数据科学中常用的工具,用于解决环境依赖和应用部署的问题。尽管它们有着相似的目标,即确保应用可以在不同的环境中以一致的方式运行,但它们在设计和工作方式上有着根本的不同。

  • Conda 的主要目的是管理不同版本的软件包和创建虚拟环境,以便在同一计算机上安装和运行不同的软件包和库。它主要用于 Python 环境。
  • 容器的主要目的是将整个应用程序及其依赖项打包成容器,以确保应用程序在不同环境中的一致性和可移植性

隔离级别:

  • Conda:Conda 提供虚拟环境,通过创建独立的环境来隔离不同软件包的依赖关系,但它仍运行于操作系统之上,依赖于宿主机的操作系统和库(尽管通过环境可以实现一定程度的隔离)。
  • 容器:与宿主机共享内核,在操作系统级别提供隔离,每个容器都有自己的文件系统、网络配置和隔离的进程空间。

8.2 在 Singularity 容器中配置 conda

实例1:构建 qiime1 容器

首先在容器中安装 miniconda

shell 复制代码
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
chmod u+x Miniconda3-latest-Linux-x86_64.sh
./Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda3
chmod --recursive a+rw /opt/miniconda3

必须注意的是,Singularity 容器内的进程默认以用户 root 的身份运行。这意味着 $HOME 被设置为 /root,此时,Miniconda 在默认情况下会被安装到 /root/miniconda3。

然而,root 目录只有 root 账号才能访问,即使里面的文件有 a+rx 权限。即如果我们将 conda 默认装到了容器内 root 目录下,我们将无法以非 root 账户使用容器内的 conda,因此,conda 一定不能被安装在 /root 目录下

针对这一问题,我们在使用 shell 修改容器时,最好添加 --no-home 参数。

安装 qiime1 及其依赖:

bash 复制代码
# source .bashrc
. ~/.bashrc

# 1 创建新的 conda 环境 qiime1
conda create -n qiime1 python=2.7
conda activate qiime1

# 2 安装matplotlib==1.4.3的时候,出现错误 "The following required packages can
# not be built: * freetype", pip 不能安装系统依赖,手动安装系统依赖后然后安装
apt-get install libfreetype6-dev libxft-dev
pip install matplotlib==1.4.3

# 3 qiime中要求biom-format>=2.1.4,<2.2.0,但是目前版本不支持python 2.7
# 手动安装2.1.4版本
pip install biom-format==2.1.4

# 4 最后安装qiime
pip install qiime

# 5 检测安装是否成功
print_qiime_config.py -t

实例2:构建 qiime2 容器

下面还展示了一种直接利用 dockerfile 构建 qiime2 容器的方式:

dockerfile 复制代码
FROM ubuntu:20.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && \
    apt-get install -y \
    apt-utils \
    wget=1.20.3-1ubuntu1 \
    git=1:2.25.1-1ubuntu3 && \
    apt-get clean && \
    rm -rf rm -rf /var/lib/apt/lists/* && \
    wget https://repo.anaconda.com/miniconda/Miniconda3-py38_4.8.3-Linux-x86_64.sh && \
    chmod +x Miniconda3-py38_4.8.3-Linux-x86_64.sh && \
    ./Miniconda3-py38_4.8.3-Linux-x86_64.sh -b -p /opt/miniconda3 && \
    ln -s /opt/miniconda3/bin/conda /usr/bin/conda && \
    wget https://data.qiime2.org/distro/core/qiime2-2020.8-py36-linux-conda.yml && \
    conda env create -n qiime2-2020.8 --file qiime2-2020.8-py36-linux-conda.yml && \
    conda install -y -n qiime2-2020.8 -c conda-forge -c bioconda -c qiime2 -c defaults q2cli q2templates q2-types q2-feature-table q2-metadata vsearch snakemake && \
    chmod --recursive a+rw /opt/miniconda3 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm /qiime2-2020.8-py36-linux-conda.yml && \
    rm /Miniconda3-py38_4.8.3-Linux-x86_64.sh

CMD ["/bin/bash"]

参考前面的方法,创建 docker 容器后转为 singularity。或是按上文中的方法直接从 dockerfile 到 singularity。

这样,singularity exec ~/dockerimage.sif conda 就能正常运行,并显示 conda 的使用情况。然而,如果尝试执行其他一些命令,例如 singularity exec ~/dockerimage.sif conda run python -v,我们会得到类似以下的错误信息:

OSError: [Errno 30] Read-only file system: '/opt/miniconda3/.tmp58csqy_a'

这是因为除了挂载的目录外,容器是不可变的。此外,运行 singularity exec ~/dockerimage.sif conda activate qiime2-2020.8 也会失败:

CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'. To initialize your shell, run

swift 复制代码
$ conda init <SHELL_NAME>

Currently supported shells are:

  • bash
  • fish
  • tcsh
  • xonsh
  • zsh
  • powershell

See 'conda init --help' for more information and options.

IMPORTANT: You may need to close and restart your shell after running 'conda init'.

即使我们已经正确修改设置了 shell,我们仍然会得到以上结果。

8.3 使用 Singularity 容器中的 conda

针对以上问题,我们可以提供两种可能的解决方案,然而,这两个都存在很强的限制,目前来看,我们还无法完美的解决这一问题:

方式1:在容器内部运行

首先进入容器:

bash 复制代码
singularity shell ~/dockerimage.sif

然后在容器内部运行:

ini 复制代码
conda init # Modifies .bashrc on your host machine
source .bashrc # Loads modified .bashrc
export LC_ALL=C.UTF-8 # Sets locale to UTF-8
export LANG=C.UTF-8 # Sets locale to UTF-8
conda activate qiime2-2020.8 # Activates the environment

这一方法在我们具有 root 权限且只需要在本地运行程序时的体验很好。然而,在我们需要搭配 HPC 使用时非常困难。

方式 2:直接调用特定 conda 环境中的程序执行

例如,我们可以使用 def 文件创建一个包含 conda 的容器后,将参数直接传递给 conda 环境中的程序:

First, you'll want to

shell 复制代码
# get the environment YML
conda activate your_env
conda env export > environment.yml
shell 复制代码
Bootstrap: docker

From: continuumio/miniconda3

%files
    environment.yml

%post
    /opt/conda/bin/conda env create -f environment.yml

%runscript
    exec /opt/conda/envs/$(head -n 1 environment.yml | cut -f 2 -d ' ')/bin/"$@"

构建容器:

shell 复制代码
singularity build conda.sif

此时,我们可以直接调用容器内 conda 环境中的 ipython 解释器:

shell 复制代码
singularity run conda.sif ipython
# 或者使用conda环境中的绝对路径
singularity exec conda.sif /opt/conda/envs/.../bin/app

然而,这种方法无法激活 conda 环境,在某些情况下会遇到环境变量问题。

方式3:手动处理 conda 环境变量

较多情况下,激活 conda 环境的作用在于重新配置环境变量。

例如我们在 base conda 环境下安装某个应用,其软件依赖的可执行程序一般会被放置在 /opt/conda/bin 目录下,在 activate conda 环境后,/opt/conda/bin 目录就会被添加到环境变量中。

因此,在不激活 conda 环境的条件下,我们可以使用三种方式实现环境变量的配置:

  1. (推荐)在调用容器前,添加需要的环境变量:

    shell 复制代码
    export PATH="/opt/conda/bin:$PATH"
  2. 在现存环境变量的路径下(例如:/usr/local/bin)为调用的软件依赖创建软链接:

    shell 复制代码
    ln -s /opt/conda/bin/curl /usr/local/bin/curl
  3. 直接修改源代码中的依赖路径为绝对路径。

本文由mdnice多平台发布

相关推荐
愤怒的代码10 分钟前
Spring Boot对访问密钥加解密——HMAC-SHA256
java·spring boot·后端
栗豆包27 分钟前
w118共享汽车管理系统
java·spring boot·后端·spring·tomcat·maven
万亿少女的梦16839 分钟前
基于Spring Boot的网络购物商城的设计与实现
java·spring boot·后端
开心工作室_kaic2 小时前
springboot485基于springboot的宠物健康顾问系统(论文+源码)_kaic
spring boot·后端·宠物
0zxm2 小时前
08 Django - Django媒体文件&静态文件&文件上传
数据库·后端·python·django·sqlite
刘大辉在路上9 小时前
突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除
git·后端·gitlab·版本管理·源代码管理
追逐时光者11 小时前
免费、简单、直观的数据库设计工具和 SQL 生成器
后端·mysql
初晴~12 小时前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
盖世英雄酱5813612 小时前
InnoDB 的页分裂和页合并
数据库·后端