You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI+Docker Compose集成OpenSearch时出现连接拒绝错误怎么办?

问题

我正在开发一个使用Docker Compose集成OpenSearch的FastAPI项目,尝试连接OpenSearch服务时持续遇到ConnectionRefusedError。以下是我的配置:

docker-compose.yml

services:
  app:
    container_name: app-search
    build: .
    command: "uvicorn main:app --host 0.0.0.0 --port 8000 --reload"
    ports:
      - 8001:8000
    env_file:
      - .env
    networks:
      - appsearchnet
    depends_on:
      - db
      - opensearch
    restart: always
    volumes:
      - .:/app  # Mount the project directory to /app in the container

  opensearch:
    image: opensearchproject/opensearch:latest
    container_name: opensearch
    environment:
      - plugins.security.disabled=true
      - OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_ADMIN_PASSWORD}
      - cluster.name=opensearch-cluster
      - node.name=opensearch
      - discovery.seed_hosts=opensearch
      - cluster.initial_cluster_manager_nodes=opensearch
      - bootstrap.memory_lock=true
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - opensearch-data:/usr/share/opensearch/data
    ports:
      - "9200:9200"
    networks:
      - appsearchnet
    healthcheck:
      test: ["CMD-SHELL", "curl -s http://localhost:9200 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
volumes:
  opensearch-data:
networks:
  appsearchnet:
    name: appsearchnet

main.py

from db import opensearch_client

@app.on_event("startup")
def on_startup():
        opensearch_client.create_index()

OpenSearch客户端配置(db/opensearch_client.py)

from dotenv import load_dotenv
from opensearchpy import OpenSearch

load_dotenv()

opensearch_client = OpenSearch(
    hosts=[{'host': "opensearch", 'port': 9200}],
    http_auth=('admin', 'XXXX'),
    http_compress=True,
    use_ssl=False,
    verify_certs=False,
    ssl_assert_hostname=False,
    ssl_show_warn=False
)

INDEX_NAME = "books"

def create_index():
    if not opensearch_client.indices.exists(INDEX_NAME):
        opensearch_client.indices.create(
            INDEX_NAME,
            body={
                "settings": {"number_of_shards": 1},
                "mappings": {
                    "properties": {
                        "id": {"type": "integer"},
                        "title": {"type": "text"},
                        "language": {"type": "keyword"},
                        "chapters": {
                            "type": "nested",
                            "properties": {
                                "chapter_no": {"type": "integer"},
                                "title": {"type": "text"},
                                "content": {"type": "text"},
                            }
                        }
                    }
                }
            }
        )

运行时日志持续出现以下错误:

2024-10-21 12:51:19,796 - WARNING - HEAD http://opensearch:9200/books [status:N/A request:0.002s]
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/urllib3/connection.py", line 196, in _new_conn
    sock = connection.create_connection(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    raise ConnectionRefusedError: [Errno 111] Connection refused

已确认OpenSearch服务正在运行,且能通过浏览器访问http://localhost:9200/获取正常响应:

{
  "name" : "opensearch",
  "cluster_name" : "opensearch-cluster",
  "cluster_uuid" : "kGBFpJNlReiU2qdifiZsFQ",
  "version" : {
    "distribution" : "opensearch",
    "number" : "2.17.1",
    "build_type" : "tar",
    "build_hash" : "1893d20797e30110e5877170e44d42275ce5951e",
    "build_date" : "2024-09-26T21:59:32.078798875Z",
    "build_snapshot" : false,
    "lucene_version" : "9.11.1",
    "minimum_wire_compatibility_version" : "7.10.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "The OpenSearch Project: https://opensearch.org/"
}

请问该错误的原因是什么,如何解决?


原因分析

  1. depends_on仅保证容器启动顺序,不等待服务就绪:虽然app服务配置了depends_on: [opensearch],但Docker只会确保OpenSearch容器先启动,不会等待OpenSearch服务完全初始化完成。FastAPI启动时执行startup事件,此时OpenSearch可能还在加载中,导致连接被拒绝。
  2. 缺少基于健康检查的依赖等待:当前depends_on没有关联OpenSearch的健康检查结果,无法确保服务可用后再启动FastAPI。

解决方案

方案1:升级Docker Compose版本并使用健康检查依赖

修改docker-compose.yml中app服务的depends_on配置,让它等待OpenSearch的健康检查通过:

depends_on:
  opensearch:
    condition: service_healthy
  db:
    condition: service_started # 如果db也需要健康检查,同理修改

注意:该特性需要Docker Compose版本2.1及以上,确保你的Compose版本符合要求。

方案2:在FastAPI启动时添加重试逻辑

修改main.py的startup事件,增加连接重试,直到OpenSearch可用:

from db import opensearch_client
import time

@app.on_event("startup")
def on_startup():
    max_retries = 10
    retry_interval = 3
    for attempt in range(max_retries):
        try:
            opensearch_client.create_index()
            break
        except Exception as e:
            if attempt == max_retries -1:
                raise e
            print(f"OpenSearch未就绪,等待{retry_interval}秒后重试...")
            time.sleep(retry_interval)

方案3:优化OpenSearch健康检查(可选)

如果OpenSearch初始化较慢,可以调整健康检查参数,确保更快检测到服务就绪:

healthcheck:
  test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health?wait_for_status=green || exit 1"]
  interval: 10s
  timeout: 5s
  retries: 10

这里使用_cluster/health?wait_for_status=green可以确保集群状态正常后才标记为健康,比单纯检查端口更可靠。


内容的提问来源于stack exchange,提问作者Rasik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 00:13:11