Docker部署环境下Web容器无法连接MySQL容器的技术求助
解决方案:MySQL容器启动失败+Web容器无法连接数据库的问题
我来帮你一步步排查并解决这两个问题:
一、MySQL容器启动失败:ERROR 1396 (HY000): Operation CREATE USER failed for 'root'@'%'
问题原因
你在docker-compose.yml的db服务环境变量里设置了MYSQL_USER: 'root',但root是MySQL默认自带的超级用户,不需要通过MYSQL_USER环境变量重复创建,所以容器启动时执行创建用户的命令就会直接报错,导致容器退出。
解决方法
二选一即可:
- 如果不需要额外的普通数据库用户:直接删除
MYSQL_USER: 'root'和对应的MYSQL_PASSWORD: 'password'这两行环境变量; - 如果需要创建额外用户:把
MYSQL_USER改成其他非root的用户名(比如db_admin),同时调整后续数据库连接的用户名(如果用这个用户连接的话)。
修改后的db服务环境变量示例(删除额外用户的情况):
services: db: image: mysql:5.7 ports: - '3306:3306' environment: MYSQL_DATABASE: 'DBM' MYSQL_ROOT_PASSWORD: 'password'
二、Web容器无法连接MySQL:MySQLdb._exceptions.OperationalError: (2002, "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)")
这个问题有两个核心原因,我们逐个解决:
1. 数据库连接的Host配置错误
你提到把host改成了src_db_1,但在你的docker-compose.yml里,db服务的名称是db——在Docker Compose的默认网络中,服务名称可以直接作为域名解析到对应容器,用服务名比容器名(通常是<项目目录名>_db_1)更可靠,不会因为项目目录变化而失效。
所以你需要把Python连接代码里的host改成db:
db = MySQLdb.connect(host="db", user="root", passwd="password", db="DBM", port=3306)
2. Web容器启动时MySQL服务还未就绪
depends_on: - db只是保证db容器先启动,但不保证MySQL服务已经完成初始化、可以接受连接。当Web容器启动并尝试连接时,MySQL可能还在初始化数据库,导致连接失败。
解决方法(二选一)
方法一:用等待脚本确保MySQL就绪
我们可以用wait-for-it脚本让Web容器等待MySQL服务完全就绪后再启动:
- 首先修改你的
Dockerfile,添加安装wait-for-it的步骤:
FROM python:3.8 ENV PYTHONUNBUFFERED 1 RUN mkdir /api_rest_mix_1_0 WORKDIR /api_rest_mix_1_0 # 安装wait-for-it工具 RUN apt-get update && apt-get install -y wait-for-it ADD requirements.txt /api_rest_mix_1_0/ RUN pip install --upgrade pip && pip install -r requirements.txt ADD . /api_rest_mix_1_0/
- 然后修改
docker-compose.yml里Web服务的command:
services: web: build: . command: wait-for-it db:3306 -- python manage.py runserver 0.0.0.0:8000 volumes: - .:/my_app_dir ports: - "8000:8000" depends_on: - db
方法二:在Python代码中添加连接重试逻辑
如果不想安装额外工具,可以在数据库连接的代码里添加重试逻辑,比如:
import time import MySQLdb def get_db_connection(): while True: try: db = MySQLdb.connect(host="db", user="root", passwd="password", db="DBM", port=3306) return db except MySQLdb._exceptions.OperationalError: print("MySQL not ready yet, waiting 2 seconds...") time.sleep(2) # 使用这个函数获取连接 db = get_db_connection()
最终验证步骤
- 先清理现有容器和数据卷(确保MySQL重新初始化):
docker-compose down -v
- 应用上面所有修改到对应的文件;
- 重新构建并启动容器:
docker-compose up --build
这样就能解决你的两个问题了。
内容的提问来源于stack exchange,提问作者Marco Antonio Bet
相关产品推荐
相关产品推荐

