2. Docker 基础入门:安装、拉取、运行、进入、提交
说到 Docker,我第一次接触还是几年前搭生信分析平台的时候。那时候被依赖环境折腾得够呛,一个工具装完发现 glibc 版本不对,另一个又跟 Python 包冲突。后来发现 Docker 可以把整个环境打包带走,嗯,从那以后我就彻底回不去了。这一章咱们先过一遍最基础、也最常用的几个命令——pull、run、exec、commit。你只要把这四个练熟,后面做镜像校验和质控就有了操作基础。
核心思路:镜像(image)是模板,容器(container)是运行实例。我们从仓库拉一个镜像,用 run 创建容器跑起来,用 exec 进去改东西,最后用 commit 把改动保存成新镜像。这个闭环就是日常操作的主干。
2.1 安装 Docker
不同系统安装方式不太一样。我个人习惯在 Ubuntu 上用官方脚本自动装,省事干净。你执行这个就行了:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
装完之后,记得把你的用户加入 docker 组,不然每次都要加 sudo:
sudo usermod -aG docker $USER
newgrp docker # 或者重新登录
docker --version 和 docker run hello-world。如果看到 "Hello from Docker!" 就说明环境搞定了。
2.2 docker pull:拉取镜像
装好 Docker 后,第一件事就是拉个镜像下来。我习惯先拉一个比较小的 base 镜像做测试,比如 Ubuntu:
docker pull ubuntu:22.04
这个命令会从 Docker Hub 下载 Ubuntu 22.04 的镜像。你可能会想,有没有其他 tag?当然有。常用的 tag 有这些:
- latest:当前最新版,但不建议在生产环境用,因为每次拉可能不同。
- 22.04、20.04:具体版本号,可重复性好。
- jammy:代号,跟版本号一样。
- slim:精简版,体积小,生信环境也够用。
如果你想拉一个生信常用的镜像,比如 bioconda 的:
docker pull biocontainers/biocontainers:latest
避坑提醒:我曾经天真地拉了一个 3GB 的镜像,结果公司网慢,半天没拉完。建议你先用 docker search 看看镜像大小,或者优先选 slim 版。网络不好的时候,可以配置国内镜像加速器。
2.3 docker run:运行容器
镜像拉下来,就该跑容器了。这是最常用的命令,我先给个典型用法:
docker run -it --rm --name my_container ubuntu:22.04 bash
拆开讲一讲:
- -i 保留标准输入(STDIN),-t 分配伪终端。两个合起来 -it 就能让你像在 SSH 里一样交互。
- --rm 容器退出后自动删除。测试时加上它,不会留下垃圾容器。
- --name 给容器起个名字,方便后面 exec 或 stop。
- ubuntu:22.04 是镜像名 + tag。
- bash 是要执行的命令,这里打开一个 shell。
你还可以添加端口映射、挂载目录、设置环境变量:
docker run -it --rm \
-p 8080:80 \
-v /home/user/data:/workspace \
-e MY_ENV=hello \
ubuntu:22.04 bash
--rm,它会一直留在磁盘里。用 docker ps -a 能看到全部容器。时间久了会有几十上百个停止的容器,赶紧用 docker container prune 清理掉。
2.4 docker exec:进入运行中的容器
在实际操作中,我们经常需要在已经运行的容器里执行命令。比如你启动了一个后台服务容器,想检查日志,或者临时装个软件。这时候 docker exec 就上场了。
docker exec -it my_container bash
这个命令会打开 my_container 容器里的一个新终端。你可以在里面做任何事——装包、改配置、跑脚本。注意 -it 同样不能少,否则你无法交互。
举个例子:假如你有个容器跑着 RStudio Server,你想进去手动装个 R 包:
docker exec -it rstudio_container R -e "install.packages('ggplot2')"
这样不用进入 shell 也能直接执行命令,适合在 CI 脚本里用。
2.5 docker commit:创建新镜像
你通过 exec 进到容器里,安装了某些工具,改了配置文件。怎么把这个修改后的环境保存下来?docker commit 就是做这个的。
docker commit my_container my_new_image:v1
执行后,当前容器里的文件系统变化会被打包成一个新镜像。你可以用 docker images 看到它。我的经验是,这个命令适合快速迭代,但不要把它当作长期方案——因为 commit 过的镜像没有 Dockerfile,别人很难复现你每一步做了什么。
docker history 查看,再写对应的 Dockerfile 正式构建。commit 只用来「抓拍」,不是「存档」。
顺便提一下,commit 时可以加 -a 指定作者,-m 写注释:
docker commit -a "yourname" -m "installed samtools and bcftools" my_container bio_env:1.0
2.6 四个命令的工作流
上面四个命令其实就构成了一个完整的「拉取 ➔ 运行 ➔ 修改 ➔ 导出」循环。我画了一张图帮你理清关系:
2.7 常用命令速查表
下面这个表格总结了我们刚讲过的所有命令,以及它们的核心参数。你可以打印出来贴在工位上,非常实用。
| 命令 | 用途 | 常用选项 |
|---|---|---|
docker pull <image> |
从 registry 拉取镜像 | 无特殊选项,可指定 tag |
docker run [OPTIONS] IMAGE [CMD] |
创建并启动容器 | -it 交互、--rm 自动删除、-v 挂载、-p 端口 |
docker exec -it <container> <cmd> |
在运行中的容器里执行命令 | -it 必须有,可加 -u 指定用户 |
docker commit [OPTIONS] CONTAINER [REPOSITORY:TAG] |
将容器保存为新镜像 | -a 作者、-m 提交信息 |
docker pull biocontainers/samtools:latest 把最近常用的镜像拉一遍,然后 docker run --rm -it 起一个临时容器,在里面干活。干完活直接退出(容器自动删掉),第二天再重新拉最新的版本,这样保证每次用的都是新环境。
好啦,这一章的核心就是四个命令:pull、run、exec、commit。你想想看,它们是不是把整个 Docker 生命周期都串起来了?镜像仓库拿到手,跑成容器,进去修改,再保存成新镜像。后面章节讲校验和质控,这些操作就是基本功。如果你现在手边还没有 Docker 环境,赶紧用安装命令装一个,然后跟着上面的例子动手敲一遍。只有亲手跑过,才记得牢。