Jak mogę uzyskać informacje o kontenerze Docker Linux z samego kontenera?

145

Chciałbym poinformować mnie docker containerso ich konfiguracji, tak samo jak można uzyskać informacje o instancjach EC2 poprzez metadane.

Mogę użyć (pod warunkiem, że dockernasłuchuje na porcie 4243)

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

aby uzyskać część jego danych, ale chciałbym wiedzieć, czy istnieje lepszy sposób przynajmniej na uzyskanie pełnego identyfikatora kontenera, ponieważ HOSTNAME jest on w rzeczywistości skrócony do 12 znaków, a docker wydaje się wykonywać na nim „najlepsze dopasowanie”.

Ponadto, jak mogę uzyskać zewnętrzny adres IP hosta dockera (inny niż dostęp do metadanych EC2, które są specyficzne dla AWS)

Alessandro
źródło
2
UWAŻAJ: powinieneś przeczytać ten lvh.io/posts/ ... przed podjęciem któregokolwiek z poniższych podejść, które próbują użyć /var/run/docker.sock wewnątrz kontenera
harschware
1
W przypadku zerwania łącza @ harschware, podsumuję tutaj: Dając kontenerowi dostęp do /var/run/docker.sock, możliwe jest (trywialne) wyrwanie się z zabezpieczenia zapewnianego przez docker i uzyskanie dostępu do maszyny hosta. Oczywiście jest to potencjalnie niebezpieczne.
John
1
Czy ktoś wie, jak uzyskać te same informacje w kontenerze Dockera systemu Windows, jeśli argument --hostname został użyty z poleceniem run, aby po prostu uruchomienie „hostname” nie dawało już identyfikatora kontenera?
Timothy John Laird

Odpowiedzi:

70

Dowiedziałem się, że identyfikator kontenera można znaleźć w / proc / self / cgroup

Możesz więc uzyskać identyfikator za pomocą:

cat /proc/self/cgroup | grep -o  -e "docker-.*.scope" | head -n 1 | sed "s/docker-\(.*\).scope/\\1/"
Thomas A.
źródło
15
Musiałem to trochę poprawić, to działa dla mnie w Docker 1.4.1 cat /proc/self/cgroup | grep "docker" | sed s/\\//\\n/g | tail -1
ICas
5
Dla dockera 1.6.2 musiałem użyć:cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1
Jay Taylor,
14
Aaaaand Docker 1.12:cat /proc/1/cgroup | grep 'docker/' | tail -1 | sed 's/^.*\///' | cut -c 1-12
smets.kevin
25
Lubię basename "$(cat /proc/1/cpuset)"ibasename "$(head /proc/1/cgroup)"
madeddie
3
W przyszłości, jeśli przestrzeń nazw cgroup i cgroup v2 są używane w dockerze, ta metoda może już nie działać.
Jing Qiu,
76

O ile nie zostanie zastąpiona, nazwa hosta wydaje się być krótkim identyfikatorem kontenera w Docker 1.12

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

Zewnętrznie

$ 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
ardochhigh
źródło
4
Tak, to ułatwiło mi pobranie informacji w nodejs. const os = require('os'); console.log(os.hostname());
pulkitsinghal
2
Aby uzyskać nazwę hosta, która jest zgodna z identyfikatorem kontenera w języku Java, użyj InetAddress.getLocalHost().getHostName().
Nathan,
2
Czasami łatwiej jest odczytać wartość zmiennej środowiskowej $HOSTNAME(na przykład w skryptach powłoki).
Faheel,
34

Z dockerem można się komunikować z wnętrza kontenera za pomocą gniazda unix poprzez Docker Remote API:

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

W kontenerze możesz znaleźć zwarty identyfikator dockera, sprawdzając $HOSTNAMEenv var. Według doc. Istnieje mała szansa na kolizję, myślę, że przy małej ilości kontenerów nie trzeba się tym martwić. Nie wiem, jak bezpośrednio uzyskać pełny identyfikator.

Możesz sprawdzić pojemnik w podobny sposób, jak opisano w odpowiedzi Banyana :

GET /containers/4abbef615af7/json HTTP/1.1

Odpowiedź:

HTTP/1.1 200 OK
Content-Type: application/json

{
         "Id": "4abbef615af7......  ",
         "Created": "2013.....",
         ...
}

Alternatywnie możesz przenieść identyfikator Dockera do kontenera w pliku. Plik znajduje się na „zamontowanym woluminie”, więc jest przenoszony do kontenera:

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

Identyfikator dockera (skrócony) będzie w pliku /mydir/host1.txt w kontenerze.

Jiri
źródło
2
Dzięki, ale jest to to samo podejście, którego i tak używam, i zepsuje się, jeśli ustawisz nazwę hosta za pomocą -h podczas uruchamiania dockera.
Alessandro,
@Alessandro Dodałem informację o parametrze -cidfile do uruchomienia dockera. Może ci pomóc przekazać identyfikator dockera do kontenera zamiast używać $ HOSTNAME.
Jiri,
Świetny! Tak, to jest coś, czego mógłbym użyć! Dziękuję Ci!
Alessandro,
Co dziwne, w 1.11.2 wygląda na to, że envnie wymienia HOSTNAME, ale echo $HOSTNAMEdziała.
Jesse Glick
To w ogóle nie działa, a Twój adres URL jest uszkodzony i teraz przekierowuje do niewłaściwej dokumentacji. requests.exceptions.MissingSchema: Invalid URL '/containers/1d26a841bf07/json': No schema supplied. Perhaps you meant http:///containers/1d26a841bf07/json?
Cerin
24

Spowoduje to pobranie pełnego identyfikatora kontenera z kontenera:

cat /proc/self/cgroup | grep "cpu:/" | sed 's/\([0-9]\):cpu:\/docker\///g'
Więzień
źródło
23

Najbardziej elegancko wygląda dla mnie komentarz Madeddie :

CID=$(basename $(cat /proc/1/cpuset))
sirex
źródło
22

OSTRZEŻENIE: przed jej rozważeniem należy zrozumieć zagrożenia bezpieczeństwa związane z tą metodą . Podsumowanie ryzyka Johna :

Dając dostęp do kontenera /var/run/docker.sock, [trywialnie łatwe] jest wyrwanie się z zabezpieczenia zapewnianego przez docker i uzyskanie dostępu do maszyny hosta. Oczywiście jest to potencjalnie niebezpieczne.


Wewnątrz kontenera dockerId jest nazwą twojego hosta. Możesz więc:

  • zainstaluj pakiet docker-io w swoim kontenerze z tą samą wersją co host
  • zacznij od --volume /var/run/docker.sock:/var/run/docker.sock --privileged
  • na koniec biegnij: docker inspect $(hostname)wewnątrz pojemnika

Unikajcie tego. Rób to tylko wtedy, gdy rozumiesz ryzyko i masz jasne środki zaradcze.

Omar Marquez
źródło
1
Podejrzewam, że to nie zadziała, jeśli --hostnamezostała użyta opcja uruchamiania dockera .
hairyhenderson
Jeśli --hostnamejest ustawiona, możesz użyć kombinacji tej odpowiedzi i komentarza @Jay Taylor w zaakceptowanej odpowiedzi: docker inspect $(cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1)aby uzyskać wszystkie informacje o uruchomionym kontenerze.
Michael K.
czy mógłbyś umieścić odniesienie do docker-io?
Brad P.
Zakładam, że to npmjs.com/package/docker-io, ale tak właśnie powiedział mi Google i być może nie to miałeś na myśli.
Brad P.
15

Aby to uprościć,

  1. Identyfikator kontenera to nazwa twojego hosta w dockerze
  2. Informacje o kontenerze są dostępne w / proc / self / cgroup

Aby uzyskać nazwę hosta,

hostname

lub

uname -n

lub

cat /etc/host

Wyjście można przekierować do dowolnego pliku i odczytać z aplikacji Np .: # hostname > /usr/src//hostname.txt

Tejas jain
źródło
10

Odkryłem, że w 17.09 jest najprostszy sposób na zrobienie tego w kontenerze dockerowym:

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

Lub jak już powiedziano, krótsza wersja z

$ cat /etc/hostname
4de1c09d3f19

Lub po prostu:

$ hostname
4de1c09d3f19
Adrian Antunez
źródło
7

Docker domyślnie ustawia nazwę hosta na identyfikator kontenera, ale użytkownicy mogą to zastąpić --hostname. Zamiast tego sprawdź /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

Oto przydatna jedna linijka do wyodrębnienia identyfikatora kontenera:

$ grep "memory:/" < /proc/self/cgroup | sed 's|.*/||'
7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
Wilfred Hughes
źródło
2

Możesz użyć tego wiersza polecenia, aby zidentyfikować bieżący identyfikator kontenera (przetestowany w Docker 1.9).

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

Następnie małe żądanie do Docker API (możesz udostępnić /var/run/docker.sock), aby pobrać wszystkie informacje.

Baptiste Donaux
źródło
1
awk -F "- | /." '/ 1: / {print $ 3}' / proc / self / cgroup
usil
2

Niektóre opublikowane rozwiązania przestały działać z powodu zmian w formacie /proc/self/cgroup. Oto pojedyncze polecenie GNU grep, które powinno być nieco bardziej odporne na zmiany formatu:

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

Dla odniesienia, oto fragmenty / proc / self / cgroup z wewnątrz kontenerów docker, które zostały przetestowane za pomocą tego polecenia:

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
źródło
1
awk -F'[:/]' '(($4 == "docker") && (lastId != $NF)) { lastId = $NF; print $NF; }' /proc/self/cgroup
Andrew Wolfe
źródło
0

Na marginesie, jeśli masz pid kontenera i chcesz uzyskać identyfikator dockera tego kontenera, dobrym sposobem jest użycie nsenter w połączeniu z magią seda powyżej:

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

anbhat
źródło
-19

Użyj docker inspect.

$ docker ps # get conteiner id
$ docker inspect 4abbef615af7
[{
    "ID": "4abbef615af780f24991ccdca946cd50d2422e75f53fb15f578e14167c365989",
    "Created": "2014-01-08T07:13:32.765612597Z",
    "Path": "/bin/bash",
    "Args": [
        "-c",
        "/start web"
    ],
    "Config": {
        "Hostname": "4abbef615af7",
...

Można uzyskać ip w następujący sposób.

$ docker inspect -format="{{ .NetworkSettings.IPAddress }}" 2a5624c52119
172.17.0.24
banyan
źródło
5
Nie o to mi chodzi. Muszę uzyskać te informacje z wnętrza kontenera. Czy w zasadzie potrzebuję sposobu, aby zrozumieć identyfikator kontenera, który uruchamiam od wewnątrz.
Alessandro,