224

I would like to make my docker containers aware of their configuration, the same way you can get information about EC2 instances through metadata.

I can use (provided docker is listening on port 4243)

curl http://172.17.42.1:4243/containers/$HOSTNAME/json 

to get some of its data, but would like to know if there is a better way at least the get the full ID of the container, because HOSTNAME is actually shortened to 12 characters and docker seems to perform a "best match" on it.

Also, how can I get the external IP of the docker host (other than accessing the EC2 metadata, which is specific to AWS)

4
  • 4
    BEWARE: you should read this lvh.io/posts/… before attempting any of the approaches below that attempt to use /var/run/docker.sock inside the container Commented Oct 19, 2017 at 16:04
  • 9
    In case @harschware's link breaks, I'll summarise here: By giving the container access to /var/run/docker.sock, it is possible (trivial) to break out of the containment provided by docker and gain access to the host machine. Obviously this is potentially dangerous. Commented Jan 12, 2018 at 2:44
  • 1
    Does anyone know how to get the same information in a windows docker container if the --hostname argument was used with the run command so that simply running 'hostname' no longer gives you the containerid? Commented May 15, 2019 at 16:05
  • Exposing docker daemon api to containers is a very bad approach in terms of security. Because compromised container can access docker and do anything it wants. There should be some separate API for non private info fetching only. Commented Nov 14, 2020 at 16:41

16 Answers 16

131

Unless overridden, the hostname seems to be the short container id in Docker 1.12

root@d2258e6dec11:/project# cat /etc/hostname d2258e6dec11 

Externally

$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d2258e6dec11 300518d26271 "bash" 5 minutes ago $ docker -v Docker version 1.12.0, build 8eab29e, experimental 
Sign up to request clarification or add additional context in comments.

8 Comments

Yup this made it easy to pull the info in nodejs for me. const os = require('os'); console.log(os.hostname());
To get the hostname that matches the Container Id in Java, use InetAddress.getLocalHost().getHostName().
Sometimes it's simpler to read the value of the environment variable $HOSTNAME (for example in shell scripts).
on a windows container, the equivalent is the COMPUTERNAME env var
To do this from python: import socket; socket.gethostname()
|
82

I've found out that the container id can be found in /proc/self/cgroup

So you can get the id with :

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

19 Comments

Had to tweak it a bit, this works for me in Docker 1.4.1 cat /proc/self/cgroup | grep "docker" | sed s/\\//\\n/g | tail -1
For docker 1.6.2 I had to use: cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1
Aaaaand Docker 1.12: cat /proc/1/cgroup | grep 'docker/' | tail -1 | sed 's/^.*\///' | cut -c 1-12
I kind of like basename "$(cat /proc/1/cpuset)" and basename "$(head /proc/1/cgroup)"
In the future, if cgroup namespace and cgroup v2 are used in docker, this method may not work anymore.
|
54

A comment by madeddie looks most elegant to me:

CID=$(basename $(cat /proc/1/cpuset)) 

4 Comments

It would be nice to elaborate what this actually does. DOes it still work if hostname was overriden for that container by the user? does it need filesystem access outside of the container?
excellent! works when network_mode=host, use export SCID=${CID:0:12} for to get the short container id - as displayed in docker ps.
In WSL and Arch, the cpuset is / so to make it work in WSL and Docker, I remove the trailing slash with the below command: export _CID=${$(basename $(cat /proc/1/cpuset))//\/} and export _SCID=${_CID:0:12} That way my shell commands can check if the _CID variable is set
WSL2 seems not fit all case: docker run -ti python:3.13.7-slim-bookworm cat /proc/1/cpuset /
38

You can communicate with docker from inside of a container using unix socket via Docker Remote API:

https://docs.docker.com/engine/reference/api/docker_remote_api/

In a container, you can find out a shortedned docker id by examining $HOSTNAME env var. According to doc, there is a small chance of collision, I think that for small number of container, you do not have to worry about it. I don't know how to get full id directly.

You can inspect container similar way as outlined in banyan answer:

GET /containers/4abbef615af7/json HTTP/1.1 

Response:

HTTP/1.1 200 OK Content-Type: application/json { "Id": "4abbef615af7...... ", "Created": "2013.....", ... } 

Alternatively, you can transfer docker id to the container in a file. The file is located on "mounted volume" so it is transfered to container:

docker run -t -i -cidfile /mydir/host1.txt -v /mydir:/mydir ubuntu /bin/bash 

The docker id (shortened) will be in file /mydir/host1.txt in the container.

5 Comments

Thanks but this is the same approach I am using anyway, and will break if you set the hostname with -h when you run docker.
@Alessandro I have added information about -cidfile parameter to docker run. It may help you to pass docker id to the container instead of using $HOSTNAME.
Great! Yes that is something I could use! Thank you!
Oddly, in 1.11.2 it seems env does not list HOSTNAME, but echo $HOSTNAME works.
This doesn't work at all, and your URL is broken and now redirects to the wrong documentation. requests.exceptions.MissingSchema: Invalid URL '/containers/1d26a841bf07/json': No schema supplied. Perhaps you meant http:///containers/1d26a841bf07/json?
25

WARNING: You should understand the security risks of this method before you consider it. John's summary of the risk:

By giving the container access to /var/run/docker.sock, it is [trivially easy] to break out of the containment provided by docker and gain access to the host machine. Obviously this is potentially dangerous.


Inside the container, the dockerId is your hostname. So, you could:

  • install the docker-io package in your container with the same version as the host
  • start it with --volume /var/run/docker.sock:/var/run/docker.sock --privileged
  • finally, run: docker inspect $(hostname) inside the container

Avoid this. Only do it if you understand the risks and have a clear mitigation for the risks.

5 Comments

I suspect this won't work if the docker run --hostname option has been used.
If --hostname is set you can use a combination from this answer and the comment from @Jay Taylor in the accepted answer: docker inspect $(cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1) to get all information about the running container.
could you put a reference to docker-io?
I assume its npmjs.com/package/docker-io but that was just what Google told me and perhaps isn't what you meant.
What would that mitigation be?
24

This will get the full container id from within a container:

cat /proc/self/cgroup | grep "cpu:/" | sed 's/\([0-9]\):cpu:\/docker\///g' 

Comments

20

To make it simple,

  1. Container ID is your host name inside docker
  2. Container information is available inside /proc/self/cgroup

To get host name,

hostname 

or

uname -n 

or

cat /etc/host 

Output can be redirected to any file & read back from application E.g.: # hostname > /usr/src//hostname.txt

Comments

15

I've found that in 17.09 there is a simplest way to do it within docker container:

$ cat /proc/self/cgroup | head -n 1 | cut -d '/' -f3 4de1c09d3f1979147cd5672571b69abec03d606afcc7bdc54ddb2b69dec3861c 

Or like it has already been told, a shorter version with

$ cat /etc/hostname 4de1c09d3f19 

Or simply:

$ hostname 4de1c09d3f19 

Comments

12

There are 3 places that I see that might work so far, each have advantages & disadvantages:

  1. echo $HOSTNAME or hostname
  2. cat /proc/self/cgroup
  3. cat /proc/self/mountinfo

$HOSTNAME is easy, but it is partial, and it will also be overwritten to pod name by K8s.

/proc/self/cgroup seems working with cgroupV1 but won't be there hosted in cgroupV2.

/proc/self/mountinfo will still have the container id for cgroupV2, however, the mount point will have different values by different container runtimes.

  • For example, in docker engine, the value looks like:
678 655 254:1 /docker/containers/7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw 
  • In ContainerD (K8s default engine lately), it looks like:
1733 1729 0:35 /kubepods/besteffort/pod3272f253-be44-4a82-a541-9083e68cf99f/7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a /sys/fs/cgroup/blkio ro,nosuid,nodev,noexec,relatime master:17 - cgroup cgroup rw,blkio 

Also, the biggest problem for all above is that they are all implementations, there's no abstraction and they all could be changed over time.

There is an effort to make it standard and I think it is worth watching:

https://github.com/opencontainers/runtime-spec/issues/1105

2 Comments

For newer Docker versions on hosts using cgroupV2 this (mountinfo) seem to be the only viable option.
Thanks! Most answers above are actually even more brittle or make little sense as they rely on the hostname being the container ID among others. This is a fairly detailed explanation of the problem and some ways around it (that work for now).
9

Docker sets the hostname to the container ID by default, but users can override this with --hostname. Instead, inspect /proc:

$ more /proc/self/cgroup 14:name=systemd:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 13:pids:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 12:hugetlb:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 11:net_prio:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 10:perf_event:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 9:net_cls:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 8:freezer:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 7:devices:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 6:memory:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 5:blkio:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 4:cpuacct:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 3:cpu:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 2:cpuset:/docker/7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 1:name=openrc:/docker 

Here's a handy one-liner to extract the container ID:

$ grep "memory:/" < /proc/self/cgroup | sed 's|.*/||' 7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605 

Comments

5

Some posted solutions have stopped working due to changes in the format of /proc/self/cgroup. Here is a single GNU grep command that should be a bit more robust to format changes:

grep -o -P -m1 'docker.*\K[0-9a-f]{64,}' /proc/self/cgroup 

For reference, here are snippits of /proc/self/cgroup from inside docker containers that have been tested with this command:

Linux 4.4:

11:pids:/system.slice/docker-cde7c2bab394630a42d73dc610b9c57415dced996106665d427f6d0566594411.scope ... 1:name=systemd:/system.slice/docker-cde7c2bab394630a42d73dc610b9c57415dced996106665d427f6d0566594411.scope 

Linux 4.8 - 4.13:

11:hugetlb:/docker/afe96d48db6d2c19585572f986fc310c92421a3dac28310e847566fb82166013 ... 1:name=systemd:/docker/afe96d48db6d2c19585572f986fc310c92421a3dac28310e847566fb82166013 

Comments

4

I believe that the "problem" with all of the above is that it depends upon a certain implementation convention either of docker itself or its implementation and how that interacts with cgroups and /proc, and not via a committed, public, API, protocol or convention as part of the OCI specs.

Hence these solutions are "brittle" and likely to break when least expected when implementations change, or conventions are overridden by user configuration.

container and image ids should be injected into the r/t environment by the component that initiated the container instance, if for no other reason than to permit code running therein to use that information to uniquely identify themselves for logging/tracing etc...

just my $0.02, YMMV...

Comments

2

You can use this command line to identify the current container ID (tested with docker 1.9).

awk -F"-|/." '/1:/ {print $3}' /proc/self/cgroup 

Then, a little request to Docker API (you can share /var/run/docker.sock) to retrieve all informations.

1 Comment

awk -F"-|/." '/1:/ {print $3}' /proc/self/cgroup
1
awk -F'[:/]' '(($4 == "docker") && (lastId != $NF)) { lastId = $NF; print $NF; }' /proc/self/cgroup 

Comments

1

As an aside, if you have the pid of the container and want to get the docker id of that container, a good way is to use nsenter in combination with the sed magic above:

nsenter -n -m -t pid -- cat /proc/1/cgroup | grep -o -e "docker-.*.scope" | head -n 1 | sed "s/docker-\(.*\).scope/\\1/"

Comments

0

The latest versions of docker does not have the information in cgroup. I recommend binding /var/run/docker.sock and access the information via a library or curl.

curl -s --unix-socket /run/docker.sock http://docker/containers/CONTAINER_ID/json

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.