
这次我们来看一个很容易让新手手抖的实验在 Ubuntu 容器里输入那些被称为“死亡命令”的 Linux 操作。不少刚接触 Docker 的人都会好奇一个问题容器不是隔离的吗那我在容器里执行rm -rf /宿主机会不会也跟着遭殃或者说容器里的 root 和宿主机 root权限边界到底在哪里这篇文章直接围绕 Ubuntu 容器做一轮破坏性命令测试覆盖rm -rf /、fork 炸弹、dd写盘、chmod、mv、mkfs、shutdown等典型危险操作。重点不是教怎么搞破坏而是搞清楚 Docker 的 namespace、cgroup、overlayfs 和 Capabilities 机制哪些能挡住哪些情况下会穿透容器影响宿主机。实验内容适合 Linux 运维、容器学习者、安全测试人员阅读。所有操作请在自己的隔离测试环境中进行不要在生产环境或未授权的系统上执行。1. 核心能力速览能力项说明实验主题Ubuntu 容器内执行破坏性 Linux 命令验证 Docker 隔离效果测试对象Docker 容器、Linux 内核隔离机制、容器权限控制推荐环境任意支持 Docker 的 Linux 主机内核 4.x 以上核心机制namespace、cgroup、overlayfs、Capabilities、Seccomp典型风险特权容器、目录挂载、资源限制缺失会导致容器保护失效适用场景容器安全测试、Docker 隔离机制学习、系统修复演练不适合场景生产环境、无授权环境、数据未备份的机器容器隔离并不是绝对的安全边界。默认情况下 Docker 对容器进程做了不少限制但一旦给容器加了--privileged、挂载了宿主机目录、或者使用了 host 网络和 pid namespace原本被隔离的风险就会迅速放大。2. 实验场景与安全边界这个实验适合谁主要是这三类人第一刚接触 Docker 的开发者。很多人会想当然地认为容器里 root 就是宿主机 root跑rm -rf /会删掉整个硬盘。实际测试后你会发现默认配置下容器删除的是自身 overlayfs 层的根文件系统宿主机目录不会被动。这个过程能帮助理解镜像层、容器层和挂载点的概念。第二Linux 运维工程师。排查故障时经常需要进入容器执行命令如果不小心把危险命令敲在容器里会影响哪些服务批量脚本里如果出现rm -rf变量为空的问题容器能不能兜底这类问题用实验验证比猜更靠谱。第三安全测试和容器加固人员。需要明确知道哪类参数会让 Docker 的防护失效。例如--privileged、--cap-addALL、--pidhost、-v /:/host这些配置一旦出现容器内的破坏行为就可能直接传导到宿主机。需要强调的安全边界这篇文章列出的所有命令都会破坏容器自身文件系统或消耗容器资源所以实验容器一旦启动基本就做好了被销毁的准备。强烈建议在虚拟机或者临时云主机上测试不要在你正在使用的开发机上直接操作。更不要对任何非授权系统执行这类命令这是基本的安全红线。3. 环境准备与前置条件先准备一台可以跑 Docker 的 Linux 主机。Ubuntu、Debian、CentOS 都行不一定非要用 Ubuntu 系统做宿主机只要容器镜像用 Ubuntu 即可。3.1 检查 Docker 环境# 查看 Docker 版本 docker version # 查看系统内核版本 uname -r # 查看 Docker 存储驱动 docker info | grep -i storage从实验角度建议使用 overlay2 存储驱动这是 Docker 默认且隔离性较好的方案。内核版本建议在 4.15 以上因为新版内核在 namespace、cgroup v2 和 Capabilities 方面做得更完善。3.2 准备实验容器拉取一个最小的 Ubuntu 镜像不需要图形界面# 拉取 Ubuntu 22.04 镜像 docker pull ubuntu:22.04 # 创建一个用于实验的容器 docker run -it --name death-test ubuntu:22.04 bash进入容器后先确认容器内环境# 查看容器内系统信息 cat /etc/os-release # 查看当前用户权限 id # 查看根文件系统挂载方式 df -h /正常情况下id会显示你是 root但这只是容器内的 rootUID 是 0却没有宿主机的完整权限。df -h /会看到 overlay 文件系统这就是 Docker 隔离的关键一点容器根目录并不是宿主机根目录而是由镜像层和容器可写层叠加出来的虚拟视图。3.3 准备观察窗口建议额外开一个终端窗口在宿主机上执行# 持续观察容器状态和资源占用 docker stats death-test # 查看容器进程 docker top death-test有了这两个窗口执行危险命令后可以立刻对比容器内部状态和宿主机状态到底有什么不同。4. 安装部署与启动方式这个实验不涉及复杂部署关键是掌握三类启动方式因为启动参数直接决定隔离效果。4.1 默认普通容器docker run -it --name death-test ubuntu:22.04 bash这种启动方式下容器没有额外权限/proc、/sys 大部分只读没有宿主块设备不能修改内核参数。绝大多数“死亡命令”的危害会被限制在容器内部。4.2 带目录挂载的容器# 将宿主机的 /tmp/test-data 挂载到容器的 /data mkdir -p /tmp/test-data docker run -it --name death-test -v /tmp/test-data:/data ubuntu:22.04 bash这种启动方式下容器内的/data是宿主机目录的真实映射。如果执行rm -rf /data宿主机上的原目录内容会被清空。这就是挂载目录穿透容器的典型场景。4.3 特权容器docker run -it --name death-test --privileged ubuntu:22.04 bash特权容器是一个危险选项。它会关闭绝大多数隔离限制容器内进程几乎拥有宿主机的全部能力可以直接访问宿主机设备、加载内核模块、修改内核参数。在这种模式下跑破坏性命令宿主机基本没有保护。4.4 限制资源的容器# 限制容器只能使用 0.5 个 CPU 和 256MB 内存 docker run -it --name death-test --cpus0.5 --memory256m ubuntu:22.04 bash这个配置对 fork 炸弹这类资源耗尽型攻击有直接遏制作用。测试时建议先建立普通容器再单独建立特权容器和挂载容器分别观察差异。5. 功能测试与效果验证下面逐个执行“死亡命令”每个测试都按“目的、命令、预期、分析”的方式展开。5.1 rm -rf / 删除根目录先看最经典的rm -rf /。测试目的验证容器内删除根目录是否会影响宿主机。执行命令rm -rf /实际现象命令执行过程中大量删除报错部分系统文件被删除容器内命令开始失效bash 报错最后容器直接退出或者进入不可用状态。结果分析默认普通容器中rm -rf /删除的是容器 overlayfs 的可写层和镜像层中的文件。宿主机根目录是独立的挂载点不在容器的根文件系统视野中因此宿主机系统不受影响。执行后容器会损坏但 docker 宿主机仍然正常。判断是否成功执行后宿主机执行docker ps -a能看到容器状态变为 Exited或者容器内 shell 不再响应。宿主机本身可以正常执行ls、top等操作说明宿主系统没有受影响。常见失败原因如果容器启动时加了-v /:/host这类挂载rm -rf /host会删除宿主机根目录下对应路径的文件这是非常严重的穿透事故。实验时务必确认没有挂载宿主机根目录。5.2 fork 炸弹内存与 CPU 耗尽下面看 fork 炸弹这是典型的资源耗尽型攻击。测试目的验证容器能否阻止进程无限繁殖以及资源限制是否有效。执行命令:(){ :|: };:实际现象如果容器没有资源限制容器内会迅速创建大量进程CPU 和内存被吃满容器卡死docker stats可以看到 CPU 使用率冲到接近 1000%或限制值。如果宿主机配置较弱宿主机整体也会变卡因为容器默认会吃满可调度的 CPU 资源。结果分析fork 炸弹不是删除文件而是不断复制自身进程直到系统资源耗尽。Docker 的 namespace 隔离了进程视图但 CPU 和内存是共享的。如果容器启动时没有--cpus和--memory限制fork 炸弹会尽可能消耗宿主机资源虽然没有直接破坏文件但会导致宿主机响应缓慢甚至无法操作。判断是否成功观察docker stats中 CPU 和内存使用率宿主机执行top能看到大量bash或ps子进程如果配置了资源限制容器会被 cgroup 抑制CPU 不会无限增长。建议这个测试不要在配置较低的机器上直接跑一定要加--cpus0.5 --memory256m限制否则整个宿主机可能短暂失联。5.3 dd 写入块设备测试目的验证容器内能否直接操作宿主机硬盘。执行命令dd if/dev/zero of/dev/sda bs1M count1实际现象默认普通容器中/dev/sda不存在。执行后提示No such file or directory或者Permission denied。结果分析Docker 默认不会把宿主机的块设备暴露给容器。容器内/dev目录是由 Docker 生成的设备列表通常只有 null、zero、random、urandom、tty 等基础设备。宿主机磁盘设备被隔离在容器视野之外因此这条命令不会对宿主机磁盘造成写入。判断是否成功如果执行后报错“No such file or directory”说明设备隔离生效。如果执行后没有报错说明容器被赋予了额外的设备访问权限需检查启动参数是否包含--device /dev/sda或--privileged。常见失败原因特权容器中/dev/sda是可访问的执行dd会直接破坏宿主机磁盘数据。所以实验时绝对不要用特权容器执行这条命令。5.4 chmod -R 777 / 权限混乱测试目的验证容器内批量修改根目录权限是否影响宿主机文件。执行命令chmod -R 777 /实际现象命令执行需要较长时间容器内大量文件权限被改写部分动态库因为权限变化导致命令无法执行容器逐渐变得不可用。结果分析这个操作修改的是容器 overlayfs 内的文件权限。宿主机文件系统是独立的权限信息不会同步到宿主机。但需要特别注意的是如果是挂载目录比如-v /opt/app:/data那么chmod -R 777 /data会真实改变宿主机/opt/app下所有文件的权限造成安全风险。判断是否成功执行后容器内输入ls可能提示权限错误或动态库加载错误。宿主机执行ls /仍然正常。实验建议这个测试对容器的破坏比较彻底执行完基本需要重建容器适合在专门实验容器中操作。5.5 mv / /dev/null 移动根目录测试目的验证根目录移动到设备文件后容器和宿主机的状态。执行命令mv / /dev/null实际现象命令执行后提示Device or resource busy或者Directory not empty但即便没有成功容器内 bash 也会陷入异常状态部分命令不可用。结果分析根目录本身是挂载点正在被系统使用mv操作内核层面不允许直接移动挂载点。不过这个命令的破坏性在于它会把系统的目录结构搞乱导致大量 shell 命令失效。由于容器根文件系统是 overlayfs 的虚拟视图宿主机/目录不会受影响。判断是否成功容器内出现mv: cannot move / to /dev/null: Device or resource busy同时后续命令经常报错说明容器的动态链接或目录结构已经异常。重建容器即可恢复。5.6 mkfs 格式化磁盘设备测试目的验证容器内能否格式化宿主机磁盘分区。执行命令mkfs.ext4 /dev/sda实际现象默认普通容器中提示/dev/sda不存在。如果手动先创建了一个名为/dev/sda的设备文件但没有任何底层块设备支撑mkfs 会报错找不到设备。结果分析容器内没有宿主磁盘块设备所以无法格式化宿主机磁盘。这个实验和 dd 的结论一致Docker 默认对块设备的隔离是有效的。潜在风险如果启动容器时指定了--device /dev/sda或使用了--privileged那么mkfs会真的格式化宿主机磁盘分区。这个后果远比删除文件严重恢复成本极高。判断是否成功执行后宿主机lsblk查看磁盘信息分区表和数据不变说明隔离有效。5.7 shutdown 与 reboot 关闭系统测试目的验证容器内能否关闭宿主机电源或重启宿主机。执行命令shutdown -h now reboot实际现象普通容器中执行shutdown -h now时通常会提示Failed to connect to bus: No such file or directory或者shutdown: Unable to shutdown system: Operation not permitted。执行reboot也会有类似权限错误。结果分析Docker 容器默认移除了CAP_SYS_BOOT能力容器内进程没有权力触发宿主机的关机和重启操作。即使容器内存在 systemd也没有权限去管理宿主机的 systemd 实例。判断是否成功命令报错且宿主机没有关机、没有重启说明 Capabilities 限制生效。如果宿主机直接重启了说明容器是以特权模式运行或者容器对宿主机的 systemd socket 有访问权限。5.8 写入内核参数测试目的验证容器内能否修改宿主机内核运行参数。执行命令echo 1 /proc/sys/kernel/hostname实际现象普通容器中/proc/sys下的多数文件是只读的执行后提示Read-only file system或者Permission denied。结果分析Docker 默认以只读方式挂载/proc/sys同时 seccomp 配置也禁止了部分系统调用。所以容器内无法直接修改宿主机内核参数。但如果使用--privileged或者单独设置/proc/sys可写容器内就能修改宿主机内核配置。判断是否成功报错说明保护生效。如果成功写入宿主机内核参数发生变化说明当前容器权限过高。6. 资源占用与性能观察这个实验虽然不涉及 GPU 和模型推理但资源监控同样重要。执行 fork 炸弹类命令时观察资源占用是判断容器是否“越界”的关键。6.1 使用 docker stats 实时观察宿主机执行docker stats death-test输出会显示容器的 CPU 使用率、内存使用量、网络 IO 和磁盘 IO。执行 fork 炸弹后CPU 使用率会快速上升如果启动时限制了--cpus0.5则最多跑到 50% 左右如果不限制可能冲到接近宿主机核数上限。6.2 使用 cgroup 核对限制在宿主机执行# 查看容器对应的 cgroup 目录 systemd-cgls # 或者直接查看 CPU 限制配置 cat /sys/fs/cgroup/cpu/docker/container-id/cpu.cfs_quota_us cat /sys/fs/cgroup/cpu/docker/container-id/cpu.cfs_period_us当cfs_quota_us为50000、cfs_period_us为100000时表示容器最多使用半个 CPU 核心。这是 cgroup 限制的直接证据也是 fork 炸弹无法拖垮宿主机的根本原因。6.3 观察宿主机负载与容器负载差异运行 fork 炸弹后在宿主机执行top注意看%Cpu(s)和load average。如果容器没有资源限制宿主机负载会迅速走高。这一现象说明Docker 隔离了文件系统和设备但没有隔离 CPU 和内存的物理消耗资源始终是共享的。6.4 降低容器资源占用的策略启动容器时指定--cpus、--memory、--pids-limit配置 systemd 的 TasksMax 限制容器内进程数量为实验容器设置独立的 ulimit使用--read-only启动只读根文件系统避免容器内文件被改写# 带 pid 数量限制和安全参数的实验容器 docker run -it --name death-test \ --cpus0.5 \ --memory256m \ --pids-limit64 \ --read-only \ ubuntu:22.04 bash7. 常见问题与排查方法问题现象可能原因排查方式解决方案容器内执行 rm -rf / 后容器退出容器根文件系统被删除bash 无法继续运行使用 docker ps -a 查看容器状态删除容器重建宿主机数据不受影响宿主机变得非常卡顿容器内进程无限复制耗尽 CPU/内存宿主机执行 top查看容器 PID 列表使用 docker stop 强制停止容器后续加 --cpus 和 --memory 限制容器内无法访问 /dev/sda默认块设备隔离生效ls /dev 查看容器设备列表属于正常现象确认未使用 --privileged执行 shudown 提示 Operation not permitted容器缺少 CAP_SYS_BOOTdocker inspect 查看 CapDrop 配置属于默认安全行为不要给容器增加该能力挂载目录中的文件被容器删除容器启动时使用了 -v 挂载宿主机目录docker inspect 查看 Mounts 字段不要挂载不需要的目录挂载时必须备份容器执行命令后提示 Read-only file system根文件系统以只读方式挂载或 /proc/sys 受限mount 查看挂载类型使用临时可写层或变更启动参数特权容器内执行 dd 后宿主机系统损坏--privileged 关闭了设备访问隔离检查 Docker 启动历史命令严格禁止特权容器执行写盘操作8. 最佳实践容器安全测试的工程化建议8.1 容器启动前审计参数每次启动容器前先确认以下参数docker inspect container-name # 检查 Privileged 是否为 true # 检查 Mounts 是否包含宿主机敏感目录 # 检查 CapAdd 是否有 SYS_ADMIN、SYS_BOOT 等高风险能力8.2 使用资源限制和只读文件系统即使只是测试容器也要加资源限制。大公司生产环境对容器的要求通常包含 CPU 限额、内存限额、PID 限额、只读根文件系统、非 root 用户运行等。# 更安全的实验容器模板 docker run -it --name safe-test \ --cpus1 \ --memory512m \ --pids-limit128 \ --read-only \ --tmpfs /tmp \ --cap-dropALL \ --security-optno-new-privileges \ ubuntu:22.04 bash--cap-dropALL会移除容器内所有 Linux capabilities此时很多破坏性命令会因为权限不足直接失败。--tmpfs /tmp给临时文件一个可写空间又不会落盘到宿主机。8.3 目录挂载规范挂载目录前要明确目的。如果确实需要挂载建议挂载一个空目录作为测试数据目录mkdir -p /tmp/container-test-data docker run -it --name mount-test -v /tmp/container-test-data:/data ubuntu:22.04 bash不要挂载/home、/etc、/root、/var/lib/docker等敏感目录。不要用-v /:/host这种看似方便但极其危险的方式。8.4 实验容器单独管理建议为破坏性测试建立单独的 Docker 网络、单独的存储卷、单独的镜像标签。做完实验直接删除容器和镜像docker rm -f death-test docker rmi ubuntu:22.04这样可以避免遗留容器占用磁盘空间也避免误操作把实验容器当成普通容器再次启动。8.5 执行前的三重确认对于任何可能造成破坏的容器内命令执行前确认三点当前终端是否在容器内而不是宿主机。可以通过hostname或cat /proc/1/cgroup确认。容器是否挂载了宿主机目录。通过docker inspect查看 Mounts。容器是否以特权模式运行。通过docker inspect查看 Privileged 字段。# 快速判断当前是否在容器内 cat /proc/1/cgroup # 输出包含 docker 或 kubepods 前缀说明在一个容器中 # 如果显示 / 或 system.slice说明当前是宿主机8.6 备份意识无论测试什么命令先备份需要保留的数据。容器的损坏可以随时重建但宿主机数据的丢失代价很高。涉及块设备的实验必须在完全隔离的虚拟机中进行。9. 总结与下一步这次实验最值得关注的点不是“死亡命令本身有多恐怖”而是容器隔离机制什么时候有效、什么时候失效。从默认 Docker 容器来看overlayfs 解决了根文件系统隔离问题rm -rf /、chmod -R 777 /基本不会影响宿主机namespace 解决了设备隔离问题dd、mkfs在没有特权时无法操作宿主机磁盘Capabilities 解决了系统操作权限问题shutdown、reboot在普通容器中会直接报错。但一旦出现几个关键条件隔离会失效--privileged特权模式、挂载宿主机目录、共享宿主机 pid namespace、移除 seccomp 限制。这些参数在很多“方便调试”的容器中很常见也是容器逃逸和宿主机被破坏的主要路径。建议你从一台临时虚拟机开始先用资源限制创建普通容器逐个执行上述命令观察docker stats、宿主机top、容器内外文件系统的差异。再单独启一个特权容器做对比测试但不要把dd、mkfs这类写盘命令放在特权容器里执行。做完实验后统一删除容器和残留镜像把测试过程记录成部署文档方便以后做容器安全复盘。下一步可以继续研究 Docker 的 Seccomp 配置、AppArmor 规则、cgroup v2 的用法以及 Kubernetes Pod 安全上下文对容器权限的限制。这些内容都比单纯记几条“死亡命令”更有实际价值也是生产环境里真正需要的容器加固能力。