Docker Compose映射3307:3306时Django无法连接MySQL容器
Django无法连接Docker Compose中MySQL容器的问题排查与解决
问题场景
Docker Compose配置主机3307端口映射到MySQL容器3306端口,但Django无法连接数据库;修改MySQL容器内部监听端口为3307后可正常运行,希望了解该问题的原因及让MySQL保持默认3306端口的正确配置方法。
初始相关配置
docker-compose.yaml
services: db: image: mysql:9.0.1 container_name: db_mysql_container environment: MYSQL_DATABASE: backend MYSQL_USER: asdf MYSQL_PASSWORD: asdf MYSQL_ROOT_PASSWORD: asdf ports: - '3307:3306' api: build: . container_name: django_container command: bash -c "pip install -q -r requirements.txt && python manage.py migrate && python manage.py runserver 0.0.0.0:8000" volumes: - .:/app ports: - '8000:8000' depends_on: - db
Django数据库配置(settings.py)
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': "backend", 'USER': "asdf", 'PASSWORD': "asdf", 'HOST': "db", 'PORT': "3307", } }
Dockerfile
# Use an official Python runtime as a parent image FROM python:3.12 # Set environment variables ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 # Set the working directory WORKDIR /app # Install dependencies COPY requirements.txt /app/ # Copy the project code into the container COPY . /app/
requirements.txt
asgiref==3.8.1 Django==5.1 mysqlclient==2.2.4 sqlparse==0.5.1
错误信息
启动容器后,Django抛出连接错误:
django.db.utils.OperationalError: (2002, "Can't connect to server on 'db' (115)")
临时可行配置(修改MySQL容器端口)
调整MySQL容器内部监听端口后可正常运行,修改后的docker-compose.yaml:
services: db: image: mysql:9.0.1 container_name: db_mysql_container environment: MYSQL_DATABASE: backend MYSQL_USER: asdf MYSQL_PASSWORD: asdf MYSQL_ROOT_PASSWORD: asdf MYSQL_TCP_PORT: 3307 ports: - '3307:3307' api: build: . container_name: django_container command: bash -c "pip install -q -r requirements.txt && python manage.py migrate && python manage.py runserver 0.0.0.0:8000" volumes: - .:/app ports: - '8000:8000' depends_on: - db
问题原因
Docker Compose创建的内部网络中,容器之间直接通过容器内部端口通信,而非主机映射的端口。初始配置中Django的PORT设为3307(主机映射端口),但MySQL容器内部实际监听的是默认3306端口,导致连接不匹配失败。临时配置修改了MySQL内部监听端口为3307,虽然能解决问题,但完全没必要改动MySQL的默认端口设置。
正确配置方法
只需调整Django的数据库配置,将PORT改为MySQL容器内部的默认端口3306即可,docker-compose.yaml的端口映射3307:3306保持不变:
修改后的Django数据库配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': "backend", 'USER': "asdf", 'PASSWORD': "asdf", 'HOST': "db", 'PORT': "3306", # 改为容器内部默认端口 } }
额外优化:确保MySQL服务就绪
depends_on仅保证容器启动顺序,不确保MySQL服务已完全就绪,建议添加等待脚本避免启动时的连接失败:
- 修改api服务的command:
command: bash -c "pip install -q -r requirements.txt && while ! nc -z db 3306; do sleep 1; done && python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
- 在Dockerfile中添加netcat工具:
RUN apt-get update && apt-get install -y netcat-traditional && rm -rf /var/lib/apt/lists/*
内容的提问来源于stack exchange,提问作者Matt Bliese
相关产品推荐
相关产品推荐

