linux 如何使用cgroup v2从容器中获取Docker容器ID

flmtquvp  于 2023-01-29  发布在  Linux
关注(0)|答案(4)|浏览(235)

由于Docker从引擎版本20.10开始支持cgroupv2,它将自动在启用cgroupv2的发行版上使用它。已知的从容器中获取唯一容器ID的解决方案不再有效。

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

/ # cat /proc/1/cpuset
/

尝试在Debian 11上使用docker v20.10.8和alpine:最新版本。
cgroup v1的工作溶液:How can I get Docker Linux container information from within the container itself?
如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)

91zkwejq

91zkwejq1#

--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()

这要归功于里奇格里斯沃尔德:https://community.toradex.com/t/python-nullresource-error-when-running-torizoncore-builder-build/15240/4

b4qexyjb

b4qexyjb2#

这看起来不需要查询cgroup,也不需要使用hostname的值,hostname有时候没有设置为container id的值,例如在gitlab runner中使用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和这个How do I identify which container owns which overlay directory?

nuypyhwy

nuypyhwy3#

我在尝试从cgroup获取容器标识时遇到了同样的问题。
但是还有另外一种方法可以达到同样的目的,Docker容器依赖于OverlayFS存储驱动程序,每个容器都被分配一个unque目录,该目录Map到一个虚拟文件系统,容器文件被写入其中。

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位于主机中,并且只服务于它被分配到的一个container。
注意,OverlayFS可以替换为任何实现存储驱动程序规范的驱动程序,但upperdir信息保持相同的结构。
请确保必须在容器内部做出决定,因为如果在主机上开发LXC,主机将显示OverlayFS装载信息。

pprl5pva

pprl5pva4#

您还可以使用以下命令获得systemmd

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

从Docker集装箱外,将:

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

输出将只是UUID,例如7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a

相关问题