Rootless Docker 的安装前提与内核配置检查清单

解读

国内面试官问这道题,核心想验证三件事:

  1. 你是否真的在生产环境落地过 Rootless 模式,还是只停留在实验阶段;
  2. 国产操作系统(麒麟 V10、统信 UOS、阿里云 Linux 3、TencentOS 3 等)的内核裁剪差异是否敏感;
  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 ”感):

  1. 内核 ≥ 4.19,且已打开 CONFIG_USER_NS、CONFIG_OVERLAY_FS、CONFIG_CGROUPS、CONFIG_MEMCG、CONFIG_BLK_CGROUP;
  2. /etc/subuid、/etc/subgid 为当前用户分配 至少 65 536 个 ID,例:
    echo "$USER:100000:65536" | sudo tee -a /etc/subuid /etc/subgid
  3. 确认 systemd 已挂载 cgroup v2
    mount | grep '^cgroup2' 有输出;若无,在 grub 内核行追加 systemd.unified_cgroup_hierarchy=1 并重启;
  4. 安装 rootless 依赖包
    • Ubuntu/Debian:apt install uidmap dbus-user-session fuse-overlayfs slirp4netns
    • RHEL/CentOS/国产麒麟:yum install shadow-utils39 fuse-overlayfs slirp4netns
  5. 若在内网,提前下载 docker-rootless-extras-20.10.xx.tgz 并解压到 $HOME/bin,避免 install.sh 在线拉取失败;
  6. 关闭或放行 4655 端口(dockerd-rootless.sh 默认监听),满足公司 等保测评 要求;
  7. 执行 dockerd-rootless-setuptool.sh install,脚本会自动写入 systemd --user 单元;若国产系统无 systemd --user,需改用 rc.local + su - USERc"dockerdrootless.sh"方式自启,并追加XDGRUNTIMEDIR=/run/user/USER -c "dockerd-rootless.sh"`** 方式自启,并追加 **XDG_RUNTIME_DIR=/run/user/(id -u) 环境变量。

内核配置检查清单(现场可背给面试官):

  • sysctl kernel.unprivileged_userns_clone 返回 1
  • ls /sys/fs/cgroup/cgroup.controllers 存在 memory、pids、cpu、io
  • grep -E 'CONFIG_USER_NS|CONFIG_OVERLAY_FS' /boot/config-$(uname -r) 均为 y
  • which fuse-overlayfs 返回路径且版本 ≥ 1.10
  • slirp4netns --version 显示 ≥ 1.1.0
  • cat /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 在等保环境跑起来。

拓展思考

  1. 国内银行客户要求 “容器内也不能用 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 进一步收缩,才能过 银保监会现场检查
  2. 如果宿主机开了 seccomp 全局默认禁止 user_namespace,rootless 模式会直接失败,如何在不改系统 seccomp 策略的情况下绕过?
    答:利用 systemd-nspawn 的 seccomp 过滤器白名单,把 dockerd-rootless 放到 nspawn 容器里运行,再映射 /dev/fuse/run/user/$UID,实现“双层容器”隔离,满足 运营商集采测试 对 seccomp 的强制基线。
  3. 国产化 CPU(鲲鹏、飞腾)内核页大小 64 k,官方 docker-rootless 二进制默认编译时假设 4 k,导致 overlayfs metacopy 报错,如何修复?
    答:需 重新编译 containerd 与 fuse-overlayfs,追加 -DPAGE_SIZE=65536 宏,并在 daemon.json 里显写 "storage-opt": ["overlay2.override_kernel_check=true"],才能通过 信创工委会兼容性认证