1. Singularity 简介
说到容器化,很多人第一反应就是 Docker。但如果你在 HPC 或者生物信息学这种强依赖底层环境的场景干过几年,就会明白 Docker 并不总是最优解。我刚开始接触 Visium 空间转录组分析时,实验室的服务器跑着 CentOS 7,环境简直是一锅粥——glibc 版本不对,Python 库冲突,连最基本的 samtools 都要手动编译。折腾了两天后,我一个同事丢过来一个 Singularity 镜像,说“试试这个”。嗯,从那以后,我就再也没回去过。
1.1 容器化到底在解决什么问题?
说白了,容器化就是把你的软件、依赖、配置甚至操作系统级别的库,打包成一个独立的小盒子。你想想看,一个项目从开发到部署,往往要经历好几台机器:笔记本、测试服务器、集群。每一台机器的 Linux 发行版、内核版本、CUDA 驱动都可能不一样。容器化就是为了消灭这种“在我电脑上明明跑得好好的”尴尬。
我个人习惯把容器想象成一个便携式环境快照。你要分析 Visium 数据,就在容器里装好 SpaceRanger、Seurat、STAR 等等。拿到新机器上,拉起容器就能跑,不用再装一遍系统库。代价?几乎为零。
核心概念:容器 ≠ 虚拟机。虚拟机模拟整个硬件,启动慢、体积大。容器共享宿主内核,只打包用户态程序——轻量、秒级启动。
1.2 Singularity 是谁?和 Docker 有什么不一样?
Singularity(现在叫 Apptainer)是专门为高性能计算(HPC)设计的容器引擎。我在项目中遇到过很多 docker 镜像在集群上跑不起来的 case——没有 root 权限、不能挂载 FUSE 文件系统、网络受限。Singularity 正是为了解决这些痛点诞生的。
下面这个表格是我归纳的几个关键区别,做运维的朋友应该能看懂:
| 特性 | Docker | Singularity |
|---|---|---|
| 用户权限 | 默认需要 root 权限运行守护进程 | 无需 root,普通用户即可运行 |
| 进程模型 | 以 root 身份启动容器进程 | 以当前用户身份运行(UID 映射) |
| 镜像格式 | 分层存储、Registry 推送 | 单一 SIF 文件,方便复制 |
| HPC 兼容性 | 常有兼容问题(MPI、InfiniBand) | 原生支持 MPI、GPU、并行文件系统 |
| 安全策略 | 需额外配置 setuid / seccomp | 默认隔离,不允许交互式提权 |
记住最核心的一点:Singularity 不需要守护进程。 每次执行 singularity run 就像运行一个普通程序。你在登录节点上可以直接启动,然后提交到计算节点,完全透明。
经验之谈:我曾经需要在 SLURM 集群上用 Visium 的 SpaceRanger 处理 50 个样本。Docker 镜像拉下来后,每个任务都要申请网络、挂载存储,折腾了两天没跑通。换成 Singularity,一行命令把镜像转成 SIF 文件,直接扔到任务脚本里——sbatch --wrap="singularity run my_visium.sif spaceranger count ...",一次成功。
1.3 应用场景:什么时候该用 Singularity?
不是所有场景都适合 Singularity。我个人建议按下面的场景选型:
- HPC / 超算环境 —— 这是 Singularity 的主场。没有 root 权限?没问题。要调用 GPU 和 InfiniBand?原生支持。你想想看,大多数生物信息学分析都是在这种共享集群上跑的,Singularity 几乎是标配。
- 生产环境复现 —— 发表论文时需要附上分析代码和软件环境。Singularity 的 SIF 文件是一个单文件,放在 GitHub release 或数据仓库里就行了。审稿人下载后
singularity exec就能直接跑,不需要装任何依赖。 - Visium 专用环境 —— SpaceRanger 需要 Python 3.8 和指定版本的 R 包,而集群上可能只有 Python 3.6。用 Singularity 构建一个 CentOS 7 + conda 环境,把 SpaceRanger 和关联的 C++ 库都打包进去。以后换集群只需拷贝 SIF 文件。
- 开发和测试的快照 —— 我自己经常在笔记本上写 Snakemake 流程,测试时用 docker,确认无误后
singularity build转成 SIF 丢到集群。这个流程非常顺滑。
避坑指南:不要试图在 Singularity 容器里运行 systemd 或者需要内核模块的应用。Singularity 共享宿主内核,任何需要自定义内核功能的软件都会失败。我曾经踩过这个坑——装了一个需要内核模块的监控工具,折腾半天最后放弃。
上面的图应该能帮你理清关系:Docker 和 Singularity 都是从物理机上层抽象出来的容器引擎,但它们的定位截然不同。Singularity 的绿框直接指向 Visium 环境,这正是我们这门课要重点做的事。
最后补充一点:如果你已经有 Docker 镜像了,转成 Singularity SIF 文件非常简单:
singularity build my_visium.sif docker://quay.io/your/visium_image:latest
甚至不需要 Docker 守护进程,Singularity 可以直接拉取 Docker Hub 上的镜像并转换。这条命令我几乎每周都在用。