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
相关产品推荐
相关产品推荐

