Docker部署Django+MySQL报(2002)mysqld.sock连接错误如何解决
问题根因
你遇到的socket连接错误核心原因是web容器内的Django读取到的MySQL HOST配置为localhost,尝试连接容器自身的MySQL服务(而非名为db的数据库容器),才会去找unix socket文件。叠加配置里的多处笔误、规则理解偏差,最终导致连接失败。
最常见的触发场景是:本地开发时项目内的.env文件配置了HOST=localhost,部署时没有修改,同时你误以为docker-compose会自动把根目录.env的配置注入容器,没有显式传参,Django加载到本地配置后就会走本地socket连接逻辑。
分步修复方案
1. 修正docker-compose.yml配置
首先纠正几个配置错误:
- 根目录的
.env默认只用于解析yml文件内的变量占位,不会自动注入服务容器,必须在web服务下显式声明env_file加载 - 数据库初始化脚本的挂载路径存在笔误:
docker-entrypoint-initbd.d应为docker-entrypoint-initdb.d(b、d顺序写反),另外你写的.setup.sql是隐藏文件路径,正常应该加载当前目录下的./setup.sql - 废弃的
links配置可以直接删除,新版Compose默认会在同一网络下用服务名做DNS解析,不需要手动配置链路 depends_on仅能保证db容器先启动,不会等待MySQL服务初始化完成,需要加健康检查避免web服务提前启动连库失败- 给MySQL数据目录加命名卷持久化,避免容器删除后数据丢失
- MySQL8默认的密码插件兼容性差,加启动参数指定为
mysql_native_password,避免mysqlclient认证失败
修正后的完整配置参考:
version: '3' services: db: image: mysql:8 ports: - '3306:3306' environment: MYSQL_DATABASE: 'database_name' MYSQL_USER: 'django' MYSQL_PASSWORD: 'django-password' MYSQL_ROOT_PASSWORD: 'password' volumes: - ./setup.sql:/docker-entrypoint-initdb.d/setup.sql - mysql_data:/var/lib/mysql command: --default-authentication-plugin=mysql_native_password healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-ppassword"] interval: 5s timeout: 5s retries: 10 web: build: . command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/code ports: - "8000:8000" env_file: .env depends_on: db: condition: service_healthy volumes: mysql_data:
2. 修正Django数据库配置
你当前的配置存在两个小问题:
- os.environ.get读取的环境变量是字符串类型,PORT参数建议显式转整数,避免类型兼容问题
- 如果你用了python-dotenv等库自动加载项目内的.env文件,确认文件内的
MYSQL_DATABASE_HOST值为db而非localhost,否则会覆盖默认配置 - 可以补充utf8mb4编码配置,避免中文存储乱码
修正后的配置参考:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': os.environ.get('MYSQL_DATABASE', 'database_name'), 'USER': os.environ.get('MYSQL_USER', 'django'), 'PASSWORD': os.environ.get('MYSQL_PASSWORD', 'django-password'), 'HOST': os.environ.get('MYSQL_DATABASE_HOST', 'db'), 'PORT': int(os.environ.get('MYSQL_DATABASE_PORT', 3306)), 'OPTIONS': {'charset': 'utf8mb4'}, } }
注意:只要HOST参数不是localhost或空字符串,mysqlclient就会走TCP协议连接指定主机,不会去找本地socket文件,这是解决你当前报错的核心逻辑。
3. 修正Dockerfile配置
你当前的Dockerfile有冗余配置,还缺少mysqlclient依赖的系统包,直接pip安装会报编译错误:
- 重复的代码拷贝命令保留一个即可,COPY语义比ADD更明确,优先用COPY
- 提前安装default-libmysqlclient-dev、build-essential两个系统依赖,否则mysqlclient安装失败
修正后的Dockerfile参考:
FROM python:3.8 ENV PYTHONUNBUFFERED 1 RUN apt-get update && apt-get install -y default-libmysqlclient-dev build-essential && rm -rf /var/lib/apt/lists/* WORKDIR /code RUN pip install --upgrade pip COPY requirements.txt /code/ RUN pip install -r requirements.txt && pip install mysqlclient COPY . /code/
4. 清理旧配置重新启动
改完所有配置后,必须清理旧容器和匿名卷,避免缓存的旧配置影响结果:
docker-compose down -v docker-compose up -d --build
验证方法
启动后按顺序检查:
- 执行
docker-compose logs db,看到ready for connections字样说明MySQL正常启动 - 执行
docker-compose exec web env | grep MYSQL_DATABASE_HOST,确认输出值为db,没有被错误覆盖为localhost - 执行
docker-compose exec web python manage.py migrate,能正常执行数据库迁移就说明连库成功
内容的提问来源于stack exchange,提问作者Damian
相关产品推荐
相关产品推荐

