Docker部署Django应用(Nginx+Gunicorn)数据库连接失败求助
问题描述
我是业余开发者,平时靠搜索能解决大部分问题,但Docker配置的多样性把我搞懵了。现在尝试把Django应用用Nginx和Gunicorn容器化部署到VPS,docker-compose里配置了db、django_gunicorn、nginx三个服务。db和nginx容器启动正常,但django_gunicorn运行时无法连接数据库,报错:
django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'db' ([Errno 111] Connection refused)")
已确认容器内数据库运行正常,Django settings.py里的凭据与数据库一致,HOST设为docker-compose中的db服务,端口3306。以下是我的文件结构及配置代码:
文件结构
whatsthefit - .venv - conf - __pycache__ - gunicorn_config.py - nginx - default.conf - Dockerfile - whatzthefit - App1 - App2 - manage.py - requirements.txt - .dockerignore - .env - .gitignore - docker-compose.yml - Dockerfile - entrypoint.sh
配置文件
docker-compose.yml
version: "3.7" services: db: image: mysql:oraclelinux8 restart: always environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - MYSQL_DATABASE=${DB_NAME} - MYSQL_USER=${DB_USER} - MYSQL_PASSWORD=${DB_PASS} ports: - "3306:3306" expose: - "3306" volumes: - data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${DB_USER}", "-p${MYSQL_ROOT_PASSWORD}"] interval: 10s retries: 3 django_gunicorn: volumes: - static:/static env_file: - /home/ynot/fitweb/whatzthefit/.env build: context: . ports: - "8080:8080" depends_on: - db nginx: build: ./nginx volumes: - static:/static - media:/media ports: - "84:84" depends_on: - django_gunicorn volumes: static: data: media:
NGINX default.conf
upstream django { server django_gunicorn:8080; } server { listen 84; location / { proxy_pass http://django; } location /static/ { alias /static; } location /media/{ alias /media; } }
nginx Dockerfile
FROM nginx:1.25.4-alpine-slim COPY ./default.conf /etc/nginx/conf.d/default.conf
主Dockerfile
FROM nginx:1.25.4-alpine-slim # replace the nginx default conf by the one we made in this folder COPY ./default.conf /etc/nginx/conf.d/default.conf
entrypoint.sh
#!/bin/sh python manage.py migrate --noinput python manage.py collectstatic --noinput gunicorn fitweb.wsgi:application --bind 0.0.0.0:8000
gunicorn_config.py
import os command = "/home/ynot/fitweb/whatzthefit/.venv/bin/gunicorn" pythonpath = "/home/ynot/fitweb/whatzthefit/whatzthefit" bind = "0.0.0.0:8000" workers = 3
核心问题与修复方案
1. 主Dockerfile镜像错误
django_gunicorn服务需要Python环境运行Django和Gunicorn,但你当前的主Dockerfile用的是Nginx镜像,完全不符合需求。替换为Python基础镜像:
FROM python:3.11-slim WORKDIR /app # 安装依赖 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制项目文件 COPY . . # 赋予entrypoint执行权限 RUN chmod +x entrypoint.sh ENTRYPOINT ["./entrypoint.sh"]
2. 服务启动顺序与健康检查依赖
depends_on仅保证容器启动顺序,不保证数据库服务就绪。修改django_gunicorn服务配置,等待db健康检查通过后再启动:
django_gunicorn: volumes: - static:/static env_file: - /home/ynot/fitweb/whatzthefit/.env build: context: . ports: - "8080:8000" # 容器内Gunicorn绑定8000,映射到主机8080,与Nginx配置对应 depends_on: db: condition: service_healthy # 等待数据库服务就绪
同时修正db服务的健康检查命令,用普通用户密码而非root密码:
healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${DB_USER}", "-p${DB_PASS}"] interval: 10s retries: 3
3. 端口映射与Gunicorn配置不匹配
entrypoint.sh中Gunicorn绑定的是8000端口,但docker-compose里django_gunicorn的端口映射是8080:8080,导致端口不通。已在上一步修正映射为8080:8000,同时修正entrypoint.sh中的WSGI模块路径(你的项目根模块是whatzthefit,不是fitweb):
#!/bin/sh python manage.py migrate --noinput python manage.py collectstatic --noinput # 修正WSGI模块路径,直接指定参数无需依赖本地配置文件 gunicorn whatzthefit.wsgi:application --bind 0.0.0.0:8000 --workers 3
4. Gunicorn配置文件路径无效
容器内不存在你本地的.venv路径,gunicorn_config.py中的路径完全无效,直接在entrypoint.sh中指定启动参数即可,无需依赖该配置文件。
验证步骤
- 清理旧容器与数据卷:
docker-compose down -v - 重新构建镜像:
docker-compose build - 启动服务:
docker-compose up -d - 查看
django_gunicorn日志确认修复:docker-compose logs django_gunicorn
内容的提问来源于stack exchange,提问作者Tony

