如何从容器本身获取 Docker Linux 容器信息?
Posted
技术标签:
【中文标题】如何从容器本身获取 Docker Linux 容器信息?【英文标题】:How can I get Docker Linux container information from within the container itself? 【发布时间】:2014-01-26 12:51:38 【问题描述】:我想让我的docker containers
了解他们的配置,就像您可以通过元数据获取有关 EC2 实例的信息一样。
我可以使用(前提是docker
正在侦听端口4243
)
curl http://172.17.42.1:4243/containers/$HOSTNAME/json
获取它的一些数据,但想知道是否有更好的方法至少获取容器的完整 ID,因为HOSTNAME
实际上缩短为 12 个字符,而 docker 似乎执行“最佳匹配”就可以了。
另外,如何获取 docker 主机的外部 IP(除了访问 AWS 特有的 EC2 元数据)
【问题讨论】:
注意:在尝试以下任何尝试在容器内使用 /var/run/docker.sock 的方法之前,您应该阅读此lvh.io/posts/… 如果@harschware 的链接断开,我将在这里总结一下:通过授予容器对/var/run/docker.sock
的访问权限,可以(微不足道)突破 docker 提供的遏制并获得访问权限主机。显然这是有潜在危险的。
如果 --hostname 参数与 run 命令一起使用,是否有人知道如何在 windows docker 容器中获取相同的信息,以便不再简单地运行“主机名”给你容器ID?
在安全性方面将 docker daemon api 暴露给容器是一种非常糟糕的方法。因为受感染的容器可以访问 docker 并做任何它想做的事情。应该有一些单独的 API 仅用于获取非私人信息。
【参考方案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
【讨论】:
是的,这让我很容易在 nodejs 中提取信息。const os = require('os'); console.log(os.hostname());
要获取与 Java 中的 Container Id 匹配的主机名,请使用 InetAddress.getLocalHost().getHostName()
。
有时读取环境变量 $HOSTNAME
的值更简单(例如在 shell 脚本中)。
在 windows 容器上,相当于 COMPUTERNAME
env var
如果在 Windows 中工作,请确保在传递到 Docker 引擎 API 之前将 COMPUTERNAME 值小写。【参考方案2】:
我发现容器id可以在/proc/self/cgroup中找到
所以你可以得到 id :
cat /proc/self/cgroup | grep -o -e "docker-.*.scope" | head -n 1 | sed "s/docker-\(.*\).scope/\\1/"
【讨论】:
不得不稍微调整一下,这对我在 Docker 1.4.1cat /proc/self/cgroup | grep "docker" | sed s/\\//\\n/g | tail -1
有效
对于 docker 1.6.2 我不得不使用:cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1
Aaaa 和 Docker 1.12:cat /proc/1/cgroup | grep 'docker/' | tail -1 | sed 's/^.*\///' | cut -c 1-12
我有点喜欢basename "$(cat /proc/1/cpuset)"
和basename "$(head /proc/1/cgroup)"
以后如果在docker中使用cgroup namespace和cgroup v2,这个方法可能已经不行了。【参考方案3】:
madeddie 的评论对我来说看起来最优雅:
CID=$(basename $(cat /proc/1/cpuset))
【讨论】:
很高兴能详细说明它的实际作用。如果用户为该容器覆盖主机名,它是否仍然有效?它是否需要容器外的文件系统访问权限?【参考方案4】:您可以通过 Docker Remote API 使用 unix 套接字从容器内部与 docker 通信:
https://docs.docker.com/engine/reference/api/docker_remote_api/
在容器中,您可以通过检查 $HOSTNAME
env var 找出缩短的 docker id。
根据文档,碰撞的可能性很小,我认为对于少量容器,您不必担心。我不知道如何直接获取完整的id。
您可以按照 banyan 回答中所述的类似方式检查容器:
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 中。
【讨论】:
谢谢,但这与我使用的方法相同,如果在运行 docker 时使用 -h 设置主机名,则会中断。 @Alessandro 我已将有关 -cidfile 参数的信息添加到 docker run。它可以帮助您将 docker id 传递给容器,而不是使用 $HOSTNAME。 太棒了!是的,这是我可以使用的东西!谢谢! 奇怪的是,在 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?
【参考方案5】:
这将从容器中获取完整的容器 ID:
cat /proc/self/cgroup | grep "cpu:/" | sed 's/\([0-9]\):cpu:\/docker\///g'
【讨论】:
【参考方案6】:警告:在考虑之前您应该了解the security risks of this method。 John的风险总结:
通过让容器访问
/var/run/docker.sock
,[非常容易] 突破 docker 提供的遏制并获得对主机的访问权限。显然,这是有潜在危险的。
在容器内,dockerId 是您的主机名。 所以,你可以:
在您的容器中安装docker-io package,与主机版本相同 以--volume
/var/run/docker.sock:/var/run/docker.sock --privileged
开头
最后,在容器内运行:docker inspect $(hostname)
避免这种情况。只有在您了解风险并明确缓解风险的情况下才这样做。
【讨论】:
我怀疑如果使用了 docker run--hostname
选项,这将不起作用。
如果设置了--hostname
,您可以使用此答案中的组合和@Jay Taylor 在接受的答案中的评论:docker inspect $(cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1)
来获取有关正在运行的容器的所有信息。
你能引用 docker-io 吗?
我认为它是 npmjs.com/package/docker-io,但这正是 Google 告诉我的,也许不是你的意思。
缓解措施是什么?【参考方案7】:
为了简单起见,
-
容器 ID 是您在 docker 中的主机名
容器信息在 /proc/self/cgroup 中可用
要获取主机名,
hostname
或
uname -n
或
cat /etc/host
输出可以重定向到任何文件并从应用程序读回
例如:# hostname > /usr/src//hostname.txt
【讨论】:
【参考方案8】:我发现在 17.09 中有一种最简单的方法可以在 docker 容器中执行此操作:
$ cat /proc/self/cgroup | head -n 1 | cut -d '/' -f3
4de1c09d3f1979147cd5672571b69abec03d606afcc7bdc54ddb2b69dec3861c
或者就像已经被告知的那样,一个较短的版本,带有
$ cat /etc/hostname
4de1c09d3f19
或者简单地说:
$ hostname
4de1c09d3f19
【讨论】:
【参考方案9】: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
【讨论】:
【参考方案10】:由于/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
【讨论】:
【参考方案11】:您可以使用此命令行来识别当前的容器 ID(使用 docker 1.9 测试)。
awk -F"-|/." '/1:/ print $3' /proc/self/cgroup
然后,向 Docker API(您可以共享 /var/run/docker.sock)发出一点请求以检索所有信息。
【讨论】:
awk -F"-|/." '/1:/ print $3' /proc/self/cgroup【参考方案12】:awk -F'[:/]' '(($4 == "docker") && (lastId != $NF)) lastId = $NF; print $NF; ' /proc/self/cgroup
【讨论】:
【参考方案13】:我认为上述所有内容的“问题”在于它取决于 docker 本身或其实现的某个实现约定以及它如何与 cgroups 和 /proc 交互,而 不是通过作为 OCI 规范一部分的承诺的、公共的、API、协议或约定。
因此,这些解决方案是“脆弱的”,并且在实现发生变化或约定被用户配置覆盖时,可能会在最意想不到的时候中断。
容器和图像 ID 应该由启动容器实例的组件注入到 r/t 环境中,如果没有其他原因 允许其中运行的代码使用该信息来唯一标识自己以进行日志记录/跟踪等...
只是我的 0.02 美元,YMMV...
【讨论】:
【参考方案14】:顺便说一句,如果你有容器的 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/"
【讨论】:
【参考方案15】:使用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
【讨论】:
这不是我的意思。我需要能够从容器 inside 获取这些信息。基本上我需要一种方法来了解我从内部运行的容器的 ID。以上是关于如何从容器本身获取 Docker Linux 容器信息?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 docker 中从一个容器获取数据到另一个容器?我收到 ECONNREFUSED 错误