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

Docker中Node应用无法连接MySQL数据库问题排查

解决Docker环境下Node应用无法连接MySQL的问题

你的Node应用连接MySQL失败的问题,和它不需要监听端口完全无关——因为它是主动发起连接的客户端,不是对外提供服务的服务端,不需要配置ports。下面是具体排查和修复步骤:

1. 确保MySQL容器完全就绪后再启动Node应用

depends_on: [db]仅保证MySQL容器先启动,但MySQL可能还在初始化(比如执行init.sql、创建数据库/用户),这时候Node应用去连接会被拒绝。Express能成功大概率是因为它启动较慢,或内部有连接重试机制。

修复方案:用Docker健康检查等待MySQL就绪

修改docker-compose.yml中db服务的配置,加入健康检查,并让node_app等待MySQL健康状态:

services:
  db:
    image: mysql:8.0.31
    cap_add:
      - SYS_NICE
    restart: always
    env_file:
           - somefile.env
    ports:
            - 127.0.0.1:external_port:3306
    volumes:
      - db:/var/lib/mysql
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
    # 新增健康检查
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${USERNAME}", "-p${PASSWORD}"]
      interval: 5s
      timeout: 5s
      retries: 5
  # ...其他服务
  node_app:
        image: some_image
        links:
                - db:db
        env_file:
                - somefile.env
        depends_on:
                # 改为等待db服务健康就绪
                db:
                  condition: service_healthy

2. 修正Node连接代码的异步逻辑错误

你的代码存在多处async/await误用,导致连接逻辑异常:

  • process.env.USERNAME/PASSWORD是同步变量,不需要await
  • mysql.createConnection不是异步函数,不能用await
  • con.connect是回调式API,不能直接用await

修正后的代码(使用mysql2/promise版本)

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

async function create_connection() {
  try {
    const username = process.env.USERNAME;
    const password = process.env.PASSWORD;
    // 用mysql2的promise版本创建连接,支持await
    con = await mysql.createConnection({
      host: "db",
      user: username,
      password: password,
      database: "database",
      port: 3306, // 端口用数字类型,不要字符串
    });
    console.log('MySQL连接成功');
  } catch (err) {
    console.error('连接失败:', err);
    // 增加重试机制,避免一次性失败
    setTimeout(create_connection, 5000);
  }
}

create_connection();

3. 检查MySQL用户的连接权限

确认你的MySQL用户拥有从任意主机(%)连接的权限——因为Node应用在Docker容器内,是通过容器IP连接MySQL,而非localhost。

验证/修复方式:

  1. 进入MySQL容器:
    docker exec -it <你的db容器名> mysql -u <用户名> -p
    
  2. 执行授权语句(替换占位符):
    GRANT ALL PRIVILEGES ON database.* TO '你的用户名'@'%';
    FLUSH PRIVILEGES;
    
  3. 也可以把这条语句加入./db/init.sql,让MySQL初始化时自动配置。

4. 关于Docker links的说明

Docker Compose中同一网络下的服务,默认可以通过服务名(比如db)直接解析IP,links配置不是必须的,它不会影响你的连接问题,可以保留也可以移除。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:05:47