Docker 容器与宿主机有何异同?从内核、Namespace 到 cgroup,彻底搞懂容器环境检测 Docker 容器与宿主机共享内核但拥有独立的文件系统、进程空间和资源限制。本文从内核架构、Namespace 隔离、cgroup 资源管控、文件系统分层等维度出发系统梳理容器与宿主机之间的本质区别并介绍多种实用的容器环境检测方法。容器与虚拟机的本质区别在深入讨论容器与宿主机的差异之前有必要先理解容器化技术的底层架构。与传统的虚拟机不同Docker 容器并非在独立操作系统上运行而是与宿主机共享同一个 Linux 内核。共享内核架构一个典型的 Linux 文件系统由bootfs和rootfs两部分组成bootfs包含 bootloader 和 kernel操作系统内核。rootfs包含操作系统所需的文件、配置和目录但不包括内核。容器正是利用了这一特性——多个不同的镜像可以在同一个宿主机内核上运行各自的 rootfs容器、镜像与父镜像之间的关系Namespace 隔离容器方案基于 Linux 内核提供的cgroup和namespace来实现隔离。Linux 内核通过以下六种 Namespace 实现不同维度的隔离Namespace 类型隔离内容作用PID进程 ID容器内进程 PID 从 1 开始与宿主机进程隔离Network网络设备、协议栈每个容器拥有独立的网络接口和 IP 地址Mount挂载点容器拥有独立的文件系统挂载视图UTS主机名和域名容器可以设置独立的主机名IPC进程间通信资源隔离 System V IPC 和 POSIX 消息队列User用户 ID容器内用户 ID 可映射到宿主机不同用户这种轻量级隔离方案存在以下特点容器间、容器与宿主机共享同一个内核。通过内核特性实现资源隔离而非硬件级虚拟化。cgroup 资源管控cgroupsControl Groups是 Linux 内核提供的一种机制它可以根据需求把一系列系统任务及其子任务整合或分隔到按资源划分等级的不同组内从而为系统资源管理提供一个统一的框架。cgroup 在 Docker 中起到的作用就是对 CPU、内存、磁盘 I/O 等物理资源的管控。Overlay2 分层文件系统Docker 镜像采用分层存储架构Overlay2每一层都是只读的容器运行时会添加一个可写层。这意味着多个容器可以共享相同的镜像层节省磁盘空间。容器对文件系统的修改不会影响镜像本身。容器的可写层数据在容器删除后默认会丢失因此需要数据卷Volume实现持久化。容器与虚拟机对比对比项Docker 容器虚拟机VM内核共享宿主机内核每个 VM 拥有独立内核启动速度秒级分钟级资源占用轻量仅包含应用及依赖重量包含完整 OS镜像大小MB 级别GB 级别隔离级别进程级隔离Namespace cgroup硬件级虚拟化迁移性高跨平台、跨云一般需兼容 Hypervisor实践判断系统是否运行在容器中理解了容器与宿主机之间的本质区别后下面介绍几种实用的检测方法按可靠程度从低到高排列。方法1内核版本对比容器与宿主机共享内核但容器的系统发行版可能与宿主机不同。通过对比内核版本号可以发现异常。例如在 Ubuntu 20.04 宿主机上创建一个 Ubuntu 22.04 的容器进入容器查看系统版本和内核版本可以看到系统版本是 22.04而 Linux 内核版本却是 5.4.0。查阅资料可知Ubuntu 22.04 will be released with kernel version 5.15. This is one of the newest kernel versions available, but has endured enough testing to yield a stable system for Ubuntu 22.04.新系统使用着较旧的系统内核这可以作为一个辅助判断依据。局限性此方法只能作为辅助判断。运行环境不同即使发行版一致内核版本也可能不一致。以 VMware 上的 Ubuntu 20.04 为例内核版本是 5.15.0用户可以自行升降级 Linux 内核版本因此不能仅凭内核版本判断。方法2Busybox 检测BusyBox 是一个集成了三百多个最常用 Linux 命令和工具的软件通常预装在大多数 Linux 发行版中。在宿主机上运行 busybox在容器中运行 busybox容器中一般无法执行 busybox 命令bin 目录中没有 busybox。Docker 容器通常是最小化安装的镜像像lsmod、lspci、lsb_release -a等命令也无法直接使用需要安装对应的软件包。局限性容器可以自行安装 Busybox 工具箱因此能使用 Busybox 的不一定是宿主机。方法3硬件设备信息/dev目录包含许多设备文件为应用提供了访问底层设备的接口。对这些设备文件的 I/O 操作流程如下设备文件 I/O —— 底层设备驱动 —— 实际设备通过对比/dev目录内容可以初步判断ls/dev宿主机容器容器的设备数量明显比宿主机少并且容器拥有两个宿主机不具备的特殊设备mqueue和shm。查看 CPU 信息也是一种有效方法lscpu宿主机容器和宿主机相比容器的 CPU 信息输出多了一项漏洞Vulnerabilities。不过在一些特殊情况下宿主机也会出现此项。方法4cgroup 检测/proc是一个虚拟文件系统其中有一些以数字命名的进程目录。系统中当前运行的每一个进程都有对应的目录以进程的 PID 号为目录名。查看进程 1init的 cgroup 信息cat/proc/1/cgroup宿主机容器容器的输出中包含 “docker” 字样这是一个非常明确的信号。方法5/.dockerenv 文件检测Docker 容器在创建时会在根目录下自动生成一个.dockerenv文件这是最简单快捷的检测方法ls-la/.dockerenv如果文件存在则当前环境几乎可以确定是 Docker 容器。宿主机上通常不存在此文件。方法6systemd-detect-virt 命令如果系统安装了 systemd可以使用以下命令检测虚拟化环境systemd-detect-virt在容器中执行输出通常为docker或container# 容器中的输出示例docker# 或container在宿主机上执行输出通常为none非虚拟化环境或对应的虚拟化技术名称如vmware、kvm。方法7/proc/1/sched 查看真实 PID容器内的进程 1 通常是容器的主进程而不是宿主机的 init 进程。通过查看/proc/1/sched可以获取进程信息cat/proc/1/sched|head-5宿主机上的输出示例init (1, #threads: 1)容器中的输出示例bash (1, #threads: 1)容器内的进程名通常是容器启动命令如bash、nginx而不是init或systemd。方法8mount 信息中的 overlay 字段Docker 容器使用 overlay2 文件系统查看挂载信息可以快速识别mount|grepoverlay容器中的输出示例overlay on / type overlay (rw,relatime,lowerdir/var/lib/docker/overlay2/...)在排查容器与宿主机时可通过查看 mount | grep overlay 的输出区分在排查容器与宿主机时可通过查看mount | grep overlay的输出区分位置典型挂载点说明宿主机/var/lib/docker/overlay2/...、/var/lib/containerd/...或/var/lib/docker/rootfs/overlayfs/...存储层数据属于容器运行时的工作目录容器内部overlay on / type overlay ...容器自身的根文件系统判断技巧如果挂载点路径包含/var/lib/docker或/var/lib/containerd则大概率在宿主机上。如果挂载点是/则基本可以确定是在容器内因为只有容器根目录才会挂载 overlay 到/。检测方法可靠性对比方法命令可靠性说明.dockerenv文件ls /.dockerenv★★★★★Docker 专属存在即确认cgroup 检测cat /proc/1/cgroup★★★★☆输出含 docker 字样mount overlaymount | grep overlay★★★★☆容器根文件系统为 overlay 类型systemd-detect-virtsystemd-detect-virt★★★★☆需 systemd 支持硬件设备对比ls /dev★★★☆☆设备数量和类型差异内核版本对比uname -r★★☆☆☆仅作辅助判断Busybox 检测busybox --help★★☆☆☆容器可自行安装简单总结宿主机系统与 Docker 容器中运行的系统主要有以下差异内核共享容器与宿主机共享同一个 Linux 内核无法运行不同内核版本的操作系统。命令可用性容器通常是最小化安装很多命令如lsmod、lspci、busybox无法直接使用。设备信息容器的/dev目录设备数量远少于宿主机且包含mqueue、shm等特殊设备。cgroup 信息容器进程 1 的 cgroup 信息中包含 “docker” 字样。文件系统容器根文件系统使用 overlay2 分层挂载而宿主机使用物理磁盘分区。安全提示检测容器环境的方法在安全领域也有重要意义——攻击者可能在入侵后通过上述方法判断自己是否在容器中从而调整攻击策略。在容器逃逸攻击场景中攻击者会尝试突破 Namespace 和 cgroup 的限制获取宿主机的访问权限。因此了解这些检测方法也有助于更好地配置容器安全策略例如避免以特权模式--privileged运行容器。限制容器对/proc、/sys等敏感目录的访问。使用安全上下文Security Context或 AppArmor / SELinux 增强容器隔离。