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

Docker中Django无法连接PostgreSQL及GitLab CI/CD测试连接失败问题

嘿,看来你碰到了两个和Django数据库连接相关的棘手问题——Docker容器里的应用连不上PostgreSQL,还有GitLab CI跑测试时也触发了连接拒绝的错误。我来帮你一步步拆解排查,给出具体的解决办法:

一、Docker容器中Django无法连接PostgreSQL的问题

这个问题大概率是容器网络隔离导致的,毕竟容器里的localhost指的是容器自身,不是宿主机或者其他容器。给你几个核心排查方向:

  • 用Docker Compose编排服务,统一网络
    单独启动的容器默认不在同一个网络,没法直接用localhost通信。建议用Docker Compose把Django和PostgreSQL放在同一个自定义网络里,这样可以用服务名作为数据库主机名。比如写一个docker-compose.yml:

    version: '3.8'
    services:
      web:
        build: .
        command: python manage.py runserver 0.0.0.0:8000
        ports:
          - "8000:8000"
        depends_on:
          - db
        environment:
          - DATABASE_HOST=db
          - POSTGRES_USER=django_user
          - POSTGRES_PASSWORD=django_pass
          - POSTGRES_DB=django_db
      db:
        image: postgres:14-alpine
        environment:
          - POSTGRES_USER=django_user
          - POSTGRES_PASSWORD=django_pass
          - POSTGRES_DB=django_db
        volumes:
          - postgres_data:/var/lib/postgresql/data/
    
    volumes:
      postgres_data:
    

    然后在Django的settings.py里,把数据库HOST改成os.getenv('DATABASE_HOST', 'localhost'),这样就能通过服务名db访问PostgreSQL容器了。

  • 确保PostgreSQL容器配置正确
    检查PostgreSQL容器是否暴露了5432端口(如果不用Compose,需要加-p 5432:5432参数),同时环境变量POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB要和Django配置完全匹配。

  • 等待PostgreSQL完全启动
    有时候Django容器启动速度比PostgreSQL快,数据库还没准备好就发起连接,会导致失败。可以给Django的启动脚本加个等待逻辑,比如用wait-for-it工具:

    wait-for-it db:5432 -- python manage.py runserver 0.0.0.0:8000
    
二、GitLab CI中测试触发数据库连接拒绝的问题

这个报错的核心是:GitLab Runner的运行环境里默认没有启动PostgreSQL服务,而且你配置里用了localhost,自然连不上。解决步骤如下:

  • 在.gitlab-ci.yml中添加PostgreSQL服务
    GitLab CI支持通过services字段引入数据库服务,这样Runner会自动启动一个PostgreSQL容器,和你的测试容器共享网络。比如修改你的.gitlab-ci.yml:

    stages:
      - test
    
    test:
      stage: test
      image: python:3.9-slim
      services:
        - name: postgres:14-alpine
          alias: postgres  # 别名,方便Django用这个主机名连接
      variables:
        # 给PostgreSQL服务设置环境变量
        POSTGRES_USER: test_user
        POSTGRES_PASSWORD: test_pass
        POSTGRES_DB: test_db
        # 给Django设置数据库连接参数
        DATABASE_HOST: postgres
        DATABASE_PORT: 5432
      before_script:
        - apt-get update && apt-get install -y postgresql-client  # 可选,用来测试连接
        - pip install --upgrade pip
        - pip install -r requirements.txt
        # 可选:测试数据库是否可达
        - psql -h $DATABASE_HOST -U $POSTGRES_USER -d $POSTGRES_DB -c "SELECT 1;"
      script:
        - python manage.py migrate
        - python manage.py test
    
  • 动态修改Django的数据库配置
    在Django的settings.py里,不要硬编码localhost,而是通过环境变量读取主机名,这样在CI环境下自动切换到postgres:

    import os
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': os.getenv('POSTGRES_DB', 'default_test_db'),
            'USER': os.getenv('POSTGRES_USER', 'test_user'),
            'PASSWORD': os.getenv('POSTGRES_PASSWORD', 'test_pass'),
            'HOST': os.getenv('DATABASE_HOST', 'localhost'),
            'PORT': os.getenv('DATABASE_PORT', '5432'),
        }
    }
    
  • 检查Runner的执行器类型
    如果你的GitLab Runner用的是shell执行器(直接在EC2实例上跑命令),那services字段不会生效,你需要在EC2实例上手动安装并启动PostgreSQL服务,然后修改Django配置连接到EC2的localhost。不过更推荐用docker执行器,这样配合services更灵活,也不会污染EC2实例环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:59:20