【问题标题】:How can I get Docker Linux container information from within the container itself?如何从容器本身获取 Docker Linux 容器信息?
【发布时间】: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 仅用于获取非私人信息。

标签: linux docker


【解决方案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.1 cat /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 methodJohn的风险总结:

    通过让容器访问/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】:

    为了简单起见,

    1. 容器 ID 是您在 docker 中的主机名
    2. 容器信息在 /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。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-11-09
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-10-12
                  • 1970-01-01
                  相关资源
                  最近更新 更多