Tortoise/Python无法连接Docker MySQL 需先通过phpMyAdmin登录才可连通
问题原因分析
- 核心原因是
docker-compose的depends_on仅保证容器启动顺序,不会等待MySQL内部服务初始化完成。MySQL官方镜像首次启动时,需要执行环境变量指定的数据库创建、用户创建、权限配置等初始化逻辑,这个过程通常需要3~10秒不等,此时db容器状态已经是running,但实际上数据库服务还无法正常响应外部连接。你打开phpMyAdmin再登录的操作刚好消耗了这段初始化等待时间,等你登录完成时MySQL刚好完成初始化,你的rest服务因为配置了restart: always不断重试连接,此时就可以正常连上了,你误以为是phpMyAdmin登录操作触发了什么逻辑,本质只是等待时间刚好够。 - 次要可能是MySQL 8.0+默认使用
caching_sha2_password认证插件,如果你Python环境使用的mysqlclient或者aiomysql驱动版本过低,不支持该认证方式,会导致连接失败。而phpMyAdmin的驱动对该认证插件兼容性更好,登录时会自动处理相关兼容逻辑,甚至触发MySQL侧的用户认证缓存刷新,之后低版本驱动就可以正常连接。 - 极小概率是自定义网桥的DNS解析延迟,首次启动时rest服务解析db域名失败,phpMyAdmin访问db的操作触发了网桥的DNS缓存,之后rest服务就可以正常解析到db的IP地址。
修复方案
- 给db服务增加健康检测,让rest服务等db完全就绪后再启动
修改docker-compose.yaml中对应服务的配置:
- 给db服务增加健康检测,让rest服务等db完全就绪后再启动
db: image: mysql:latest restart: always environment: MYSQL_DATABASE: "bbms" MYSQL_USER: "bbms" MYSQL_PASSWORD: "B37PTdaWvbUQm" MYSQL_ROOT_PASSWORD: "asdasdasdasd" ports: - "3306:3306" volumes: - dbdata:/var/lib/mysql # 新增健康检测配置 healthcheck: test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-ubbms", "-pB37PTdaWvbUQm"] timeout: 20s retries: 10 rest: build: context: ./ dockerfile: ./docker/rest/Dockerfile restart: always # 修改依赖条件,等待db服务健康 depends_on: db: condition: service_healthy environment: MYSQL_DATABASE: "bbms" MYSQL_USER: "bbms" MYSQL_PASSWORD: "B37PTdaWvbUQm" MYSQL_HOST: db MYSQL_PORT: 3306 volumes: - ./src:/app ports: - "5000:5000"
- 强制MySQL使用兼容度更高的旧版认证插件,解决驱动兼容问题
在db服务中新增command配置:
- 强制MySQL使用兼容度更高的旧版认证插件,解决驱动兼容问题
db: image: mysql:latest restart: always # 新增这行配置 command: --default-authentication-plugin=mysql_native_password environment: MYSQL_DATABASE: "bbms" MYSQL_USER: "bbms" MYSQL_PASSWORD: "B37PTdaWvbUQm" MYSQL_ROOT_PASSWORD: "asdasdasdasd" ports: - "3306:3306" volumes: - dbdata:/var/lib/mysql
- 升级Python的MySQL驱动版本,确保支持
caching_sha2_password认证,比如将aiomysql、mysqlclient升级到最新稳定版。
- 升级Python的MySQL驱动版本,确保支持
- 也可以在rest服务的启动脚本中增加等待逻辑,确认MySQL端口可访问后再启动Python服务,示例启动脚本:
#!/bin/bash until nc -z $MYSQL_HOST $MYSQL_PORT do echo "等待MySQL服务就绪..." sleep 2 done python main.py
再修改rest服务的command配置执行该启动脚本即可。
内容的提问来源于stack exchange,提问作者Scratcha
相关产品推荐
相关产品推荐

