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

Docker化全栈项目:Node.js API连MySQL容器遇ECONNREFUSED错误求助

问题与需求

我正在开发MySQL数据库+Express API的全栈项目,本地运行正常,Docker化后遇到以下问题:

  • Node.js API连接MySQL容器时抛出ECONNREFUSED错误(主机可通过MySQL Workbench正常连接)
  • 临时通过修改MySQL容器默认认证插件为mysql_native_password解决了连接问题,但该方案已弃用,希望适配MySQL 8.0默认的caching_sha2_password认证方案
  • 首次启动时需手动重启node_api容器,因MySQL启动耗时更长

我的完整docker-compose.yml配置如下:

version: '3'

services:
  db:
    image: mysql:latest
    command: --bind-address='0.0.0.0'
    container_name: mysql_db
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: housesdb
      MYSQL_PASSWORD: password
    volumes:
      - app-data:/var/lib/mysql
    networks:
      - my-network

  api:
    build: ./Backend
    container_name: node_api
    ports:
      - "3005:3005"
    environment:
      DB_HOST: db
      DB_PORT: 3306
      DB_USER: root
      DB_PASSWORD: password
      DB_NAME: housesdb
    depends_on:
      - db
    networks:
      - my-network

  web:
    build: ./frontend-jm
    container_name: react_app
    ports:
      - "3000:3000"
    
    depends_on:
      - db
      - api
    
    networks:
      - my-network
      
networks:
  my-network:
    driver: bridge

volumes:
  app-data:

排查过程中,我尝试执行SQL切换认证插件:

alter user 'root'@'%' identified with mysql_native_password by 'password'

得到错误:

Error Code: 1524. Plugin 'mysql_native_password' is not loaded

最优解决方案

一、适配caching_sha2_password认证方案

1. 升级Node.js MySQL客户端

停止使用已停止维护的mysql包,改用mysql2包(原生支持caching_sha2_password):

# 在Backend目录执行
npm install mysql2

2. 修改API连接代码

使用mysql2/promise建立连接池,无需额外配置即可自动适配caching_sha2_password:

const mysql = require('mysql2/promise');

// 创建连接池
const pool = mysql.createPool({
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

// 测试连接示例
async function testConnection() {
  try {
    const [rows] = await pool.query('SELECT 1 + 1 AS solution');
    console.log('数据库连接成功:', rows[0].solution);
  } catch (err) {
    console.error('连接失败:', err);
  }
}

testConnection();

3. 确认MySQL用户配置

MySQL 8.0默认用caching_sha2_password创建root用户,无需修改。若需创建专用应用用户,执行以下SQL:

CREATE USER 'app_user'@'%' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON housesdb.* TO 'app_user'@'%';
FLUSH PRIVILEGES;

之后修改API环境变量中的DB_USER为app_user即可。

二、解决容器启动顺序问题

depends_on仅保证容器启动顺序,不保证MySQL服务就绪,需通过健康检查或等待脚本解决:

方案1:Docker健康检查(推荐)

修改docker-compose.yml中db服务的配置,添加健康检查,让api服务等待db健康后再启动:

services:
  db:
    image: mysql:latest
    container_name: mysql_db
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: housesdb
      MYSQL_PASSWORD: password
    volumes:
      - app-data:/var/lib/mysql
    networks:
      - my-network
    # 添加健康检查
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
      interval: 5s  # 每5秒检查一次
      timeout: 5s   # 超时时间5秒
      retries: 5    # 重试5次后标记为不健康

  api:
    build: ./Backend
    container_name: node_api
    ports:
      - "3005:3005"
    environment:
      DB_HOST: db
      DB_PORT: 3306
      DB_USER: root
      DB_PASSWORD: password
      DB_NAME: housesdb
    depends_on:
      db:
        condition: service_healthy  # 等待db服务健康后启动
    networks:
      - my-network

方案2:API启动脚本添加等待逻辑

在Backend的Dockerfile中安装wait-for-it工具,修改启动脚本等待MySQL就绪:

  1. 修改Backend的package.json:
"scripts": {
  "start": "wait-for-it db:3306 -- node server.js"
}
  1. 修改Backend的Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
# 安装wait-for-it
RUN apk add --no-cache wait-for-it
COPY . .
CMD ["npm", "start"]
总结
  • 使用mysql2客户端是适配caching_sha2_password的最优方案,无需修改MySQL默认配置,符合官方推荐
  • 通过Docker健康检查或启动等待脚本,可彻底解决首次启动需手动重启API容器的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:04:52