Docker 基础:从安装到多阶段构建
各位同学,开始干活前先聊聊 Docker。说实话,几年前我第一次接触 NGS 流程部署时,最头疼的就是环境依赖。你是不是也遇到过——换台服务器,Python 版本不对,某个 C 库没装,跑了一天的分析中途报错,想死的心都有。
Docker 就是解决这个问题的。它把整个运行环境打包成一个「集装箱」,你随身带着走,到哪都能跑。我个人习惯把 Docker 看作「轻量级虚拟机」,但它比虚拟机快得多、省得多。
4.1 Docker 安装:不同系统的坑与招
安装 Docker 本身不复杂,但不同系统有不同的坑。我踩过的雷,帮你先排一排。
Linux(Ubuntu / CentOS)
官方推荐用仓库安装,别去官网下 .deb 手动装,除非你网络实在太差。
# Ubuntu 22.04 示例
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER
newgrp docker
macOS / Windows
桌面版直接去 Docker Hub 下 Docker Desktop,双击安装就行。不过我要提醒一句——Windows 用户,确保 BIOS 里开启了硬件虚拟化。我曾经帮一个同事远程调了半天,发现他主板 VT-x 没开,Docker Desktop 启动不了,白白浪费一小时。
| 系统 | 推荐方式 | 避坑点 |
|---|---|---|
| Ubuntu 20.04+ | APT 仓库安装 | 不要用 snap 安装,权限和版本都别扭 |
| CentOS 7+ | YUM 仓库安装 | CentOS 7 内核旧,建议先升级内核或直接用 Rocky Linux |
| macOS / Windows | Docker Desktop | Windows 必须开 WSL 2 和虚拟化 |
4.2 镜像拉取与容器运行:日常三板斧
装好了 Docker,第一个动作就是拉个镜像跑跑看。说白了,镜像就是模板,容器是模板的实例。
拉取镜像
# 拉取 Ubuntu 22.04 官方镜像
docker pull ubuntu:22.04
# 拉取指定 tag
docker pull ubuntu:22.04
# 不写 tag 默认 latest
docker pull ubuntu
运行容器
# 最简单的交互式运行
docker run -it --rm ubuntu:22.04 /bin/bash
# 后台运行一个 Nginx 服务
docker run -d --name my-nginx -p 8080:80 nginx:1.25
参数解释一下:
-it:交互模式,让你进到容器里敲命令--rm:容器退出后自动删除,临时测试用,省得留下一堆垃圾-d:后台运行(detached)--name:给容器起个名字,方便管理-p:端口映射,宿主机端口:容器端口
docker run -it --rm \
-v /home/user/ngs_data:/data \
ubuntu:22.04 /bin/bash
4.3 Dockerfile 编写:把环境写成代码
手工敲 docker commit 做的镜像,维护起来要命。Dockerfile 就是那个让你把环境「代码化」的东西。我带的团队,Dockerfile 必须进版本控制,和业务代码一起管理。
一个 NGS 流程的 Dockerfile 例子
# ===== 基础镜像选择 =====
FROM ubuntu:22.04 AS base
# ===== 元数据 =====
LABEL maintainer="your-email@example.com"
LABEL description="NGS 变异分析基础镜像"
# ===== 环境变量 =====
ENV DEBIAN_FRONTEND=noninteractive
ENV LANG=C.UTF-8
# ===== 系统依赖安装 =====
RUN apt-get update && apt-get install -y \
wget \
curl \
git \
build-essential \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# ===== 生物信息学工具 =====
RUN pip3 install --no-cache-dir \
cutadapt==4.4 \
fastqc==0.12.1
# ===== 工作目录 =====
WORKDIR /workspace
# ===== 默认命令 =====
CMD ["/bin/bash"]
写 Dockerfile 的几个原则:
- FROM 只有一个:除非你做多阶段构建,否则别叠罗汉
- 尽量用标签版本:FROM ubuntu:22.04 比 FROM ubuntu 可靠一百倍
- 清理缓存:apt-get install 后用 rm -rf /var/lib/apt/lists/*
- 保证幂等:同样的 Dockerfile,任何时候构建结果应该一样
- 用 .dockerignore:别把本地 .git、node_modules 带进镜像
# .dockerignore 示例
.git
*.md
__pycache__/
.env
4.4 多阶段构建:瘦身利器
嗯,这里要重点聊聊多阶段构建。为啥需要它?因为我们的 NGS 工具链里,很多软件是 C++ 写的,编译要一堆开发库,但运行的时候只需要编译好的二进制文件。以前的做法是,把编译用的工具链全塞进最终镜像,一个镜像能占几个 GB。
多阶段构建的思路很简单——一个 Dockerfile 里能写多个 FROM,前面的阶段负责编译,后面的阶段只拷贝产物。
# ===== 第一阶段:编译 =====
FROM ubuntu:22.04 AS builder
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
git \
libz-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY bwa-0.7.17.tar.gz .
RUN tar xzf bwa-0.7.17.tar.gz && \
cd bwa-0.7.17 && \
make
# ===== 第二阶段:运行 =====
FROM ubuntu:22.04 AS runtime
RUN apt-get update && apt-get install -y \
libz1 \
python3 \
&& rm -rf /var/lib/apt/lists/*
# 只拷贝编译好的二进制
COPY --from=builder /src/bwa-0.7.17/bwa /usr/local/bin/
WORKDIR /workspace
CMD ["bwa"]
看看构建结果,感受一下差异:
# 构建命令
docker build -t ngs-bwa:multi-stage -f Dockerfile.multistage .
# 查看镜像大小
docker images ngs-bwa
# REPOSITORY TAG SIZE
# ngs-bwa multi-stage 182MB
# ngs-bwa single-stage 1.12GB
从 1.12GB 瘦身到 182MB,你说香不香?
4.5 实战:构建一个轻量级 NGS 分析镜像
来,我们把前面学的东西串一遍。假设你要制作一个包含 BWA、SAMtools、BCFtools 的迷你分析镜像。
# Dockerfile.ngs-mini
FROM ubuntu:22.04 AS builder
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
git \
libz-dev \
libbz2-dev \
liblzma-dev \
libcurl4-openssl-dev \
wget \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
# 下载并编译 BWA
RUN wget https://github.com/lh3/bwa/archive/refs/tags/v0.7.17.tar.gz && \
tar xzf v0.7.17.tar.gz && \
cd bwa-0.7.17 && \
make
# 下载并编译 SAMtools
RUN wget https://github.com/samtools/samtools/releases/download/1.17/samtools-1.17.tar.bz2 && \
tar xjf samtools-1.17.tar.bz2 && \
cd samtools-1.17 && \
./configure --prefix=/build/samtools_install && \
make && \
make install
# 下载并编译 BCFtools
RUN wget https://github.com/samtools/bcftools/releases/download/1.17/bcftools-1.17.tar.bz2 && \
tar xjf bcftools-1.17.tar.bz2 && \
cd bcftools-1.17 && \
./configure --prefix=/build/bcftools_install && \
make && \
make install
# 第二阶段:运行
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
libz1 \
libbz2-1.0 \
liblzma5 \
libcurl4 \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /build/bwa-0.7.17/bwa /usr/local/bin/
COPY --from=builder /build/samtools_install/bin/* /usr/local/bin/
COPY --from=builder /build/bcftools_install/bin/* /usr/local/bin/
WORKDIR /data
CMD ["/bin/bash"]
构建并验证:
docker build -t ngs-mini:1.0 -f Dockerfile.ngs-mini .
docker run --rm ngs-mini:1.0 bwa # 应该能看到 BWA 帮助信息
这张图把 Docker 的完整工作流串起来了:你写 Dockerfile,构建成镜像,推送到仓库,别人拉下来运行容器。NGS 流程的自动化部署,其实就是把这个过程脚本化、参数化。