Flask Docker容器连MySQL失败:docker-compose up报2002 手动启动正常
失败核心原因
这个问题本质是容器启动时序不匹配,和网络连通性、Docker镜像配置没有直接关系:
depends_on指令的作用仅为约束容器的创建启动顺序,即等db容器的主进程启动后再创建my_app容器,它不会等待db内的数据库服务完成初始化、可以正常受理业务连接后再放行- MariaDB容器从启动到真正可以接受MySQL连接,需要完成一整套初始化流程:创建系统表、加载权限配置、完成端口监听,首次启动时这套流程通常需要3~15秒
- 你的Flask应用在模块导入阶段就会直接执行
db.create_all(),启动时没有任何重试逻辑,一旦碰到db还没就绪的状态,就会直接抛出连接错误退出进程 - 你日志里出现的
(115)错误,本质是目标主机对应端口无监听的连接超时,不是账号、密码、主机名配置错误——因为等db容器完全启动后,你手动启动my_app容器时,用的还是同一套配置,就能正常连上数据库。
你手动执行docker start my_app_container时,db容器已经提前完成了全部初始化流程,3306端口正常对外提供服务,所以应用启动时可以顺利建立数据库连接,不会报错。
可落地的修复方案
- 替换裸的
depends_on依赖为健康检查绑定,让compose等数据库真正就绪后再启动应用:
在db服务配置中增加健康检查规则,MariaDB官方镜像自带了数据库连通性检测脚本:
同时修改my_app的依赖规则,匹配健康检查状态:db: image: mariadb # 原有其他配置保持不变 healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--user=root", "--password=test"] interval: 5s timeout: 3s retries: 10my_app: # 原有其他配置保持不变 depends_on: db: condition: service_healthy - 给应用启动流程增加数据库连接重试逻辑:即使compose层做了时序控制,也可能因为网络抖动、主机资源不足出现偶发连接失败,在执行
db.create_all()前增加最多30秒的重试间隔,碰到连接错误时等待2~3秒后重连,避免单次连接失败导致容器直接退出。 - 可清理过时的冗余配置:compose v3版本已经默认提供服务间DNS发现,旧版的
links配置可以直接移除,只需要保证应用配置中的数据库主机名和db服务的实际访问名(或自定义网络别名)保持一致即可。临时调试用的tty: true、stdin_open: true配置在正式运行时也可以根据实际需要删除。
内容的提问来源于stack exchange,提问作者Viswajith Kalavapudi
相关产品推荐
相关产品推荐

