Как я могу получить информацию о контейнере Docker Linux из самого контейнера?

136

Я хотел бы сообщить мне docker containersоб их конфигурации так же, как вы можете получить информацию об экземплярах EC2 через метаданные.

Я могу использовать (при условии dockerпрослушивания порта 4243)

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

чтобы получить некоторые из его данных, но хотел бы знать, есть ли лучший способ получить хотя бы полный идентификатор контейнера, потому что HOSTNAMEна самом деле он сокращен до 12 символов, и докер, похоже, выполняет с ним «наилучшее совпадение».

Кроме того, как я могу получить внешний IP-адрес хоста докеров (кроме доступа к метаданным EC2, которые характерны для AWS)

Alessandro
источник
2
ОСТОРОЖНО: вы должны прочитать этот lvh.io/posts/… перед тем, как пытаться использовать любой из описанных ниже подходов, пытающихся использовать /var/run/docker.sock внутри контейнера
harschware
1
Если ссылка @harschware разрывается, я резюмирую здесь: предоставив контейнеру доступ к /var/run/docker.sock, можно (тривиально) вырваться из сдерживания, обеспечиваемого докером, и получить доступ к хост-машине. Очевидно, это потенциально опасно.
Джон
1
Кто-нибудь знает, как получить ту же информацию в контейнере докеров Windows, если аргумент --hostname использовался с командой запуска, так что простой запуск hostname больше не дает вам containerid?
Тимоти Джон Лэрд

Ответы:

68

Я обнаружил, что идентификатор контейнера можно найти в / proc / self / cgroup

Итак, вы можете получить идентификатор с помощью:

cat /proc/self/cgroup | grep -o  -e "docker-.*.scope" | head -n 1 | sed "s/docker-\(.*\).scope/\\1/"
Томас А.
источник
15
Пришлось немного подправить, у меня это работает в Docker 1.4.1 cat /proc/self/cgroup | grep "docker" | sed s/\\//\\n/g | tail -1
ICas
5
Для docker 1.6.2 мне пришлось использовать: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
смец.кевин
24
Я вроде как basename "$(cat /proc/1/cpuset)"иbasename "$(head /proc/1/cgroup)"
madeddie
3
В будущем, если пространство имен cgroup и cgroup v2 будут использоваться в Docker, этот метод может больше не работать.
Цзин Цю
70

Если не переопределить, имя хоста кажется коротким идентификатором контейнера в Docker 1.12.

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

внешне

$ 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
источник
4
Ага, это облегчило мне получение информации в nodejs. const os = require('os'); console.log(os.hostname());
Pulkitsinghal 03
2
Чтобы получить имя хоста, соответствующее идентификатору контейнера в Java, используйте InetAddress.getLocalHost().getHostName().
Натан
2
Иногда проще прочитать значение переменной окружения $HOSTNAME(например, в сценариях оболочки).
Faheel 05
34

Вы можете общаться с докером изнутри контейнера, используя сокет unix через Docker Remote API:

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

В контейнере вы можете узнать сокращенный идентификатор докера, проверив $HOSTNAMEenv var. Согласно документу, есть небольшая вероятность столкновения, я думаю, что для небольшого количества контейнеров вам не нужно об этом беспокоиться. Я не знаю, как получить полный идентификатор напрямую.

Вы можете проверить контейнер аналогично тому, как указано в ответе баньяна :

GET /containers/4abbef615af7/json HTTP/1.1

Отклик:

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

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

Кроме того, вы можете передать идентификатор докера в контейнер в файле. Файл находится на «смонтированном томе», поэтому он переносится в контейнер:

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

Идентификатор докера (сокращенно) будет в файле /mydir/host1.txt в контейнере.

Иржи
источник
2
Спасибо, но это тот же подход, который я использую в любом случае, и он сломается, если вы установите имя хоста с помощью -h при запуске docker.
Алессандро
@Alessandro Я добавил информацию о параметре -cidfile для запуска докера. Это может помочь вам передать идентификатор докера в контейнер вместо использования $ HOSTNAME.
Jiri
Большой! Да, это то, что я мог бы использовать! Спасибо!
Алессандро
Как ни странно, в 1.11.2 вроде envне перечисляет HOSTNAME, но echo $HOSTNAMEработает.
Джесси Глик,
Это вообще не работает, и ваш URL-адрес не работает и теперь перенаправляет на неправильную документацию. requests.exceptions.MissingSchema: Invalid URL '/containers/1d26a841bf07/json': No schema supplied. Perhaps you meant http:///containers/1d26a841bf07/json?
Cerin
24

Это получит полный идентификатор контейнера из контейнера:

cat /proc/self/cgroup | grep "cpu:/" | sed 's/\([0-9]\):cpu:\/docker\///g'
пленный
источник
22

Мне кажется, что комментарий madeddie выглядит наиболее элегантно:

CID=$(basename $(cat /proc/1/cpuset))
Sirex
источник
21

ВНИМАНИЕ: вы должны понимать риски безопасности этого метода, прежде чем рассматривать его. Краткое изложение риска Джоном :

Предоставив контейнеру доступ к /var/run/docker.sock, [тривиально легко] вырваться из сдерживания, обеспечиваемого докером, и получить доступ к хост-машине. Очевидно, это потенциально опасно.


Внутри контейнера dockerId - это ваше имя хоста. Итак, вы могли:

  • установите пакет docker-io в свой контейнер с той же версией, что и хост
  • начни это с --volume /var/run/docker.sock:/var/run/docker.sock --privileged
  • наконец, запустите: docker inspect $(hostname)внутри контейнера

Избегайте этого. Делайте это только в том случае, если вы понимаете риски и имеете четкое представление о снижении рисков.

Омар Маркес
источник
1
Я подозреваю, что это не сработает, если использовалась --hostnameопция запуска докера .
hairyhenderson
Если --hostnameустановлено, вы можете использовать комбинацию из этого ответа и комментария от @Jay Taylor в принятом ответе: docker inspect $(cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1)чтобы получить всю информацию о запущенном контейнере.
Майкл К.
не могли бы вы поставить ссылку на docker-io?
Брэд П.
Я предполагаю, что это npmjs.com/package/docker-io, но это именно то, что мне сказал Google, и, возможно, не то, что вы имели в виду.
Брэд П.
15

Чтобы было проще,

  1. ID контейнера - это ваше имя хоста внутри докера.
  2. Информация о контейнере доступна внутри / proc / self / cgroup

Чтобы получить имя хоста,

hostname

или

uname -n

или

cat /etc/host

Вывод может быть перенаправлен в любой файл и считан из приложения. Например: # hostname > /usr/src//hostname.txt

Теджас Джайн
источник
10

Я обнаружил, что в 17.09 есть самый простой способ сделать это в контейнере докера:

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

Или, как уже было сказано, более короткая версия с

$ cat /etc/hostname
4de1c09d3f19

Или просто:

$ hostname
4de1c09d3f19
Адриан Антунес
источник
6

Docker по умолчанию устанавливает имя хоста для идентификатора контейнера, но пользователи могут изменить это с помощью --hostname. Вместо этого проверьте /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

Вот удобный однострочник для извлечения идентификатора контейнера:

$ grep "memory:/" < /proc/self/cgroup | sed 's|.*/||'
7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
Уилфред Хьюз
источник
2

Вы можете использовать эту командную строку для определения текущего идентификатора контейнера (проверено с помощью docker 1.9).

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

Затем небольшой запрос к Docker API (вы можете поделиться /var/run/docker.sock), чтобы получить всю информацию.

Baptiste Donaux
источник
1
awk -F "- | /." '/ 1: / {print $ 3}' / proc / self /
cgroup
2

Некоторые опубликованные решения перестали работать из-за изменений в формате /proc/self/cgroup. Вот одна команда GNU grep, которая должна быть немного более устойчивой к изменениям формата:

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

Для справки, вот фрагменты / proc / self / cgroup из контейнеров докеров, которые были протестированы с помощью этой команды:

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
канак
источник
1
awk -F'[:/]' '(($4 == "docker") && (lastId != $NF)) { lastId = $NF; print $NF; }' /proc/self/cgroup
Эндрю Вулф
источник
0

В стороне, если у вас есть pid контейнера и вы хотите получить идентификатор докера этого контейнера, хороший способ - использовать nsenter в сочетании с магией sed выше:

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

anbhat
источник
-19

Используйте 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",
...

Получить ip можно следующим образом.

$ docker inspect -format="{{ .NetworkSettings.IPAddress }}" 2a5624c52119
172.17.0.24
маклер
источник
5
Я не это имел в виду. Мне нужно , чтобы иметь возможность получить эту информацию из внутри контейнера. В основном мне нужен способ понять идентификатор контейнера, который я запускаю изнутри.
Алессандро