Get a container's full id from inside of itself

Hello,

For a project, I absolutely need to know a container’s full id from inside of itself (without executing any command on the host). Is there any way to get this information?

For information, this is the function which I use from the host to get this information, which is obviously unusable from inside of a container.

function docker_full_id(){
  docker inspect $(docker ps | grep "$1" | awk '{print $1}') | grep '"Id":' | awk '{print $2}' | tr --delete '"' | tr --delete ','
}

Many thanks !

Regards

Well, it seems that I already found the solution !
I simply have to run the following command from inside a container

cat /proc/self/cgroup | head -1 | tr --delete ‘10:memory:/docker/’

Best regards

Try
cat /proc/self/cgroup | grep -o -e “docker-..scope" | head -n 1 | sed "s/docker-(.).scope/\1/”

head -1 /proc/self/cgroup|cut -d/ -f3

3 Likes

is there a bash command for getting the container name instead of the id inside docker?

export containerid=$(cat /proc/self/cgroup | head -n 1 | tr ‘/’ ‘\n’ | tail -1 | cut -c1-12) >/dev/null 2>&1 || :

This doesn’t work for me:

ohnobinki@gibby ~ $ docker exec -it sharp_albattani cat /proc/self/cgroup
10:perf_event:/
9:net_cls:/
8:freezer:/
7:devices:/
6:memory:/
5:blkio:/
4:cpuacct:/
3:cpu:/
2:cpuset:/
1:name=openrc:/sshd
0::/sshd
ohnobinki@gibby ~ $

I’m using rootless.

Is there a method that works everywhere—even in rootless?

I have been using the /proc/self/cgroup file to get the container id.
But when I upgraded to Docker 4.3.1, that file only contains: 0::/

$ cat /proc/self/cgroup
0::/

My program was working correctly with Docker Desktop 4.2.0, but with 4.3.1 it is not.
Is this a bug in 4.3.1 or do I need to change how I get the container id ?

The release notes for version 4.3.0 include:

Docker Desktop now uses cgroupv2 . If you need to run systemd in a container then:

​When I add ‘–cgroupns=host’, to my docker command then the /proc/self/cgroup file has what I need.
Since that is not the case by default, is there some other (more reliable) way to get the ID from inside the container ?

If you can change the parameters of docker run or the alternative command, you can do this:

docker run --rm -it --hostname bash --cidfile containerid -v $PWD/containerid:/containerid bash

then

cat /containerid

If you don’t change the hostname, then the default hostname is the short version of the container id.

Thanks!

Knowing about the --cidfile arg is helpful.

And knowing that “If you don’t change the hostname, then the default hostname is the short version of the container id.” is very helpful.

Sometimes I have a tiny lag between when a file is written to a mounted directory inside/outside the container and when I can read it from the other side. I worry that (some of the time) my program inside the container would look for the file before it could see it, because of this delay.

A simple test image with curl (based on Nathan LeClair’s post)

echo 'FROM alpine' > addCurl.dockerfile
echo 'RUN apk add --update curl' >> addCurl.dockerfile
docker build -f ./addCurl.dockerfile -t curltest .

For my purposes, this seems to work:

docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  curltest /bin/sh

# And then inside the container:
echo $HOSTNAME
# 9e17ce753e96
curl --unix-socket /var/run/docker.sock http:/v1.38/containers/${HOSTNAME}/json
# {"Id":"9e17ce753e9677b8b255ccaea1c0bd0d8abf8f3ee5e909b4957e628ebbb16c09",
# ...

This has the downsides of:

  • needing to map in the docker sock,
  • the container must have curl,
  • you still have to extract it from the json string.
  • If the value of $HOSTNAME is set with --hostname then this does not work.

An alternative to using $HOSTNAME is to assign the container a name. I haven’t found a way to access that value internally, but I can pass it as an environment variable.

DNAME=$(date +%Y_%m_%d_%H_%M_%S)
docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --name $DNAME -e DNAME=$DNAME \
  curltest /bin/sh

# And then inside the container:
curl --unix-socket /var/run/docker.sock http:/v1.38/containers/${DNAME}/json

Without any id, I can get the info for all docker containers; so IF you have a way to figure out which container is the right one, then you don’t even need the hostname.

docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  curltest /bin/sh
#
curl --unix-socket /var/run/docker.sock http:/v1.38/containers/json

It seems you know how the docker API works so you could create a web service which could return the ID based on from which IP address (on the docker network) you send the request. You don’t need curl for this on an HTTP port. Bash has a builtin feature to send HTTP requests.

exec 3<>/dev/tcp/yourdomain.tld/80
echo -e "GET / HTTP/1.1\r\nHost: yourdomain.tld\r\nConnection: close\r\n\r\n" >&3
cat <&3

The response will contain the HTTP header so you would have to get the last line of the response if that is the ID.

exec 3<>/dev/tcp/yourdomain.tld/80
echo -e "GET / HTTP/1.1\r\nHost: yourdomain.tld\r\nConnection: close\r\n\r\n" >&3
cat <&3 | tail -n1

In this case only one container would need to access the docker socket.

1 Like