Rootless Docker 的安装前提与内核配置检查清单
解读
国内面试官问这道题,核心想验证三件事:
- 你是否真的在生产环境落地过 Rootless 模式,还是只停留在实验阶段;
- 对 国产操作系统(麒麟 V10、统信 UOS、阿里云 Linux 3、TencentOS 3 等)的内核裁剪差异是否敏感;
- 能否把“官方文档要求”翻译成 可落地的运维清单,并给出 故障回退方案。
答得太泛会被追问“你检查过哪些 sysctl 参数”,答得太细又容易陷入内核源码细节,因此需要给出 “运维视角的最小可用集合”,并突出 国内云厂商常见坑点。
知识点
- uid_map / gid_map:/etc/subuid、/etc/subgid 必须存在且范围 ≥ 65 536,国产系统经常缺失。
- user_namespaces:内核编译选项 CONFIG_USER_NS,麒麟默认关闭,需 kexec 重启或更换内核包。
- overlayfs:CONFIG_OVERLAY_FS,必须带 index=on 特性;部分国产化内核阉割该选项,导致 rootless 无法启动 overlay2 存储驱动。
- cgroup v2:Rootless 依赖 cgroup v2 做资源限额,需 systemd.legacy_systemd_cgroup_controller=0 且挂载 unified 层级;TencentOS 2 默认混合模式,需 grub 追加 systemd.unified_cgroup_hierarchy=1。
- fuse-overlayfs:用户态替代方案,国内内网环境需提前下载 fuse-overlayfs-1.10-1.el8.x86_64.rpm 并解决 libc 版本冲突。
- slirp4netns:提供用户态网络,版本 ≥ 1.1.0 才支持 --enable-seccomp,否则无法限制 syscall,安全评审会被挑战。
- ipa / pam_systemd:国产系统若用 中标麒麟专用 PAM 模块,会导致 loginuid 审计字段异常,Docker 守护进程启动报 “could not set loginuid”。
- apparmor / selinux:Ubuntu 20.04 自带 apparmor 策略缺省拒绝 user_namespace,需要 aa-complain /usr/bin/slirp4netns 或自定义本地策略。
- /proc/sys/kernel/unprivileged_userns_clone:Debian/Ubuntu 系列默认 0,需 sysctl -w kernel.unprivileged_userns_clone=1;该参数在国产化定制内核里可能被 lockdown 模块写保护,需重新签名内核模块。
- /etc/docker/daemon.json:rootless 模式下文件位于 $HOME/.config/docker/daemon.json,国内镜像加速需写 https://registry.docker-cn.com 或 阿里云加速器地址,但注意 证书链必须完整,否则 docker pull 报 “x509: certificate signed by unknown authority”。
答案
安装前提(按面试口语化顺序回答,给面试官“ checklist ”感):
- 内核 ≥ 4.19,且已打开 CONFIG_USER_NS、CONFIG_OVERLAY_FS、CONFIG_CGROUPS、CONFIG_MEMCG、CONFIG_BLK_CGROUP;
- /etc/subuid、/etc/subgid 为当前用户分配 至少 65 536 个 ID,例:
echo "$USER:100000:65536" | sudo tee -a /etc/subuid /etc/subgid - 确认 systemd 已挂载 cgroup v2:
mount | grep '^cgroup2'有输出;若无,在 grub 内核行追加 systemd.unified_cgroup_hierarchy=1 并重启; - 安装 rootless 依赖包:
- Ubuntu/Debian:apt install uidmap dbus-user-session fuse-overlayfs slirp4netns
- RHEL/CentOS/国产麒麟:yum install shadow-utils39 fuse-overlayfs slirp4netns
- 若在内网,提前下载 docker-rootless-extras-20.10.xx.tgz 并解压到 $HOME/bin,避免 install.sh 在线拉取失败;
- 关闭或放行 4655 端口(dockerd-rootless.sh 默认监听),满足公司 等保测评 要求;
- 执行 dockerd-rootless-setuptool.sh install,脚本会自动写入 systemd --user 单元;若国产系统无 systemd --user,需改用 rc.local + su - (id -u) 环境变量。
内核配置检查清单(现场可背给面试官):
sysctl kernel.unprivileged_userns_clone返回 1ls /sys/fs/cgroup/cgroup.controllers存在 memory、pids、cpu、iogrep -E 'CONFIG_USER_NS|CONFIG_OVERLAY_FS' /boot/config-$(uname -r)均为 ywhich fuse-overlayfs返回路径且版本 ≥ 1.10slirp4netns --version显示 ≥ 1.1.0cat /proc/self/uid_map能看到 100000 65536 映射docker info 2>/dev/null | grep -i rootless输出 “rootless: true”
一句话收尾:
以上七步三查,国产麒麟缺 USER_NS 就换内核包,TencentOS 缺 cgroup v2 就改 grub,内网离线就把 rpm 提前下好,10 分钟之内能让 Rootless Docker 在等保环境跑起来。
拓展思考
- 国内银行客户要求 “容器内也不能用 root”,但业务镜像硬编码了 root,如何在不改 Dockerfile 的前提下,用 --user 65534:65534 跑起来?
思路:rootless dockerd 本身以用户身份运行,容器内 uid 0 会被 uid_map 映射到宿主机普通 uid,满足“宿主机无 root”要求;但容器内进程仍显式 uid 0,需通过 --security-opt no-new-privileges + --cap-drop ALL + seccomp 自定义 profile 进一步收缩,才能过 银保监会现场检查。 - 如果宿主机开了 seccomp 全局默认禁止 user_namespace,rootless 模式会直接失败,如何在不改系统 seccomp 策略的情况下绕过?
答:利用 systemd-nspawn 的 seccomp 过滤器白名单,把 dockerd-rootless 放到 nspawn 容器里运行,再映射 /dev/fuse 和 /run/user/$UID,实现“双层容器”隔离,满足 运营商集采测试 对 seccomp 的强制基线。 - 国产化 CPU(鲲鹏、飞腾)内核页大小 64 k,官方 docker-rootless 二进制默认编译时假设 4 k,导致 overlayfs metacopy 报错,如何修复?
答:需 重新编译 containerd 与 fuse-overlayfs,追加 -DPAGE_SIZE=65536 宏,并在 daemon.json 里显写"storage-opt": ["overlay2.override_kernel_check=true"],才能通过 信创工委会兼容性认证。