第2章:Docker 镜像 —— 拉取、构建与推送至私有仓库
镜像,说白了就是容器的“快照”。你要跑 AlphaFold,第一步就是搞定镜像。这一章我带你过一遍最常用的三个操作:拉取别人的镜像、自己动手构建、以及推到你自己的仓库里。别看都是基础动作,用错了也够你折腾半天。
2.1 拉取官方镜像
拉取镜像是 Docker 最简单的操作。一条 docker pull 就搞定了。
docker pull alpine:3.18
但实际干活时,我建议你养成两个习惯:指定具体标签,不要用 latest。为什么?因为 latest 指向的版本随时可能变,你今天拉的跟同事昨天拉的不一样,复现结果就成了玄学。
拿 AlphaFold 来说,DeepMind 官方提供了镜像。我记得最早时他们只放了一个 latest,后来才加了版本号。我在项目中就吃过这个亏:2022 年 3 月拉的镜像跑通了,12 月再拉一次,CUDA 版本变了,模型推理死活报错。解决办法也很简单——用 Git 标签对应的 Docker 镜像。
小经验:拉取前先查查目标仓库的 Tags 页面。例如:
docker pull deepmind/alphafold:2.3.2
这样你就锁死了环境,谁也改不了。
拉取完之后,用 docker images 确认一下:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
deepmind/alphafold 2.3.2 abc123def456 2 weeks ago 12.4GB
ubuntu 22.04 xyz987zyx654 1 month ago 77.8MB
看到那个 12.4GB 没?AlphaFold 的镜像包含了完整的 Python 环境、模型权重和依赖库,体积大是正常的。如果你拉一半断了,重新执行 docker pull 会继续断点续传,不会从头再来——这一点 Docker 做得挺贴心。
2.2 构建自定义镜像
有时候官方镜像不满足需求,比如你想换个数据库路径、加个 GPU 驱动适配、或者集成自己的脚本。这时候就得自己写 Dockerfile 来构建。
我拿一个简化的 AlphaFold 类 Dockerfile 举例:
FROM nvidia/cuda:11.8-runtime-ubuntu22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
python3 python3-pip wget unzip \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir \
biopython==1.79 \
numpy==1.24 \
jax[cuda11_local]==0.4.13
COPY ./scripts /app/scripts
COPY ./models /app/models
WORKDIR /app
ENTRYPOINT ["python3", "/app/scripts/run_alphafold.py"]
构建命令很简单:
docker build -t my-alphafold:1.0 .
这里 -t 是给镜像打标签,格式是 name:tag。注意末尾那个点,表示使用当前目录的 Dockerfile。
避坑指南:我曾经在构建镜像时忽略了一个细节——上下文(context)。Docker 会把当前目录整个打包给守护进程,如果你的目录里有几个 G 的数据库文件,构建会慢到让你怀疑人生。建议把 Dockerfile 放在一个干净的文件夹里,只放必要的文件和依赖。
别忘了 .dockerignore:跟 .gitignore 一样,写在里面文件就不会被发到 Docker 守护进程。我通常至少写上:
*.tar.gz
*.pdb
.git
__pycache__
一句话:构建要快,上下文要小。
2.3 推送至私有仓库
镜像构建好了,总不能只在你本地躺着。团队协作或者生产部署,需要一个私有仓库来存。推送到私有仓库分三步走:打标签、登录、推送。
2.3.1 打标签
先把你本地的镜像重新标记成仓库地址格式:
docker tag my-alphafold:1.0 registry.internal.company.com/alphafold:v1.0
标签的格式固定是 <registry>/<repo>:<tag>。如果仓库不在默认 443 端口,可以写成 registry.internal.company.com:5000/alphafold:v1.0。
2.3.2 登录
推送之前先登录:
docker login registry.internal.company.com
它会让你输入用户名和密码。我建议你配置 长期有效的 access token 而不是用个人密码,尤其是生产环境。不然密码一换,CI/CD 就全断了。
2.3.3 推送
最后推送:
docker push registry.internal.company.com/alphafold:v1.0
推送速度取决于你本地带宽和仓库带宽。一个 12GB 的镜像,如果千兆内网,大概两分钟内能传完。注意:推送是上传整个镜像层,如果只改了某几个 layer,Docker 只推送变化的层,不会全量重传。
核心命令速查表:
| 操作 | 命令示例 | 说明 |
|---|---|---|
| 拉取 | docker pull ubuntu:22.04 |
指定标签,避免 latest |
| 构建 | docker build -t my-img:1.0 . |
-t 打标签,点指上下文目录 |
| 打标签 | docker tag src:dst:tag |
改名为仓库地址格式 |
| 登录 | docker login <registry> |
建议用 token 登录 |
| 推送 | docker push <registry>/img:tag |
增量传输,只传变化层 |
完整流程一览
把上面三步串起来,一张图就能说明白:
图里三个动作:从 Hub 拉取,本地构建,推送到私有仓库。Dockerfile 就是你的蓝图,docker build 就是执行工。只要把 docker tag 和 docker push 记住,私有仓库这块儿就算稳了。
关于私有仓库选型:小团队自己起一个 docker registry 就够用:
docker run -d -p 5000:5000 --restart=always --name registry registry:2
但生产环境我推荐用 Harbor——自带 Web UI、镜像复制、漏洞扫描,省心很多。
嗯,镜像这块儿基础就这些。别小看这几个命令,我见过不少人在 docker login 时用错 registry 地址,或者推上去后发现标签跟代码版本对不上。养成好习惯:每次推送前先 docker images 看一眼,确认本地镜像 ID 是不是你期望的那个。