在 Linux 主机上的 docker 容器中访问 PROPER IP 运行 上的服务

Accessing a service on the PROPER IP running in docker container on a Linux host

我的问题特定于 k6 和 InfluxDB,但我认为根本原因更为普遍。

我正在使用官方 k6 发行版及其 docker-compose.yml 到 运行 Grafana 和 InfluxDB,我从 docker-compose up -d influxdb grafana 命令开始。

Grafana 仪表板可从 localhost:3000 访问,但 运行ning k6 使用推荐的命令 $ docker run -i loadimpact/k6 run --out influxdb=http://localhost:8086/myk6db - <script.js(遵循 this 指南)k6 抛出以下错误(在 Linux 和 MacOS):

level=error msg="InfluxDB: Couldn't write stats" error="Post \"http://localhost:8086/write?consistency=&db=myk6db&precision=ns&rp=\": dial tcp 127.0.0.1:8086: connect: connection refused"

我也尝试使用 localhost 和 127.0.0.1 以及 InfluxDB 的命令。还有 docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' k6_influxdb_1 返回的 IP 地址,它要么因上述错误而失败,要么没有工作,这意味着 k6 没有抱怨,但没有数据出现在 InfluxDB 中。

但是,如果我查询网络接口正在使用的“内部 IP”地址(使用 ifconfig 命令)并使用该 IP (192.168.1.66) ,一切正常:

docker run -i loadimpact/k6 run --out influxdb=http://192.168.1.66:8086/k6db  - <test.js

所以我的问题是:

  1. 为什么 Grafana 可以与 localhost:3000 一起正常工作而 InfluxDB 与 localhost:8086 不能正常工作?
  2. 为什么只有“内部 IP”有效而其他 IP 无效?

我知道有一个类似的问题,但没有回答我的问题。

Docker 个容器 运行 在隔离网络 space 中。 Docker 可以维护内部网络,并且有 Compose 语法来创建它们。

如果您从外部 Docker space 调用 Docker 容器但在同一主机上,您通常可以连接到它 localhost , 以及 Compose ports: 部分中列出的第一个端口号。如果查看 link 的 docker-compose.yml 文件,它会列出 ports: [3000:3000],因此主机上的端口 3000 转发到容器中的端口 3000;如果您从同一主机上的浏览器调用 http://localhost:3000,它将到达转发的端口。

否则,从一个容器到另一个容器的调用通常可以使用容器的名称(如 docker run --name)或 Compose 服务名称;但是,它们必须在同一个 Docker 网络上。该 docker-compose.yml 文件还列出了

services:
  influxdb:
    networks:
      - k6
      - grafana

因此您可以使用服务的正常端口号访问 http://influxdb:8086,前提是调用容器位于这两个网络之一上。如果服务有 ports:,则不考虑容器间调用。

在 Docker 文档中,Networking in Compose 提供了有关此设置的更多详细信息。

最后一个技巧可以帮助您 运行 您尝试执行的特定命令 运行。 docker-compose run 将 运行 一个一次性命令,使用 docker-compose.yml 中某个容器的设置,除了不使用其 ports: 并替换其 command:。您引用的 docker-compose.yml 文件包含一个 k6 容器,在 k6 网络上,运行 连接 loadimpact/k6 图像。所以你大概可以 运行

docker-compose run k6 \
  run --out influxdb=http://influxdb:8086/myk6db - \
  <script.js

(可能 docker-compose.yml 中的 K6_OUT 环境变量可以为您提供 --out 选项。)

您永远不需要查找容器私有 IP 地址。它们在各种常见场景中不可用,并且在 Docker 用于容器之间调用的网络和用于来自外部的调用的已发布端口 Docker 之间,有更好的方法来调用容器。