如何从node.js应用程序获取docker映射的端口?

Nie*_*ala 8 node.js docker docker-compose

我想从node.js应用程序内部获取映射端口。

例如

docker-compose

my-app:
    build:
        context: ./my-app
    ports:
        - "80"     
    volumes:
        - /var/run/docker.sock:/tmp/docker.sock
    networks:
        - private
Run Code Online (Sandbox Code Playgroud)

docker ps -a

1234 my-app "/usr/local/bin/dock…"   About a minute ago   Up About a minute   0.0.0.0:33962->80/tcp
Run Code Online (Sandbox Code Playgroud)

我想33962从node.js应用程序获取端口。

有任何想法吗?

Tar*_*ani 8

所以第一件事是,当前,docker不会以任何直接方式在容器内部提供元数据信息。尽管有一些解决方法

现在,将Docker套接字传递到容器中时,当它涉及开发环境而不是产品环境时,您可以使用它

因此,您要做的是构建自己的元数据服务,然后让其将信息返回给您的容器,而无需暴露docker套接字本身。

现在,要获取此元数据,您可以使用两种方法

基于容器ID的元数据服务

在这种情况下,您将创建一个简单的终结点,例如/metadata/container_id,然后返回所需的数据。

该服务可以在主主机本身上运行,也可以在映射了docker套接字的容器上运行。

现在,在您的NodeJS服务中,您将获得当前的容器ID,然后使用相同的容器ID来调用此服务。可以按照以下线程中列出的不同方式完成此操作

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

您可以限制返回的数据,以防万一我只希望公开端口,仅返回端口的详细信息。

这种方法的问题在于,您仍然要让服务找出其自己的容器ID,同时还要信任它正在发送正确的容器ID

元数据服务,不传递任何信息

要获取元数据信息而不传递信息,我们需要确定哪个垫向元数据服务器发出了呼叫

可以通过使用源IP进行标识。然后,我们需要确定哪个容器属于该IP。有了容器ID后,就可以返回元数据。

下面是一个执行相同操作的简单bash脚本

#!/bin/bash
CONTAINER_IP=$SOCAT_PEERADDR
CONTAINER_ID=$(docker ps -q | xargs docker inspect -f '{{.Id}}|{{range .NetworkSettings.Networks}}{{.IPAddress}}|{{end}}' | grep "|$CONTAINER_IP|" | cut -d '|' -f 1)
echo -e "HTTP/1.1 200 OK\r\nContent-Type: application/json;\r\nServer: $SOCAT_SOCKADDR:$SOCAT_SOCKPORT\r\nClient: $SOCAT_PEERADDR:$SOCAT_PEERPORT\r\nConnection: close\r\n";
METADATA=$(docker inspect -f '{{ json .NetworkSettings.Ports }}' $CONTAINER_ID)
echo $METADATA
Run Code Online (Sandbox Code Playgroud)

现在,可以将其转换为Web服务器了socat

sudo socat -T 1 TCP-L:10081,pktinfo,reuseaddr,fork EXEC:./return_metadata.sh
Run Code Online (Sandbox Code Playgroud)

现在在容器中,当我们调用此元数据服务器时

root@a9cf6dabdfb4:/# curl 192.168.33.100:10081
{"80/tcp":[{"HostIp":"0.0.0.0","HostPort":"8080"}]}
Run Code Online (Sandbox Code Playgroud)

和docker ps相同

CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                  NAMES
a9cf6dabdfb4        nginx                 "nginx -g 'daemon of…"   3 hours ago         Up 3 hours          0.0.0.0:8080->80/tcp   nginx
Run Code Online (Sandbox Code Playgroud)

现在由您决定如何创建这样的元数据服务器。您可以使用任何方法

您也可以使用添加服务的IP extra_hosts在你docker-compose.yml做出像电话curl metaserver:10081

这应该是一种相当安全的方法,而不会损害您的需求


BMi*_*tch 3

您可以用于docker port此用途。

docker port my-app 80
Run Code Online (Sandbox Code Playgroud)

这将包括侦听器 IP。如果您需要将其剥离,可以使用 shell 来完成:

docker port my-app 80 | cut -f2 -d:
Run Code Online (Sandbox Code Playgroud)

不幸的是,这仅适用于访问 docker 套接字。我不建议在容器内安装该插座以实现这种级别的访问。

通常,大多数人通过向应用程序传递变量并控制在 docker-compose 文件中发布的端口来解决此问题。例如:

my-app:
    build:
        context: ./my-app
    ports:
        - "8080:80"     
    environment:
        - PUBLISHED_PORT=8080
    volumes:
        - /var/run/docker.sock:/tmp/docker.sock
    networks:
        - private
Run Code Online (Sandbox Code Playgroud)

然后应用程序将查看环境变量以重新配置自身。