如何从主机访问 Docker 容器的内部 IP 地址?

How to access Docker container's internal IP address from host?

我的 Mac 主机上有 2 docker 个容器 运行 - 容器 1 是 Jenkins from Docker Hub and container 2 is 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 容器的 returns IP 地址为 172.17.0.2,SonarQube 容器的 IP 地址为 172.17.0.3。但是当我尝试通过转到 http://172.17.0.2:8080 从我的主机访问 Jenkins 容器时,我收到请求超时。当我尝试通过转到 http://172.17.0.3:9000

从我的主机访问 SonarQube 容器时,也会发生同样的事情

这是正常行为吗?

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

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

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

您有多种选择。

  1. 您可以在 Jenkins 中将 http://172.17.0.3:9000 配置为声纳端点。
  2. 您可以在声纳中将 http://172.17.0.2:8000 配置为您的 jenkins 端点。
  3. 如果您不想在 Ips 之上进行硬编码,那么您的两个容器都可以使用 Docker 默认 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 启动两个容器,那么您可以 link 使用服务名称来启动两个容器。关注 Networking in Compose.

Is this normal behavior? Shouldn't I be able to access each container from my host by their internal IP address?

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

How can I test that one container (e.g. Jenkins) can access the other container (e.g. SonarQube) by IP address?

这不是我通常 "test" 本身 的东西。启动两个进程并让它们建立正常的(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 发布端口即可通过这种方式访问​​它们;无论您是否这样做,都使用服务器进程正在侦听的端口(docker run -p 选项中的 second 端口号)。

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

接受的答案 () 已经提供了有效的选项,我个人通常更喜欢使用 docker 撰写。

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

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