Docker底层-User Namespace

复制代码
root@LAPTOP-LU4HDAFV:~# id
uid=0(root) gid=0(root) groups=0(root),987(docker)
root@LAPTOP-LU4HDAFV:~# echo $$
285399
root@LAPTOP-LU4HDAFV:~# cat /proc/$$/uid_map
         0          0 4294967295
root@LAPTOP-LU4HDAFV:~# 

UID/GID 详解

基本概念

  • UID (User ID):用户标识符,Linux 用数字标识用户
  • GID (Group ID):组标识符,Linux 用数字标识用户组

    ┌─────────────────────────────────────────────────────────┐
    │ Linux 用户系统结构 │
    │ │
    │ ┌──────────────────────────────────────────────────┐ │
    │ │ 用户名 (Username) │ │
    │ │ │ │
    │ │ 例如:alice, bob, root │ │
    │ │ (人类可读的名称) │ │
    │ └──────────────────────────────────────────────────┘ │
    │ │ │
    │ │ 映射关系 │
    │ ↓ │
    │ ┌──────────────────────────────────────────────────┐ │
    │ │ UID (User ID) │ │
    │ │ │ │
    │ │ 例如:1000, 1001, 0 │ │
    │ │ (系统内部使用的数字) │ │
    │ └──────────────────────────────────────────────────┘ │
    │ │ │
    │ │ 属于某个组 │
    │ ↓ │
    │ ┌──────────────────────────────────────────────────┐ │
    │ │ GID (Group ID) │ │
    │ │ │ │
    │ │ 例如:1000, 1001, 0 │ │
    │ │ (用户所属组的数字) │ │
    │ └──────────────────────────────────────────────────┘ │
    │ │
    │ 系统实际使用 UID/GID,而不是用户名! │
    └─────────────────────────────────────────────────────────┘

为什么需要 UID/GID?

  1. 性能:数字比较更快
  1. 唯一性:每个用户有唯一 UID
  1. 系统内部:内核使用数字,用户名只是映射

    ┌─────────────────────────────────────────────────────────┐
    │ 用户名 vs UID │
    │ │
    │ 人类视角: │
    whoami │ │ alice │ │ │ │ 系统视角: │ │ id │
    │ uid=1000(alice) gid=1000(alice) │
    │ │
    │ 内核实际使用: │
    │ UID: 1000 ← 内核只认识这个数字 │
    │ GID: 1000 ← 内核只认识这个数字 │
    │ │
    │ 用户名 "alice" 只是方便人类记忆的别名! │
    └─────────────────────────────────────────────────────────┘

User Namespace 工作原理详解

核心概念:UID/GID 映射

User Namespace 通过映射表将 Namespace 内的 UID/GID 映射到主机上的真实 UID/GID。

复制代码
┌─────────────────────────────────────────────────────────┐
│  User Namespace 的 UID/GID 映射机制                     │
│                                                          │
│  ┌──────────────────────────────────────────────────┐  │
│  │ 主机上的真实用户                                  │  │
│  │                                                  │  │
│  │  用户:alice                                     │  │
│  │  UID: 1000  (主机上的真实 UID)                  │  │
│  │  GID: 1000  (主机上的真实 GID)                  │  │
│  │                                                  │  │
│  │  执行命令:                                       │  │
│  │  unshare --user --map-root-user /bin/bash        │  │
│  │         │                                        │  │
│  │         └─────────┐                              │  │
│  └───────────────────┼──────────────────────────────┘  │
│                      │                                  │
│                      │ 创建新的 User Namespace           │
│                      ↓                                  │
│  ┌──────────────────────────────────────────────────┐  │
│  │ User Namespace 内部                               │  │
│  │                                                  │  │
│  │  ┌──────────────────────────────────────────┐   │  │
│  │  │ UID/GID 映射表                          │   │  │
│  │  │                                        │   │  │
│  │  │ Namespace UID  →  主机 UID             │   │  │
│  │  │ ──────────────    ─────────            │   │  │
│  │  │      0        →     1000               │   │  │
│  │  │      1        →     1001               │   │  │
│  │  │      2        →     1002               │   │  │
│  │  │    ...        →     ...                │   │  │
│  │  │   65534       →    106534              │   │  │
│  │  └──────────────────────────────────────────┘   │  │
│  │                                                  │  │
│  │  进程在 Namespace 内看到:                       │  │
│  │  $ id                                            │  │
│  │  uid=0(root) gid=0(root) groups=0(root)         │  │
│  │                                                  │  │
│  │  但实际上映射到主机的 UID 1000!                 │  │
│  └──────────────────────────────────────────────────┘  │
│                                                          │
│  关键:Namespace 内的 root (uid=0) 映射到主机的 UID 1000 │
└─────────────────────────────────────────────────────────┘

为什么不需要 root 权限?

Linux 内核允许普通用户创建 User Namespace(自 Linux 3.8 起),原因:

  1. 安全性:Namespace 内的 root 权限被限制在 Namespace 内
  1. 隔离性:无法影响主机上的其他进程
  1. 映射机制:通过 UID/GID 映射表控制权限

    ┌─────────────────────────────────────────────────────────┐
    │ 权限检查流程 │
    │ │
    │ 进程在 User Namespace 内执行操作: │
    │ │
    │ 1. 访问 Namespace 内的文件 │
    │ ↓ │
    │ 检查:Namespace 内的 UID (0) │
    │ ✓ 允许(在 Namespace 内是 root) │
    │ │
    │ 2. 访问主机上的文件 │
    │ ↓ │
    │ 检查:映射后的主机 UID (1000) │
    │ ✗ 拒绝(主机上不是 root) │
    │ │
    │ 3. 影响主机上的其他进程 │
    │ ↓ │
    │ 检查:映射后的主机 UID (1000) │
    │ ✗ 拒绝(主机上不是 root) │
    │ │
    │ 结论:Namespace 内的 root 权限被限制在 Namespace 内! │
    └─────────────────────────────────────────────────────────┘

    ┌─────────────────────────────────────────────────────────┐
    │ 1. 普通用户执行命令 │
    │ │
    unshare --user --map-root-user /bin/bash │ │ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ 2. 内核创建新的 User Namespace │ │ │ │ │ │ │ │ • 分配新的 Namespace ID │ │ │ │ • 创建新的进程(bash) │ │ │ │ • 设置初始 UID/GID 映射 │ │ │ └──────────────────────────────────────────────────┘ │ │ │ │ │ ↓ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ 3. --map-root-user 自动设置映射表 │ │ │ │ │ │ │ │ /proc/self/uid_map: │ │ │ │ 0 <当前用户UID> 1 │ │ │ │ │ │ │ │ /proc/self/gid_map: │ │ │ │ 0 <当前用户GID> 1 │ │ │ └──────────────────────────────────────────────────┘ │ │ │ │ │ ↓ │ │ ┌──────────────────────────────────────────────────┐ │ │ │ 4. 进程在 Namespace 内运行 │ │ │ │ │ │ │ │ id │ │
    │ │ uid=0(root) gid=0(root) │ │
    │ │ │ │
    │ │ 但实际权限检查时: │ │
    │ │ • Namespace 内操作 → 使用 UID 0 │ │
    │ │ • 主机操作 → 使用映射后的 UID 1000 │ │
    │ └──────────────────────────────────────────────────┘ │
    │ │ │
    │ ↓ │
    │ ┌──────────────────────────────────────────────────┐ │
    │ │ 5. 权限检查机制 │ │
    │ │ │ │
    │ │ 访问 Namespace 内资源: │ │
    │ │ ✓ 使用 Namespace UID (0) → 有 root 权限 │ │
    │ │ │ │
    │ │ 访问主机资源: │ │
    │ │ ✗ 使用主机 UID (1000) → 只有普通用户权限 │ │
    │ └──────────────────────────────────────────────────┘ │
    └─────────────────────────────────────────────────────────┘

相关推荐
ONE_SIX_MIX4 小时前
ubuntu 24.04 用rdp连接,桌面黑屏问题,解决
linux·运维·ubuntu
龙飞054 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
春日见4 小时前
如何创建一个PR
运维·开发语言·windows·git·docker·容器
DARLING Zero two♡4 小时前
告别 Docker 命令行!Portainer+cpolar 让容器管理从局域网走向公网
运维·docker·容器
消失的旧时光-19434 小时前
Linux 编辑器入门:nano 与 vim 的区别与选择指南
linux·运维·服务器
斯普信专业组4 小时前
构建基于MCP的MySQL智能运维平台:从开源服务端到交互式AI助手
运维·mysql·开源·mcp
liu****5 小时前
2.深入浅出理解虚拟化与容器化(含Docker实操全解析)
运维·c++·docker·容器·虚拟化技术
池央5 小时前
CANN 诊断工具链深度解析:oam-tools 的自动化故障信息收集、软硬件状态快照与 AI Core 错误溯源机制
运维·人工智能·自动化
云边有个稻草人6 小时前
打工人摸鱼新姿势!轻量斗地主服务器,内网穿透让同事远程联机不翻车
运维·服务器·cpolar
乾元6 小时前
终端安全(EDR):用深度学习识别未知勒索软件
运维·人工智能·网络协议·安全·网络安全·自动化·安全架构