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

Docker Compose下Python服务无法连接MySQL的问题求助

Docker Compose下Python服务无法连接MySQL的问题排查

错误信息

_mysql_connector.MySQLInterfaceError: Can't connect to MySQL server on 'localhost:3306' (99)

文件结构

docker-compose.yml
.env
mysql/
├── database.sql
└── Dockerfile
python/
├── server.py
└── Dockerfile

相关配置内容

docker-compose.yml

version: '3.8'

services:

  mysql:
    build: 
      context: ./mysql
      dockerfile: Dockerfile
    restart: always
    environment:
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    ports:
      - '3306:3306'

  pythonapp:
    build:
      context: ./python
      dockerfile: Dockerfile
    depends_on:
      - mysql
    ports:
      - '8080:8080'

python/Dockerfile

FROM python:3.11-slim

RUN pip install mysql-connector-python && \
    pip install python-dotenv

COPY . /app

WORKDIR /app

CMD ["python", "-u", "server.py"]

EXPOSE 8080

mysql/Dockerfile

FROM mysql:latest

COPY ./database.sql /docker-entrypoint-initdb.d/

python/server.py

from http.server import HTTPServer, BaseHTTPRequestHandler
from dotenv import load_dotenv
import mysql.connector
import json
import os 

load_dotenv('../.env')

# Establish connection to MySQL
db_connection = mysql.connector.connect(
    user=os.getenv('MYSQL_USER'), 
    password=os.getenv('MYSQL_ROOT_PASSWORD'), 
    host=os.getenv('_HOST'),
    port=3306,
    database=os.getenv('MYSQL_DATABASE'))
print("DB connected")
...

.env

_HOST=localhost
MYSQL_DATABASE=db
MYSQL_USER=root
MYSQL_ROOT_PASSWORD=password

排查与解决步骤

1. 修复.env文件加载路径问题

容器内Python服务的工作目录是/app,load_dotenv('../.env')会尝试在容器根目录找.env文件,但你并未将.env复制到容器中,导致环境变量未加载成功。

解决方法:

  • 修改python/Dockerfile,添加复制.env的命令:
FROM python:3.11-slim

RUN pip install mysql-connector-python && \
    pip install python-dotenv

COPY . /app
COPY ../.env /app/.env  # 新增:将.env复制到app目录

WORKDIR /app

CMD ["python", "-u", "server.py"]

EXPOSE 8080
  • 同步修改server.py的加载路径:
load_dotenv('.env')  # 改为加载当前目录的.env

2. 修正容器间网络连接配置

Docker Compose会自动为服务创建默认网络,服务名就是容器的主机名,Python服务要连接MySQL,需用服务名mysql作为host。

修改.env文件:

_HOST=mysql  # 替换localhost为mysql服务名
MYSQL_DATABASE=db
MYSQL_USER=root
MYSQL_ROOT_PASSWORD=password

3. 处理MySQL初始化延迟问题

depends_on仅保证MySQL容器启动,但不保证数据库服务完全就绪(比如执行database.sql初始化需要时间),此时Python直接连接会失败。

在server.py中添加连接重试逻辑:

from http.server import HTTPServer, BaseHTTPRequestHandler
from dotenv import load_dotenv
import mysql.connector
from mysql.connector.errors import InterfaceError
import json
import os 
import time

load_dotenv('.env')

# 重试连接数据库
db_connection = None
retries = 5
while retries > 0:
    try:
        db_connection = mysql.connector.connect(
            user=os.getenv('MYSQL_USER'), 
            password=os.getenv('MYSQL_ROOT_PASSWORD'), 
            host=os.getenv('_HOST'),
            port=3306,
            database=os.getenv('MYSQL_DATABASE'))
        print("DB connected")
        break
    except InterfaceError:
        retries -= 1
        print(f"Failed to connect, retries left: {retries}")
        time.sleep(2)

if not db_connection:
    raise Exception("Could not connect to MySQL after multiple retries")
...

4. 验证MySQL服务状态

执行以下命令进入MySQL容器,确认服务正常运行:

docker-compose exec mysql mysql -u root -p

输入密码后,检查目标数据库是否存在:

SHOW DATABASES;

确保db数据库已创建并可正常访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 21:04:53