如何从容器内部获取Docker Linux容器信息?

我想让我的docker containers知道他们的配置,就像您可以通过元数据获得有关EC2实例的信息一样。

我可以使用(前提是docker正在侦听端口4243

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

获得它的一些数据,但想知道是否有更好的方法至少获得容器的完整ID,因为HOSTNAME实际上被缩短为12个字符,而Docker似乎对其执行“最佳匹配”。

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

156629 次浏览

使用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

您可以通过Docker远程API使用Unix套接字从容器内部与Docker通信:

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

容器中,您可以通过检查$HOSTNAME env var来找出缩短的docker ID. 根据DOC的说法,碰撞的可能性很小,我认为对于数量较少的集装箱,你不必担心。我不知道如何直接获得完整的ID.

您可以使用与榕树中所述类似的方法检查集装箱。答案:

GET /containers/4abbef615af7/json HTTP/1.1

回应:

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


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

或者,您可以将Docker ID传输到文件中的容器。 文件位于“已挂载的卷”上,因此它被传输到容器:

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

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

警告:您应该先了解这种方法的安全风险,然后再考虑它。ABC_2的风险摘要_:

通过授予容器对/var/run/docker.sock的访问权限,可以[非常容易地]突破Docker提供的限制并获得对主机的访问权限。显然,这有潜在的危险。


在容器中,dockerID是您的主机名。 所以,你可以:

  • 在您的容器中安装与主机版本相同的docker-io包
  • --volume
  • 启动它 /var/run/docker.sock:/var/run/docker.sock--privileged
  • 最后,运行:_容器内的ABC_0

避免这个。只有当你了解风险并对风险有明确的缓解措施时,才能这样做。

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

因此,您可以通过以下方式获取ID:

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

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

cat /proc/self/cgroup | grep "cpu:/" | sed 's/\([0-9]\):cpu:\/docker\///g'
awk -F'[:/]' '(($4 == "docker") && (lastId != $NF)) { lastId = $NF; print $NF; }' /proc/self/cgroup

您可以使用此命令行来识别当前容器ID(使用Docker 1.9进行测试)。

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

然后,向Docker API发出一个小请求(您可以共享/var/run/docker.sock)来检索所有信息。

顺便说一句,如果你有容器的PID,并且想要获得该容器的docker ID,一个好方法是结合上面的sed魔法使用nsenter:

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

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

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

我发现在17.09中,在Docker容器中有一个最简单的方法:

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

或者就像它已经被告知的那样,一个更短的版本

$ cat /etc/hostname
4de1c09d3f19

或者简单地说:

$ hostname
4de1c09d3f19

为了使其简单,

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

要获取主机名,

hostname

uname -n

cat /etc/host
可以将

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

默认情况下,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

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

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

由于/proc/self/cgroup的格式发生变化,某些发布的解决方案已停止工作。下面是一个GNU grep命令,它对于格式更改应该更健壮一些:

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

作为参考,以下是使用此命令测试过的Docker容器内部的/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

马迪迪的评论在我看来非常优雅:

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

我相信“问题”上述所有内容都取决于Docker本身或其实现的特定实现约定,以及如何与cgroups和/proc交互,并通过作为OCI规范一部分的承诺、公共、API、协议或约定

因此,这些溶液是“易碎的”。并且当实现发生变化或约定被用户配置覆盖时,可能会在最意想不到的时候被破坏。

容器和映像ID应该由启动容器实例的组件注入到R/T环境中,如果没有其他原因的话 以允许在其中运行的代码使用该信息来唯一地标识它们自己以进行记录/跟踪等。

只有我的$0.02,YMMV..

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

  1. echo $HOSTNAMEhostname
  2. cat /proc/self/cgroup
  3. cat /proc/self/mountinfo

$HOSTNAME是容易的,但是它是部分的,并且它也将被K8S已覆盖到POD名称。

/proc/self/cgroup似乎与cGroupV1一起工作,但不会在那里托管在cGroupV2中。

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

  • 例如,在Docker Engine中,值如下所示:
678 655 254:1 /docker/containers/7a0144cee1256c539fab790199527b7051aff1b603ebcf7ed3fd436440ef3b3a/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw
  • 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

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

有一种努力使其标准化,我认为值得一看:

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