跳转至

用 Docker + JupyterHub 搭建团队生信分析平台

一句话说明: 使用 Docker 容器化和 JupyterHub 多用户管理,为团队快速搭建一个可复现、可扩展的生物信息学分析工作台。


为什么要学

  1. 面试加分 — 展示你具备 DevOps + 生信双重能力,理解可复现研究的工程实践
  2. 实用性 — 团队共享一套标准化分析环境,新人到岗即用,告别"我的电脑上能跑"
  3. 可复现 — Docker 镜像 + 版本锁定,论文发表后任何人都能重现分析结果
  4. 可扩展 — 从单机到集群无缝迁移,支持 GPU 加速

核心概念详解

为什么用 Docker?

白话: 生信工具依赖复杂(不同版本的 Python/R/Java/C 库),Docker 把整个环境打包成"集装箱",搬到哪台机器都能跑。

对比项手动安装Conda 环境Docker 容器
隔离性部分完全
可复现中等优秀
系统依赖手动解决部分覆盖完全包含
共享写文档environment.yml镜像推送
启动速度秒级秒级
多用户困难困难原生支持

JupyterHub 架构

白话: Jupyter Notebook 是单人使用的。JupyterHub 是多人版——每个人有独立的 Notebook 实例,管理员统一管理用户和资源。

用户浏览器 → JupyterHub(Proxy + Hub) → Spawner → 用户容器(Notebook)
                                                  → 用户容器(Notebook)
                                                  → 用户容器(Notebook)

Bioconductor / Conda-forge

白话: 生信工具的两大来源——R 包去 Bioconductor,Python/命令行工具去 conda-forge/bioconda。Docker 里两个都装好。


安装与配置

前置要求

# 安装 Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

# 安装 Docker Compose
sudo apt install docker-compose-plugin

# 验证
docker --version
docker compose version

项目结构

bioinfo-workbench/
├── docker-compose.yml        # 服务编排
├── jupyterhub/
│   ├── Dockerfile            # Hub 镜像
│   ├── jupyterhub_config.py  # Hub 配置
│   └── requirements.txt
├── notebook/
│   ├── Dockerfile            # 用户 Notebook 镜像
│   ├── environment.yml       # Conda 环境
│   └── postBuild             # 构建后脚本
├── data/                     # 共享数据目录
└── config/
    └── nginx.conf            # 反向代理(可选)

快速上手

5 分钟最小可用版本

# docker-compose.yml
version: "3.9"

services:
  jupyterhub:
    image: quay.io/jupyterhub/jupyterhub:4
    ports:
      - "8000:8000"
    volumes:
      - ./jupyterhub/jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py
      - /var/run/docker.sock:/var/run/docker.sock
      - jupyterhub-data:/srv/jupyterhub/data
    environment:
      DOCKER_NETWORK_NAME: bioinfo-net
    networks:
      - bioinfo-net

volumes:
  jupyterhub-data:

networks:
  bioinfo-net:
    name: bioinfo-net
# jupyterhub/jupyterhub_config.py
import os

c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
c.DockerSpawner.image = 'bioinfo-notebook:latest'
c.DockerSpawner.network_name = 'bioinfo-net'
c.DockerSpawner.volumes = {
    'jupyter-user-{username}': '/home/jovyan/work',
    '/srv/data': {'bind': '/home/jovyan/shared-data', 'mode': 'ro'},
}

# 资源限制
c.DockerSpawner.mem_limit = '4G'
c.DockerSpawner.cpu_limit = 2

# 简单认证(生产环境换 LDAP/OAuth)
c.JupyterHub.authenticator_class = 'nativeauthenticator.NativeAuthenticator'
c.Authenticator.admin_users = {'admin'}
# 启动
docker compose up -d

# 访问 http://localhost:8000
# 首次用 admin 注册账号

进阶用法

1. 自定义生信 Notebook 镜像

# notebook/Dockerfile
FROM jupyter/scipy-notebook:latest

USER root

# 系统级生信工具
RUN apt-get update && apt-get install -y \
    samtools \
    bcftools \
    bedtools \
    fastqc \
    bwa \
    bowtie2 \
    && rm -rf /var/lib/apt/lists/*

USER ${NB_UID}

# Conda 环境(Python 生信)
COPY environment.yml /tmp/environment.yml
RUN mamba env update -n base -f /tmp/environment.yml && \
    mamba clean -afy

# R 包
RUN mamba install -n base -c conda-forge -c bioconda \
    r-base=4.3 \
    bioconductor-deseq2 \
    bioconductor-edger \
    bioconductor-clusterProfiler \
    r-seurat \
    r-ggplot2 \
    r-tidyverse \
    && mamba clean -afy

# Jupyter kernels
RUN pip install --no-cache-dir \
    scanpy \
    scvi-tools \
    cellrank \
    squidpy

# R kernel for Jupyter
RUN R -e "IRkernel::installspec(user = FALSE)"
# notebook/environment.yml
name: base
channels:
  - conda-forge
  - bioconda
  - defaults
dependencies:
  - python=3.11
  - numpy
  - pandas
  - scipy
  - matplotlib
  - seaborn
  - scikit-learn
  - biopython
  - pysam
  - pyvcf3
  - snakemake
  - nextflow
  - multiqc
  - cutadapt
  - trim-galore
  - star
  - hisat2
  - salmon
  - kallisto
  - subread
# 构建镜像
docker build -t bioinfo-notebook:latest ./notebook/

2. 完整 Docker Compose(生产级)

# docker-compose.yml
version: "3.9"

services:
  jupyterhub:
    build: ./jupyterhub
    ports:
      - "8000:8000"
    volumes:
      - ./jupyterhub/jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py
      - /var/run/docker.sock:/var/run/docker.sock
      - jupyterhub-data:/srv/jupyterhub/data
    environment:
      DOCKER_NETWORK_NAME: bioinfo-net
      POSTGRES_HOST: db
    depends_on:
      - db
    networks:
      - bioinfo-net
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: jupyterhub
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: jupyterhub
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - bioinfo-net
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./config/nginx.conf:/etc/nginx/nginx.conf
      - ./certs:/etc/nginx/certs
    depends_on:
      - jupyterhub
    networks:
      - bioinfo-net
    restart: unless-stopped

volumes:
  jupyterhub-data:
  postgres-data:

networks:
  bioinfo-net:
    name: bioinfo-net

3. GPU 支持(深度学习 + AlphaFold)

# docker-compose.gpu.yml
services:
  jupyterhub:
    # ... 其他配置 ...
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
# jupyterhub_config.py 补充
c.DockerSpawner.extra_host_config = {
    'device_requests': [
        docker.types.DeviceRequest(
            count=-1,
            capabilities=[['gpu']]
        )
    ]
}

4. 用户资源配额

# jupyterhub_config.py
# 不同用户组不同配额
c.DockerSpawner.mem_limit = '8G'
c.DockerSpawner.cpu_limit = 4

# 或按 profile 提供多种选择
c.DockerSpawner.profile_list = [
    {
        'display_name': '基础环境 (2 CPU, 4GB RAM)',
        'slug': 'basic',
        'default': True,
        'kubespawner_override': {
            'mem_limit': '4G',
            'cpu_limit': 2,
        }
    },
    {
        'display_name': '高性能 (8 CPU, 32GB RAM, GPU)',
        'slug': 'gpu',
        'kubespawner_override': {
            'mem_limit': '32G',
            'cpu_limit': 8,
            'extra_resource_limits': {'nvidia.com/gpu': '1'},
        }
    },
]

5. 共享数据管理

# 共享只读数据(参考基因组、注释文件)
c.DockerSpawner.volumes = {
    'jupyter-user-{username}': '/home/jovyan/work',
    '/srv/data/reference': {'bind': '/data/reference', 'mode': 'ro'},
    '/srv/data/shared-results': {'bind': '/data/shared', 'mode': 'rw'},
}
# 数据目录结构
/srv/data/
├── reference/
   ├── genomes/
      ├── hg38/
      └── mm39/
   ├── annotations/
      ├── gencode.v44.gtf
      └── ensembl_109/
   └── indices/
       ├── star_hg38/
       └── bwa_hg38/
└── shared-results/
    ├── project-A/
    └── project-B/

6. 自动备份

#!/bin/bash
# backup.sh - 定期备份用户数据
BACKUP_DIR="/backup/jupyter-$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"

# 备份所有用户 volume
for vol in $(docker volume ls -q | grep jupyter-user-); do
    user=$(echo $vol | sed 's/jupyter-user-//')
    docker run --rm \
        -v "$vol:/data" \
        -v "$BACKUP_DIR:/backup" \
        alpine tar czf "/backup/${user}.tar.gz" -C /data .
done

# 备份 Hub 数据库
docker exec bioinfo-db pg_dump -U jupyterhub jupyterhub | \
    gzip > "$BACKUP_DIR/hub-db.sql.gz"

echo "Backup completed: $BACKUP_DIR"
# 加入 crontab
# 每天凌晨 2 点备份
0 2 * * * /opt/bioinfo-workbench/backup.sh

7. 监控与健康检查

# docker-compose.yml 补充
services:
  monitoring:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    networks:
      - bioinfo-net

  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
    networks:
      - bioinfo-net

常见问题与排错

问题原因解决方案
Spawner 超时镜像太大首次拉取慢预先 docker pull,增大 spawn_timeout
内存不足用户分析占满设置 mem_limit,监控资源使用
权限问题容器内外 UID 不匹配确保用 jovyan (UID 1000) 或映射
网络不通容器不在同一 network检查 network_name 配置一致
R 包安装失败系统依赖缺失在 Dockerfile 中用 apt 装依赖
GPU 不可见nvidia-docker 未配置安装 nvidia-container-toolkit

面试高频考点

  1. 为什么生信需要容器化?
  2. 工具依赖冲突严重、版本敏感、可复现性是发表要求

  3. JupyterHub 的 Spawner 机制?

  4. Hub 管理认证和路由,Spawner 按需为每个用户创建独立容器

  5. 如何保证分析的可复现性?

  6. 锁定镜像版本(tag/digest)+ Snakemake/Nextflow 流程 + 数据版本管理

  7. 单机 vs 集群部署的选择?

  8. <10 用户单机 Docker;>10 用户考虑 Kubernetes + KubeSpawner

  9. 数据安全考虑?

  10. RLS 权限隔离、volume 加密、网络隔离、定期备份、审计日志

参考资源