当前位置: 首页 > 知识库问答 >
问题:

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

张炳
2023-03-14

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

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

/ # cat /proc/1/cpuset
/

尝试与docker v20.10.8在Debian 11与阿尔卑斯山:最新。

cgroup v1的工作解决方案:如何从容器本身中获取DockerLinux容器信息?

正如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-给定容器的-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)

共有3个答案

王杰
2023-03-14

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

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

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装载信息。

陆昊
2023-03-14

--cgroupns主机修复程序有效,但如果不控制容器的创建,则不可用。此外,此docker run选项在API或docker compose中不可用(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

寿阳华
2023-03-14

这似乎不需要查询cgroup,也不需要使用hostname的值,hostname有时没有设置为容器id的值,例如在带有docker执行器的gitlab Runner中。

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,我如何识别哪个容器拥有哪个覆盖目录?

 类似资料:
  • 问题内容: 从容器名称获取docker容器ID的命令是什么? 问题答案: 在Linux中: 或在OS X,Windows中: 您的容器名称在哪里。 如@llia Sidorenko所述,为避免产生误报,您可以使用正则表达式锚点,如下所示: 说明: 为了安静。仅输出ID 对所有人。即使您的容器未运行也能正常工作 用于过滤器。 容器名称必须以该字符串 开头 容器名称必须 结束 这个字符串

  • 从容器名称中获取Docker容器id的命令是什么?

  • 问题内容: 我想了解它们的配置,就像通过元数据获取有关EC2实例的信息一样。 我可以使用(假设正在侦听port ) 来获取它的一些数据,但是想知道是否有更好的方法,至少获取容器的完整ID,因为实际上缩短到了12个字符,而docker似乎对其执行了“最佳匹配”。 另外,如何获取docker主机的外部IP(除了访问EC2元数据(特定于AWS)之外) 问题答案: 我发现可以在/ proc / self

  • 我想让我的知道它们的配置,就像您可以通过元数据获得EC2实例的信息一样。 我可以使用(提供正在监听端口) 获取它的一些数据,但想知道是否有更好的方法,至少是获取容器的完整ID,因为实际上缩短为12个字符,docker似乎对其执行“最佳匹配”。 另外,如何获取docker主机的外部IP(除了访问特定于AWS的EC2元数据之外)

  • 如何使用PHP在容器本身中获取Docker容器ID? 我刚刚发现linux命令如下:

  • 要获取节点版本-我希望运行以下内容: 我正在和docker一起运行以下程序: 我明白了: 我的问题是:如何从docker容器中获取节点的版本?