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

Node.js Express-GraphQL容器无法访问Docker MySQL容器问题求助

问题排查与解决方法

1. 修复数据库密码不匹配问题

你的配置存在密码不一致的低级错误:docker-compose中给Node服务传入的DATABASE_PASS值为root,但MySQL服务里给ernest用户设置的MYSQL_PASSWORD值为password,二者不匹配会直接导致认证失败。
修改server服务的environment配置即可:

environment:
  DATABASE_HOST: 'mysqldb'
  DATABASE_USER: 'ernest'
  DATABASE_PASS: 'password' # 和mysql配置中的MYSQL_PASSWORD值保持一致
  DATABASE_NAME: 'test'

2. 解决容器启动时序问题

depends_on仅能保证MySQL容器先于Node容器启动,不会等待MySQL完成初始化(创建库、创建用户、启动端口监听)。从日志可以看出,Node服务在01:27:01就发起连接请求,此时MySQL还在运行初始化逻辑,直到01:27:08才完成用户和库的创建,自然连接被拒绝。
两种解决方案二选一即可:

  • 方案1:给Node服务添加端口等待逻辑,使用wait-for-it这类工具等待MySQL的3306端口可用后再启动服务,修改docker-compose中server的command配置:
command: sh -c "wait-for-it mysqldb:3306 -- yarn dev:docker"

只需提前把wait-for-it脚本放到项目根目录,或者在Node镜像中预先安装该工具即可。

  • 方案2:在Node代码中添加数据库连接重试逻辑,连接失败后间隔1秒重试,最多重试5次,避免时序问题导致的报错:
// index.js中添加重试方法
const connectWithRetry = async (retryCount = 5) => {
  try {
    await createConnection({
      // 保持原有的数据库配置不变
      type: "mysql",
      host: process.env.DATABASE_HOST,
      database: process.env.DATABASE_NAME,
      username: process.env.DATABASE_USER,
      password: process.env.DATABASE_PASS,
      logging: true,
      synchronize: false,
      entities: [Users]
    })
    console.log("数据库连接成功")
  } catch (err) {
    if (retryCount <= 0) throw err
    console.log(`数据库连接失败,${retryCount}秒后重试:`, err.message)
    await new Promise(res => setTimeout(res, 1000))
    return connectWithRetry(retryCount - 1)
  }
}
// 调用重试方法代替原有的直接调用createConnection
await connectWithRetry()

额外优化

MySQL官方镜像的默认数据存储路径为/var/lib/mysql,你当前配置的挂载路径/data/db是MongoDB的默认存储路径,不会生效,会导致容器重建后数据丢失,修改mysqldb服务的volumes配置即可:

volumes:
  - ./mysqlData:/var/lib/mysql

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:39:03