相关文章推荐
从容的西瓜  ·  Spring RestTemplate ...·  12 月前    · 
忐忑的黑框眼镜  ·  libicui18n.so.52 ...·  1 年前    · 
风流的绿豆  ·  【IntelliJ ...·  1 年前    · 

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

13 人关注

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

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

在Debian 11上尝试使用docker v20.10.8和alpine:fresh。

Working solutions for 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

Edit 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

Question:

有什么办法可以从内部获得唯一的容器ID吗?(不需要依赖容器的主机名或者使用docker api来获取id)

3 个评论
你为什么需要它? 你能展示与之相关的示例应用程序代码吗? 除非重写,否则容器的主机名(8)将是容器的 ID,而且一些软件(特别是 RabbitMQ)使用该主机名来识别自己。
@DavidMaze 我有一个容器,它与docker api进行通信。它的工作之一是临时创建一个网络,并将其连接到自己和特定的容器之间。docker API需要容器的ID来连接网络和现有的容器。因此,我希望有一种可靠的方法来获取ID,即使主机名可能被改变。
这里你可以看到Jenkins的docker插件是如何寻找容器ID的,而不考虑cgroups版本。 github.com/jenkinsci/docker-workflow-plugin/pull/280/files
linux
docker
cgroups
jan-di
jan-di
发布于 2021-08-17
3 个回答
RichardH
RichardH
发布于 2021-09-09
已采纳
0 人赞同

替换代码0】的修复是有效的,但如果你不控制容器的创建,则无法使用。 此外,这个 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()

Credit goes to richgriswold: https://community.toradex.com/t/python-nullresource-error-when-running-torizoncore-builder-build/15240/4

ste
ste
发布于 2021-09-09
0 人赞同

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

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命令时,这就很好用了,但情况并不总是这样。对我来说,这在很多情况下解决了问题,但也许有人有办法在不使用docker命令的情况下做到这一点。
soxfmr
soxfmr
发布于 2021-09-09
0 人赞同

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

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

root@container:~# cat /proc/self/mountinfo | grep -i overlay