前言在上一篇博文中我们完成了 Docker 环境的搭建与镜像构建。但 Docker 容器究竟是如何实现“逻辑隔离”和“资源限制”的为什么镜像构建速度会这么快今天我们通过实验直接穿透 Docker 的表象去 Linux 内核里寻找Namespace、Cgroup和UnionFS的真相。一、 Namespace容器的“隐身术”容器之所以觉得自己运行在一个独立的环境中是因为 Linux 内核的Namespace命名空间为其做了视图隔离。1. 寻找容器的真实身份通过docker inspect我们可以找到容器在宿主机上的真实进程 PID。dockerinspect-f{{.State.Pid}}my-nginx2. 深度对比容器 vs 宿主机我们分别查看容器进程和宿主机 Shell 进程的 Namespace 节点# 查看容器 Namespacesudols-l/proc/容器PID/ns/# 查看宿主机 Shell Namespacesudols-l/proc/$$/ns/ 实验观察不同点你会发现pid、net、mnt、uts等 inode 号完全不同。这意味着容器拥有独立的进程空间、网络堆栈和挂载点。相同点user或cgroup有时可能相同这取决于 Docker 的配置模式。二、 Cgroup给容器加个“紧箍咒”Namespace 解决了“能看到什么”的问题而Cgroup (Control Groups)解决了“能用多少”的问题。1. 启动资源受限的容器我们启动一个限制内存为128MBCPU 为0.5 核的容器dockerrun-d--namelimited-nginx--memory128m--cpus0.5nginx:1.252. 内核文件实证在 Ubuntu 22.04Cgroup v2中我们直接去内核文件系统中读取限制数值# 查看内存上限cat/sys/fs/cgroup/system.slice/docker-CID.scope/memory.max# 查看 CPU 上限cat/sys/fs/cgroup/system.slice/docker-CID.scope/cpu.max 换算小课堂内存128×1024×1024134,217,728128 \times 1024 \times 1024 134,217,728128×1024×1024134,217,728字节。内核数值精准匹配CPU配额 (50000) / 周期 (100000) 0.5 核。三、 UnionFS镜像构建的“乐高艺术”Docker 镜像并不是一个巨大的二进制文件而是由多层只读层堆叠而成的。这就是UnionFS联合文件系统的魅力。1. 查看镜像层级 (RootFS)dockerimage inspect lab1-flask:v1|grep-A20RootFS2. 增量构建实验v1 vs v2当我们修改app.py的代码后重新构建v2镜像会发生什么dockerbuild-tlab1-flask:v2. 实验发现层复用 (Cache)基础镜像和WORKDIR等未改变的层显示为52 minutes ago复用 v1 的层。层更新 (New)从COPY app.py开始后续所有层的 ID 都更新了显示为16 seconds ago。结论Docker 只会重新构建发生变动的层及其上层这极大地提高了开发迭代的效率。四、 总结通过本次实验我们实证了 Docker 的三大核心支柱Namespace资源视图隔离逻辑上的独立。Cgroup资源配额限制物理上的约束。UnionFS镜像分层存储存储上的高效。掌握了这些底层逻辑我们在后续面对复杂的 Kubernetes 编排时才能更加游刃有余你在做 Cgroup 限制时有没有遇到过 OOM内存溢出的问题 下一篇预告从 Docker 到 KubernetesMinikube 集群搭建全记录