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) → 只有普通用户权限 │ │
    │ └──────────────────────────────────────────────────┘ │
    └─────────────────────────────────────────────────────────┘

相关推荐
Bert.Cai21 分钟前
Linux let命令详解
linux·运维·服务器
枕星而眠24 分钟前
Linux 线程:原理、属性、实战与面试避坑
linux·运维·c语言·面试
晚风予卿云月29 分钟前
【Linux】环境变量概念、作用、配置与修改详解
linux·运维·服务器·环境变量
~黄夫人~1 小时前
零基础速通|Windows&Linux 常用命令行对照表大全
linux·运维·windows·笔记·备忘录·整理表格
benjiangliu1 小时前
LINUX系统-17-EXT系列文件系统(二)
linux·运维·服务器
杨云龙UP1 小时前
Linux 根分区被日志吃满?一次 58G Broker 日志清理实战_2026-05-20
linux·运维·服务器·数据库·hdfs·apache
热金鼠1 小时前
Ubuntu 22.04 Docker 完整使用手册(2)
docker
络合白泽1 小时前
Debian 13 + NVIDIA Optimus 笔记本:从零配置 Wayland Explicit Sync 完整指南
运维·debian
珠海西格电力1 小时前
零碳园区的碳排放指标计算的实操步骤
大数据·运维·人工智能·物联网·能源
叶半欲缺1 小时前
Linux通过lvm扩容根目录
linux·运维·服务器