特权容器和能力

88

如果我在特权模式下运行一个容器,它是否具有所有内核功能或者我需要单独添加它们?

4个回答

93

在特权模式下运行确实使容器具备所有功能。但是最好的做法是始终给容器提供其所需的最小要求。

Docker run命令文档提到了此标志:

完整的容器能力 (--privileged)

--privileged标志赋予容器所有能力,并且还解除了设备cgroup控制器强制执行的所有限制。换句话说,容器几乎可以做主机能做的一切。这个标志存在是为了允许特殊用例,比如在 Docker 中运行 Docker。

您可以使用 --cap-add 标志来赋予特定的能力。有关这些功能的更多信息,请参见man 7 capabilities。可以使用文字名称,例如 --cap-add CAP_FOWNER


有没有办法找出一个特定应用程序需要哪些功能?对于大多数应用程序来说,这似乎是未记录的。 - codefx
@codefx 这里没有一条铁律,它取决于应用程序以及在运行时可能调用的系统调用。如果您使用来自 hub 的现成 docker 镜像,则很可能会在那里提到。如果您使用自己编写的东西,则应该知道您使用了哪些内核 API,这些 API 可能需要特殊的功能。 - buddy123
@buddy123,你有关于这个的文档参考吗?你的版本比我在Docker运行参考中找到的更有意义:“当操作员执行docker run --privileged时,Docker将启用对主机上所有设备的访问,并设置一些AppArmor或SELinux配置,以允许容器几乎具有与在主机上运行的容器外进程相同的访问权限。”它只是模糊地提到了“扩展特权”,而没有提到任何能力。 - Iain Samuel McLean Elder
@IainSamuelMcLeanElder 嗯,我的评论已经快7年了。当时引用的是docker文档中的原文,但在这段时间里已经多次更改了... :-) - buddy123
1
实际上,运行命令(而不是参考)有一个不同但重叠的页面。您的引用至今仍然存在:https://github.com/docker/cli/blob/c780f7c4abaf67034ecfaa0611e03695cf9e4a3e/docs/reference/commandline/run.md 我会编辑您的答案以链接到该页面。 - Iain Samuel McLean Elder

68

您永远不应该使用--privileged来运行容器。

我在我的笔记本电脑上进行此操作,它具有NVMe驱动器,但它适用于任何主机:

docker run --privileged -t -i --rm ubuntu:latest bash

首先,让我们做一些小事情,测试/proc文件系统。

从容器中:

root@507aeb767c7e:/# cat /proc/sys/vm/swappiness
60
root@507aeb767c7e:/# echo "61" > /proc/sys/vm/swappiness    
root@507aeb767c7e:/# cat /proc/sys/vm/swappiness
60

好的,它是针对容器还是主机进行更改的?
$ cat /proc/sys/vm/swappiness
61

抱歉!我们可以任意更改主机内核参数。但这只是DOS情况,请看看我们是否可以从父主机收集特权信息。
让我们遍历/sys树并找到启动盘的主次编号。
注意:我有两个NVMe驱动器,容器正在另一个驱动器上运行的LVM下。
root@507aeb767c7e:/proc# cat /sys/block/nvme1n1/dev
259:2

好的,在一个dbus规则不会自动扫描的位置创建设备文件:

root@507aeb767c7e:/proc# mknod /devnvme1n1 b 259 2
root@507aeb767c7e:/proc# sfdisk -d /devnvme1n1 
label: gpt
label-id: 1BE1DF1D-3523-4F22-B22A-29FEF19F019E
device: /devnvme1n1
unit: sectors
first-lba: 34
last-lba: 2000409230
<SNIP>

好的,我们可以读取启动磁盘,让我们为其中一个分区制作设备文件。虽然我们不能挂载它,因为它将是打开的,但我们仍然可以使用dd进行复制。

root@507aeb767c7e:/proc# mknod /devnvme1n1p1 b 259 3
root@507aeb767c7e:/# dd if=devnvme1n1p1 of=foo.img
532480+0 records in
532480+0 records out
272629760 bytes (273 MB, 260 MiB) copied, 0.74277 s, 367 MB/s

好的,让我们将其挂载并查看我们的努力是否奏效!

root@507aeb767c7e:/# mount -o loop foo.img /foo
root@507aeb767c7e:/# ls foo
EFI
root@507aeb767c7e:/# ls foo/EFI/
Boot  Microsoft  ubuntu

基本上,任何您允许任何人在其中启动--privileged容器的容器主机都等同于将根访问权限授予该主机上每个容器的用户。
不幸的是,Docker项目选择了可信计算模型,在认证插件之外,没有办法保护自己免受此类攻击,因此始终优先考虑添加所需功能而不是使用--privileged

5

这里有一篇来自RedHat的好文章,涵盖了相关内容。

尽管 Docker 容器运行时以“root”身份比主机上的 root 权限少,但根据您的用例(作为开发环境使用还是共享生产集群),它仍然可能需要加固。


1

与其改变swappiness,您可以将相同的值写入其中,并检查返回的结果:

非特权docker:

root@8191892d9f7f:/# cat /proc/sys/vm/swappiness
20
root@8191892d9f7f:/# echo 20 >  /proc/sys/vm/swappiness
bash: /proc/sys/vm/swappiness: Read-only file system

特权 Docker:

root@7c6c0a793ca0:/# cat /proc/sys/vm/swappiness
20
root@7c6c0a793ca0:/# echo 20 >  /proc/sys/vm/swappiness
root@7c6c0a793ca0:/#

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接