Docker入门指南:使用Docker Compose遇mysql:3306连接超时
问题描述
我在学习Docker官方文档「使用Docker Compose」章节时遇到连接错误:Node应用在MySQL完成初始化前尝试连接,导致崩溃并抛出ECONNREFUSED错误。我的docker-compose.yml配置如下:
services: app: image: node:18-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 working_dir: /app volumes: - ./:/app environment: MYSQL_HOST: mysql MYSQL_USER: root MYSQL_PASSWORD: secret MYSQL_DB: todos mysql: image: mysql:8.0 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos volumes: todo-mysql-data:
日志关键报错片段:
app-app-1 | Waiting for mysql:3306............ app-app-1 | Timeout app-app-1 | Error: connect ECONNREFUSED 172.18.0.2:3306
我试过wait-for-it.sh、restarts: always、healthcheck和depends_on等方案,但错误仍持续出现。奇怪的是,朋友用相同配置操作却能正常运行。
解决方案
1. 给MySQL配置健康检查,让Compose等待服务真正就绪
默认的depends_on仅等待容器启动,不检测服务是否就绪。给MySQL添加健康检查,并让Node应用依赖MySQL的健康状态:
修改docker-compose.yml的mysql服务:
mysql: image: mysql:8.0 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] interval: 10s timeout: 5s retries: 20 start_period: 30s # 给初始化留足够缓冲时间
给app服务添加健康依赖:
app: # ... 原有配置 depends_on: mysql: condition: service_healthy
2. 延长Node应用的数据库等待超时
如果应用自带的等待逻辑(日志里的Waiting for mysql:3306)超时时间太短:
- 直接修改应用代码中的等待时长(比如从30秒改成300秒)
- 若用第三方工具(如
wait-port),在启动命令中增加超时参数:command: sh -c "yarn install && npx wait-port -t 300000 mysql:3306 && yarn run dev"
3. 预初始化MySQL数据卷(针对性能较差的机器)
首次启动MySQL时,InnoDB初始化可能因机器性能差耗时极长。可以提前预初始化数据卷:
- 单独启动MySQL容器,等待它完全初始化完成后停止
- 备份该数据卷内容,后续在Compose中直接使用这个已初始化的卷
4. 排查MySQL初始化日志
查看完整的MySQL日志,确认是否存在初始化错误(如权限、磁盘空间问题):
docker compose logs mysql
为什么朋友的配置能正常运行?
可能的原因:
- 朋友的机器性能更好,MySQL初始化耗时短,在应用等待超时内完成
- 朋友的数据卷已预初始化过(之前启动过MySQL,数据卷已有初始化后的文件)
- 朋友的应用等待逻辑超时时间更长
内容的提问来源于stack exchange,提问作者Aung Kaung Khant - Takao
相关产品推荐
相关产品推荐

