Docker容器中Pymysql连接MySQL容器被拒绝问题求助
容器内Python应用无法连接Docker MySQL的解决方案
核心问题分析
连接拒绝错误由以下三个关键原因导致:
- API容器启动早于MySQL容器,数据库服务未就绪就发起连接
.env文件中数据库密码与Docker Compose配置的MySQL密码不匹配- 旧版
links指令的依赖管理可靠性不足
解决方案1:修正数据库密码匹配问题
你的.env文件中DB_PASSWORD为空,但docker-compose.yml里MySQL的MYSQL_ROOT_PASSWORD设为了password,这会导致容器内Python应用用空密码连接被拒绝。
修改.env文件:
#DB credentials DB_HOST=database DB_USER=root DB_PASSWORD=password # 改为与docker-compose.yml一致的密码 DB_NAME=data DB_ENGINE=mysql+pymysql
解决方案2:确保API容器等待数据库就绪
Docker Compose的depends_on仅保证数据库容器先启动,不会等待数据库服务完全就绪。可通过以下两种方式解决:
方法A:给MySQL容器添加健康检查
更新docker-compose.yml,让API容器仅在数据库健康检查通过后启动:
version: "3.9" services: api: build: . ports: - "8000:8000" depends_on: database: condition: service_healthy # 等待数据库就绪后启动API # 移除links,新版Docker Compose默认网络已支持通过服务名访问 database: image: mysql ports: - "3306:3306" environment: - MYSQL_DATABASE=data - MYSQL_ROOT_PASSWORD=password healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-ppassword"] interval: 5s timeout: 5s retries: 5
方法B:在Python应用中添加重连逻辑
修改db.py,添加连接重试机制,避免数据库未就绪时直接报错:
from sqlalchemy import create_engine, MetaData from dotenv import load_dotenv import os import time load_dotenv() DB_ENGINE = os.getenv('DB_ENGINE') DB_USER = os.getenv('DB_USER') DB_PASSWORD = os.getenv('DB_PASSWORD') DB_HOST = os.getenv('DB_HOST') DB_NAME = os.getenv('DB_NAME') # 添加连接重试逻辑 engine = None connection = None max_retries = 5 retry_count = 0 while retry_count < max_retries: try: engine = create_engine( f"{DB_ENGINE}://{DB_USER}:{DB_PASSWORD}@{DB_HOST}/{DB_NAME}", pool_pre_ping=True ) connection = engine.connect() print("数据库连接成功") break except Exception as e: print(f"连接失败,重试中... ({retry_count+1}/{max_retries})") retry_count += 1 time.sleep(3) if not connection: raise Exception("数据库连接失败,已达最大重试次数") meta = MetaData()
解决方案3:优化Dockerfile(可选)
先复制依赖文件以利用Docker缓存,同时指定绑定0.0.0.0确保容器内服务可被外部访问:
FROM python:3.9.12 WORKDIR /usr/src/app # 先复制依赖文件,缓存依赖安装层 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 再复制应用代码 COPY . . # 开发环境保留--reload,生产环境建议移除 CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
内容的提问来源于stack exchange,提问作者FGMN
相关产品推荐
相关产品推荐

