206

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)

Lucas
  • 17,277
  • 5
  • 45
  • 40
Alessandro
  • 2,378
  • 2
  • 15
  • 13
  • 4
    BEWARE: you should read this https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html before attempting any of the approaches below that attempt to use /var/run/docker.sock inside the container – harschware Oct 19 '17 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. – ProgrammingLlama Jan 12 '18 at 02: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? – Timothy John Laird May 15 '19 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. – Marat Mkhitaryan Nov 14 '20 at 16:41

15 Answers15

121

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
Jason
  • 9,408
  • 5
  • 36
  • 36
port5432
  • 5,889
  • 10
  • 60
  • 97
  • 8
    Yup this made it easy to pull the info in nodejs for me. `const os = require('os'); console.log(os.hostname());` – pulkitsinghal Jun 03 '17 at 17:09
  • 4
    To get the hostname that matches the Container Id in Java, use `InetAddress.getLocalHost().getHostName()`. – Nathan Jan 18 '19 at 00:15
  • 2
    Sometimes it's simpler to read the value of the environment variable `$HOSTNAME` (for example in shell scripts). – Faheel Aug 05 '19 at 08:21
  • 1
    on a windows container, the equivalent is the `COMPUTERNAME` env var – solstice333 Feb 24 '21 at 23:39
  • If working in Windows though, be sure to lowercase the COMPUTERNAME value before passing into the Docker Engine API. – nickwesselman Apr 08 '21 at 21:34
  • To do this [from python](https://stackoverflow.com/a/4271755/913098): `import socket; socket.gethostname()` – Gulzar Feb 08 '22 at 13:04
79

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/"
Thomas A.
  • 814
  • 7
  • 2
  • 19
    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` – ICas Feb 11 '15 at 19:21
  • 7
    For docker 1.6.2 I had to use: `cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1` – Jay Taylor Jul 24 '15 at 19:30
  • 1
    For docker 1.8 and beyond that file seems to be available under /proc/1/cgroup. – anbhat Apr 14 '16 at 14:25
  • 16
    Aaaaand Docker 1.12: `cat /proc/1/cgroup | grep 'docker/' | tail -1 | sed 's/^.*\///' | cut -c 1-12` – smets.kevin Jul 27 '16 at 21:05
  • both `/proc/1` and `/proc/self` should work. Actually, `/proc/self` is pointing to the process running `cat /proc/self`. This process is in the same cgroup as the pid 1 process. :) – andy Sep 06 '16 at 12:54
  • 36
    I kind of like `basename "$(cat /proc/1/cpuset)"` and `basename "$(head /proc/1/cgroup)"` – madeddie Nov 14 '16 at 12:06
  • 1
    Not working for me in 1.12.3. `/proc/self/mountinfo` does include the ID, however. – Jesse Glick Feb 07 '17 at 22:47
  • Or rather, `cgroup` works under most conditions, but not under some conditions I have yet to identify (whereas `mountinfo` seems to work consistently). – Jesse Glick Feb 08 '17 at 15:39
  • I like the basic method, although I'm guessing the format of /proc/self/cgroup may change between version. This worked on my version: head -1 /proc/self/cgroup | cut -d: -f3 | sed -e's&/docker/&&' (version 17.03.1-ce) – Gerry Gleason Apr 18 '17 at 19:27
  • Maybe this: API version: 1.27 (minimum version 1.12)) – Gerry Gleason Apr 18 '17 at 19:35
  • Or: cut -d/ -f3 /proc/1/cpuset (based on smets.kevin above, thx) I only see one line in this /proc file, can there be several? When? – Gerry Gleason Apr 18 '17 at 19:40
  • 7
    In the future, if cgroup namespace and cgroup v2 are used in docker, this method may not work anymore. – Jing Qiu Sep 06 '17 at 10:51
  • 1
    How do we do this for a Windows container? – Web User Dec 01 '17 at 21:26
  • I haven't been able to get this working in Docker version 17.12.0-ce, build c97c6d6. – Ryan Jul 10 '18 at 11:38
  • Doesn't work on `Docker version 18.06.1-ce, build e68fc7a` – 25b3nk Mar 14 '19 at 05:59
  • Alternatively for me this worked, `cat /proc/self/cgroup | grep "\/docker\/" | head -n 1 | sed 's/.*\/docker\///' | cut -c1-12`. I saw the container ID information when I did `cat`, then it was about extracting the 12-character ID from the complete ID. – 25b3nk Mar 14 '19 at 06:06
  • 1
    I used `cat /proc/1/cpuset | head -n 1 | sed "s/\/docker\/\(.*\)/\\1/"` – ste Dec 20 '19 at 16:29
  • `cat /proc/self/cgroup | sed -n '1s/.*docker-\(.*\).scope/\1/p'` – Ibrahim Quraish Sep 17 '20 at 16:52
  • 1
    with cgroup v2 in use this won't work anymore as @JingQiu said. there is another question here: https://stackoverflow.com/questions/68816329/how-to-get-docker-container-id-from-within-the-container-with-cgroup-v2/70685581#70685581 – ste Jan 13 '22 at 11:26
50

A comment by madeddie looks most elegant to me:

CID=$(basename $(cat /proc/1/cpuset))
sirex
  • 4,593
  • 2
  • 32
  • 21
  • 5
    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? – simon Oct 01 '21 at 07:30
  • 1
    excellent! works when `network_mode=host`, use `export SCID=${CID:0:12}` for to get the short container id - as displayed in `docker ps`. – pangyuteng Jun 17 '22 at 17:12
  • 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 – Loligans Oct 03 '22 at 01:13
37

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.

Wes Lord
  • 463
  • 5
  • 11
Jiri
  • 16,425
  • 6
  • 52
  • 68
  • 2
    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 Jan 09 '14 at 10:24
  • @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. – Jiri Jan 09 '14 at 12:22
  • 1
    Great! Yes that is something I could use! Thank you! – Alessandro Jan 09 '14 at 16:14
  • Oddly, in 1.11.2 it seems `env` does not list `HOSTNAME`, but `echo $HOSTNAME` works. – Jesse Glick Jun 23 '16 at 15:51
  • 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?` – Cerin May 28 '19 at 19:09
24

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.

floer32
  • 2,190
  • 4
  • 29
  • 50
Omar Marquez
  • 329
  • 1
  • 3
  • 1
    I suspect this won't work if the docker run `--hostname` option has been used. – hairyhenderson Jan 18 '15 at 01:25
  • 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. – Michael K. Nov 12 '15 at 09:36
  • could you put a reference to docker-io? – Brad P. Oct 13 '16 at 11:49
  • I assume its https://www.npmjs.com/package/docker-io/ but that was just what Google told me and perhaps isn't what you meant. – Brad P. Oct 13 '16 at 11:55
  • What would that mitigation be? – human Nov 26 '21 at 08:11
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'
Prisoner
  • 27,391
  • 11
  • 73
  • 102
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

Tejas jain
  • 742
  • 7
  • 20
14

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
Adrian Antunez
  • 990
  • 7
  • 12
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
Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192
6

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

Jonas Andersson
  • 8,678
  • 2
  • 19
  • 14
Saar
  • 199
  • 1
  • 8
  • For newer Docker versions on hosts using cgroupV2 this (mountinfo) seem to be the only viable option. – Jonas Andersson Jun 16 '22 at 06:59
  • 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). – takecare Aug 23 '22 at 09:30
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
kanaka
  • 70,845
  • 23
  • 144
  • 140
3

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...

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.

Baptiste Donaux
  • 1,300
  • 13
  • 34
1
awk -F'[:/]' '(($4 == "docker") && (lastId != $NF)) { lastId = $NF; print $NF; }' /proc/self/cgroup
Andrew Wolfe
  • 2,020
  • 19
  • 25
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/"

anbhat
  • 427
  • 4
  • 12