Docker容器用户权限隔离核心是User Namespace映射:启用"userns-remap":"default"后,容器内UID 0被映射为宿主机非特权UID(如100000),需重启docker服务、同步挂载目录属主,并禁用--privileged等特权操作。

Docker 容器实现不同用户间的权限隔离,核心不是靠“容器内用户”本身,而是通过 Linux 用户命名空间(User Namespace)+ 宿主机用户映射 + 容器运行时配置 三层机制协同完成。单纯在 Dockerfile 里写 USER 1001 只解决容器内身份,无法防止越权访问宿主机资源;真正安全的多用户隔离必须从 daemon 层启用 user namespace remapping。
✅ 启用 Docker 用户命名空间映射(最关键一步)
这是实现租户级权限隔离的基础。它让容器内的 root 映射为宿主机上的普通用户,彻底切断容器提权后对宿主机的威胁。
- 编辑
/etc/docker/daemon.json,添加:{ "userns-remap": "default" } - 重启 Docker:
sudo systemctl restart docker - Docker 会自动创建名为
dockremap的系统用户,并在/etc/subuid和/etc/subgid中分配一段不重叠的从属 ID 范围(如dockremap:100000:65536),用于将容器内 UID 0~65535 映射到宿主机 UID 100000~165535。
⚠️ 注意:启用后,所有新容器默认运行在独立 user namespace 下。旧容器需重建才生效;且绑定挂载(
-v)的宿主机路径需确保目标用户(如100000)有对应权限,否则出现Permission denied。
✅ 为每个用户分配专属容器环境(运行时隔离)
单靠 daemon 级映射还不够——多个 SSH 用户若共用同一镜像、同一网络,仍可能互相干扰。推荐两种落地方式:
-
方案一:用 dockersh 自动绑定用户与容器
每个用户 SSH 登录时,自动进入以自己用户名命名的独立容器,主目录挂载、网络隔离、shell 环境独立:- 配置
/etc/dockershrc:imagename = ubuntu:24.04 mounthome = true shell = /bin/bash
- 用户
alice登录后,实际运行的是alice_dockersh容器,进程、网络、文件视图完全隔离,且alice在容器内 UID=0,但在宿主机上只等效于dockremap用户的子 ID。
- 配置
-
方案二:手动启动带用户约束的容器
对服务类容器(非交互式),显式指定运行用户和能力:docker run \ --user 1001:1001 \ --cap-drop=ALL \ --cap-add=NET_BIND_SERVICE \ --read-only \ --tmpfs /tmp \ -v /home/alice/.config:/app/config:ro \ my-app:latest
这样即使镜像里有 root 启动逻辑,也会被强制降权,且无法写系统路径、无法获取高危 capability。
✅ 文件与资源访问控制(避免 UID/GID 错配)
用户数据挂载时最常出错:宿主机上 alice 创建的配置文件 UID=1000,但容器内运行用户是 UID=1001 → 权限拒绝。
-
统一 UID/GID 映射:在
/etc/subuid中为每个业务用户预设映射段,例如:alice:100000:65536 bob:165536:65536
再配置 daemon 使用
{"userns-remap": "alice"}(仅用于测试),或统一用default+ 应用层适配。 -
挂载时指定 uid/gid(适用于 bind mount):
docker run -v /home/alice:/home/alice:Z -u 1000:1000 ...
:Z标签让 SELinux 自动打标;-u强制容器内 UID/GID 与宿主机一致。
✅ 网络与资源层面补强(防横向移动)
权限隔离不止看用户,还要堵住其他通路:
-
网络隔离:禁用默认 bridge 互通,为每组用户建独立网络:
docker network create --driver bridge --internal alice-net docker run --network alice-net --name alice-app ...
-
资源限制:防 DoS 式抢占:
docker run --memory=1g --cpus=1.0 --pids-limit=100 ...
-
禁用特权与危险挂载:
绝不使用--privileged;禁止挂载/var/run/docker.sock;敏感路径如/proc,/sys默认不挂载。
不复杂但容易忽略。


















