
很多人装 Docker 时,会看到系统里突然多了三个服务:
docker.service、docker.socket、containerd.service有人会问:
这三个都要不要装?
能不能只起 docker.service?
containerd 是不是可以不要?
docker.socket 是干嘛的?
如果你没把这件事搞清楚,Docker 出问题时你一定不知道该从哪下手。
一、先给结论
正常安装 Docker:你只需要“安装 Docker”,不需要单独安装或手工启动这三个服务。
原因是:
docker.service是 Docker 主服务containerd.service是 Docker 的底层运行时docker.socket是 Docker 的按需启动入口
👉 它们是一个完整体系,不是三个独立组件。
二、Docker 的真实架构
Docker 并不是一个“单体程序”,而是一个分层架构:
docker CLI
│
▼
dockerd(docker.service)
│
▼
containerd(containerd.service)
│
▼
runc / OCI runtime
这 3 个 systemd 单元,对应的是 不同层级的职责。

三、docker.service:Docker 的“大脑”
1️⃣ 它是什么?
docker.service对应的进程是:
dockerd它是 Docker Daemon(守护进程)。

2️⃣ docker.service 主要干什么?
接收
docker命令(CLI)管理镜像(pull / build)
管理容器生命周期(start / stop / restart)
管理网络、volume、日志、plugin
对外提供 Docker API(HTTP)
只要你在用 Docker,docker.service 一定在。
3️⃣ 没有 docker.service 会怎样?
docker ps
Cannot connect to the Docker daemon👉 Docker 完全不可用

四、containerd.service:真正“跑容器”的人
1️⃣ 它是什么?
containerd.service对应的进程是:
containerd它是一个 通用的容器运行时(CNCF 项目)。
2️⃣ containerd 在 Docker 里干什么?
真正创建 / 启动 / 停止容器
管理容器进程
管理镜像 layer
调用
runc执行 OCI 容器
👉 dockerd 不直接跑容器,是 containerd 在跑。
3️⃣ containerd 和 Docker 是什么关系?
Docker 依赖 containerd
containerd 可以独立使用(Kubernetes 就是直接用它)
但 Docker 离不开 containerd
如果你停掉 containerd:
systemctl stop containerd结果是:
Docker Daemon 可能还在
容器全部起不来
4️⃣ containerd 需要你单独安装吗?
不需要
在现代 Docker(20.x 以后)中:
安装 Docker 时
会自动安装并管理 containerd
特点:
没有 systemd unit
containerd 由 dockerd fork 出来
systemctl status containerd必然不存在
你不应该:
手工单独装一个 containerd
自己改 containerd.service(除非你很清楚后果)


五、docker.socket:被误解最多的一个
1️⃣ 它是什么?
docker.socket这是一个 systemd socket unit(套接字激活)。
2️⃣ docker.socket 干什么用?
它监听:
/var/run/docker.sock当发生以下情况之一:
执行
docker ps有程序访问 Docker API
systemd 会:
自动拉起
docker.service再把请求转交给 dockerd
👉 这叫“按需启动(socket activation)”。
3️⃣ docker.socket 存在 ≠ docker.service 已启动
你可能会看到:
docker.socket active
docker.service inactive
这是完全正常的。
只要你一运行 docker ps:
docker.service 就会被自动拉起
4️⃣ docker.socket 可以关掉吗?
可以,但要明确后果。
systemctl disable docker.socket后果:
docker.service 不再自动启动
你必须手动
systemctl start docker
👉 在服务器/生产环境,一般保留 docker.socket。

六、三者关系一句话总结(非常重要)
关系是:
docker.socket → docker.service → containerd.service → runc七、安装 Docker 时,正确的“认知与操作姿势”
✅ 正确做法
# 安装 docker-ce / docker.io
# 系统会自动安装并配置:
# - docker.service
# - docker.socket
# - containerd.service你只需要关心:
systemctl status docker❌ 错误做法(常见踩坑)
❌ 手工单独安装 containerd
❌ 停用 containerd 以为 Docker 还能跑
❌ 删除 docker.socket 但不手动启动 docker.service
❌ 把 docker.service 和 containerd.service 当成“可选组件”
八、在什么场景下,你才需要“单独关注”它们?
1️⃣ Docker 起不来
看
docker.service日志再看
containerd.service
2️⃣ 容器起不来
containerd / runc 报错
3️⃣ Docker 被莫名自动拉起
你启用了
docker.socket
4️⃣ Kubernetes / CRI 场景
你可能 不用 docker.service
但一定用
containerd.service
Docker 的运行依赖 docker.service、containerd.service 及 docker.socket 三个 systemd 单元,安装 Docker 时无需单独部署;其中 docker.service 提供控制平面,containerd.service 提供容器运行时能力,docker.socket 用于按需激活 Docker 服务。
九、runc又是什么
runc是“真正创建并运行 Linux 容器进程”的最底层执行器。
Docker / containerd 都不直接跑容器,它们最终都是 调用 runc。
官方身份
OCI Runtime Reference Implementation
CNCF(云原生计算基金会)项目
原 Docker 核心代码拆分而来
用一句话概括
runc把“普通 Linux 进程”放进“隔离的命名空间 + 受控的资源限制”里运行。
9.1、为什么一定要有 runc?
Linux 本身并没有“容器”这个概念,只有:
namespace(隔离)
cgroups(资源限制)
capabilities / seccomp(权限与系统调用控制)
runc 做的事就是:
根据配置(OCI spec)
创建 namespace(pid / net / mnt / ipc / uts / user)
应用 cgroups 限制(CPU / 内存 / IO)
设置安全策略(capabilities / seccomp)
fork + exec 真正的容器进程
它是“把配置变成真实进程”的那一步。
实际上是:
docker CLI
│
▼
dockerd (管理、API、网络、镜像)
│
▼
containerd (容器生命周期管理)
│
▼
runc (真正创建容器进程)
│
▼
Linux Kernel
9.2、runc 和 “容器 ≠ 虚拟机” 的关系
虚拟机
有自己的内核
通过 Hypervisor
容器(runc)
共享宿主机内核
本质是 受限的 Linux 进程
你在容器里看到的:
ps aux其实就是宿主机上的进程,只是:
PID 被隔离
文件系统被 chroot/mount
资源被限制
runc 就是“制造这种错觉”的工具。
以 Docker 20.10.24 为例:
Docker 强依赖 containerd
containerd 强依赖 runc
没有 runc:
container create failed: runtime create failed常见报错关键词:
runc did not terminate successfully
failed to create shim taskrunc 是“不可替代的最后一环”。



十、最后一句“工程化总结”
Docker 不是一个服务,而是一套协同工作的服务体系。
你只负责安装 Docker,剩下的交给 systemd。