> For AI agents: the site index is available at https://www.juniortree.com/llms.txt; this page is available as Markdown at https://www.juniortree.com/blog/self-hosted-colabfold.md.
> 尝试在本地服务器上部署ColabFold

## Page metadata

- **Published:** 2025-09-26
- **Updated:** 2025-09-26
- **Tags:** bioinfo
- **Source URL:** https://www.juniortree.com/blog/self-hosted-colabfold

# 本地部署的 ColabFold

## 前人指路

有一个项目叫做 LocalColabFold，但是在国内服务器上安装各种依赖和解决依赖冲突实在是灾难，项目在这里：[GitHub - YoshitakaMo/localcolabfold: ColabFold on your local PC](https://github.com/YoshitakaMo/localcolabfold)

一个很好的解决办法是使用 Docker/Singularity 来运行 ColabFold：[Running ColabFold in Docker · sokrypton/ColabFold Wiki · GitHub](https://github.com/sokrypton/ColabFold/wiki/Running-ColabFold-in-Docker)

## 拉取镜像

将 `ghcr.io` 替换为 `ghcr.nju.edu.cn` 即可，用南大的镜像站

```bash
singularity pull docker://ghcr.nju.edu.cn/sokrypton/colabfold:1.5.5-cuda12.2.2
```

## 权重文件下载

```bash
singularity run -B ./cache:/cache \
  colabfold_1.5.5-cuda12.2.2.sif \
  python -m colabfold.download
```

这个会在当前目录下创建一个 `cache` ，里面会下载权重文件，速度忽好忽慢

## 运行预测

我写了俩脚本，一个用于快速预测，另外一个用来精细化预测，而且因为实验室的卡有两张 A100，所以我还尝试做了并行优化

这个优化的逻辑其实很简单，就是在一个文件夹下面放多个蛋白的 fasta 文件，然后脚本去取两个蛋白，分别丢到两个 GPU 上，这个过程并不涉及交火，所以其实性能损耗很小

但是似乎效果不太好

运行脚本大概是：

```bash
bash run_parallel_colabfold.sh --input liueic/protein_data --out liueic/output_dir --cache liueic/colabfold_cache --work-bind liueic/protein_data --sif liueic/colabfold_1.5.5-cuda12.2.2.sif --gpus 1 --tasks-per-gpu 1 --colabfold-args "--num-models 5 --num-recycle 6 --max-seq 256 --max-extra-seq 512 --msa-mode mmseqs2_uniref_env --pair-mode unpaired_paired --model-type auto --stop-at-score 90 --zip"
```

刚开始预测的时候速度比较慢，但是我能看到显存已经被占用了，打开日志可以看到，是因为请求 MSA 服务：

```bash
[00:23:21] [GPU 0] [] WARNING: You are welcome to use the default MSA server, however keep in mind that it's a
[00:23:21] [GPU 0] [] limited shared resource only capable of processing a few thousand MSAs per day. Please
[00:23:21] [GPU 0] [] submit jobs only from a single IP address. We reserve the right to limit access to the
[00:23:21] [GPU 0] [] server case-by-case when usage exceeds fair use. If you require more MSAs: You can
[00:23:21] [GPU 0] [] precompute all MSAs with `colabfold_search` or host your own API and pass it to `--host-url`
```

如果是要做高通量并行这样是不行的，比较好的方法是自部署一个 MSA 服务，可以参考：[GitHub - sokrypton/ColabFold: Making Protein folding accessible to all!](https://github.com/sokrypton/ColabFold#generating-msas-for-large-scale-structurecomplex-predictions)

但是这个磁盘需求比较大，应该需要一台专门的服务器来做这个：

> First create a directory for the databases on a disk with sufficient storage (940 GB (!)). Depending on where you are, this will take a couple of hours
>

目前即使不自己部署 MSA，其实也是能接受的，大不了晚上睡一觉起来又好了，因为也就几百个蛋白（？可能）

# 自部署MSA服务

## 安装 MMseqs 2 (带 AVX 2 支持)

需要安装最新版的 MMseqs 2，建议使用静态编译版本以获得最佳性能

```bash
# 下载静态编译版本 (Linux AVX2)
wget https://mmseqs.com/latest/mmseqs-linux-avx2.tar.gz
tar xvf mmseqs-linux-avx2.tar.gz
export PATH=$(pwd)/mmseqs/bin/:$PATH

# 验证安装
mmseqs -h
```

## 下载并构建数据库

可以前往这个网站进行下载：[Steinegger Lab Dataset](https://opendata.mmseqs.org/colabfold)

需要下载的数据库有：`uniref30_2302.db.tar.gz`、`colabfold_envdb_2023.tar.gz`

数据库非常大

## 解压，创建索引

创建对应的目录：

```bash
mkdir MMSeqs # 创建目录
cd MMSeqs
tar -I pigz -xvf /48T/software/colabfold_envdb_2023.tar.gz -C .
tar -I pigz -xvf /48T/software/uniref30_2302.db.tar.gz -C .
```

然后等待，这一步等待时间非常长，建议使用 `tmux` 或者其他的东西挂起终端，怕意外中断

做 `padding`，(对 `colabfold_envdb_2023` 同理)：

```bash
# 语法: mmseqs makepaddedseqdb <输入数据库> <输出数据库名称>
mmseqs makepaddedseqdb uniref30_2302_db uniref30_2302_db_padded
```

这一步发生了什么？ 它会生成一个新的数据库（`uniref 30_2302_db_padded`），里面的序列长度会被补齐（Pad）到特定的倍数，这会占用额外的磁盘空间，但对于 A 100 这种大卡来说，能极大地减少显存访问的碎片化，速度至关重要

这一步无法使用 GPU 进行加速，只能使用 CPU

## 开始推理

可以直接参考我写的这个脚本，你可能需要根据自己的需求来更改，MMseqs 本身应该是支持多序列单文件的输入的：

```bash
#!/bin/bash
# =====================================================================
# MMseqs2 多物种批量 MSA 生成脚本
# =====================================================================

set -u
set -e

# --- 1. 核心路径配置 (请核对) ---
# 输入数据的文件夹 (当前目录)
INPUT_ROOT="./Gene_Family"
# 输出结果的总目录
OUTPUT_ROOT="./MSA_Results"

# MMseqs 程序和数据库路径 (根据你之前的记录填写)
MMSEQS_BIN="/mnt/liueic/MMSeqs/mmseqs/bin/mmseqs"
DB_UNIREF="/mnt/liueic/MMSeqs/uniref30_2302_db"
DB_ENV="/mnt/liueic/MMSeqs/colabfold_envdb_2023"

# --- 2. 参数设置 ---
THREADS=16
GPU_ID=1
export CUDA_VISIBLE_DEVICES="$GPU_ID"

# 创建总输出目录
mkdir -p "$OUTPUT_ROOT"

echo "=========================================================="
echo "开始批量处理 MSA"
echo "扫描目录: $INPUT_ROOT"
echo "结果输出: $OUTPUT_ROOT"
echo "=========================================================="

# 遍历所有 .faa 文件
for fasta_file in "${INPUT_ROOT}"/*.faa; do
    # 检查文件是否存在 (防止目录为空)
    [ -e "$fasta_file" ] || continue

    # --- A. 提取物种名，创建独立文件夹 ---
    filename=$(basename "$fasta_file")
    # 提取物种名 (去掉后缀 blast.pep.faa，让文件夹名更短更干净)
    species_name="${filename%.pep.faa}"
    # 或者如果你想要完整文件名做文件夹，用这个: species_name="${filename%.*}"

    # 定义该物种的专属输出目录
    JOB_DIR="${OUTPUT_ROOT}/${species_name}"
    TMP_DIR="${JOB_DIR}/tmp"
    FINAL_DIR="${JOB_DIR}/final_a3m"

    mkdir -p "$JOB_DIR" "$TMP_DIR" "$FINAL_DIR"

    echo ""
    echo "----------------------------------------------------------"
    echo "正在处理物种: $species_name"
    echo "输入文件: $filename"
    echo "专属目录: $JOB_DIR"
    echo "----------------------------------------------------------"

    # --- B. 运行 MMseqs2 流程 ---

    # 1. CreateDB
    "$MMSEQS_BIN" createdb "$fasta_file" "$JOB_DIR/query_db" --shuffle 0 > /dev/null

    # 2. Search UniRef30 (A100 加速)
    echo "   Running Search UniRef30..."
    "$MMSEQS_BIN" search "$JOB_DIR/query_db" "$DB_UNIREF" \
        "$JOB_DIR/res_uniref" "$TMP_DIR" \
        --threads "$THREADS" -s 8 --gpu 1 --max-seqs 2000 --num-iterations 3 > /dev/null

    # 3. Search EnvDB
    echo "   Running Search EnvDB..."
    "$MMSEQS_BIN" search "$JOB_DIR/query_db" "$DB_ENV" \
        "$JOB_DIR/res_env" "$TMP_DIR" \
        --threads "$THREADS" -s 8 --gpu 1 --max-seqs 2000 --num-iterations 3 > /dev/null

    # 4. Result2MSA
    echo "   Converting to MSA..."
    "$MMSEQS_BIN" result2msa "$JOB_DIR/query_db" "$DB_UNIREF" \
        "$JOB_DIR/res_uniref" "$JOB_DIR/msa_uniref" \
        --msa-format-mode 2 --threads "$THREADS" > /dev/null

    "$MMSEQS_BIN" result2msa "$JOB_DIR/query_db" "$DB_ENV" \
        "$JOB_DIR/res_env" "$JOB_DIR/msa_env" \
        --msa-format-mode 2 --threads "$THREADS" > /dev/null

    # 5. Unpack (解包)
    # 先解包到一个临时 merged 目录方便合并
    RAW_A3M_DIR="$JOB_DIR/raw_a3m"
    mkdir -p "$RAW_A3M_DIR"

    "$MMSEQS_BIN" unpackdb "$JOB_DIR/msa_uniref" "$RAW_A3M_DIR" --unpack-name-mode 0 --unpack-suffix ".uniref" > /dev/null
    "$MMSEQS_BIN" unpackdb "$JOB_DIR/msa_env" "$RAW_A3M_DIR" --unpack-name-mode 0 --unpack-suffix ".env" > /dev/null

    # --- C. 合并 & 重命名 (自动化修正文件名) ---
    echo "   Merging and Renaming..."

    # 读取 ID 映射表 (MMseqs 自动生成的 query_db.lookup)
    LOOKUP_FILE="$JOB_DIR/query_db.lookup"

    while read -r id original_header; do
        # 1. 解析文件名
        # original_header 可能是 ">SeqID description..."，我们要取第一个词作为文件名
        clean_name=$(echo "$original_header" | awk '{print $1}' | tr -d '>' | tr '|/ ' '___')

        # 定义输入输出
        uni_file="${RAW_A3M_DIR}/${id}.uniref"
        env_file="${RAW_A3M_DIR}/${id}.env"
        final_file="${FINAL_DIR}/${clean_name}.a3m"

        # 2. 合并操作
        if [ -f "$uni_file" ]; then
            cat "$uni_file" > "$final_file"

            # 如果有环境序列，去掉第一行后追加
            if [ -f "$env_file" ]; then
                tail -n +2 "$env_file" >> "$final_file"
            fi
        fi
    done < "$LOOKUP_FILE"

    # --- D. 清理 ---
    echo "   Cleaning up tmp files for $species_name..."
    rm -rf "$TMP_DIR" "$RAW_A3M_DIR" "$JOB_DIR/res_uniref*" "$JOB_DIR/res_env*" "$JOB_DIR/msa_*"

    echo "$species_name 完成!"
done

echo "=========================================================="
echo "所有物种处理完毕！"
echo "请查看结果目录: $OUTPUT_ROOT"
echo "=========================================================="
```

查看是否运行成功，查看显卡调用 `nvidia-smi`：

![](https://s3.juniortree.com/pic/2025/12/89e596d07560d9b7c89b0f096656e9fc.webp)

运行结束后的目录结构：

```
MSA_Results_P450/
├── Manduca_sexta/                <-- 自动根据文件名创建的文件夹
│   ├── query_db                  <-- 保留了 DB 以备不时之需
│   └── final_a3m/                <-- 这里是可以直接喂给 ColabFold 的！
│       ├── SeqA.a3m
│       ├── SeqB.a3m
│       └── SeqC.a3m
├── Papilio_xuthus/
│   └── final_a3m/
│       ├── ...
└── ...
```

MMseqs 2 的工作流是： `FASTA` -> `Createdb` -> `Search` (生成 `ResultDB`) -> `Result 2 MSA` (转换) -> `UnpackDB` (解压出文件)

## 后话

### MSA Search

ColabFold 里面允许我们自定义 `host-url`，于是我就病急乱投医，我真的去找了 MSA Search 的容器镜像，在英伟达的官网这里可以找到：[Overview — NVIDIA NIM for MSA Search](https://docs.nvidia.com/nim/bionemo/msa-search/latest/overview.html)

然后非常令人哭笑不得的是，如果你直接使用中国大陆的 IP 去拉这个容器，他会告诉你说让你去找大陆的代理商

![](https://s3.juniortree.com/pic/2025/12/64776c97b7cd243a84e3faaa7f39be16.webp)

![](https://s3.juniortree.com/pic/2025/12/df78a2b3ca1635ec10d738950a67122c.webp)

但是据我测试这个代理商国内如果你要使用的话，需要以机构/企业的身份去申请，就很离谱，因为英伟达上面下载只需要个人开发者申请一个 key 就可以了

所以我整了个花活，我用了 Azure 东京地区的服务器，去拉这个容器，然后再把容器中转到阿里云的容器仓库，再用集群从阿里云容器仓库拉这个容器

虽然我最后没有跑起来，因为我用的是 `singularity`，这个东西有各种奇奇怪怪的文件系统写入的问题，很无语

### gpuserver

因为这个 MMseqs 每次都需要重新读取数据，导致速度非常慢！需要启动一个守护进程，把数据写入到显存/内存中，以一个服务端的形式提供服务

```bash
#!/bin/bash
# ===============================================================
# MMseqs2 GPU 驻留服务启动脚本 (修正版)
# ===============================================================

set -u

# === 1. 配置路径 ===
MMSEQS_BIN="mmseqs/bin/mmseqs"
WORKDIR=$(pwd)

# 数据库路径 (确保这些路径是正确的)
DB_UNIREF="uniref30_2302_db"
DB_ENV="colabfold_envdb_2023"

# 日志文件
LOG_UNIREF="server_uniref.log"
LOG_ENV="server_env.log"

# === 2. GPU 环境设置 ===
# 指定卡，这里简化处理，默认使用 GPU 0 或 1
# 如果你有特定 GPU 编号，请修改这里
export CUDA_VISIBLE_DEVICES=0

echo "------------------------------------------------"
echo "正在启动 MMSeqs2 GPU Resource Managers..."
echo "注意：gpuserver 不是网络服务器，它不监听端口。"
echo "它将数据库锁定在 GPU/内存中以加速本地搜索。"
echo "------------------------------------------------"

# 检查可执行文件
if [ ! -f "$MMSEQS_BIN" ]; then
    echo "错误: 找不到 mmseqs 可执行文件: $MMSEQS_BIN"
    exit 1
fi

# --- 启动 UniRef30 Server ---
echo "启动 UniRef30 GPU Resident Process..."
# 去掉了 --port, --gpu-mode, --gpu-mem, --db-load-mode, --threads
# gpuserver 只需要数据库路径。其他参数通常是在 'search' 时指定的，
# 或者它会默认加载。
nohup "$MMSEQS_BIN" gpuserver "$DB_UNIREF" \
    > "$LOG_UNIREF" 2>&1 &

PID_UNIREF=$!
echo "   PID: $PID_UNIREF | Log: $LOG_UNIREF"

# --- 启动 ColabFold EnvDB Server ---
echo "启动 EnvDB GPU Resident Process..."
nohup "$MMSEQS_BIN" gpuserver "$DB_ENV" \
    > "$LOG_ENV" 2>&1 &

PID_ENV=$!
echo "   PID: $PID_ENV | Log: $LOG_ENV"

echo "------------------------------------------------"
echo "   GPU 服务已启动。"
echo "------------------------------------------------"
```

然后这个坑点在于，新版本的 MMseqs 的参数已经改了，不能使用启动 `http` 服务器这种方式处理任务了，我也没想好要怎么处理这个问题
