昨天偶然读到 Kojima 等刚发表在 Nature Structural & Molecular Biology 上的论文 Universal pipeline for high-resolution GPCR structure determination。文章关注的是 GPCR 结构解析中一个很实际的问题:对于缺少 G protein 等稳定结合伙伴的 inactive-state GPCR,尤其是 antagonist-bound 状态,往往需要在 TM5-ICL3-TM6 区域反复尝试不同融合位置,才能找到表达、稳定性和刚性都足以支持高分辨率 cryo-EM 重构的构建,实验筛选成本很高。
作者的方案包含两个相互配合的部分。NOAH 先枚举 TM5-TM6 融合构建,利用 ColabFold 预测结构,再依次检查连接区是否保持连续 α-helix、局部 pLDDT、helix phase,以及融合蛋白与膜边界之间的距离,从几百个组合中筛出少量更值得实验验证的候选。随后,作者又设计了约 40 kDa、刚性更强的 de novo fusion partner ARK1,作为帮助 cryo-EM 粒子对齐的 fiducial marker,并在多个 Class A GPCR 和不同配体状态中完成了验证。
这套方法并不是按一下按钮就能直接得到实验结构,后续仍然需要表达、纯化、制样和 cryo-EM;目前的系统性验证也主要集中在 Class A GPCR。不过,对于正在做 inactive-state GPCR、antagonist complex,或者长期卡在融合构建筛选上的课题,它可能减少相当一部分前期试错。因此我打算先把 NOAH 的计算流程复现出来,看看它能否为手头或周围的课题提供帮助,这篇文章记录的就是部署过程中遇到的问题。
Intro
昨天偶然读到 Kojima 等刚发表在 Nature Structural & Molecular Biology 上的论文 Universal pipeline for high-resolution GPCR structure determination。文章关注的是 GPCR 结构解析中一个很实际的问题:对于缺少 G protein 等稳定结合伙伴的 inactive-state GPCR,尤其是 antagonist-bound 状态,往往需要在 TM5-ICL3-TM6 区域反复尝试不同融合位置,才能找到表达、稳定性和刚性都足以支持高分辨率 cryo-EM 重构的构建,实验筛选成本很高。
作者的方案包含两个相互配合的部分。NOAH 先枚举 TM5-TM6 融合构建,利用 ColabFold 预测结构,再依次检查连接区是否保持连续 α-helix、局部 pLDDT、helix phase,以及融合蛋白与膜边界之间的距离,从几百个组合中筛出少量更值得实验验证的候选。随后,作者又设计了约 40 kDa、刚性更强的 de novo fusion partner ARK1,作为帮助 cryo-EM 粒子对齐的 fiducial marker,并在多个 Class A GPCR 和不同配体状态中完成了验证。
这套方法并不是按一下按钮就能直接得到实验结构,后续仍然需要表达、纯化、制样和 cryo-EM;目前的系统性验证也主要集中在 Class A GPCR。不过,对于正在做 inactive-state GPCR、antagonist complex,或者长期卡在融合构建筛选上的课题,它可能减少相当一部分前期试错。因此我打算先把 NOAH 的计算流程复现出来,看看它能否为手头或周围的课题提供帮助,这篇文章记录的就是部署过程中遇到的问题。
作为第一步,我尝试在一台带 NVIDIA GPU 的 Linux 服务器上部署 NOAH。NOAH 会编排 GPCRdb 数据、DSSP、PPM3 和 ColabFold 完成候选构建筛选。项目已经提供了 Dockerfile,看上去只要三条命令就能启动:
实际部署却没有这么顺利。我先后遇到了 DSSP 依赖不兼容、Docker 无法使用 NVIDIA GPU、服务器访问外部资源不稳定,以及运行参数说明不足等问题。这篇文章记录完整的定位过程和最终可复用的部署方法。
NOAH 当前的 LICENSE 只允许非商业研究和教育使用,并且明确禁止以原版或修改版形式向第三方再分发,包括上传到公开 GitHub 仓库。因此我无法公开修改后的内容,本文分享的是部署思路和排障经验;如果你也遇到类似的问题,可以将本文作为上下文交给 AI,应该会让你的部署变得顺利一些。
一、构建失败:DSSP 与 libmcfp 的版本组合不稳定
第一次直接执行 docker build 时,问题出在 DSSP 环境:mkdssp 和 dssp 虽然能被找到,但在版本检查或由 Biopython 调用时无法正常运行。也就是说,问题不是“没有安装 DSSP”,而是 DSSP 与底层 libmcfp 的二进制接口组合不兼容。
原 Dockerfile 先创建 NOAH 的 Conda 环境并安装 DSSP,后面又单独安装 gsutil。两次独立的 Conda 求解可能更新前面已经安装的间接依赖。同时,原来的 PATH 把 ColabFold 环境放在 NOAH 环境之前,也增加了调用错误环境中程序或动态库的风险。
最终采用的处理方式有四点:
核心修改思路如下:
二、宿主机看得到显卡,不代表 Docker 能使用显卡
第二个问题发生在 GPU 层。服务器上执行 nvidia-smi 正常,只能证明 NVIDIA 驱动工作正常;Docker 要把 GPU 暴露给容器,还需要安装并配置 NVIDIA Container Toolkit。
可以先检查 Docker 当前认识哪些 runtime:
在 Ubuntu 或 Debian 系统中,我按照 NVIDIA Container Toolkit 官方安装文档完成配置。下面的版本号是截至 2026-08-30 官方文档所列的 1.20.0-1;以后部署时应先到官方页面确认当前版本。
nvidia-ctk runtime configure 会修改宿主机的 /etc/docker/daemon.json,使 Docker 能调用 NVIDIA runtime。配置后不要只看 docker info,最好真正启动一个临时容器验证。NVIDIA 官方给出的测试命令是:
只有这条命令能在容器内输出显卡信息,GPU runtime 才算真正配置完成。对应的官方验证方法见 Running a Sample Workload。
三、为 Docker 构建过程中传入代理
NOAH 的镜像构建过程需要访问 Conda、PyPI、GitHub 和 Google Cloud Storage 等外部服务。服务器网络受限时,可以先在宿主机终端中设置代理:
这些 export 只为当前宿主机 Shell 及其启动的普通进程设置代理,因此可以解决宿主机上 git clone 等命令的联网问题。但是,Docker 不会自动把这些环境变量传入镜像构建过程中 Dockerfile 的 RUN 环境。于是可能出现这样的现象:宿主机已经可以正常克隆仓库,但 docker build 里的 wget、Conda、pip 或 gsutil 仍然超时。
因此,执行构建时还需要通过 --build-arg 显式传入代理:
这里的 $http_proxy、$https_proxy 和 $all_proxy 取自宿主机当前 Shell,再由 --build-arg 传给构建环境。把占位符替换成自己的代理地址即可。Docker 已经预定义了 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 等代理构建参数,不需要为了代理在 Dockerfile 中增加永久 ENV;否则代理地址可能被保留在镜像配置中。详见 Docker CLI 代理文档。
四、补充 README
原 README 给出了最简命令,但没有系统解释哪些参数必填、默认值是什么,以及结果写到哪里。直接照抄命令时,很容易产生几个疑问:不写 -m 会怎样?-f 是否必填?--reverse 到底是开启还是关闭反向筛选?甚至都不知道有这些参数。
NOAH 的核心命令可以概括为:
最重要的参数如下:
参数
是否必填
默认值
含义
-n, --name
是
无
GPCR 名称;数据库模式下需要匹配数据库目录名,例如 v2r。
-p, --ppm
是
无
PPM3 代码目录,其中应包含 immers。
-d, --database
条件必填
无
NOAH/GPCRdb 数据库目录;不用数据库时需同时提供 -s 和 -j。
-s, --structure
条件必填
无
自定义 GPCR PDB 结构。
-j, --json
条件必填
无
GPCRdb residues/extended 格式的残基注释。
-m, --mode
否
Inactive
构象状态,只接受 Active 或 Inactive。
-f, --fp
否
ARK1
融合蛋白,可选 ARK1、BRIL 或 A2A_BRIL。
-r, --reverse
否
默认执行反向筛选
这个名字容易误解:传入该选项反而会关闭反向 helix-phase 筛选。
另一个关键点是:NOAH 没有独立的 --output 参数,结果会写入当前工作目录。不同靶点、构象或融合蛋白应使用不同的空目录;直接在已有结果目录里重跑,可能因为部分文件采用排他方式创建而失败。
因此,我更推荐把目标、构象和融合蛋白写进 RUN_ID,并显式传入 -m、-f,不要依赖默认值:
这里使用 --gpus device=0,只把第 0 张 GPU 暴露给容器。它比“暴露所有 GPU,再设置 CUDA_VISIBLE_DEVICES=0”更直接。Docker 对指定 GPU 的官方说明见 GPU access。
当前 NOAH 会逐个调用 ColabFold 处理候选构建,并不会因为服务器有多张显卡、命令使用 --gpus all 就自动获得近似线性加速。如果没有自行改造调度逻辑,单次任务只分配一张 GPU 通常更清晰,也便于把不同任务分配到不同显卡。
任务以后台模式启动后,可以这样查看进度:
五、为什么修改版仓库不公开
为了减少后来者重复踩坑,我整理了 Docker 依赖锁定和 README 参数说明,也曾将修改提交到个人 fork。不过,NOAH 的项目许可证明确限制代码再分发,并特别提到不得将原版或修改版上传到公开 GitHub 仓库。虽然 GitHub 对公开仓库的原生 fork 另有平台条款,但为了避免许可解释上的冲突,也为了尊重作者表达的使用边界,我决定不公开分发修改版仓库,只在自己的内部、非商业研究环境中保留这些修改。
因此,本文只分享部署过程和排障思路,不提供修改版仓库链接。读者应从原始仓库获取代码并遵守其许可证;如需公开修改版、向第三方分发或用于商业场景,应先取得作者的明确许可。
总结
这次 NOAH 部署最终可以归纳为四条经验:
NOAH 本身的思路很有价值,但要把它变成稳定、可重复的服务器工作流,环境锁定、GPU runtime、网络配置和运行文档缺一不可。