Docker中使用userns-remap做用户命名空间

使用普通用户运行docker容器

在docker中,在容器内创建的文件在从主机检查时往往具有不可预测的所有权。默认情况下,卷上文件的所有者是root(uid 0),但只要非root用户帐户涉及容器并写入文件系统,所有者就会从主机角度变得或多或少随机 。
您需要使用调用docker命令的同一用户帐户从主机访问卷数据时,这是一个问题.
典型的解决方法是

  • 在Dockerfiles中创建时强制用户uID(非可移植)
  • 将主机用户的UID作为环境变量传递给docker run命令,然后在入口点脚本中的卷上运行一些chown 命令 .

这两种解决方案都可以控制容器外的实际权限.
用户命名空间( user namespace)是这个问题的最终解决方案.
通过 user namespace 技术,把宿主机中的一个普通用户(只有普通权限的用户)映射到容器中的 root 用户。在容器中,该用户在自己的 user namespace 中认为自己就是 root,也具有 root 的各种权限,但是对于宿主机上的资源,它只有很有限的访问权限(普通用户)。

使用user namespace进行权限隔离设置如下:

1、kernel内核开启namespace

grubby --args="namespace.unpriv_enable=1 user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
echo "user.max_user_namespaces=15076" >> /etc/sysctl.conf

重启系统生效

reboot

2、新建用户(这里的用户名为:dku)

useradd -u 5000 dku
groupadd -g 500000 dku-root
useradd -u 500000 -g dku-root dku-root

在/etc/subuid 和 /etc/subgid 文件中修改自动生成的从属ID范围:
dku:500000:65536
如果这两个文件有内容,就可以执行以下sed命令进行修改,没内容手动添加进入即可。

sed -ri '/dku/s/:[0-9]+:/:500000:/' /etc/subuid
sed -ri '/dku/s/:[0-9]+:/:500000:/' /etc/subgid

用户dku 在当前的 user namespace 中具有 65536 个从属用户,用户 ID 为 500000-565535,在一个子 user namespace 中,这些从属用户被映射成 ID 为 0-65535 的用户。subgid 的含义和 subuid 相同。

3、使用docker权限映射(注意:使用映射代表容器root用户映射到宿主机docker指定的用户uid上)

这里有3步:
(1)在/etc/default/docker上追加配置DOCKER_OPTS
(2)修改 /usr/lib/systemd/system/docker.service 启动文件,在ExecStart前添加 EnvironmentFile变量文件
(3)修改 /usr/lib/systemd/system/docker.service 启动文件中的ExecStart,最后添加$DOCKER_OPTS

echo 'DOCKER_OPTS="--userns-remap=dku"' >> /etc/default/docker
sed -i '/ExecStart/iEnvironmentFile=/etc/default/docker' /usr/lib/systemd/system/docker.service
sed -i 's/ExecStart.*/& $DOCKER_OPTS/'  /usr/lib/systemd/system/docker.service

重新启动docker:

systemctl daemon-reload
systemctl restart docker.service

4、访问数据卷中的文件

假如,在容器里面创建一个 UID 为1000 的 test 用户,他能读取挂载在容器里面的什么权限的文件呢?
测试文件权限:在系统的 /data/test 目录上,创建几个不同的测试文件
1. 一个属主和属组都为 501000 的文件,权限为600,文件名为:501000.txt 。
3. 一个属主和属组都为 dku-root (UID为500000)的文件,权限为600,文件名为:dku-root.txt 。
4. 一个在系统上权限为 root (UID为0)的文件,权限为600,文件名为:root.txt 。
5. 一个在系统上权限为 root (UID为0)的文件,权限为666,文件名为:test.txt 。

在这里插入图片描述
6.启动一个centos 7.9 的容器,并在里面创建一个 UID 为 1000 的test 用户,进入挂载的 /test 目录。
查看权限如下:
在这里插入图片描述
结果是只有 501000.txt 和 test.txt 这两个文件可以看到里面内容。剩下两个均没有权限。其中501000.txt 有权限,是因为在系统上这个文件的属主和属组都是 501000,其映射在容器里面的属主和属组就是1000,所以UID 为 1000 的 test 用户可以查看里面的内容。
test.txt 能查看,因为文件的权限是666,other 位的权限是 rw,所以其他用户都有权限查看。

所以要给容器里面挂载一个有root 权限的目录,在系统上就需要给这个目录 权限给dku-root。比如要挂载的目录是 /data,那命令就是命令如下:

chown -R dku-root:dku-root /data

5、宿主机的进程 UID 和 容器的 UID

当启动了user namespace 后,容器里面的进程是怎样的呢?指定root 用户启动一个 centos 7.9 的容器,里面执 sleep 1000 命令。
在这里插入图片描述
在系统中查看该sleep 1000 的进程属主时发现不是 root,而是定义的UID 为 500000 的 dku-root 用户。
在这里插入图片描述
有没有办法可以在启动 user namespace 情况下,里面的进行又想恢复 root 运行呢?也是有的。

6、在容器中禁用 user namespace

一旦为docker daemon设置了"userns-remap"参数,所有的容器默认都会启用用户隔离的功能(默认创建一个新的 user namespace)。有些情况下我们可能需要回到没有开启用户隔离的场景,,这时可以通过--userns=host参数为单个的容器禁用用户隔离功能。在version: "3"版本的docker-compose.yml文件中对应的容器增加userns_mode: "host"

以同样的 sleep 1000 为例子,启动的时候加上--userns=host
在这里插入图片描述
在系统中,查看 sleep 1000 进程时,进程的属主恢复为 root。
在这里插入图片描述

参考地址:https://www.shuzhiduo.com/A/ZOJPrrrxdv/

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值