Neo4j Docker 与 Python FastAPI、https 上的 Traefic 组合,"Connection refused"

Neo4j Docker Compose with Python FastAPI, Traefic on https, "Connection refused"

我正在使用 Docker 组合多个容器(Full Stack FastAPI 的自定义版本,但包含 Neo4j)。

完整 docker-compose.yml here 和 neo4j 的摘录:

  neo4j:
    image: neo4j
    networks:
      - ${TRAEFIK_PUBLIC_NETWORK?Variable not set}
      - default
    ports:
      - "6477:6477"
      - "7474:7474"
      - "7687:7687"
    volumes:
      - app-neo4j-data:/data
      - app-neo4j-plugins:/plugins
    env_file:
      - .env
    environment:
      - NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
      - NEO4J_AUTH=${NEO4J_USERNAME?Variable not set}/${NEO4J_PASSWORD?Variable not set}
      - NEO4J_dbms_default__advertised__address=0.0.0.0
      - NEO4J_dbms_default__listen__address=0.0.0.0
      - NEO4J_dbms_connector_bolt_advertised__address=0.0.0.0:7687
      - NEO4J_dbms_connector_bolt_listen__address=0.0.0.0:7687
      - NEO4J_dbms_connector_http_listen__address=:7474
      - NEO4J_dbms_connector_http_advertised__address=:7474
      - NEO4J_dbms_connector_https_listen__address=:6477
      - NEO4J_dbms_connector_https_advertised__address=:6477
      - NEO4J_dbms_connector_bolt_listen__address=:7687
      - NEO4J_dbms_mode=SINGLE
    deploy:
      labels:
        - traefik.enable=true
        - traefik.docker.network=${TRAEFIK_PUBLIC_NETWORK?Variable not set}
        - traefik.constraint-label=${TRAEFIK_PUBLIC_TAG?Variable not set}
        - traefik.http.routers.${STACK_NAME?Variable not set}-neo4j-http.rule=Host(`neo4j.${DOMAIN?Variable not set}`)
        - traefik.http.routers.${STACK_NAME?Variable not set}-neo4j-http.entrypoints=http
        - traefik.http.routers.${STACK_NAME?Variable not set}-neo4j-http.middlewares=${STACK_NAME?Variable not set}-https-redirect
        - traefik.http.routers.${STACK_NAME?Variable not set}-neo4j-https.rule=Host(`neo4j.${DOMAIN?Variable not set}`)
        - traefik.http.routers.${STACK_NAME?Variable not set}-neo4j-https.entrypoints=https
        - traefik.http.routers.${STACK_NAME?Variable not set}-neo4j-https.tls=true
        - traefik.http.routers.${STACK_NAME?Variable not set}-neo4j-https.tls.certresolver=le
        - traefik.http.services.${STACK_NAME?Variable not set}-neo4j.loadbalancer.server.port=7474
      replicas: 1
      resources:
        limits:
          memory: 1024M
        reservations:
          memory: 500M
      restart_policy:
        condition: on-failure

我尝试使用 bolt://login:password@neo4j:7687 从后端访问 bolt 但出现以下错误:

neo4j.exceptions.ServiceUnavailable: Couldn't connect to neo4j:7687 (resolved to ('10.0.3.11:7687',)):
Failed to establish connection to ResolvedIPv4Address(('10.0.3.11', 7687)) (reason [Errno 111] Connection refused)

我在 Whosebug 上查看了大量回复,但一无所获。这确实适用于开发,但我还没有在那里实现 https,所以我不确定这是否是导致问题的原因。

我很茫然,希望得到任何指导。

此特定问题与 Docker 或 Neo4j 没有直接关系。相反,它需要有限的时间来初始化数据库。解决方案是重试连接。这是我的处理方式:

from tenacity import after_log, before_log, retry, stop_after_attempt, wait_fixed

max_tries = 60 * 5  # 5 minutes
wait_seconds = 1

@retry(
    stop=stop_after_attempt(max_tries),
    wait=wait_fixed(wait_seconds),
    before=before_log(logger, logging.INFO),
    after=after_log(logger, logging.WARN),
)
def initNeo4j() -> None:
    try:
        init_gdb()
    except Exception as e:
        raise e

其中 init_gdb() 是初始化 Neo4j 的脚本。

问题出现在 Docker 完成容器实例化并且主后端服务器开始初始化和构建自身之后。创建管理员用户时,数据库必须已启动并且 运行,如果未启动,则会出现此错误。

鉴于相同的错误被用于涵盖众多问题,不一定清楚数据库未准备就绪,而不是到达它的某些设置不正确。