2. Docker基础:核心概念与安装归纳总结

Docker 这东西,说白了就是一套“集装箱”系统。你写的代码、依赖的环境、配置好的系统,全部塞进一个标准化的箱子里,想搬哪搬哪。我在项目中遇到过几次“在我电脑上能跑”的惨案,后来全栈迁移到 Docker,这类问题基本绝迹了。

这一章我们聚焦两个事:核心概念怎么看,以及怎么把 Docker 装好。概念懂了,安装顺了,后面跑 MaxQuant 和特征学习环境才不卡壳。

2.1 镜像、容器、仓库 – 三剑客

这三个词你得刻在脑子里。我刚开始也迷糊,后来用一句话记牢了:

镜像 = 蓝图(只读模板)
容器 = 房子(镜像运行出来的实例)
仓库 = 图书馆(存镜像的地方)

你想想看,镜像就像一个只读的打包文件,里面装了操作系统、库、代码、配置文件。容器是镜像的运行态,可以读写、可以启动停止,就像从蓝图上盖出的房子,你可以在里面生活、折腾。

仓库呢?Docker Hub 就是最大的公共图书馆,你也可以自己搭私有馆。我习惯把生产环境的镜像推到自己搭的 Harbor 仓库里,既不暴露到公网,拉取速度也快。

概念类比关键点
镜像 (Image)DVD 光盘,只读分层构建,可复用
容器 (Container)DVD 播放机里的播放状态可读写、可销毁
仓库 (Registry)光盘库 / 网盘支持标签 (tag) 版本管理

2.2 Docker 引擎到底干了啥

Docker 引擎是一个 C/S 架构。客户端(docker 命令)发请求给守护进程(dockerd),守护进程负责拉镜像、启停容器、管理网络和存储。

我刚开始以为 Docker 就是纯虚拟化,其实它用的是内核命名空间和cgroups,比虚拟机轻量太多。你运行一个容器,共享宿主机内核,资源隔离却做得不错。

小提示:可以用 docker info 看看你的引擎版本、存储驱动、镜像数量。我第一次跑这个命令,才发现我本地堆了十几个废弃镜像。

2.3 镜像分层与 UnionFS

Docker 镜像是由一层层只读文件系统堆起来的。每一层对应 Dockerfile 里的一条指令。比如:

FROM ubuntu:22.04        # 基础层
RUN apt update            # 安装包层
COPY app /app             # 应用层

修改时只在最上层写,底层不变。这就带来一个好处:拉取时只传输差异层。我在项目里切换过几回基础镜像,发现 alpine 版本只有 5MB 左右,省带宽也省磁盘。

2.4 Dockerfile – 镜像制造说明书

Dockerfile 是构建镜像的唯二正规方式(另一个是 commit,但我几乎不用)。你得学会写 Dockerfile,后面装 MaxQuant 和特征学习环境全靠它。

常见的指令就这几个:

  • FROM – 指定基础镜像
  • RUN – 运行命令(安装软件)
  • COPY / ADD – 复制本地文件
  • CMD / ENTRYPOINT – 定义启动命令
  • EXPOSE – 声明端口(文档作用,不实际开放)
  • WORKDIR – 切换工作目录

踩坑回忆:我曾经在 Dockerfile 里写了 CMD service mysql start && tail -f /dev/null,结果容器启动后进程一直僵着。后来改用 supervisord 才解决。所以别偷懒用这种 hack,老老实实设计进程管理。

2.5 安装 Docker – 三平台速览

Docker 安装现在简单多了。我按照三种常见环境给操作步骤:

Ubuntu / Debian(我用得最多)

# 卸载旧版本
sudo apt remove docker docker-engine docker.io containerd runc

# 安装依赖
sudo apt update
sudo apt install ca-certificates curl gnupg

# 添加 Docker 官方 GPG 密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 添加仓库
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker 引擎
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

# 验证
sudo docker run hello-world

跑完 hello-world 能看到欢迎信息,说明引擎正常。我建议顺手把当前用户加入 docker 组,免去每次 sudo:

sudo usermod -aG docker $USER
# 重新登录或执行 newgrp docker 生效

CentOS / RHEL

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker

macOS / Windows

直接去 Docker Desktop 下载安装包。装好后托盘里出现小鲸鱼图标,点开设置可以调资源(CPU、内存、磁盘)。

我个人的做法:macOS 下我习惯限制 Docker 内存为 4GB,因为 MaxQuant 跑质谱数据挺吃内存,如果 Docker 抢太多,宿主机就卡了。Windows 同理。

2.6 第一个 Docker 命令:跑起来

装好后,试试这组命令感受一下:

docker pull ubuntu:22.04
docker images
docker run -it --name my-first ubuntu:22.04 /bin/bash
# 在容器里:cat /etc/os-release
# exit 退出
docker ps -a
docker rm my-first

看到了吗?从拉取镜像到创建容器、退出删除,几秒钟搞定。同样的流程,虚拟机得等几分钟。

2.7 镜像仓库 – 从私有库拉镜像

因为生产环境经常要拉私有仓库的镜像,我习惯在安装后立即配置镜像加速器和登录私有仓库。加速器推荐阿里云或中科大:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://xxxx.mirror.aliyuncs.com"
  ]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

然后登录私有库:

docker login your-registry.example.com
# 输入用户名和密码
docker pull your-registry.example.com/maxquant:1.6.17

2.8 本章知识体系一览

下面这张图把 Docker 核心概念和安装搭建串在一起了。你能看到从镜像仓库到本地引擎,再到容器实例的完整链路。

Docker 核心概念与安装链路 Docker Hub 公共镜像仓库 私有 Registry Harbor / Nexus Docker 引擎 dockerd + client 镜像 (Image) 分层只读模板 容器 (Container) 运行态实例 安装配置 daemon.json / 用户组 关键操作示例 docker pull / push docker run / stop docker build -t ...

2.9 避坑指南 & 经验总结

最后整理几条我踩过的坑,希望你绕开:

  • 磁盘空间:Docker 默认把镜像存到 /var/lib/docker,容易撑爆系统盘。我习惯挂一个独立分区,或者在 daemon.json 里指定 "data-root": "/data/docker"。
  • 用户权限:不加 docker 组的话,每次都要 sudo,还可能导致 ~/.docker 权限问题。一步到位搞定用户组。
  • 镜像清理:别堆一堆无标签镜像。定期跑 docker system prune -a 能释放几十 G。
  • 网络代理:公司内网需要 HTTP_PROXY,记得在 daemon.json 里也配一份,否则 docker build 拉 package 会失败。

曾经有一次,我在一台只有 20G 根分区的服务器上跑 Docker,忘记调整 data-root,结果数据库容器写日志把磁盘撑满,整个系统挂掉。从此我养成了先 df -h 再装 Docker 的习惯。