如何将在 Docker 容器中运行的 Grafana 连接到在主机上运行的 Prometheus 数据源(在 Docker for Mac 上)?

Posted

技术标签:

【中文标题】如何将在 Docker 容器中运行的 Grafana 连接到在主机上运行的 Prometheus 数据源(在 Docker for Mac 上)?【英文标题】:How to connect Grafana running in a Docker container to a Prometheus data source running on the host machine (on Docker for Mac)? 【发布时间】:2020-03-01 03:16:53 【问题描述】:

我已经在localhost:57475/metrics 启动了一个 Prometheus 服务器:

使用以下 Go 代码:

package main

import (
    "net/http"

    "contrib.go.opencensus.io/exporter/prometheus"
    log "github.com/sirupsen/logrus"
    "go.opencensus.io/plugin/ochttp"
    "go.opencensus.io/stats/view"
)

func main() 
    stop := make(chan struct)

    server := &http.ServerAddr: ":8080"

    statsMux := http.NewServeMux()
    statsServer := &http.ServerHandler: statsMux, Addr: ":57475"

    if err := view.Register(ochttp.DefaultServerViews...); err != nil 
        log.WithError(err).Fatal("register HTTP metrics view")
    

    exporter, err := prometheus.NewExporter(prometheus.Options
        Namespace: "default",
    )
    if err != nil 
        log.WithError(err).Fatal("create Prometheus exporter")
    

    view.RegisterExporter(exporter)

    statsMux.Handle("/metrics", exporter)

    originalHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) 
        w.Write([]byte("Hello, World!"))
    )
    och := &ochttp.Handler
        Handler: originalHandler,
    

    server.Handler = och

    go func() 
        log.Info("Starting stats server...")
        if err := statsServer.ListenAndServe(); err != nil 
            log.WithError(err).Fatal("listen and serve stats")
        
    ()

    go func() 
        log.Info("Starting server...")
        if err := server.ListenAndServe(); err != nil 
            log.WithError(err).Fatal("listen and serve service endpoints")
        
    ()

    <-stop

我还使用以下命令(在 https://grafana.com/docs/installation/docker/ 之后)在容器中启动了 Grafana:

> docker run --detach --publish 3000:3000  --env "GF_SECURITY_ADMIN_PASSWORD=secret" grafana/grafana
2a17ad2bcc05e2955190129b981b3329cd2c5e89098e28b443337ac79ed607f2

在 Grafana 中,我想连接到在我的 Mac 上运行的 Prometheus 导出器 localhost。在https://docs.docker.com/docker-for-mac/networking/ 之后,我尝试使用特殊的DNS 名称host.docker.internal,因此将URL 指定为http://host.docker.internal:57475/metrics。但是,当我单击“保存并测试”时,这会导致 HTTP Error Not Found

知道为什么这不起作用吗?

更新

我没有使用特殊的 DNS 名称 host.docker.internal,而是尝试将服务器和 Grafana 组合成一个 Docker Compose 多容器应用程序,并使用 Docker 网桥连接它们,但这也没有用。具有以下目录结构:

.
├── docker-compose.yml
└── server
    ├── Dockerfile
    ├── go.mod
    ├── go.sum
    └── main.go

还有以下docker-compose.yml

version: '3'
services:
  server:
    build: ./server
    ports:
      - "8080:8080"
      - "57475:57475"
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"

还有以下Dockerfile

FROM golang:1.12

WORKDIR /go/src/app
COPY . .

RUN go get -d -v ./...
RUN go install -v ./...

CMD ["app"]

如果我附加到 Grafana 容器并 curl server:8080server:57475/metrics,我会收到响应:

useprometheus> docker exec -it --user root useprometheus_grafana_1 /bin/ash
/usr/share/grafana # apk add curl
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
(1/3) Installing nghttp2-libs (1.39.2-r0)
(2/3) Installing libcurl (7.66.0-r0)
(3/3) Installing curl (7.66.0-r0)
Executing busybox-1.30.1-r2.trigger
OK: 17 MiB in 24 packages
/usr/share/grafana # curl server:8080
Hello, World!/usr/share/grafana # curl server:57475/metrics
# HELP default_opencensus_io_http_server_latency Latency distribution of HTTP requests
# TYPE default_opencensus_io_http_server_latency histogram
default_opencensus_io_http_server_latency_bucketle="1" 1
default_opencensus_io_http_server_latency_bucketle="2" 1
default_opencensus_io_http_server_latency_bucketle="3" 1
default_opencensus_io_http_server_latency_bucketle="4" 1

但是,如果我尝试在 Grafana 管理员中添加相同的 URL,我会收到相同的错误:

换句话说,虽然我可以从 Grafana 容器中 curl 这个端点,但我不能将它用作 Grafana 仪表板中的数据源 URL,这让我觉得这是 Grafana 特有的。知道为什么这不起作用吗?

【问题讨论】:

使用你的主机 ip 连接或在你的 docker run 容器中使用 --network host 并使用 localhost 连接 【参考方案1】:

事实证明我不太了解 Prometheus 的工作原理。示例中的 Go 应用程序创建了一个 Prometheus exporter,它仍然需要被 Prometheus server 抓取,而该服务器又是 Grafana 的数据源。

我把目录结构修改成这样:

.
├── docker-compose.yml
├── prometheus
│   ├── Dockerfile
│   └── prometheus.yml
└── server
    ├── Dockerfile
    ├── go.mod
    ├── go.sum
    └── main.go

docker-compose.yml 在哪里

version: '3'
services:
  server:
    build: ./server
    ports:
      - "8080:8080"
      - "57475:57475"
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
  prometheus:
    build: ./prometheus
    ports:
      - "9090:9090"

prometheus/Dockerfile

FROM prom/prometheus

ADD prometheus.yml /etc/prometheus

prometheus/prometheus.yml

global:
  scrape_interval:     15s

scrape_configs:
  - job_name: 'server'

    static_configs:
      - targets: ['server:57475']

现在我可以将 prometheus:9090 添加为数据源 URL:

【讨论】:

【参考方案2】:

--network host 添加到您的docker run 命令中:

docker run --network host...

然后在 Grafana 设置中使用localhost:[prometheus_port]

相关docs

【讨论】:

如果我尝试这个并尝试curl http://localhost:3000/,我会得到Failed to connect to localhost port 3000: Connection refused(也就是说,我根本看不到 Grafana 仪表板) Grafana 容器启动了吗?它可能已经关闭了。 服务正在运行,我可以在来自docker-compose up 的日志中看到grafana_1 | t=2019-11-04T20:48:07+0000 lvl=info msg="HTTP Server Listen" logger=http.server address=0.0.0.0:3000 protocol=http subUrl= socket=(在第二个示例中,我在docker-compose.yml 中指定了network: "host")。【参考方案3】:

格拉法纳 - 普罗米修斯 只要您将 Grafana 和 Prometheus 都作为 docker 映像运行,这将起作用,因此在开始之前,请运行以下命令,通过运行此命令“docker ps”确保 prometheus 和 Grafana 映像均已启动

如果它们没有启动,请在终端上运行此命令

docker run -p 9090:9090 prom/prometheus .
docker run -d -p 3000:3000 grafana/grafana-enterprise

要将 prometheus 连接到 GRAFANA,您需要从主机获取作为 docker 映像运行的 prometheus 服务器 IP 地址。在终端上使用此命令显示所有容器 ID docker ps -a

您将看到显示的 prometheus 服务器容器 ID,例如“faca0c893603”。请复制 ID 并在您的终端上运行以下命令以查看您的 Prometheus 服务器的 IP 地址

docker inspect -f 'range.NetworkSettings.Networks.IPAddressend' faca0c893603

注意:(faca0c893603 是 prom/prometheus 服务器的 ContainerID)当你运行命令时,它会显示 Prometheus 容器的 IP 地址(172.17.0.4),它需要与 prometheus 服务器的端口进行映射格拉法纳。

在 Grafana 上的数据源上,将其放在 URL http://172.17.0.3:9090 上并尝试保存并测试

【讨论】:

以上是关于如何将在 Docker 容器中运行的 Grafana 连接到在主机上运行的 Prometheus 数据源(在 Docker for Mac 上)?的主要内容,如果未能解决你的问题,请参考以下文章

将在 Ubuntu VM 内运行的 docker 容器端口与 VM 的主机网络连接 [关闭]

如何以编程方式(在 Docker 上)获取运行容器的容器 ID?

Docker 容器详解

docker容器

Riddler助力Docker容器为runC运行环境做准备

Docker 容器