Docker化Django+MySQL+Nginx项目时数据库连接失败求助
Django + MySQL + Nginx Docker化连接错误排查
问题描述
执行docker-compose up --build时,Django容器抛出错误:
django.db.utils.OperationalError: (2002, "Can't connect to local server through socket '/run/mysqld/mysqld.sock' (2)")
尝试修改settings.py中数据库HOST为127.0.0.1时,报错:
(2002, "Can't connect to MySQL server on '127.0.0.1' (115)")
改为sqldb(Docker Compose中MySQL服务名)时,报错:
(2002, "Can't connect to MySQL server on 'sqldb' (115)")
现有配置文件
docker-compose.yml
version: '3.7' services: app: build: ./app env_file: - .env container_name: app restart: always expose: - 8000 command: bash -c "python3 manage.py collectstatic --noinput && python3 manage.py migrate --noinput --fake-initial && \ gunicorn -b 0.0.0.0:8000 veblog.wsgi" environment: - MYSQL_DATABASE=${NAME} - MYSQL_USER=${USER_NAME} - MYSQL_PASSWORD=${PASSWORD} - MYSQL_HOST=sqldb mem_limit: 1g depends_on: - sqldb # - nginx volumes: - ./volumes/app:/app - type: bind source: ./volumes/media target: /app/media - type: bind source: ./volumes/static target: /app/static nginx: build: ./nginx container_name: nginx restart: always ports: - 8000:80 sqldb: image: mysql:latest container_name: sqldb restart: always depends_on: - nginx expose: - 3306 environment: - MYSQL_DATABASE=${NAME} - MYSQL_USER=${USER_NAME} - MYSQL_PASSWORD=${PASSWORD} - MYSQL_ROOT_PASSWORD=${ROOT_PASSWORD} - MYSQL_INITDB_SKIP_TZINFO=true - MYSQL_INIT_COMMAND=SET GLOBAL host_cache_size=0; volumes: - type: bind source: ./volumes/dbdata target: /var/lib/mysql - /usr/share/zoneinfo:/usr/share/zoneinfo:ro
app/Dockerfile
FROM python:3 ENV PYTHONDONTWRITEBYCODE 1 ENV PYTHONUNBUFFERED 1 RUN mkdir -p /app WORKDIR /app COPY . . RUN apt update RUN apt install gcc python3-dev musl-dev -y RUN pip install --upgrade pip RUN pip install mysqlclient COPY ./requirement.txt . RUN pip install -r requirement.txt ADD . /app/ RUN pip install gunicorn
nginx/Dockerfile
FROM nginx:alpine RUN rm /etc/nginx/conf.d/default.conf ADD default.conf /etc/nginx/conf.d/default.conf
nginx/default.conf
upstream app { server app:8000; } server { listen 80; server_name localhost; location / { proxy_pass http://app; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_redirect off; } location /media/ { alias /app/media; } location /static/ { alias /app/static; } }
Django settings.py 数据库配置
'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': config('NAME'), 'USER': config('USER_NAME'), 'PASSWORD': config('PASSWORD'), 'HOST': 'localhost', # host.docker.internal 'PORT': '3306', }
已尝试的无效操作
- 调整本地MySQL权限:
sudo chmod -R 755 /var/run/mysqld - 创建socket软链接:
ln -s /var/lib/mysql/mysql.sock /var/run/mysqld/mysqld.sock - 卸载重装本地MySQL
- 在MySQL配置文件中设置
bind-address=0.0.0.0(但执行SHOW VARIABLES LIKE 'bind-address'返回空集合) - 开放防火墙权限
- 单独执行
docker build构建镜像
解决方案
1. 修正数据库连接目标
Docker Compose中服务通过服务名通信,Django应连接容器化的MySQL服务而非本地MySQL。修改settings.py的数据库配置:
'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': config('NAME'), 'USER': config('USER_NAME'), 'PASSWORD': config('PASSWORD'), 'HOST': 'sqldb', # 改为Docker Compose中的MySQL服务名 'PORT': '3306', }
2. 修复服务依赖顺序
当前sqldb依赖nginx的逻辑错误,会导致MySQL启动延迟,Django可能在MySQL就绪前发起连接。调整docker-compose.yml的依赖关系:
- 移除
sqldb中的depends_on: - nginx - 让
nginx依赖app(Nginx需反向代理已启动的Django服务)
修改后的关键片段:
services: app: # 其他配置不变 depends_on: - sqldb nginx: # 其他配置不变 depends_on: - app sqldb: # 其他配置不变 # 移除depends_on: - nginx
3. 确保MySQL就绪后启动Django
depends_on仅保证启动顺序,不确保服务完全就绪。给Django添加等待MySQL就绪的逻辑:
- 在
app目录下添加wait-for-it.sh脚本(功能为等待指定端口服务就绪) - 修改
app/Dockerfile添加脚本权限:
# 其他配置不变 COPY wait-for-it.sh /app/ RUN chmod +x /app/wait-for-it.sh
- 更新
docker-compose.yml中app的启动命令:
command: bash -c "./wait-for-it.sh sqldb:3306 -- python3 manage.py collectstatic --noinput && python3 manage.py migrate --noinput --fake-initial && gunicorn -b 0.0.0.0:8000 veblog.wsgi"
4. 排查本地MySQL冲突
若本地MySQL占用3306端口,可能干扰Docker内部通信,建议暂时停止本地MySQL测试:
sudo systemctl stop mysql
5. 验证MySQL容器状态
启动后查看MySQL容器日志,确认服务正常就绪:
docker logs sqldb
日志中出现ready for connections即为正常状态。
内容的提问来源于stack exchange,提问作者zahra hemmati
相关产品推荐
相关产品推荐

