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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:50:57