15

As Docker supports cgroup v2 since engine version 20.10, it will automatically use it on distributions that have cgroups v2 enabled. The known solutions to get the unique container ID from within the container, do not work anymore.

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

/ # cat /proc/1/cpuset
/

Tried with docker v20.10.8 on Debian 11 with alpine:latest.

Working solutions for cgroup v1: How can I get Docker Linux container information from within the container itself?

As stated in the docker reference, with cgroup v2, the container id is still visible in the filesystem at the following places, but those aren't accessible from the container itself.

/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:

One Workaround is to run the container with the option --cgroupns host. But that requires control over the creation of the container.

$ 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::/

Question:

Is there any way, to get the unique container id from within? (without relying on the container hostname or having to use the docker api to fetch the id)

jan-di
  • 755
  • 7
  • 16
  • Why do you need it? Can you show sample application code where it's relevant? Unless overridden the hostname(8) of the container will be the container ID, and some software (notably RabbitMQ) uses that hostname to identify itself. – David Maze Aug 17 '21 at 12:24
  • @DavidMaze I have a container, that communicates with the docker api. One part of its job is to temporarily create a network and connect it between itself and specific containers. The docker API needs the container ID to connect a network to an extisting container. Therefore I want a reliable way of getting the ID, even if the hostname is possibly changed. – jan-di Aug 17 '21 at 15:10
  • Here you can see what the Jenkins docker plugin does to find the container ID regardless of cgroups version: https://github.com/jenkinsci/docker-workflow-plugin/pull/280/files – Simon Oelerich Oct 25 '22 at 13:10

5 Answers5

11

The --cgroupns host fix is effective, but not available if you don't control the container's creation. Further, this docker run option is not available in the API or docker compose (https://github.com/compose-spec/compose-spec/issues/148).

But... good news - the container ID is still exposed via /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

Here's a Python snippet that'll parse it:

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

RichardH
  • 251
  • 2
  • 4
2

This seems to work without the need to query to cgroup and without using the value of hostname, which sometimes is not set to the value of container id, for example in gitlab runners with docker executors.

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

Thanks @soxfmr and to this How do I identify which container owns which overlay directory?

ste
  • 1,479
  • 10
  • 19
  • This works great when you have access to the docker command from inside the container which is not always the case. For me it solves the problem in very many cases, but maybe someone has an idea how to do it without using the docker command. – Simon Oelerich Jan 14 '22 at 11:28
1

run this command inside the container :

cat /proc/self/mountinfo | grep "/docker/containers/" | head -1 | awk '{print $4}' | sed 's/\/var\/lib\/docker\/containers\///g' | sed 's/\/resolv.conf//g'
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 27 '23 at 17:07
0

I have encountered the same problem while trying to fetch the container identification from cgroup.

But there is another way to achieve the same goal. Docker containers are rely on OverlayFS storage driver, each container will be assigned an unqiue directory which is mapped to a virtual filesystem where the container files are written.

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

as the command result has shown above, upperdir=/var/lib/docker/overlay2/76c8877e95fa589df1fb97bf831ec221df130fdfb8f1f1cb8166bd99bebf51de/diff locates in host machine and it serves only one container that it is allocated to.

Notice that OverlayFS could be replace to any driver that implement the speicification of storage driver, but upperdir information remains the same structure.

Make sure that the decision must take inside the container since the host machine would show up OverlayFS mount information if LXC is delopyed on the host machine.

soxfmr
  • 58
  • 7
  • But the ID of the overlayFS mount point is not the same as the container ID. I can see via `docker inspect` that the overlay ID is indeed the one associated with that container, but how can I get the container ID via the overlay ID inside the container, without access to the host? – jan-di Sep 09 '21 at 15:34
  • @jan-di The ID of OverlayFS is different on each container, so it can be used to indentify the container instead of ID that retrives from `/proc/self/cgroup`. You could refer to [machineid](https://github.com/soxfmr/machineid/blob/master/id_linux.go#L129) for more details. But if you want to get the ID excatly assgined to the container by Docker, you may need to find another way. – soxfmr Sep 10 '21 at 03:15
0

You could also get the systemmd using:

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

from outside the Docker container, will be:

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

And the output will be just the UUID, for example, 7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a.

juanbretti
  • 418
  • 8
  • 9