Ubuntu 24.0.4 下的 apptainer 初始化与使用
前情提要
我系“点六”服务器所装的
GNU/Linux发行版为Ubuntu 24.04.4 LTS,可通过以下方法验证:cat /etc/os-release # PRETTY_NAME="Ubuntu 24.04.4 LTS" # NAME="Ubuntu" # VERSION_ID="24.04" # VERSION="24.04.4 LTS (Noble Numbat)" # VERSION_CODENAME=noble # ID=ubuntu # ID_LIKE=debian # HOME_URL="https://www.ubuntu.com/" # SUPPORT_URL="https://help.ubuntu.com/" # BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" # PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" # UBUNTU_CODENAME=noble # LOGO=ubuntu-logo之前我在“点六”上使用
conda-forge源安装的apptainer时,不论进行什么操作(如shell、build等),都会出现以下错误:ERROR: Could not write info to setgroups: Permission denied ERROR: Error while waiting event for user namespace mappings: no event received而使用管理员(也是我)通过
apt安装的singularity则一切顺利。
原因排查
去 Github 上一搜得知,原来是
Ubuntu在 23.10 版本号后使用了 AppArmor 以增强安全性:Apparmor Profile (Ubuntu 23.10+)
Beginning with the 23.10 release and including the 24.04 LTS release, Ubuntu does not permit applications to create unprivileged user namespaces by default.
从 23.10 版本开始,包括 24.04 LTS版本,Ubuntu 默认不允许应用程序创建无权限的用户命名空间。
If you install Apptainer from a GitHub release .deb package then an apparmor profile will be installed that permits Apptainer to create unprivileged user namespaces.
如果你从 GitHub 版本.deb包安装 Apptainer,那么会安装一个 apparmor 配置文件,允许 Apptainer 创建非特权用户命名空间。
If you install Apptainer from source you must either configure apparmor or disable the restriction on unprivileged user namespaces. To create an apparmor profile:
如果你从源头安装 Apptainer,必须配置 AppArmor 或关闭对非特权用户命名空间的限制。
所以通过
apt之外方法安装的apptainer或singularity都会被AppArmor拦截,影响正常运行。必须配置AppArmor或关闭对非特权用户命名空间的限制。
解决办法
- 基于
apptainer官方的解决措施以及 这篇博客,我的解决方法如下:# 全面禁用非特权用户命名空间限制(写入文件以永久生效) echo 'kernel.apparmor_restrict_unprivileged_userns = 0' | sudo tee /etc/sysctl.d/20-apparmor-donotrestrict.conf sudo sysctl --load /etc/sysctl.d/20-apparmor-donotrestrict.conf # 禁用 apparmor 服务 sudo systemctl disable --now apparmor
实际应用
- 假设这样一个情景:你有一个
conda虚拟环境containertools,里面装了很多软件。 - 实验室有另一台性能强劲的服务器,管理员在上面提前装好了
apptainer/singularity,现在需要把你的虚拟环境containertools移植到上面跑一个项目。 - 可是你又不想从头配置
conda/mamba,该怎么偷懒呢?
0. 基础准备
- 确保虚拟环境
containertools所在的服务器上安装有fakeroot与uidmap软件包。 - 如果缺少可联系服务器管理员进行安装:
# 以 Debian 系发行版为例,根据实际情况调整 sudo apt update && sudo apt upgrade -y sudo apt install fakeroot uidmap fuse2fs -y
1. 打包虚拟环境
- 使用
conda-pack对虚拟环境containertools进行打包。 - 这里我安装了若干软件进行模拟,
conda-pack可安装在base环境内。# 配置 “containertools” 虚拟环境 #(默认你配置好了 bioconda 与 conda-forge 频道以及对应镜像源) mamba env create -n containertools fastp fastqc bwa bedtools # 在 base 环境安装 conda-pack 与 apptainer mamba install conda-pack apptainer # 使用 conda-pack 打包虚拟环境 “containertools” conda-pack -n containertools # conda-pack 的进度条结束后会在当前路径生成一个 containertools.tar.gz 压缩包
2. 构建 sif 镜像
使用你喜欢的文本编辑器(例如 vim)新建一个
containertools.def文件:# 使用 docker 镜像中的 ubuntu:24.04 作为基础镜像 # 国内由于网络原因,无法直连 dockerhub 网站,所以需要配置镜像源(我这里选择了 1panel 提供的) Bootstrap: docker From: docker.1panel.live/library/ubuntu:24.04 %files # 将刚才 conda-pack 打包好的压缩包拷贝进镜像内部 containertools.tar.gz /opt/containertools.tar.gz %environment # 设置镜像内的语言环境变量,否则会有很多脚本会报 warning export LANG=C export LANGUAGE=C export LC_ALL=C # 设置环境变量,让镜像运行后默认就能找到这个环境里的软件 export PATH=/opt/containertools/bin:$PATH %post # 给镜像内的 apt 换源,加快安装速度 # 这里我选择南京大学的镜像源 sed -E -i 's/(archive|security)\.ubuntu\.com/mirrors.nju.edu.cn/g' /etc/apt/sources.list.d/* # 安装 python,在后续的 conda-unpack 过程中会用到 apt update && apt upgrade -y apt install python3 -y # 软链接一下,因为 conda-unpack 脚本的 shebang 行是 #!/usr/bin/env python # 而 apt 安装的 python3 默认未被指向 ln -s /usr/bin/python3 /usr/bin/python # 创建目录并解压环境 mkdir -p /opt/containertools tar -xzf /opt/containertools.tar.gz -C /opt/containertools rm /opt/containertools.tar.gz # 激活虚拟环境 containertools 中的 conda-unpack 脚本(修复路径) /opt/containertools/bin/conda-unpack %runscript # 默认执行命令 exec "$@"开始构建吧~
apptainer build --fakeroot containertools.sif containertools.def # 耐心等待ing... # 网速给力的情况下应该挺快的,我测试时整个 build 阶段就花了40多秒 # # time apptainer build --fakeroot containertools.sif containertools.def # real 0m41.421s # user 1m26.779s # sys 0m5.683s
3. 使用 sif 镜像
3.1 交互模式
- 将上一步生成的
containertools.sif通过scp/sftp等方法上传到另一台服务器上,就可以运行啦~# 在另一台服务器上 apptainer shell containertools.sif # 检查版本与安装路径 # Apptainer> fastp --version # fastp 1.3.2 # Apptainer> fastqc --version # FastQC v0.12.1 # Apptainer> bedtools --version # bedtools v2.31.1 # Apptainer> which bwa # /opt/containertools/bin/bwa apptainer会默认将你的主目录挂载到镜像内部,如果想要在镜像里使用除主目录外的路径,需要添加--bind参数。- ⚠️ 注意:冒号左侧的为宿主机中的真实路径
/public/workspace/shaojf/Course/NGS/Reference,冒号右侧的为镜像内映射的虚拟路径/ref。# 假如我想挂载主目录中邵老师下载好的参考基因文件到镜像内的/ref路径 apptainer shell \ --bind /public/workspace/shaojf/Course/NGS/Reference:/ref \ containertools.sif # 随便看看人类 hg38 参考基因组的前几行 head -5 /ref/Ensembl/Homo_sapiens.GRCh38.dna.chromosome.22.fa - 使用完
apptainer镜像后, 按下Ctrl + D或输入exit后回车退出镜像交互模式,可回到宿主机。
3.2 非交互模式
- 除了交互模式,
apptainer也像conda那样支持免激活运行(详见我的上一个博客:conda run) - 非交互模式对于编写脚本或流程时调用多个虚拟环境内的不同软件会更加友好~
# 检查 fastp 的版本与安装路径 apptainer exec \ --bind /public/workspace/shaojf/Course/NGS/Reference:/ref \ containertools.sif \ fastp --version # fastp 1.3.2 apptainer exec \ --bind /public/workspace/shaojf/Course/NGS/Reference:/ref \ containertools.sif \ which fastp # /opt/containertools/bin/fastp # 随便看看人类 hg38 参考基因组的前几行 apptainer exec \ --bind /public/workspace/shaojf/Course/NGS/Reference:/ref \ containertools.sif \ head -5 /ref/Ensembl/Homo_sapiens.GRCh38.dna.chromosome.22.fa