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

在GitHub Actions和Docker中使用Sequelize时遇ECONNREFUSED错误

GitHub Actions中Sequelize连接MySQL容器出现ECONNREFUSED错误

问题描述

推送PR或提交到master分支时,GitHub Actions运行的集成测试无法通过Sequelize连接Docker启动的MySQL数据库,报错ECONNREFUSED 127.0.0.1:3305。本地运行测试完全正常,且两周前该CI流程无异常,期间未修改相关代码。

具体错误信息

connect ECONNREFUSED 127.0.0.1:3305
ConnectionRefusedError [SequelizeConnectionRefusedError]: connect ECONNREFUSED 127.0.0.1:3305
...
parent: Error: connect ECONNREFUSED 127.0.0.1:3305
      at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16) {
    errno: -111,
    code: 'ECONNREFUSED',
    syscall: 'connect',
    address: '127.0.0.1',
    port: 3305,
    fatal: true
  }

相关配置与代码

GitHub Actions配置文件

name: Node.js CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:
    name: "Building"
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Use Node.js
      uses: actions/setup-node@v4
      with:
        node-version: 20
    - run: npm ci
    - run: npm test // this is the relevant test that is failing

Docker Compose测试配置文件

version: "3.3"

services:
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - ./init_db:/docker-entrypoint-initdb.d
    ports:
      - 3305:3306
    extra_hosts:
      - "host.docker.internal:host-gateway"

测试代码相关部分

async function setUpMySQLServer() {

  // Stop any existing MySQL container.
  child_process.spawnSync("docker-compose", ["-f", __dirname + "/docker-compose.test.yaml", "down"]);

  // Start a container for MySQL server.
  const { status, stderr, error } = child_process.spawnSync("docker-compose", ["-f", __dirname + "/docker-compose.test.yaml", "up", "--detach"]);

  if (error)
    throw new Error("Unable to run docker-compose. Docker is required in order to set up a MySQL server.");
  if (status != 0)
    throw new Error("docker-compose exited with an error: " + stderr);

  console.log("Docker set up...");

  await sleep(30000);  // Wait for MySQL server to start (did this as an attempt to fix the issue, does not work)

  // Connect to the MySQL server.
  let sequelize;
  try {
    sequelize = new Sequelize("test", "root", "root", {
      host: "127.0.0.1",
      port: 3305,
      dialect: "mysql",
      dialectOptions: {
        decimalNumbers: true,
        multipleStatements: true
      }
    });
  } catch (error) {
    console.log(error.message);
    throw new Error("Unable to connect to the MySQL server. Make sure the MySQL server is running and the connection settings are correct.");
  }

  // Wait for the MySQL server to be up.
  let attempts = 0;
  while (true) {
    attempts++;
    try {
      // Test the connection. This is where I am getting the ECONNREFUSED error.
      await sequelize.authenticate();
      break;
    } catch (error) {
      if (attempts >= 300) {
        console.log(error.message);
        throw error;
      }
    }

    await sleep(1000);
  }

  await populateDatabase(sequelize);
  sequelize.close();
}

已尝试的无效方案

  • 增加MySQL容器启动后的等待时间(已设为30秒)
  • 修改端口映射(替换其他端口)
  • 更换Node.js版本
  • 添加Docker extra_hosts配置
  • 配置Sequelize连接池

本地首次运行时会弹出“允许访问文件”弹窗,同意后可正常运行,拒绝则出现相同错误,不确定是否与CI问题相关。

解决方案

1. 改用Docker服务名称作为连接主机

GitHub Actions的Ubuntu runner中,通过127.0.0.1访问容器端口可能存在网络隔离问题,直接用Docker Compose的服务名作为连接主机更可靠:

  • 修改Sequelize连接配置:
sequelize = new Sequelize("test", "root", "root", {
  host: "db", // 对应Docker Compose中的服务名
  port: 3306, // 使用容器内部的MySQL端口,无需映射到主机
  dialect: "mysql",
  dialectOptions: {
    decimalNumbers: true,
    multipleStatements: true
  }
});
  • 同时将Docker Compose的端口映射配置移除,避免不必要的网络暴露。

2. 检查Docker服务状态并添加网络权限

在GitHub Actions步骤中,先确保Docker服务正常运行,并且测试进程和容器在同一网络:

# 在npm ci之后添加
sudo systemctl restart docker
docker network create test-network
# 修改启动容器的命令,加入自定义网络
# 测试代码中spawnSync的参数改为:
["-f", __dirname + "/docker-compose.test.yaml", "up", "--detach", "--network", "test-network"]

3. 指定稳定版本的MySQL镜像

近期MySQL官方镜像可能有更新导致启动逻辑变化,指定具体稳定版本(如mysql:8.0):
修改Docker Compose中的image字段:

image: mysql:8.0

4. 排查数据库初始化脚本问题

在GitHub Actions中添加步骤查看容器日志,确认MySQL是否因初始化脚本错误未正常启动:

# 在启动容器后添加
docker logs $(docker ps -q --filter "name=db")

检查./init_db中的脚本是否存在路径、权限或语法问题。

5. 验证端口映射是否生效

在GitHub Actions中添加端口监听检查步骤:

# 在npm test之前添加
sudo netstat -tulpn | grep 3305

如果端口未被监听,说明Docker端口映射失败,需检查runner的Docker权限配置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 23:05:58