問題
我正在嘗試創建一個將托管三個服務的 docker-compose 檔案。InfluxDB、Grafana 和填充資料庫的客戶 Dockerfile 中的自定義腳本。我遇到網路問題,由于連接被拒絕錯誤(如下所示),自定義腳本無法連接到 InfluxDB 。
到目前為止什么作業
有趣的是,當我從 docker-compose 檔案中洗掉自定義腳本服務(稱為 ads_agent)并從本地主機運行該腳本或什至在其自己的容器中構建和運行該 Dockerfile 時,它??連接得很好。
兩者有什么區別
我的腳本讀取一個名為 KTS_TELEMETRY_INFLUXDB_URL 的環境變數,用于 InfluxDB 客戶端的 URL 連接。當我僅從命令列運行時,我可以使用“http://localhost:8086”作為 URL,這是有效的。當我將腳本包裝在 Docker 容器中時,我使用本地機器的 LAN IP 地址,因為對它來說,localhost 只是容器。但盡管如此,這作業得很好。
在我的 docker-compose 中,由于所有三個服務都在同一個網路上,我使用“http://influxdb:8086”,因為該主機名應該系結到該服務的網路介面。確實如此,因為Grafana 使用該 URL 連接得很好。可悲的是,當我使用腳本嘗試此操作時,連接被拒絕。
錯誤
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7f18c1fec970>: Failed to establish a new connection: [Errno 111] Connection refused
我的代碼
這是我的 docker-compose.yaml
version: "3"
services:
influxdb:
container_name: influxdb
image: influxdb:2.0.9-alpine # influxdb:latest
networks:
- telemetry_network
ports:
- 8086:8086
volumes:
- influxdb-storage:/var/lib/influxdb2
restart: always
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=$KTS_TELEMETRY_INFLUXDB_USERNAME
- DOCKER_INFLUXDB_INIT_PASSWORD=$KTS_TELEMETRY_INFLUXDB_PASSWORD
- DOCKER_INFLUXDB_INIT_ORG=$KTS_TELEMETRY_INFLUXDB_ORG
- DOCKER_INFLUXDB_INIT_BUCKET=$KTS_TELEMETRY_INFLUXDB_BUCKET
- DOCKER_INFLUXDB_INIT_RETENTION=$KTS_TELEMETRY_INFLUXDB_RETENTION
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=$KTS_TELEMETRY_INFLUXDB_TOKEN
grafana:
container_name: grafana
image: grafana/grafana:8.1.7 # grafana/grafana:latest
networks:
- telemetry_network
ports:
- 3000:3000
volumes:
- grafana-storage:/var/lib/grafana
restart: always
depends_on:
- influxdb
ads_agent:
container_name: ads_agent
build: ./ads_agent
networks:
- telemetry_network
restart: always
depends_on:
- influxdb
environment:
- KTS_TELEMETRY_INFLUXDB_URL=http://influxdb:8086
- KTS_TELEMETRY_INFLUXDB_TOKEN=$KTS_TELEMETRY_INFLUXDB_TOKEN
- KTS_TELEMETRY_INFLUXDB_ORG=$KTS_TELEMETRY_INFLUXDB_ORG
- KTS_TELEMETRY_INFLUXDB_BUCKET=$KTS_TELEMETRY_INFLUXDB_BUCKET
networks:
telemetry_network:
volumes:
influxdb-storage:
grafana-storage:
這是我的 ads_agent/Dockerfile
FROM python:3.9
COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r /requirements.txt
COPY main.py .
ENTRYPOINT /usr/local/bin/python3 /main.py
ads_agent/requirements.txt 只有 influxdb-client,這是我的 ads/main.py
import os
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS
from datetime import datetime
import random
import time
token = os.environ["KTS_TELEMETRY_INFLUXDB_TOKEN"]
org = os.environ["KTS_TELEMETRY_INFLUXDB_ORG"]
bucket = os.environ["KTS_TELEMETRY_INFLUXDB_BUCKET"]
url = os.environ["KTS_TELEMETRY_INFLUXDB_URL"]
client = InfluxDBClient(url=url, token=token)
dbh = client.write_api(write_options=SYNCHRONOUS)
while True:
symbol_name = 'rand_num'
value = random.random()
timestamp = datetime.utcnow()
print(timestamp, symbol_name, value)
point = Point("mem") \
.field(symbol_name, value) \
.time(timestamp, WritePrecision.NS)
dbh.write(bucket, org, point)
time.sleep(1)
uj5u.com熱心網友回復:
你的問題不相關network connectivity,只相關startup order。盡管您定義了depends_on - influxdbfor ads_agent,但仍然有可能當您的腳本嘗試連接 influxdb 時,influx db 仍未完成。
這就是為什么手動操作可以成功的原因,因為手動操作有時間延遲,此時資料庫已經準備就緒。
原因看這個:
depends_on在啟動 web 之前不會等待 db 和 redis “準備好” - 只在它們啟動之前。如果您需要等待服務準備就緒。)
為了在腳本啟動之前確保您的資料庫真正啟動,您需要參考Compose 中的控制啟動和關閉順序:
要處理此問題,請將您的應用程式設計為在失敗后嘗試重新建立與資料庫的連接。如果應用程式重試連接,它最終可以連接到資料庫。
最好的解決方案是在您的應用程式代碼中執行此檢查,無論是在啟動時還是在由于任何原因丟失連接時。但是,如果您不需要這種級別的彈性,則可以使用包裝器腳本解決該問題:
使用諸如wait-for-it、dockerize、 sh-compatible wait-for或RelayAndContainers模板之類的工具。這些是小的包裝腳本,您可以將它們包含在應用程式的映像中以輪詢給定的主機和埠,直到它接受 TCP 連接。例如,要使用 wait-for-it.sh 或 wait-for 來包裝服務的命令:
version: "2" services: web: build: . ports: - "80:8000" depends_on: - "db" command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"] db: image: postgres或者,撰寫您自己的包裝器腳本來執行更多特定于應用程式的健康檢查。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/312804.html
標籤:码头工人 docker-compose 流入数据库 docker-networking influxdb-python
上一篇:如何組織多個Dockerfile,docker-compose.yaml和.dockerignore
下一篇:來自主機的特定容器的`ps`
