部署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
相关产品推荐
相关产品推荐

