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

Docker容器(Flask+MariaDB)偶发连接失败:无法连接db:3306

问题原因分析与解决方案

核心原因

  • 容器启动时序不匹配:Docker Compose的depends_on仅保证容器启动顺序,无法确保MariaDB服务完全就绪。Flask容器启动时,MariaDB容器虽已启动,但数据库进程可能还在执行初始化(如加载系统表、配置权限),此时发起连接必然被拒绝。
  • 重启场景的初始化延迟:停止并删除容器后重新启动,MariaDB需要重新初始化数据库文件(无缓存加持),初始化耗时比首次启动更长,连接失败的概率更高。

具体解决方案

1. 给MariaDB配置健康检查,让Flask等待数据库就绪

修改docker-compose.yml,为db服务添加健康检查规则,同时让app服务仅在db服务健康就绪后启动:

services:
  db:
    image: mariadb:latest
    env_file: .env
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${MYSQL_USER}", "-p${MYSQL_PASSWORD}"]
      interval: 5s
      timeout: 5s
      retries: 5
  app:
    build: .
    env_file: .env
    ports:
      - "5000:5000"
    depends_on:
      db:
        condition: service_healthy

2. 在Flask代码中添加连接重试逻辑

修改app.py的数据库连接代码,增加重试机制,避免因数据库未就绪导致的一次性连接失败:

import mysql.connector
from mysql.connector.errors import InterfaceError
import time
import os

def get_db_connection():
    max_retries = 10
    retry_delay = 2  # 每次重试间隔2秒
    for _ in range(max_retries):
        try:
            conn = mysql.connector.connect(
                host=os.getenv('DB_HOST'),
                user=os.getenv('DB_USER'),
                password=os.getenv('DB_PASSWORD'),
                database=os.getenv('DB_NAME')
            )
            return conn
        except InterfaceError:
            time.sleep(retry_delay)
    raise Exception("无法连接到数据库,重试次数已耗尽")

3. 排查初始化脚本的执行状态

如果有自定义的数据库初始化脚本(挂载到/docker-entrypoint-initdb.d目录),需确认脚本执行完成后数据库服务才会对外提供连接。可在脚本末尾添加mysqladmin ping之类的校验逻辑,确保初始化彻底完成。

额外排查点

  • 确认.env文件中DB_HOST的值为db(即docker-compose中db服务的名称),禁止使用localhost或127.0.0.1
  • 查看MariaDB容器日志docker logs <db容器名>,检查数据库启动过程中是否有初始化错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:58:19