使用用户命名空间重映射避免 Docker 目录挂载权限为 root

540 阅读3分钟

前言

在 Docker 中,默认情况下,容器内运行的进程以 root 用户身份运行,这可能会带来安全隐患。如果将容器的目录挂载到宿主机,容器内创建的文件将归属于宿主机上的 root 用户。本文将介绍如何通过用户命名空间重映射(User Namespaces Remapping)来解决这个问题,使得容器内的 root 用户映射为宿主机上的非特权用户。

步骤

1. 永久修改内核参数

首先,需要确保内核允许创建足够的用户命名空间。默认情况下,user.max_user_namespaces 参数可能为 0,需要将其修改为较大的值,例如 10000

临时修改内核参数

sudo sysctl -w user.max_user_namespaces=10000

永久修改内核参数

将该参数写入 /etc/sysctl.conf 文件,以确保在系统重启后设置依然生效:

echo "user.max_user_namespaces=10000" | sudo tee -a /etc/sysctl.conf

重新加载 sysctl 配置

sudo sysctl -p

2. 设置 /etc/subuid/etc/subgid 文件

接下来,需要配置子用户和子用户组。假设我们创建了一个用户 lbs,并且其 UID 和 GID 均为 1001。可以使用以下命令确认用户的 UID 和 GID:

id lbs

输出应类似于:

uid=1001(lbs) gid=1001(lbs) groups=1001(lbs),27(sudo),999(docker)

配置 /etc/subuid 文件

sudo nano /etc/subuid

添加以下内容:

lbs:1001:1
lbs:100000:65536

配置 /etc/subgid 文件

sudo nano /etc/subgid

添加以下内容:

lbs:1001:1
lbs:100000:65536

3. 配置 /etc/docker/daemon.json 文件

编辑 Docker 守护进程配置文件 /etc/docker/daemon.json,启用用户命名空间重映射:

sudo nano /etc/docker/daemon.json

添加以下内容:

{
    "userns-remap": "lbs"
}

4. 重启 Docker 并启动容器验证

重启 Docker 服务

sudo systemctl restart docker

确认目录权限

确保挂载目录的权限正确:

sudo chown -R lbs:lbs /home/lbs/data

重新尝试运行容器

切换到 lbs 用户并重新运行容器:

su lbs
cd ~
docker run -it --rm \
    -v $PWD/data:/data \
    bash:5.0 \
    touch /data/lbs_with_subuid

检查文件权限

ls -l data

输出应类似于:

-rw-r--r-- 1 lbs lbs 0 0 00:00 lbs_with_subuid

限制

但这个方案会有一些限制:

  • 不可使用 --pid=host 或 --network=host
  • 不可使用无法识别或使用用户映射的挂载磁盘。
  • 若使用 docker run --privileged 则必须同时使用 --userns=host

总结

通过以上步骤,我们成功地配置了 Docker 的用户命名空间重映射,使得容器内的 root 用户被映射为宿主机上的非特权用户 lbs。这样在挂载目录中创建的文件将归属于 lbs 用户,而不是 root 用户,从而提高了系统的安全性和方便性。

这种方法特别适用于需要在多用户环境中运行 Docker 容器的场景,可以有效避免由于目录挂载权限导致的安全问题。如果还有其他问题或需要进一步配置,请参考 Docker 官方文档或联系系统管理员。

参考文章:geofftools.cn/blog/mount-…