You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker化Django应用无法连接本地端口转发的MySQL服务器

解决Docker化Django应用连接MySQL容器的问题

我运行Docker化的Django应用,尝试连接另一Docker容器(端口转发到本地29998)的MySQL服务器,本地已通过MySQL Workbench确认能正常连接。将Django应用设置为network_mode: host后,执行docker-compose build时仍报错:django.db.utils.OperationalError: (2002, "Can't connect to MySQL server on '127.0.0.1' (115)"),目标是让应用成功连接localhost:29998的MySQL服务器。

相关配置

Django应用settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mytestdb',
        'USER': 'userone',
        'PASSWORD': 'password',
        'HOST': '127.0.0.1',
        'PORT': '29998',
    }
}

Django应用docker-compose.yml

version: '3.3'
services:
  mydjangoapp:
    container_name: mydjangoapp
    restart: always
    env_file: .env
    build: .
    volumes:
      - ./apps:/apps
      - ./core:/core
    network_mode: host

Django应用Dockerfile

FROM python:3.9

COPY . .

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

COPY requirements.txt .
# install python dependencies
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt

# running migrations
RUN python manage.py migrate

# gunicorn
CMD ["gunicorn", "--config", "gunicorn-cfg.py", "core.wsgi"]

MySQL容器docker-compose.yml

version: '3.3'

services:
  mysql:
    image: mysql:latest
    container_name: mymysqlserver
    environment:
      - MYSQL_DATABASE=mytestdb
      - MYSQL_USER=userone
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_PASSWORD=password
    ports:
      - 29998:3306

问题根源

  1. 网络模式兼容性:network_mode: host在Linux下容器直接复用宿主机网络,但Windows/macOS中Docker运行在虚拟机内,容器里的127.0.0.1指向虚拟机而非物理宿主机,导致无法连接到宿主机映射的MySQL端口。
  2. 构建时机问题:Dockerfile中的RUN python manage.py migrate是在镜像构建阶段执行的,此时MySQL容器可能尚未启动,或者网络连通性未建立,直接触发连接失败。

解决方案

方案一:使用自定义Docker网络(推荐)

通过共享网桥网络让两个容器直接通信,无需端口映射,稳定性更强:

  1. 修改MySQL的docker-compose.yml,添加自定义网络:
version: '3.3'

services:
  mysql:
    image: mysql:latest
    container_name: mymysqlserver
    environment:
      - MYSQL_DATABASE=mytestdb
      - MYSQL_USER=userone
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_PASSWORD=password
    networks:
      - app-network

networks:
  app-network:
    driver: bridge
  1. 修改Django应用的docker-compose.yml,加入同一网络,并配置依赖关系:
version: '3.3'
services:
  mydjangoapp:
    container_name: mydjangoapp
    restart: always
    env_file: .env
    build: .
    volumes:
      - ./apps:/apps
      - ./core:/core
    networks:
      - app-network
    depends_on:
      - mysql  # 确保MySQL容器先启动(需额外脚本检测服务就绪)

networks:
  app-network:
    external: true  # 若先启动MySQL的compose,启用此配置;否则删除external,由Django的compose创建网络
  1. 更新Django的settings.py,用MySQL容器名作为数据库主机:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mytestdb',
        'USER': 'userone',
        'PASSWORD': 'password',
        'HOST': 'mymysqlserver',  # 替换为MySQL容器名
        'PORT': '3306',  # 使用MySQL默认端口
    }
}
  1. 调整Dockerfile,将迁移命令移到启动阶段(避免构建时MySQL未就绪):
CMD ["sh", "-c", "python manage.py migrate && gunicorn --config gunicorn-cfg.py core.wsgi"]

方案二:针对Windows/macOS,修改数据库主机IP

若坚持使用network_mode: host,需找到Docker虚拟机的宿主机IP(通常为192.168.65.2或192.168.99.100),替换settings.py中的127.0.0.1:

DATABASES = {
    'default': {
        # ...其他配置不变
        'HOST': '192.168.65.2',  # 替换为你的Docker宿主机IP
        'PORT': '29998',
    }
}

同时需将Dockerfile中的RUN python manage.py migrate移到启动命令中,确保MySQL已运行。

方案三:Linux系统下调整迁移时机

Linux环境中network_mode: host可直接生效,但仍需将迁移命令从构建阶段移到启动阶段,避免构建时MySQL未启动:
修改Dockerfile的CMD部分为:

CMD ["sh", "-c", "python manage.py migrate && gunicorn --config gunicorn-cfg.py core.wsgi"]

内容的提问来源于stack exchange,提问作者Fletchy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:15:37