使用docker-compose部署Flask+MySQL时遭遇数据库连接超时错误
Docker-Compose部署Flask+MySQL连接失败问题
我尝试用docker-compose部署搭配MySQL数据库的Flask应用,试过多种方法让Flask启动前等待数据库就绪,但还是遇到连接超时错误。
我的docker-compose配置
version: "3.7" services: waitfordb: image: dadarek/wait-for-dependencies depends_on: mysql: condition: service_completed_successfully environment: MYSQL_PORT: "5432" networks: - backend command: mysql:5432 mysql: image: mysql:5.7 ports: - "5432:5432" networks: - backend volumes: - ./mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: "12345678" MYSQL_DATABASE: flaskmysql web: build: . depends_on: mysql: condition: service_completed_successfully waitfordb: condition: service_completed_successfully ports: - 5000:5000 environment: MYSQL_HOST: mysql MYSQL_USER: root MYSQL_PASSWORD: "12345678" MYSQL_DB: flaskmysql networks: backend: driver: bridge
Flask应用数据库配置
app.config['SQLALCHEMY_DATABASE_URI']= f"mysql+pymysql://{config.MYSQL_USER}:{config.MYSQL_PASS}@5432/flaskmysql"
执行命令
docker-compose --env-file .env up
错误信息
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on '5432' (timed out)")
问题修复方案
1. 修正MySQL端口配置
MySQL默认监听端口是3306,你把容器端口映射成5432(PostgreSQL默认端口),但MySQL容器内部并没有在5432端口启动服务,导致端口检查和连接全错。修改mysql服务的端口映射:
ports: - "3306:3306" # 恢复默认端口映射,外部通过3306访问容器内的MySQL
2. 修正waitfordb的等待命令
waitfordb需要等待MySQL容器的3306端口,而非5432:
waitfordb: # 其他配置不变 command: mysql:3306
3. 修正Flask的数据库连接URI
连接地址应该用docker-compose服务名mysql作为主机,而非直接写端口号。正确格式为mysql+pymysql://用户名:密码@服务名:端口/数据库名:
# 用环境变量里的MYSQL_HOST对应服务名mysql,默认3306端口可省略 app.config['SQLALCHEMY_DATABASE_URI']= f"mysql+pymysql://{config.MYSQL_USER}:{config.MYSQL_PASSWORD}@{config.MYSQL_HOST}/{config.MYSQL_DB}"
注意:如果你的环境变量密码字段是MYSQL_PASS,替换成config.MYSQL_PASS即可,确保和docker-compose里的变量名一致。
4. 可选:增强数据库就绪检查
dadarek/wait-for-dependencies仅检查端口是否开放,但MySQL可能端口开放后仍未完成初始化(如创建数据库、加载权限)。可在Flask应用中添加连接重试逻辑:
from sqlalchemy import create_engine from sqlalchemy.exc import OperationalError import time def init_db(): max_retries = 10 retry_count = 0 while retry_count < max_retries: try: engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI']) with engine.connect(): print("数据库连接成功") break except OperationalError: retry_count += 1 print(f"数据库未就绪,第{retry_count}次重试...") time.sleep(2) else: raise Exception("数据库连接超时") # 应用启动前调用初始化 init_db()
内容的提问来源于stack exchange,提问作者Juan Cruz Alric Cortabarria
相关产品推荐
相关产品推荐

