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

时间:2014-01-08 12:13:46

标签: docker

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

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

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

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

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

16 个答案:

答案 0 :(得分:62)

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

中找到

所以你可以获得id:

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

答案 1 :(得分:41)

除非被覆盖,否则主机名似乎是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

答案 2 :(得分:32)

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

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

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

您可以按照 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中。

答案 3 :(得分:20)

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

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

答案 4 :(得分:18)

警告:在考虑之前,您应该了解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)

避免这种情况。只有了解风险并明确减轻风险,才能做到这一点。

答案 5 :(得分:8)

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

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

或者就像已经被告知过,

更短的版本
$ cat /etc/hostname
4de1c09d3f19

或者简单地说:

$ hostname
4de1c09d3f19

答案 6 :(得分:6)

为了简单起见,

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

    获取主机名,

    uname -n
    

    cat /etc/host
    

    # hostname > /usr/src//hostname.txt

    可以将输出重定向到任何文件&amp;从应用程序回读 例如:#include <stdio.h> // scanf(), printf() #include <stdlib.h> // exit(), EXIT_FAILURE #include <string.h> // strcmp() #include <stdbool.h> // bool, true, false #define MAX_COUNTRY_NAME_LENGTH 50 #define NUM_COUNTRIES 4 struct CountryTvWatch_struct { char countryName[ MAX_COUNTRY_NAME_LENGTH ]; int tvMinutes; }; typedef struct CountryTvWatch_struct CountryTvWatch; // prototypes void PrintCountryNames( CountryTvWatch ctryList[], int numCountries ); int main(void) { // Source: www.statista.com, 2010 CountryTvWatch countryList[NUM_COUNTRIES]; char countryToFind[ MAX_COUNTRY_NAME_LENGTH+1]; strcpy(countryList[0].countryName, "Brazil"); countryList[0].tvMinutes = 222; strcpy(countryList[1].countryName, "India"); countryList[1].tvMinutes = 119; strcpy(countryList[2].countryName, "U.K."); countryList[2].tvMinutes = 242; strcpy(countryList[3].countryName, "U.S.A."); countryList[3].tvMinutes = 283; // let user know what countries are available and how they are spelled PrintCountryNames(countryList, NUM_COUNTRIES); printf("Enter country name: \n"); // Note: following statement // checks for error // includes a MAX_CHAR modifier that is one less than // the length of the input field if( 1 != scanf("%49s", countryToFind) ) { perror( "scanf failed" ); exit( EXIT_FAILURE ); } // implied else, scanf successful bool countryFound = false; for ( int i = 0; i < NUM_COUNTRIES; ++i ) { // Find country's index if (strcmp(countryList[i].countryName, countryToFind) == 0) { countryFound = true; printf("People in %s watch\n", countryToFind); printf("%d minutes of TV daily.\n", countryList[i].tvMinutes); break; // exit the search loop early } } if (!countryFound) { printf("Country not found, try again.\n"); printf("Valid countries:\n"); PrintCountryNames(countryList, NUM_COUNTRIES); } return 0; } void PrintCountryNames( CountryTvWatch ctryList[], int numCountries ) { for( int i = 0; i < numCountries; i++ ) { printf("%s\n", ctryList[ i ].countryName); } }

答案 7 :(得分: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

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

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

答案 8 :(得分:6)

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

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

答案 9 :(得分:2)

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

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

然后,对Docker API的一点请求(你可以共享/var/run/docker.sock)来检索所有信息。

答案 10 :(得分:1)

某些发布的解决方案由于/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 :(得分:1)

我认为上述所有内容的“问题”在于它取决于 docker 本身或其实现的特定实现约定,以及它如何与 cgroups 和 /proc 交互,不是通过承诺的、公开的、API、协议或约定作为 OCI 规范的一部分。

因此,这些解决方案是“脆弱的”,并且可能会在实现更改或约定被用户配置覆盖时发生最不预期的情况。

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

只是我的 0.02 美元,YMMV...

答案 12 :(得分:0)

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

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

答案 13 :(得分:0)

快捷方式:

//MainController() which is a tab bar controller

class MainController: UITabBarController, LoginDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        checkLoggedInUserStatus()
    }

    fileprivate func checkLoggedInUserStatus(){
        if Auth.auth().currentUser == nil{
            DispatchQueue.main.async {
                let welcomeController = UINavigationController(rootViewController: WelcomeController())
                welcomeController.modalPresentationStyle = .fullScreen
                self.present(welcomeController, animated: false, completion: nil)
                return
            }
        } else {
            setupTabBar()
        }
    }

    fileprivate func setupTabBar(){
        tabBar.isTranslucent = false
        tabBar.barTintColor = TDGOtherBlue

        let homeController = HomeController()
        homeController.fetchCurrentUser()
        let homeViewController = UINavigationController(rootViewController: homeController)
    let chatViewController = UINavigationController(rootViewController: EditProfileController())

        viewControllers = [homeViewController, chatViewController]
    }

    func didTapLogIn() {
        checkLoggedInUserStatus()
    }
}
//NOTE: ABOVE IS THE DELEGATED FUNCTION BUT WHERE DO I DO THE DELEGATE SELF DECLARATIOn

答案 14 :(得分:-1)

我发现的最简单方法是: docker inspect --format =“ {{。Id}}”

答案 15 :(得分:-18)

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