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

添加PostgreSQL后Docker中Gunicorn无法启动的问题求助

Django+PostgreSQL Docker部署连接问题排查与解决

问题概述

已成功实现Django+Gunicorn+Nginx的Docker部署,添加PostgreSQL后出现异常:Postgres容器可正常启动,但Gunicorn容器无法启动,日志显示连接127.0.0.1:5432被拒绝。修改settings中的PostgreSQL主机IP后仅改变错误信息,问题未解决。

错误日志

C:\Users\stephane.bernardelli>docker logs testapp-django_gunicorn-1
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 244, in ensure_connection
    self.connect()
  File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 225, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/postgresql/base.py", line 203, in get_new_connection
    connection = Database.connect(**conn_params)
  File "/usr/local/lib/python3.10/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: connection to server at "127.0.0.1", port 5432 failed: Connection refused
        Is the server running on that host and accepting TCP/IP connections?


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/app/manage.py", line 22, in <module>
    main()
  File "/app/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 414, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 98, in wrapped
    res = handle_func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/migrate.py", line 91, in handle
    self.check(databases=[database])
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 487, in check
    all_issues = checks.run_checks(
  File "/usr/local/lib/python3.10/site-packages/django/core/checks/registry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "/usr/local/lib/python3.10/site-packages/django/core/checks/model_checks.py", line 36, in check_all_models
    errors.extend(model.check(**kwargs))
  File "/usr/local/lib/python3.10/site-packages/django/db/models/base.py", line 1461, in check
    *cls._check_indexes(databases),
  File "/usr/local/lib/python3.10/site-packages/django/db/models/base.py", line 1864, in _check_indexes
    connection.features.supports_covering_indexes
  File "/usr/local/lib/python3.10/site-packages/django/utils/functional.py", line 49, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/postgresql/features.py", line 84, in is_postgresql_11
    return self.connection.pg_version >= 110000
  File "/usr/local/lib/python3.10/site-packages/django/utils/functional.py", line 49, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/postgresql/base.py", line 354, in pg_version
    with self.temporary_connection():
  File "/usr/local/lib/python3.10/contextlib.py", line 135, in __enter__
    return next(self.gen)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 639, in temporary_connection
    with self.cursor() as cursor:
  File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 284, in cursor
    return self._cursor()
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 260, in _cursor
    self.ensure_connection()
  File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 243, in ensure_connection
    with self.wrap_database_errors:
  File "/usr/local/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 244, in ensure_connection
    self.connect()
  File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 225, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/backends/postgresql/base.py", line 203, in get_new_connection
    connection = Database.connect(**conn_params)
  File "/usr/local/lib/python3.10/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: connection to server at "127.0.0.1", port 5432 failed: Connection refused
        Is the server running on that host and accepting TCP/IP connections?

配置文件

docker-compose.yml

version: '3.8'

services:
  rabbitmq3:
    image: rabbitmq:3-alpine
    ports:
      - 5672:5672
    networks:
      - main

  postgres:
    container_name: postgres
    hostname: postgres
    image: postgres:latest
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=Scripts Application
    networks:
      - main
    ports:
      - "5432:5432"
    restart: on-failure
    volumes:
      - postgresql-data:/var/lib/postgresql/data

  django_gunicorn:
    volumes:
      - static:/static
      - media:/media
    env_file:
      - env
    build:
      context: .
    ports: 
      - "8000:8000"
    command: sh -c "python manage.py migrate && python manage.py collectstatic --no-input && gunicorn main.wsgi:application --bind 0.0.0.0:8000"
    depends_on:
      - postgres
    networks:
      - main

  nginx:
    build: ./nginx
    volumes:
      - static:/static
      - media:/media
    ports:
      - "80:80"
    depends_on:
      - django_gunicorn
    networks:
      - main

  celery:
    restart: always
    build:
      context: .
    command: celery -A main worker -P eventlet -c 100 -l INFO
    env_file:
      - env
    depends_on:
      - rabbitmq3
      - django_gunicorn
      - postgres
    networks:
      - main

networks:
  main:

volumes:
  postgresql-data:
  static:
  media:

Dockerfile

FROM python:3.10.5-alpine

ENV PYTHONUNBEFFERED = 1 

RUN pip install --upgrade pip

COPY ./requirements.txt .
RUN \
 apk add --no-cache postgresql-libs && \
 apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev && \
 python3 -m pip install -r requirements.txt --no-cache-dir && \
 apk --purge del .build-deps
COPY ./src /app

WORKDIR /app

排查与解决步骤

1. 修正Django数据库连接的HOST配置

在Docker Compose的同一网络中,容器之间可以通过服务名直接通信。你的PostgreSQL服务名为postgres,因此Django的数据库配置中HOST必须设置为postgres,而非127.0.0.1或其他IP地址。

修改settings.py中的数据库配置:

import os

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('POSTGRES_DB', 'Scripts Application'),
        'USER': os.environ.get('POSTGRES_USER', 'postgres'),
        'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
        'HOST': 'postgres',  # 关键:使用服务名作为主机
        'PORT': '5432',
    }
}

建议通过环境变量读取配置,保持与docker-compose.yml的一致性,避免硬编码。

2. 解决容器启动顺序与数据库就绪问题

depends_on仅保证Postgres容器先启动,但不保证数据库服务已完全就绪(比如初始化完成)。Gunicorn容器启动后立即执行migrate,此时Postgres可能还未准备好接受连接,导致失败。

方案:添加等待脚本

在django_gunicorn的启动命令中加入等待逻辑,直到Postgres服务就绪再执行后续操作:

  • 首先在Dockerfile中安装PostgreSQL客户端工具(用于pg_isready命令):
    FROM python:3.10.5-alpine
    
    ENV PYTHONUNBUFFERED=1 
    
    RUN pip install --upgrade pip
    
    COPY ./requirements.txt .
    RUN \
     apk add --no-cache postgresql-libs postgresql-client && \  # 添加postgresql-client
     apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev && \
     python3 -m pip install -r requirements.txt --no-cache-dir && \
     apk --purge del .build-deps
    COPY ./src /app
    
    WORKDIR /app
    
  • 修改docker-compose.yml中django_gunicorn的command:
    command: sh -c "until pg_isready -h postgres -p 5432 -U postgres; do sleep 2; done; python manage.py migrate && python manage.py collectstatic --no-input && gunicorn main.wsgi:application --bind 0.0.0.0:8000"
    

这段命令会每隔2秒检查一次Postgres是否就绪,直到连通后再执行迁移和启动Gunicorn。

3. 检查数据库名称的空格问题

你的POSTGRES_DB设置为Scripts Application(包含空格),虽然PostgreSQL支持带空格的数据库名,但可能在某些场景下引发解析问题。建议将其修改为下划线分隔的格式:

  • 在docker-compose.yml中修改:
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=Scripts_Application
    
  • 同步修改settings.py中的NAME配置,或通过环境变量统一设置。

4. 验证容器网络连通性

如果以上步骤仍未解决问题,可手动验证Gunicorn容器与Postgres容器的网络连通性:

  1. 进入Gunicorn容器:
    docker exec -it testapp-django_gunicorn-1 sh
    
  2. 尝试Ping Postgres服务:
    ping postgres
    
    如果能Ping通,说明网络连接正常;如果不通,检查Docker网络配置是否正确(确保两个容器都在main网络中)。
  3. 测试端口连通性:
    telnet postgres 5432
    
    如果连接成功,说明Postgres端口开放正常;如果失败,检查Postgres容器是否正常监听5432端口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 21:36:29