Docker环境下添加NGINX后Django无法连接PostgreSQL的问题
基于Docker的项目已成功创建Django、NGINX和PostgreSQL镜像与容器,项目可正常启动,但登录管理面板时Django抛出错误:OperationalError at /admin/login/ connection to server at "database" (192.168.144.2), port 5432 failed: fe_sendauth: no password supplied
未添加NGINX时一切正常,添加后无法访问数据库。尝试修改nginx.conf未解决,怀疑PostgreSQL无法识别用户,也怀疑docker-compose.yml的端口配置问题,但按文档最佳实践隐藏了Django和PostgreSQL端口,仅通过NGINX连接。
相关代码片段
uwsgi.ini
[uwsgi] wsgi-file = config/wsgi.py strict = true socket = :8000 protocol = http master = true no-orphans = true die-on-term = true lazy-apps = true processes = 4 threads = 8 enable-threads = true max-requests = 500 reload-on-rss = 1024 worker-reload-mercy = 60 harakiri = 60 harakiri-verbose = true vacuum = true post-buffering = 1048576 buffer-size = 65535
nginx.conf
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; include /etc/nginx/uwsgi_params; server { listen 80; server_name localhost; location / { proxy_pass http://django:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }
Dockerfile
FROM python:3.10.0-alpine RUN apk add postgresql-client build-base postgresql-dev linux-headers pcre-dev WORKDIR /movies_admin COPY requirements.txt . RUN pip install -r requirements.txt --no-cache-dir EXPOSE 8000 COPY movies_admin .
docker-compose.yml
version: '3.8' services: django: build: context: . volumes: - "./movies_admin:/movies_admin" environment: - DB_HOST=database - POSTGRES_DB=movies_database - POSTGRES_USER=app - POSTGRES_PASSWORD=123qwe - SECRET_KEY='django-insecure-8h%wg+drqmqjkw$8wm7#)#%*fb3b%(-e!-kbdth^#9u)23u!48' command: sh -c "uwsgi --ini /movies_admin/uwsgi.ini" depends_on: - database database: image: postgres:16 environment: - POSTGRES_DB=movies_database - POSTGRES_USER=app - POSTGRES_PASSWORD=123qwe volumes: - $HOME/postgresql/data:/var/lib/postgresql/data nginx: image: nginx:latest volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf ports: - "80:80" depends_on: - django
components/database.py
import os DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ.get('DB_NAME'), 'USER': os.environ.get('DB_USER'), 'PASSWORD': os.environ.get('DB_PASSWORD'), 'HOST': os.environ.get('DB_HOST', 'database'), # name of docker container with postgresql 'PORT': os.environ.get('DB_PORT', 5432), 'OPTIONS': { 'options': '-c search_path=public,content' } } }
问题核心是Django数据库配置的环境变量名与docker-compose中的配置不匹配:
在docker-compose.yml的django服务中,你设置的数据库相关环境变量是POSTGRES_DB、POSTGRES_USER、POSTGRES_PASSWORD,但在components/database.py里,Django尝试读取的是DB_NAME、DB_USER、DB_PASSWORD,两者完全不对应,导致Django无法获取数据库的用户名、密码和库名,自然连不上PostgreSQL。
和NGINX没有关系,之前未添加NGINX时能正常工作,应该是当时的环境变量配置或本地配置文件覆盖了当前的数据库配置。
修复步骤二选一即可:
- 修改
docker-compose.yml中django服务的环境变量名,与数据库配置对应:environment: - DB_HOST=database - DB_NAME=movies_database - DB_USER=app - DB_PASSWORD=123qwe - SECRET_KEY='django-insecure-8h%wg+drqmqjkw$8wm7#)#%*fb3b%(-e!-kbdth^#9u)23u!48' - 或者修改
components/database.py中的环境变量读取名,与docker-compose中的配置对应:DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ.get('POSTGRES_DB'), 'USER': os.environ.get('POSTGRES_USER'), 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), 'HOST': os.environ.get('DB_HOST', 'database'), 'PORT': os.environ.get('DB_PORT', 5432), 'OPTIONS': { 'options': '-c search_path=public,content' } } } - 重启所有容器生效:
docker-compose down && docker-compose up -d --build
补充:depends_on仅保证容器启动顺序,不保证PostgreSQL服务完全就绪,可在django启动命令前添加等待脚本(如wait-for-it或简单shell循环)避免数据库未就绪导致的启动失败,但这不是当前报错的直接原因。
内容的提问来源于stack exchange,提问作者Артём

