第二讲:Docker 的五大核心组件

说实话,我刚接触 Docker 的时候,也容易把几个概念搞混。
镜像、容器、仓库,还有 Daemon 和 Client——一开始听起来像是五个独立的玩意儿。
但用久了你会发现,它们其实是一个完整的协作链条。

这一讲,我就带着你把这五个角色拆开看透。
搞懂了它们的关系,Docker 就算入门了一大半。

镜像(Image):只读的模板

镜像是什么?说白了就是一个快照。
它包含了运行应用所需的一切:操作系统底层库、运行时、代码、环境变量、配置文件。
但镜像本身是只读的,你不能直接在它上面改东西。

我个人习惯把镜像类比成光盘或者 ISO 安装文件——内容固定,你可以用它来批量刻录。

关键词:只读、层叠文件系统、构建一次、到处运行。

用 docker image ls 可以查看本地已有的镜像列表。

docker image ls

REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
ubuntu        22.04     a0a45b2a3f4e   2 weeks ago    77.8MB
nginx         latest    2b7f9a9e4c3d   5 days ago     187MB

容器(Container):镜像的运行实例

容器是镜像的「活体」。
从同一个镜像可以启动多个容器,每个容器都是隔离的——有自己的文件系统、网络栈、进程空间。

我在项目中遇到过,有同事直接把容器当虚拟机用,进去装软件、改配置。
嗯,这里要注意:容器默认是可写的,但写入的数据在容器销毁后就没了。
如果你要持久化数据,必须挂载卷(Volume)。

小技巧:用 docker run -it ubuntu bash 启动一个交互式容器,进去玩一玩,感受一下隔离环境。

常用命令一览:

docker run -d --name my-app nginx        # 后台启动
docker ps                                # 查看运行中的容器
docker stop my-app                       # 停止容器
docker rm my-app                         # 删除容器
docker exec -it my-app bash              # 进入容器内部

仓库(Registry):镜像的存储与分发中心

镜像从哪来?从仓库拉下来。
Docker Hub 是最著名的公共仓库,你可以 push 自己的镜像上去,也可以 pull 别人的。
企业里常用私有仓库,比如 Harbor、AWS ECR、GitLab Container Registry。

你想想看,如果没有仓库,每次部署都要从 Dockerfile 重新构建,那得多慢?
仓库让镜像可以复用、共享、版本管理。

docker pull ubuntu:22.04                  # 从 Docker Hub 拉取镜像
docker push myregistry.com/my-app:v1      # 推送到私有仓库
docker tag ubuntu:22.04 my-alias:latest   # 给镜像打标签

注意:默认连的是 Docker Hub。如果你用私有仓库,记得先 docker login。

Docker Daemon(dockerd):核心引擎

Daemon 是 Docker 的后台守护进程。
它负责管理镜像、容器、网络、存储卷——说白了,你所有操作最终都由它来执行。
Daemon 跑在宿主机上,监听 REST API 请求。

我曾经在一次生产事故里发现 Daemon 日志堆满了磁盘,导致容器调度卡死。
从那以后,我习惯把 Daemon 的日志单独设置轮转。

Daemon 的默认配置文件在 /etc/docker/daemon.json。

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2",
  "registry-mirrors": ["https://mirror.example.com"]
}

Client(docker CLI):用户的前端工具

Client 就是你终端里敲的那个 docker 命令。
它把你的输入转成 REST API 请求,发送给 Daemon。

Client 和 Daemon 可以不在同一台机器上——只要网络通,就能远程管理。
这一点在 CI/CD 流水线里特别有用。

查看 Client 与 Daemon 的版本信息:

docker version

Client:
 Version:           24.0.6
 API version:       1.43
 Go version:        go1.20.7

Server:
 Engine:
  Version:          24.0.6
  API version:      1.43
  Go version:       go1.20.7

注意 Server 那一块显示的就是 Daemon 的信息。如果只连上了 Client 连不上 Daemon,你会看到一堆连接拒绝的报错。

它们怎么协作?

下面这张图展示了五者的关系——我建议你多看几遍,在脑子里形成画面。

Docker 核心组件架构 docker CLI Client dockerd Docker Daemon REST API 镜像 Image 容器 Container 仓库 Registry 管理 运行 实例化 push / pull 核心流程 Client 通过 REST API 告诉 Daemon 做什么 → Daemon 从仓库拉镜像 → 从镜像启动容器 → 容器运行你的应用

五大组件对比速查

组件 角色 是否持久化 典型操作
镜像 只读模板 是(存储于本地或仓库) docker pull、docker build、docker tag
容器 镜像的运行实例 默认不持久(除非用卷) docker run、docker stop、docker exec
仓库 镜像的集中存储和分发 是(远程或本地) docker push、docker pull
Daemon 后台守护进程,核心引擎 常驻内存 自动处理 API 请求
Client 命令行工具,发送指令 瞬态(每次命令启动一次) docker 命令

一句话总结:Client 发命令,Daemon 干活,镜像当模板,容器跑应用,仓库存镜像。

搞清楚了这五个组件,后续讲构建镜像、写 Dockerfile、做多阶段构建,你就知道每一层是在跟谁打交道。
嗯,下个知识点见。