第二讲: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 pull、docker build、docker tag |
| 容器 | 镜像的运行实例 | 默认不持久(除非用卷) | docker run、docker stop、docker exec |
| 仓库 | 镜像的集中存储和分发 | 是(远程或本地) | docker push、docker pull |
| Daemon | 后台守护进程,核心引擎 | 常驻内存 | 自动处理 API 请求 |
| Client | 命令行工具,发送指令 | 瞬态(每次命令启动一次) | docker 命令 |
一句话总结:Client 发命令,Daemon 干活,镜像当模板,容器跑应用,仓库存镜像。
搞清楚了这五个组件,后续讲构建镜像、写 Dockerfile、做多阶段构建,你就知道每一层是在跟谁打交道。
嗯,下个知识点见。