Docker环境下Sequelize连接MySQL持续报ECONNREFUSED错误求助
Docker环境下Sequelize连接MySQL报错ECONNREFUSED的解决方案
问题现象
在Docker环境中使用Sequelize连接MySQL时,反复出现连接拒绝错误:
ConnectionRefusedError [SequelizeConnectionRefusedError]: connect ECONNREFUSED 192.168.112.2:3306
已尝试将Sequelize配置的host改为docker-compose中MySQL服务名mysql,执行docker compose down -v清理卷后重启,问题仍未解决。
相关配置文件
docker-compose.yml
version: "3.8" services: mysql: image: "mysql" volumes: - data:/var/lib/mysql environment: - MYSQL_DATABASE=test - MYSQL_ROOT_PASSWORD=realpassword backend: build: ./backend ports: - "80:80" volumes: - logs:/app/logs - ./backend:/app - /app/node_modules depends_on: - mysql volumes: data: logs:
sequelize index.js
const Sequelize = require("sequelize"); const dotenv = require("dotenv"); dotenv.config({ path: "./env/mysql.env" }); const db = {}; const Goal = require("./goal"); const sequelize = new Sequelize( process.env.MYSQL_DATABASE, process.env.MYSQL_USER, process.env.MYSQL_ROOT_PASSWORD, { port: process.env.MYSQL_PORT, host: "mysql", dialect: "mysql", logging: false, pool: { max: 5, min: 0, acquire: 30000, idle: 10000, }, } ); db.sequelize = sequelize; db.Sequelize = Sequelize; db.Goal = Goal.init(sequelize); module.exports = db;
env/mysql.env
MYSQL_DATABASE=test MYSQL_ROOT_PASSWORD=realpassword MYSQL_USER=root MYSQL_PORT=3306
后端日志(docker logs backend)
[nodemon] watching extensions: js,mjs,json [nodemon] starting `node app.js` 80 port is ready ConnectionRefusedError [SequelizeConnectionRefusedError]: connect ECONNREFUSED 192.168.112.2:3306 at ConnectionManager.connect (/app/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:92:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async ConnectionManager._connect (/app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:222:24) at async /app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:174:32 at async ConnectionManager.getConnection (/app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:197:7) at async /app/node_modules/sequelize/lib/sequelize.js:305:26 at async MySQLQueryInterface.tableExists (/app/node_modules/sequelize/lib/dialects/abstract/query-interface.js:102:17) at async Goals.sync (/app/node_modules/sequelize/lib/model.js:939:21) at async Sequelize.sync (/app/node_modules/sequelize/lib/sequelize.js:377:9) { parent: Error: connect ECONNREFUSED 192.168.112.2:3306 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1602:16) { errno: -111, code: 'ECONNREFUSED', syscall: 'connect', address: '192.168.112.2', port: 3306, fatal: true }, original: Error: connect ECONNREFUSED 192.168.112.2:3306 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1602:16) { errno: -111, code: 'ECONNREFUSED', syscall: 'connect', address: '192.168.112.2', port: 3306, fatal: true }
解决方案
1. 解决MySQL服务未就绪问题
depends_on仅保证MySQL容器启动,不保证MySQL服务完全初始化完成。后端启动时MySQL可能还在加载数据,导致连接被拒绝。
方案一:给MySQL添加健康检查
修改docker-compose.yml中mysql服务配置,添加健康检查规则,让后端等待MySQL服务就绪后再启动:
mysql: image: "mysql" volumes: - data:/var/lib/mysql environment: - MYSQL_DATABASE=test - MYSQL_ROOT_PASSWORD=realpassword healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] interval: 5s timeout: 5s retries: 5 backend: # 保留原有配置 depends_on: mysql: condition: service_healthy
方案二:后端添加连接重试逻辑
修改Sequelize初始化代码,增加连接失败后的重试机制:
async function connectDB() { try { await sequelize.authenticate(); console.log('数据库连接成功'); await sequelize.sync(); } catch (error) { console.log('连接失败,5秒后重试...'); setTimeout(connectDB, 5000); } } connectDB();
2. 处理MySQL 8.0+认证插件兼容问题
MySQL 8.0默认使用caching_sha2_password认证插件,部分旧版本客户端(包括Sequelize依赖的mysql2)可能不兼容。可以强制MySQL使用旧版认证插件:
修改docker-compose.yml的mysql服务环境变量:
mysql: image: "mysql" volumes: - data:/var/lib/mysql environment: - MYSQL_DATABASE=test - MYSQL_ROOT_PASSWORD=realpassword - MYSQL_ROOT_HOST=% # 允许root从任意主机连接 - MYSQL_DEFAULT_AUTH=mysql_native_password
3. 验证Sequelize配置参数
检查配置参数是否正确加载:
- 在代码中添加日志打印确认环境变量:
console.log('MySQL配置:', process.env.MYSQL_USER, process.env.MYSQL_PORT) - 确认Sequelize构造函数参数顺序正确:数据库名、用户名、密码,无拼写错误
4. 测试容器间网络连通性
进入backend容器,验证是否能访问mysql服务:
# 进入backend容器 docker exec -it <backend容器名称> /bin/sh # 测试mysql服务解析 ping mysql # 测试3306端口是否开放 telnet mysql 3306
如果ping不通,检查Docker网络配置,默认情况下docker-compose会为所有服务创建专属网络,确保两个服务在同一网络中。
内容的提问来源于stack exchange,提问作者brgndy
相关产品推荐
相关产品推荐

