Docker,如何从容器中获取容器信息?

Ale*_*dro 111 linux docker

我想让我docker containers了解他们的配置,就像通过元数据获取有关EC2实例的信息一样.

我可以使用(提供的docker是监听端口4243)

curl http://172.17.42.1:4243/containers/$HOSTNAME/json
Run Code Online (Sandbox Code Playgroud)

得到它的一些数据,但想知道是否有更好的方法至少获得容器的完整ID,因为HOSTNAME实际上缩短为12个字符,并且docker似乎在它上执行"最佳匹配".

另外,如何获取docker主机的外部IP(除了访问特定于AWS的EC2元数据)

小智 66

我发现容器ID可以在/ proc/self/cgroup中找到

所以你可以获得id:

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

  • 我有点像`basename"$(cat/proc/1/cpuset)"`和`basename"$(head/proc/1/cgroup)"` (20认同)
  • Aaaaand Docker 1.12:`cat/proc/1/cgroup | grep'docker /'| 尾巴-1 | sed's /^.*,///'| 切-c 1-12` (14认同)
  • 不得不调整一下,这在Docker 1.4.1`cat/proc/self/cgroup |中适用于我 grep"docker"| sed s/\\ // \\n/g | 尾巴-1` (13认同)
  • 这似乎在Docker v1.3.0中不起作用. (11认同)
  • 对于docker 1.6.2我不得不使用:`cat/proc/self/cgroup | grep'docker'| sed's /^.*,///'| 尾巴-n1` (5认同)
  • 将来,如果在docker中使用cgroup namespace和cgroup v2,则此方法可能不再起作用. (3认同)

ard*_*igh 54

除非被覆盖,否则主机名似乎是Docker 1.12中的短容器ID

root@d2258e6dec11:/project# cat /etc/hostname
d2258e6dec11
Run Code Online (Sandbox Code Playgroud)

外部

$ 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
Run Code Online (Sandbox Code Playgroud)

  • 是的,这很容易为我提取nodejs中的信息。`const os = require('os'); console.log(os.hostname());` (3认同)
  • 要获取与 Java 中的容器 ID 匹配的主机名,请使用 `InetAddress.getLocalHost().getHostName()`。 (2认同)
  • 有时读取环境变量 `$HOSTNAME` 的值会更简单(例如在 shell 脚本中)。 (2认同)

Jir*_*iri 33

您可以使用unix socket通过Docker Remote API从容器内部与docker通信:

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

在容器中,您可以通过检查$HOSTNAMEenv var 找到缩短的docker id .根据doc,碰撞的可能性很小,我认为对于少量的容器,你不必担心它.我不知道如何直接获得完整的id.

您可以按照榕树回答中概述的方式检查容器:

GET /containers/4abbef615af7/json HTTP/1.1
Run Code Online (Sandbox Code Playgroud)

响应:

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

{
         "Id": "4abbef615af7......  ",
         "Created": "2013.....",
         ...
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以将docker id传输到文件中的容器.该文件位于"已安装的卷"上,因此它被转移到容器:

docker run -t -i -cidfile /mydir/host1.txt -v /mydir:/mydir ubuntu /bin/bash
Run Code Online (Sandbox Code Playgroud)

docker id(缩短)将位于容器中的文件/mydir/host1.txt中.

  • 谢谢,但这与我正在使用的方法相同,如果在运行docker时使用-h设置主机名,则会中断. (2认同)

Pri*_*ner 21

这将从容器中获取完整的容器ID:

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


小智 20

警告:在考虑此方法之前,您应该了解此方法的安全风险.约翰对风险的总结:

通过让容器访问/var/run/docker.sock,可以轻松地打开docker提供的包含并获得对主机的访问权限.显然这有潜在危险.


在容器内,dockerId是您的主机名.所以,你可以:

  • 使用与主机相同的版本在您的容器中安装docker-io软件包
  • 开始吧 --volume /var/run/docker.sock:/var/run/docker.sock --privileged
  • 最后,运行:docker inspect $(hostname)容器内部

避免这样做.只有了解风险并明确减轻风险,才能做到这一点.

  • 是的,甚至```docker inspect $ HOSTNAME```也可以. (4认同)

sir*_*rex 13

Madeddie的评论对我来说似乎最优雅:

CID=$(basename $(cat /proc/1/cpuset))
Run Code Online (Sandbox Code Playgroud)

  • 最好详细说明这实际上是做什么的。如果用户覆盖该容器的主机名,它仍然有效吗?它是否需要容器外部的文件系统访问权限? (6认同)

Tej*_*ain 12

为了简单起见,

  1. Container ID是docker中的主机名
  2. 容器信息在/ proc/self/cgroup中可用

要获得主机名,

hostname
Run Code Online (Sandbox Code Playgroud)

要么

uname -n
Run Code Online (Sandbox Code Playgroud)

要么

cat /etc/host
Run Code Online (Sandbox Code Playgroud)

输出可以重定向到任何文件并从应用程序读回例如: # hostname > /usr/src//hostname.txt


Adr*_*nez 9

我发现在17.09中有一种最简单的方法可以在docker容器中执行它:

$ cat /proc/self/cgroup | head -n 1 | cut -d '/' -f3
4de1c09d3f1979147cd5672571b69abec03d606afcc7bdc54ddb2b69dec3861c
Run Code Online (Sandbox Code Playgroud)

或者就像它已被告知,更短的版本

$ cat /etc/hostname
4de1c09d3f19
Run Code Online (Sandbox Code Playgroud)

或者干脆:

$ hostname
4de1c09d3f19
Run Code Online (Sandbox Code Playgroud)


小智 8

到目前为止,我认为有 3 个地方可能可行,每个地方都有优点和缺点:

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

$HOSTNAME很简单,但是是片面的,而且也会被K8s覆盖为pod名称。

/proc/self/cgroup似乎与cgroupV1一起使用,但不会托管在cgroupV2中。

/proc/self/mountinfo仍将具有cgroupV2的容器 ID ,但是,不同的容器运行时挂载点将具有不同的值。

  • 例如,在 docker 引擎中,该值如下所示:
678 655 254:1 /docker/containers/7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw
Run Code Online (Sandbox Code Playgroud)
  • ContainerD(最近的 K8s 默认引擎)中,它看起来像:
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
Run Code Online (Sandbox Code Playgroud)

另外,以上所有的最大问题是它们都是实现,没有抽象,并且它们都可能随着时间的推移而改变。

人们正在努力使其成为标准,我认为值得关注:

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


Wil*_*hes 6

Docker默认将主机名设置为容器ID,但用户可以使用--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
Run Code Online (Sandbox Code Playgroud)

这是一个方便的单行程序来提取容器ID:

$ grep "memory:/" < /proc/self/cgroup | sed 's|.*/||'
7be92808767a667f35c8505cbf40d14e931ef6db5b0210329cf193b15ba9d605
Run Code Online (Sandbox Code Playgroud)


kan*_*aka 5

由于/proc/self/cgroup. 下面是一个 GNU grep 命令,它对于格式更改应该更加稳健:

grep -o -P -m1 'docker.*\K[0-9a-f]{64,}' /proc/self/cgroup
Run Code Online (Sandbox Code Playgroud)

作为参考,以下是来自 docker 容器内部的 /proc/self/cgroup 的片段,这些片段已经使用此命令进行了测试:

Linux 4.4:

11:pids:/system.slice/docker-cde7c2bab394630a42d73dc610b9c57415dced996106665d427f6d0566594411.scope
...
1:name=systemd:/system.slice/docker-cde7c2bab394630a42d73dc610b9c57415dced996106665d427f6d0566594411.scope
Run Code Online (Sandbox Code Playgroud)

Linux 4.8 - 4.13:

11:hugetlb:/docker/afe96d48db6d2c19585572f986fc310c92421a3dac28310e847566fb82166013
...
1:name=systemd:/docker/afe96d48db6d2c19585572f986fc310c92421a3dac28310e847566fb82166013
Run Code Online (Sandbox Code Playgroud)