Docker启用UserNS后,容器内root(UID 0)映射为宿主机非特权UID(如100000),实现权限解耦;需配置daemon.json启用"userns-remap":"default"并重启服务,绑定挂载须同步调整宿主机目录属主,且不兼容--privileged模式。

在Docker中启用User Namespace,能让容器内的root用户(UID 0)不再等同于宿主机的root用户,而是映射为宿主机上一个普通、非特权的UID(如100000),从根本上切断容器逃逸后直接操控宿主机关键资源的路径。这不是禁止root,而是“重映射”——容器内照常用root,宿主机上实际受限。
配置Docker Daemon启用UserNS映射
全局开启是前提,需修改Docker守护进程配置:
- 编辑/etc/docker/daemon.json,加入:
{"userns-remap": "default"}
保存后执行sudo systemctl restart docker - Docker会自动创建系统用户
dockremap,并在/etc/subuid和/etc/subgid中分配一段子ID范围(如dockremap:100000:65536) - 若需审计可控,可改用指定用户:先手动写入
myuser:200000:65536到subuid/subgid,再将daemon.json设为"userns-remap": "myuser"
理解并验证UID映射效果
启用后,容器内与宿主机的用户身份呈现“内外不一致”:
- 容器内执行
id -u仍显示0,但宿主机上查看该进程(如ps aux | grep yourcmd),UID已是映射起始值(如100000) - 绑定挂载(
-v /host/path:/container/path)时,宿主机目录属主需同步设为映射UID,否则容器内可能无写权限:sudo chown -R 100000:100000 /host/path - 进入运行中容器,执行
capsh --print可确认当前capabilities是否被合理裁剪(避免残留CAP_SYS_ADMIN等高危能力)
配合镜像层USER指令强化纵深防御
UserNS是运行时隔离,而Dockerfile中的USER指令是构建时加固,二者叠加效果更佳:
- 在Dockerfile中显式创建非root用户并切换:
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -D appuserUSER appuser - 这样即使UserNS未启用,应用也已脱离root上下文;若UserNS已启用,该UID 1001还会被进一步偏移(如映射为101001),双重限制
- 避免使用
--privileged——UserNS与特权模式互斥,启用后该参数会被拒绝
注意兼容性与常见适配点
启用UserNS带来安全提升的同时,需主动适配部分场景:
- 镜像中硬编码依赖UID 0的应用(如旧版MySQL启动脚本),需改用
USER指令或调整其内部逻辑,不能强求容器内必须用root - 访问
/var/run/docker.sock等宿主机资源时,需确保宿主机对应socket文件的属组包含映射后的GID(如GID 100000),否则权限拒绝 - UserNS只隔离用户/组ID,不影响网络、PID、Mount等其他命名空间,它们仍可独立配置


















