直接原因是cgroup v2环境下Docker容器无法访问完整cgroup层级,需通过--cgroupns=host、--cap-add=CAP_SYS_ADMIN等配置使容器共享宿主机cgroup视图,并确保基础镜像适配systemd启动逻辑。
直接原因很明确:容器启动时 systemd 或其依赖的 cgroup 接口不可用,常见于启用 cgroup v2 的现代系统(如 ubuntu 22.04+、fedora 36+、debian 12+),而 docker 默认未正确挂载或传递 cgroup 文件系统。
cgroup v2 必须统一挂载且容器需共享宿主机视图
与 cgroup v1 不同,cgroup v2 要求整个层级在 /sys/fs/cgroup 单点挂载,且 systemd 依赖该路径下的控制器(如 cpu、memory)正常暴露。Docker 容器默认使用自己的 cgroup 命名空间,导致容器内看不到完整结构。
- 确认宿主机是否启用 cgroup v2:
stat -fc %T /sys/fs/cgroup返回cgroup2fs即为 v2 - 检查挂载是否完整:
mount | grep cgroup应只有一行类似none on /sys/fs/cgroup type cgroup2 (rw,relatime,seclabel) - 若挂载缺失或不全(如只有部分子系统),需在宿主机
/etc/default/grub中确保GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=1",然后运行sudo update-grub && sudo reboot
启动容器时显式启用 cgroup 命名空间共享
Docker 20.10+ 支持 --cgroup-parent 和 --cgroupns=host,但最关键的是让容器“看到”宿主机的 cgroup 视图,而非隔离副本。
- 启动命令中加入:
--cgroupns=host --privileged(--privileged是临时绕过权限限制的常用方式,含CAP_SYS_ADMIN) - 更安全的替代方案(推荐):
--cap-add=CAP_SYS_ADMIN --security-opt seccomp=unconfined --tmpfs /run --tmpfs /run/lock --tmpfs /tmp,再配合--cgroupns=host - 若使用
docker-compose.yml,在 service 下添加:
cgroup_parent: "docker"
cgroupns_mode: "host"
cap_add: ["SYS_ADMIN"]
验证容器内 cgroup 状态是否可用
容器启动后,进入容器执行以下检查,确认关键路径和权限就绪:
-
ls /sys/fs/cgroup—— 应列出cpu、memory、pids等子目录(非空) -
cat /proc/1/cgroup—— 第一列应为0::/(v2)或包含多个 controller(v1),不能是空或报错 -
systemctl --no-pager list-units --state=failed—— 若 systemd 已启动,可快速定位失败服务 - 若仍报
Failed to create root cgroup hierarchy: Permission denied,说明CAP_SYS_ADMIN未生效,需回查--cap-add或改用--privileged
镜像层需适配 systemd 启动逻辑
即使 cgroup 就绪,基础镜像若未按 systemd 容器规范构建,仍会启动失败。关键点:
- 基础镜像应基于官方
ubuntu:22.04、debian:12或centos:9等支持 systemd 的发行版 -
Dockerfile中必须设置ENTRYPOINT ["/sbin/init"]或ENTRYPOINT ["/usr/lib/systemd/systemd"],不能用sh -c替代 - 禁用默认的
systemd.unit=multi-user.target干扰:在docker run中加参数--tmpfs /run --tmpfs /run/lock,并确保/etc/systemd/system.conf中未设DefaultTimeoutStartSec过短


















