【问题标题】:How to access Docker container's internal IP address from host?如何从主机访问 Docker 容器的内部 IP 地址?
【发布时间】:2019-05-28 06:39:26
【问题描述】:

我的 Mac 主机上运行了 2 个 docker 容器 - 容器 1 是 Jenkins from Docker Hub,容器 2 是 SonarQube from Docker Hub。我有两个容器成功运行。我可以通过转到 http://localhost:8080/ 从我的主机访问 Jenkins,我可以通过转到 http://localhost:9000/ 访问我的 SonarQube。

Jenkins 容器是这样启动的:

docker run -d -p 8080:8080 -p 50000:50000 jenkins/jenkins:latest

SonarQube 容器是这样启动的:

docker run -d -p 9000:9000 sonarqube

现在我想让每个容器相互通信,所以我需要向每个容器提供另一个容器的 IP 地址。

我通过执行这个得到了IP address of each container

docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_name_or_id

这将为 Jenkins 容器返回 IP 地址 172.17.0.2,为 SonarQube 容器返回 172.17.0.3。但是,当我尝试通过转到http://172.17.0.2:8080 从我的主机访问 Jenkins 容器时,我得到一个请求超时。当我尝试通过转到 http://172.17.0.3:9000 来从主机访问 SonarQube 容器时,也会发生同样的事情

这是正常行为吗?

难道我不能通过它们的内部 IP 地址从我的主机访问每个容器吗?

我如何测试一个容器(例如 Jenkins)是否可以通过 IP 地址访问另一个容器(例如 SonarQube)?

【问题讨论】:

    标签: docker jenkins sonarqube


    【解决方案1】:

    接受的答案 (https://stackoverflow.com/a/53992787/7730554) 已经提供了我个人通常更喜欢使用 docker compose 的有效选项。

    但是当您在 Mac 上运行 Docker 时,您也可以将 host.docker.internal 与定义的转发主机端口结合使用。因此,即使您的主机 IP 发生变化,Docker 也会注意将 host.docker.internal 解析为相应的 IP。

    https://docs.docker.com/desktop/mac/networking/。 请注意,这仅适用于开发模式,并且在您使用 Docker Desktop 时有效。

    【讨论】:

    • 您能否展示一个示例或文档链接?我猜这 host.docker.internal 是 docker-compose 中的一条路径,但根据您的描述,我无法确定该设置的外观。
    • 我添加了对我的答案的引用。使用 Docker Desktop 时,您可以简单地将 host.docker.internal 作为主机名从容器内连接到主机,Docker 会注意将其解析为主机的当前 IP。
    【解决方案2】:

    这是正常行为吗?我不应该能够通过它们的内部 IP 地址从我的主机访问每个容器吗?

    您所描述的是正常行为:您无法从 MacOS 主机直接访问 Docker 内部 IP 地址。见"Per-container IP addressing is not possible" in the Docker for Mac docs

    如何测试一个容器(例如 Jenkins)是否可以通过 IP 地址访问另一个容器(例如 SonarQube)?

    这不是我通常“测试”的东西本身。启动两个进程并让它们建立正常的(HTTP)连接;如果有效,您将看到适当的日志消息,如果无效,您将看到投诉。 (在容器中获取根 shell 以将 ICMP 数据包从一个容器发送到另一个容器似乎是一种流行的选择,但效果并不明显。)

    另外:不要通过明确的 IP 地址建立此连接。正如您已经注意到的,Docker 内部 IP 地址在某些情况下不可用,并且在您重新启动容器时它们会发生变化。相反,Docker 提供了一个内部 DNS 服务,可以在容器之间通信时解析主机名,但需要显式设置一个non-default bridge network。该设置如下所示:

    docker network create jenkinsnet
    docker run --name sonarqube -d --net jenkinsnet \
      -p 9000:9000 \
      sonarqube
    docker run --name jenkins -d --net jenkinsnet \
      -p 8080:8080 -p 50000:50000 \
      -e SONARQUBE_URL=http://sonarqube:9000 \
      jenkins/jenkins:latest
    

    所以我明确地创建了一个网络;启动连接到它的两个容器;并告诉客户端容器(通过环境变量)服务器容器在哪里。您不必使用docker run -p 发布端口以通过这种方式访问​​它们;无论您是否这样做,都使用服务器进程正在侦听的端口(@98​​7654325@ 选项中的 second 端口号)。

    从主机,您到达容器的唯一(便携、可靠)路径是通过其发布的端口。

    【讨论】:

    • 您的解决方案要优雅得多,但我意识到我可以只使用主机的 IP 作为另一个容器的地址。因此,当我在主机上执行ifconfig 并看到我的IP 为192.168.0.14 时,我将Jenkins 容器中的Sonar 地址设置为192.168.0.14:9000,而在Sonar 容器中,我将Jenkins 地址设置为192.168.0.14:8080。我将不得不更新这些 IP,因为我的主机 IP 可以更改,但它足以满足我的需要。
    【解决方案3】:

    看起来您正在使用默认的bridge 网络模型。内部 IP 用于每个容器在 bridge 网络下相互通信。您无法从主机访问它们。

    您有多种选择。

    1. 您可以在 Jenkins 中将 http://172.17.0.3:9000 配置为您的声纳端点。
    2. 您可以在声纳中将 http://172.17.0.2:8000 配置为您的 jenkins 端点。
    3. 如果您不想在 Ips 以上硬编码,那么您的两个容器都可以使用 Docker Default GatewayIp(172.17.0.1) 及其internal 端口与每个容器通信。所以基本上你也可以配置http://172.17.0.1

    注意 - 如果您定义 user defined bridge network,则会更改默认网关 IP。

    https://docs.docker.com/v17.09/engine/userguide/networking/#the-default-bridge-network

    https://docs.docker.com/network/network-tutorial-standalone/

    如果您想使用 docker-compose 启动两个容器,那么您可以使用服务名称链接两个容器。只需关注Networking in Compose

    【讨论】:

    • 我意识到我可以只使用我的主机的 IP 作为另一个容器的地址。因此,当我在主机上执行ifconfig 并看到我的IP 为192.168.0.14 时,我将Jenkins 容器中的Sonar 地址设置为192.168.0.14:9000,在Sonar 容器中,我将Jenkins 地址设置为192.168.0.14:8080。我将不得不更新这些 IP,因为我的主机 IP 可以更改,但它足以满足我的需要。
    • @gomisha 是的。您可以使用主机 IP。在典型的 DevOps 环境中,我尝试使用docker-compose 将两个容器相互链接,这样它们就可以只使用服务名称和端口进行通信,而无需硬编码 IP 或使用主机 Ip。
    猜你喜欢
    • 1970-01-01
    • 2013-06-14
    • 2014-05-21
    • 2022-06-29
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 2021-03-21
    相关资源
    最近更新 更多