如何从cgroup v2的容器内获取docker容器ID



由于Docker从引擎版本20.10开始支持cgroup v2,它将自动在启用了cgroups v2的发行版上使用它。从容器内获取唯一容器ID的已知解决方案不再工作。

/ # cat /proc/self/cgroup
0::/
/ # cat /proc/1/cpuset
/

在Debian 11上使用docker v20.10.8与alpine:latest.

cgroup v1的工作解决方案:我如何从容器本身内获得Docker Linux容器信息?

正如docker参考中所述,在cgroup v2中,容器id在文件系统中的以下位置仍然可见,但这些位置不能从容器本身访问。

/sys/fs/cgroup/memory/docker/<longid>/ on cgroup v1, cgroupfs driver
/sys/fs/cgroup/memory/system.slice/docker-<longid>.scope/ on cgroup v1, systemd driver
/sys/fs/cgroup/docker/<longid/> on cgroup v2, cgroupfs driver
/sys/fs/cgroup/system.slice/docker-<longid>.scope/ on cgroup v2, systemd driver

https://docs.docker.com/config/containers/runmetrics/find-the-cgroup-for-a-given-container

编辑1/2021-09-01:

一种解决方法是使用选项--cgroupns host运行容器。但是这需要控制容器的创建。

$ docker run -it --cgroupns host alpine cat /proc/self/cgroup
0::/system.slice/docker-09ec67119d38768dbf7994d81c325e2267214428a3c2e581c81557e3650863d8.scope
$ docker run -it alpine cat /proc/self/cgroup
0::/

问题:

是否有任何方法,从内部获得唯一的容器id ?(不依赖于容器主机名或必须使用docker API来获取id)

--cgroupns host修复是有效的,但如果不控制容器的创建则不可用。此外,这个docker run选项在API或docker组合(https://github.com/compose-spec/compose-spec/issues/148)中不可用。

但是…好消息-容器ID仍然通过/proc/self/mountinfo:

暴露
678 655 254:1 /docker/containers/7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw
679 655 254:1 /docker/containers/7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a/hostname /etc/hostname rw,relatime - ext4 /dev/vda1 rw
680 655 254:1 /docker/containers/7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a/hosts /etc/hosts rw,relatime - ext4 /dev/vda1 rw

下面是解析它的Python代码片段:

with open( '/proc/self/mountinfo' ) as file:
line = file.readline().strip()    
while line:
if '/docker/containers/' in line:
containerID = line.split('/docker/containers/')[-1]     # Take only text to the right
containerID = containerID.split('/')[0]                 # Take only text to the left
break
line = file.readline().strip()

功劳归richgriswold: https://community.toradex.com/t/python-nullresource-error-when-running-torizoncore-builder-build/15240/4

这似乎不需要查询cgroup,也不使用主机名的值,有时不设置为容器id的值,例如在gitlab运行器与docker执行器

OVERLAY_ID=`cat /proc/self/mountinfo | grep -i overlay | sed -n "s/.+upperdir\=\(.+\)\/diff.+/1/p"`
CONTAINER_ID=`docker inspect -f $'{{.ID}}t{{.Name}}t{{.GraphDriver.Data.MergedDir}}' $(docker ps -aq) | grep $OVERLAY_ID | sed -n "s/t+.+//p"`
echo $CONTAINER_ID

感谢@soxfmr,我如何识别哪个容器拥有哪个覆盖目录?

在容器内运行此命令:

cat /proc/self/mountinfo | grep "/docker/containers/" | head -1 | awk '{print $4}' | sed 's//var/lib/docker/containers///g' | sed 's//resolv.conf//g'

我在试图从cgroup获取容器标识时遇到了同样的问题。

但是还有另一种方法可以达到同样的目的。Docker容器依赖于OverlayFS存储驱动程序,每个容器将被分配一个唯一的目录,该目录映射到一个虚拟文件系统,容器文件被写入。

root@container:~# cat /proc/self/mountinfo | grep -i overlay
767 553 0:187 / / rw,relatime master:167 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/ZTHS22AHCPD2HJEY6UIKIO3BHY:/var/lib/docker/overlay2/l/4P6QELQ6532G5362S5VVTA7Y7K,upperdir=/var/lib/docker/overlay2/76c8877e95fa589df1fb97bf831ec221df130fdfb8f1f1cb8166bd99bebf51de/diff,workdir=/var/lib/docker/overlay2/76c8877e95fa589df1fb97bf831ec221df130fdfb8f1f1cb8166bd99bebf51de/work

如上面所示的命令结果,upperdir=/var/lib/docker/overlay2/76c8877e95fa589df1fb97bf831ec221df130fdfb8f1f1cb8166bd99bebf51de/diff位于主机上,它只服务于分配给它的一个容器。

请注意,OverlayFS可以被替换为任何实现存储驱动规范的驱动程序,但upperdir信息保持相同的结构。

确保决策必须在容器内进行,因为如果在主机上部署了LXC,那么主机将显示OverlayFS挂载信息。

您也可以使用:

获取systemmd
grep 'systemd' /proc/self/mountinfo|cut -d/ -f3 

从Docker容器外部,将是:

docker run -it alpine grep 'systemd' /proc/self/mountinfo|cut -d/ -f3

输出将只是UUID,例如:7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a.

最新更新