关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

怎么对docker容器中的用户进行隔离

发布时间:2021-04-06 19:34:08

如何在docker容器中隔离用户?针对这个问题,本文详细介绍了相应的分析和解决方法,希望能帮助更多想解决这个问题的伙伴找到更简单易行的方法。

User  namespace  的用户映射

在配置docker守护程序以启用用户名称空间之前,我需要了解一些关于从属用户/组和重新映射的概念。下属用户和组的映射由两个配置文件控制,即/etc/sub  id和/etc/sub  id。查看它们的默认内容:在配置docker守护程序以启用用户命名空间之前,我需要了解一些关于从属用户/组和重新映射的概念:

怎么对docker容器中的用户进行隔离

对于subuid,这一行记录的含义是:

用户nick在当前用户命名空间中有65536个下级用户,用户ID为100000-165535。在子用户命名空间中,这些从属用户映射到ID为0-65535的用户。sub  id和sub  id的意思一样。

例如,用户nick只是一个在主机上拥有普通权限的用户。我们可以将他的一个下属ID(例如100000)分配给容器所属的用户命名空间,并将ID  100000映射到用户命名空间中的uid  0。此时,即使容器中的进程具有根权限,它也只在容器所在的用户命名空间中。一旦你到了主机,你最多有nick用户权限。

当docker支持用户命名空间(docker的userns-remap函数)时,我们可以指定不同的用户映射到容器。例如,我们专门创建了一个用户dockeruser,然后手动设置其sub  id和sub  id:

镍:100000336065536

码头工人用户:165536336065536,并将其分配给码头工人守护程序:

{

userns-remap':'dockeruser  '

}请注意subuID的设置信息。我们为码头工人设置的下属标识与尼克用户不重叠。事实上,任何用户的从属id设置都不能重叠。

或者保持一切简单,让docker为我们做这些繁琐的事情,直接把docker守护进程的userns-rempa参数指定为‘default’:

{

userns-remap': '默认'

}此时,docker将自动完成其他配置。

配置 docker  daemon  启用用户隔离

这里,我用一个简单的方法让docker为用户命名空间创建一个默认用户。我们需要首先创建/etc/docker/daemon.json文件:

$ sudotouch/etc/docker/daemon  . JSON然后编辑其内容如下(如果文件已经存在,只需添加以下配置项),并重新启动docker服务:

{

userns-remap': '默认'

} $ sudosystemctlrestardocker  . service我们来验证一下关于用户隔离的几点。

首先,验证docker是否创建了名为dockremap的用户:

怎么对docker容器中的用户进行隔离

然后检查新用户dockremap相关项目是否添加到/etc/sub  id和/etc/sub  id文件中:

怎么对docker容器中的用户进行隔离

接下来,我们发现在/var/lib/docker目录下创建了一个新目录:165533.165536。检查此目录的权限:

lt="怎么对docker容器中的用户进行隔离">

165536 是由用户 dockremap 映射出来的一个 uid。查看 165536.165536 目录的内容:

怎么对docker容器中的用户进行隔离

与 /var/lib/docker 目录下的内容基本一致,说明启用用户隔离后文件相关的内容都会放在新建的 165536.165536 目录下。

通过上面的检查,我们可以确认 docker daemon 已经启用了用户隔离的功能。

宿主机中的 uid 与容器中 uid

在 docker daemon 启用了用户隔离的功能后,让我们看看宿主机中的 uid 与容器中 uid 的变化。

$dockerrun-d--namesleepmeubuntusleepinfinity

怎么对docker容器中的用户进行隔离

uid 165536 是用户 dockremap 的一个从属 ID,在宿主机中并没有什么特殊权限。然而容器中的用户却是 root,这样的结果看上去很完美:

怎么对docker容器中的用户进行隔离

新创建的容器会创建 user namespace

在 docker daemon 启用用户隔离的功能前,新创建的容器进程和宿主机上的进程在相同的 user namespace 中。也就是说 docker 并没有为容器创建新的 user namespace:

怎么对docker容器中的用户进行隔离

上图中的容器进程 sleep 和宿主机上的进程在相同的 user namespace 中(没有开启用户隔离功能的场景)。

在 docker daemon 启用用户隔离的功能后,让我们查看容器中进程的 user namespace:

怎么对docker容器中的用户进行隔离

上图中的 4404 就是我们刚启动的容器中 sleep 进程的 PID。可以看出,docker 为容器创建了新的 user namespace。在这个 user namespace 中,容器中的用户 root 就是天神,拥有至高无上的权力!

访问数据卷中的文件

我们可以通过访问数据卷中的文件来证明容器中 root 用户究竟具有什么样的权限?创建四个文件,分别属于用户 root 、165536 和 nick。rootfile 只有 root 用户可以读写,用户 nick 具有 nickfile 的读写权限,uid 165536 具有文件 165536file 的读写权限,任何用户都可以读写 testfile 文件:

怎么对docker容器中的用户进行隔离

下面把这几个文件以数据卷的方式挂载到容器中,并检查从容器中访问它们的权限:

$dockerrun-it--nametest-w=/testv-v$(pwd)/testv:/testvubuntu

怎么对docker容器中的用户进行隔离

容器中的 root 用户只能访问 165536file 和 testfile,说明这个用户在宿主机中只有非常有限的权限。

在容器中禁用 user namespace

一旦为 docker daemon 设置了 "userns-remap" 参数,所有的容器默认都会启用用户隔离的功能(默认创建一个新的 user namespace)。有些情况下我们可能需要回到没有开启用户隔离的场景,这时可以通过 --userns=host 参数为单个的容器禁用用户隔离功能。--userns=host 参数主要给下面三个命令使用:

dockercontainercreate
dockercontainerrun
dockercontainerexec

比如执行下的命令:

$dockerrun-d--userns=host--namesleepmeubuntusleepinfinity

查看进程信息:

怎么对docker容器中的用户进行隔离

进程的有效用户又成 root 了,并且也没有为进程创建新的 user namespace:

怎么对docker容器中的用户进行隔离

已知问题

User namespace 属于比较高级的功能,目前 docker 对它的支持还算不上完美,下面是已知的几个和现有功能不兼容的问题:

  • 共享主机的 PID 或 NET namespace(--pid=host or --network=host)

  • 外部的存储、数据卷驱动可能不兼容、不支持 user namespace

  • 使用 --privileged 而不指定 --userns=host

总结

Docker 是支持 user namespace 的,并且配置的方式也非常简便。在开启 user namespace 之后我们享受到了安全性的提升,但同时也会因为种种限制让其它的个别功能出现问题。这时我们需要作出选择,告别一刀切的决策,让合适的功能出现的合适的场景中。

关于怎么对docker容器中的用户进行隔离问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注微子网络行业资讯频道了解更多相关知识。


/template/Home/Zkeys/PC/Static