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

部署PostgreSQL数据库时遭遇psycopg.OperationalError连接失败求助

部署PostgreSQL时遭遇psycopg.OperationalError连接失败

错误日志

File "/app/migrations/__main__.py", line 41, in <module>
    run(migrate())
  File "/usr/local/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/app/migrations/__main__.py", line 24, in migrate
    await up(db_url, to=amount)
  File "/app/migrations/__init__.py", line 94, in up
    await ensure_migrations_table(db_url)
  File "/app/migrations/__init__.py", line 68, in ensure_migrations_table
    async with await AsyncConnection.connect(db_url) as conn:
  File "/usr/local/lib/python3.10/site-packages/psycopg/connection_async.py", line 130, in connect
    raise ex.with_traceback(None)
psycopg.OperationalError: connection failed: Connection refused
	Is the server running on host "10.28.10.150" and accepting
	TCP/IP connections on port 5432?

GitLab CI的build-db-image配置

build-db-image:
  stage: build
  image: docker
  services:
    - docker:git
    - docker:dind
  variables:
    POSTGRES_USER: example_user
    POSTGRES_PASSWORD: password
    POSTGRES_DB: example_db
    POSTGRES_VOLUME: /var/lib/postgresql/data
    POSTGRES_PORT: 5432
    GITLAB_DB_IMAGE: ${CI_REGISTRY_IMAGE}/postgres
  before_script:
    - apk add --no-cache docker-compose
    - echo $CI_JOB_TOKEN | docker login -u gitlab-ci-token registry.gitlab.com --password-stdin
  script:
    - docker run -d --name mar-15-et-database-service.default.svc.cluster.local -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD -e POSTGRES_USER=$POSTGRES_USER -e POSTGRES_DB=$POSTGRES_DB -p $POSTGRES_PORT:5432 -v postgres_data:$POSTGRES_VOLUME postgres:14.5-bullseye
    - docker build -f api/Dockerfile.dev --build-arg POSTGRES_HOST=mar-15-et-database-service.default.svc.cluster.local --tag my_migration_image:latest api
    - docker run -e POSTGRES_HOST=mar-15-et-database-service.default.svc.cluster.local my_migration_image:latest
    - docker tag my_migration_image:latest $GITLAB_DB_IMAGE:latest
    - docker push $GITLAB_DB_IMAGE:latest

    # - docker build -f api/Dockerfile.dev --tag $GITLAB_DB_IMAGE:latest api
    # - docker push $GITLAB_DB_IMAGE:latest
  only:
    - main

Dockerfile.dev内容

FROM python:3.10-bullseye
RUN python -m pip install --upgrade pip
# RUN pip install python-dotenv
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.9.0/wait /wait
RUN chmod +x /wait
WORKDIR /deps
COPY requirements.txt requirements.txt
RUN python -m pip install -r requirements.txt
WORKDIR /app
COPY migrations migrations
CMD /wait && python -m migrations up && uvicorn main:app --reload --host 0.0.0.0

云端部署命令

% glv-cloud-cli deploy -a database \
  -i registry.gitlab.com/wmo90/reel-reviews/postgres:latest \
  -e POSTGRES_DB=example_db \
  -e POSTGRES_USER=example_user \
  -e POSTGRES_PASSWORD=password \
  -m /var/lib/postgresql/data \
  -p 5432 \
  -x=false

已尝试的解决方法

  • 跳过GitLab CI中启动Postgres并构建镜像的步骤,直接部署"database"应用,仍出现相同错误
  • 在GitLab CI中启动Postgres容器并执行迁移,迁移脚本仍无法连接数据库

问题根源与修复方案

1. 镜像混淆(核心问题)

你推送到GitLab Registry的是Python应用镜像(包含迁移脚本和API服务),但部署"database"应用时却使用了这个镜像——该镜像内部根本没有运行PostgreSQL服务,迁移脚本自然无法连接到数据库。

修复:

  • 部署"database"应用时使用官方PostgreSQL镜像,而非应用镜像:
    % glv-cloud-cli deploy -a database \
      -i postgres:14.5-bullseye \
      -e POSTGRES_DB=example_db \
      -e POSTGRES_USER=example_user \
      -e POSTGRES_PASSWORD=password \
      -m /var/lib/postgresql/data \
      -p 5432 \
      -x=false
    
  • 修改GitLab CI任务,单独构建推送Python应用镜像,避免与PostgreSQL镜像混淆:
    # 新增或修改CI任务为构建应用镜像
    build-app-image:
      stage: build
      image: docker
      services:
        - docker:dind
      variables:
        GITLAB_APP_IMAGE: ${CI_REGISTRY_IMAGE}/app
      before_script:
        - echo $CI_JOB_TOKEN | docker login -u gitlab-ci-token registry.gitlab.com --password-stdin
      script:
        - docker build -f api/Dockerfile.dev --tag $GITLAB_APP_IMAGE:latest api
        - docker push $GITLAB_APP_IMAGE:latest
      only:
        - main
    

2. 迁移脚本的数据库等待逻辑失效

你使用了wait工具但未配置任何等待规则,导致迁移脚本在PostgreSQL未完全启动就绪时就开始执行,触发连接拒绝。

修复:
修改Dockerfile.dev,添加wait工具所需的环境变量,确保它等待数据库服务就绪:

FROM python:3.10-bullseye
RUN python -m pip install --upgrade pip
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.9.0/wait /wait
RUN chmod +x /wait
# 配置wait工具等待数据库地址,可在运行时通过环境变量覆盖
ENV WAIT_HOSTS=postgres:5432
ENV WAIT_TIMEOUT=300
ENV WAIT_SLEEP_INTERVAL=5
WORKDIR /deps
COPY requirements.txt requirements.txt
RUN python -m pip install -r requirements.txt
WORKDIR /app
COPY migrations migrations
COPY main.py main.py # 确保复制API服务的入口文件
CMD /wait && python -m migrations up && uvicorn main:app --reload --host 0.0.0.0

3. GitLab CI中的容器网络与就绪问题(可选)

如果需要在CI中验证迁移逻辑,需确保Postgres容器和迁移容器在同一网络,且迁移脚本等待数据库就绪:

script:
  # 创建专用网络,避免容器名解析问题
  - docker network create app-net
  # 启动Postgres并加入网络
  - docker run -d --name postgres --network app-net -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD -e POSTGRES_USER=$POSTGRES_USER -e POSTGRES_DB=$POSTGRES_DB postgres:14.5-bullseye
  # 构建迁移镜像
  - docker build -f api/Dockerfile.dev --tag my_migration_image:latest api
  # 运行迁移容器,指定数据库地址和等待规则
  - docker run --network app-net -e POSTGRES_HOST=postgres -e WAIT_HOSTS=postgres:5432 my_migration_image:latest

4. 云端应用的数据库地址配置

部署Python应用时,需将POSTGRES_HOST设置为云端"database"应用的服务域名(或集群内部服务名,比如database),确保应用能正确访问数据库服务。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:47:05