Docker部署Django+PostgreSQL后localhost无法访问问题求助
问题背景
系统:Ubuntu 22.04.1 LTS
按照《Django for Professionals》步骤操作,使用SQLite时Django项目正常运行;容器化Django+PostgreSQL后,访问127.0.0.1:8000提示无法连接,等待后查看日志出现如下错误:
psycopg2.OperationalError: connection to server at "db" (172.21.0.2), port 5432 failed: Connection timed out
web_1 | Is the server running on that host and accepting TCP/IP connections?
当前配置文件如下:
Dockerfile
# Pull base image FROM python:3.10.6-slim-bullseye # Set environment variables ENV PIP_DISABLE_PIP_VERSION_CHECK 1 ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 # Set work directory WORKDIR /code # Install dependencies COPY ./requirements.txt . RUN pip install -r requirements.txt # Copy project COPY . .
docker-compose.yml
version: "3.9" services: web: build: . command: python /code/manage.py runserver 0.0.0.0:8000 volumes: - .:/code ports: - 8000:8000 depends_on: - db db: image: postgres:13 volumes: - postgres_data:/var/lib/postgresql/data/ environment: - "POSTGRES_HOST_AUTH_METHOD=trust" volumes: postgres_data:
settings.py数据库配置
DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": "postgres", "USER": "postgres", "PASSWORD": "postgres", "HOST": "db", # set in docker-compose.yml "PORT": 5432, # default postgres port } }
解决方案
1. 统一数据库认证配置
settings.py中设置了密码postgres,但PostgreSQL容器未配置对应环境变量,同时启用POSTGRES_HOST_AUTH_METHOD=trust会导致认证逻辑冲突。修改docker-compose.yml的db服务,明确配置与settings匹配的数据库参数:
db: image: postgres:13 volumes: - postgres_data:/var/lib/postgresql/data/ environment: - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres # 移除POSTGRES_HOST_AUTH_METHOD=trust,使用密码认证更安全
2. 解决PostgreSQL未就绪就启动Django的问题
depends_on仅保证容器启动顺序,不保证PostgreSQL服务完全就绪(如初始化完成、可接受连接),可通过以下方式处理:
方式A:添加健康检查
给db服务添加健康检查,让web服务等db就绪后再启动:
db: image: postgres:13 volumes: - postgres_data:/var/lib/postgresql/data/ environment: - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 web: build: . command: python /code/manage.py runserver 0.0.0.0:8000 volumes: - .:/code ports: - 8000:8000 depends_on: db: condition: service_healthy
方式B:添加启动等待脚本
在Dockerfile中安装wait-for-it工具,让web服务等待PostgreSQL端口就绪:
# 安装wait-for-it RUN apt-get update && apt-get install -y wait-for-it
修改web服务启动命令:
web: build: . command: wait-for-it db:5432 -- python /code/manage.py runserver 0.0.0.0:8000 volumes: - .:/code ports: - 8000:8000 depends_on: - db
3. 确保使用兼容的PostgreSQL驱动
slim版Python镜像缺少编译psycopg2的依赖,建议使用预编译的psycopg2-binary。检查requirements.txt:
# 其他依赖... psycopg2-binary>=2.9.0 django>=4.0 # 匹配书籍使用的版本
重新构建镜像:
docker-compose build --no-cache
4. 验证容器间网络连通性
若以上步骤无效,进入web容器测试与db的连通性:
# 进入web容器 docker-compose exec web bash # 测试ping db容器 ping db # 测试端口连通性 telnet db 5432
若ping不通,检查Docker网络配置;若telnet不通,确认Postgres服务是否正常启动。
内容的提问来源于stack exchange,提问作者Lite Pal

