Docker Compose部署Node服务连接MySQL失败求助
Docker构建Node服务时TypeORM迁移无法连接MySQL的问题解决
问题背景
使用docker-compose部署Node服务与MySQL时,构建阶段执行RUN yarn typeorm:migrate命令失败,报错无法连接MySQL(ECONNREFUSED 127.0.0.1:3306)。
当前配置
1. docker-compose.yml
version: "3" services: db: image: mysql restart: always environment: MYSQL_ROOT_PASSWORD: root MYSQL_ROOT_USER: root MYSQL_DATABASE: bl ports: - "3306:3306" volumes: - ./data:/var/lib/mysql server: env_file: "./server/.env" build: context: ./server dockerfile: ./Dockerfile image: "server" ports: - "5000:5000" depends_on: - db
2. Node服务Dockerfile
FROM node:lts-alpine WORKDIR /server COPY . . COPY package*.json ./ COPY .env ./ RUN yarn install EXPOSE 5000 EXPOSE 3306 ENV NODE_ENV=docker RUN yarn typeorm:migrate RUN yarn typeorm:run-migrations CMD ["yarn", "start"]
3. TypeORM DataSource配置
export const appDataSource = new DataSource({ type: "mysql", host, port, username: rootUser, password, database, entities: [Company, Order], migrationsTableName: "migrations", migrations: [`${__dirname}/../migrations/*.ts`], });
报错信息
> [7/8] RUN yarn typeorm:migrate: #10 0.857 yarn run v1.22.19 #10 0.943 $ yarn create:migrate-repo && yarn run typeorm -- -d ./src/systems/typeOrm.config.ts migration:generate ./src/migrations/migration #10 1.344 $ mkdir -p ./src/migrations #10 1.757 warning From Yarn 1.0 onwards, scripts don't require "--" for options to be forwarded. In a future version, any explicit "--" will be forwarded as-is to the scripts. #10 1.769 $ ts-node ./node_modules/typeorm/cli -d ./src/systems/typeOrm.config.ts migration:generate ./src/migrations/migration #10 7.524 Error during migration generation: #10 7.527 Error: connect ECONNREFUSED 127.0.0.1:3306 #10 7.527 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1494:16) { #10 7.527 errno: -111, #10 7.527 code: 'ECONNREFUSED', #10 7.527 syscall: 'connect', #10 7.527 address: '127.0.0.1', #10 7.527 port: 3306, #10 7.527 fatal: true #10 7.527 } #10 7.565 error Command failed with exit code 1. #10 7.565 info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. #10 7.594 error Command failed with exit code 1. #10 7.594 info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. ------
已尝试的方法
- 创建网桥网络连接两个服务
- 将DataSource的host修改为MySQL服务名
db - 直接使用MySQL容器的IP地址(172.23.0.2)
核心原因
Dockerfile中的RUN命令是在镜像构建阶段执行的,此时docker-compose定义的db服务还未启动,构建环境与运行环境属于完全隔离的网络空间,因此无论怎么配置host都无法连接到未运行的MySQL服务。
解决方案
1. 移除构建阶段的迁移命令,将迁移移至服务启动阶段
修改Dockerfile,删除构建时的迁移命令,仅保留依赖安装和启动命令:
FROM node:lts-alpine WORKDIR /server COPY package*.json ./ RUN yarn install COPY . . COPY .env ./ EXPOSE 5000 ENV NODE_ENV=docker CMD ["yarn", "start"]
2. 配置服务启动时等待MySQL可用并执行迁移
方法1:使用等待脚本
在Node服务项目中添加一个等待MySQL连接的脚本wait-for-db.js:
const { appDataSource } = require('./src/systems/typeOrm.config'); const waitForDB = async () => { let retries = 10; while (retries > 0) { try { await appDataSource.initialize(); console.log('MySQL连接成功'); await appDataSource.destroy(); break; } catch (err) { console.log(`MySQL连接失败,${retries}次重试剩余...`); retries--; await new Promise(resolve => setTimeout(resolve, 3000)); } } if (retries === 0) { console.error('多次重试后仍无法连接MySQL,退出服务'); process.exit(1); } }; waitForDB().then(() => { // 执行迁移并启动服务 require('child_process').execSync('yarn typeorm:run-migrations', { stdio: 'inherit' }); require('./dist/index.js'); // 替换为你的服务入口文件路径 });
修改package.json的启动脚本:
{ "scripts": { "start": "node wait-for-db.js", "typeorm:run-migrations": "ts-node ./node_modules/typeorm/cli -d ./src/systems/typeOrm.config.ts migration:run" } }
方法2:使用docker-compose的健康检查
修改docker-compose.yml,为MySQL添加健康检查,确保Node服务在MySQL完全就绪后再启动:
version: "3" services: db: image: mysql restart: always environment: MYSQL_ROOT_PASSWORD: root MYSQL_ROOT_USER: root MYSQL_DATABASE: bl ports: - "3306:3306" volumes: - ./data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"] interval: 5s timeout: 5s retries: 5 server: env_file: "./server/.env" build: context: ./server dockerfile: ./Dockerfile image: "server" ports: - "5000:5000" depends_on: db: condition: service_healthy
然后在Node服务的启动脚本中直接执行迁移(因为docker-compose已经确保MySQL可用):
{ "scripts": { "start": "yarn typeorm:run-migrations && node dist/index.js" } }
3. 修正DataSource的环境变量配置
确保server/.env中的数据库连接配置指向docker-compose的db服务:
DB_HOST=db DB_PORT=3306 DB_USER=root DB_PASSWORD=root DB_NAME=bl
在DataSource配置中读取这些环境变量:
import 'dotenv/config'; export const appDataSource = new DataSource({ type: "mysql", host: process.env.DB_HOST || 'localhost', port: parseInt(process.env.DB_PORT || '3306'), username: process.env.DB_USER || 'root', password: process.env.DB_PASSWORD || 'root', database: process.env.DB_NAME || 'bl', entities: [Company, Order], migrationsTableName: "migrations", migrations: [`${__dirname}/../migrations/*.ts`], });
4. 迁移生成的正确方式
迁移文件的生成(typeorm:migrate)应该在本地开发环境执行,而不是构建阶段。本地连接到开发数据库(或临时启动的MySQL容器)生成迁移文件后,将文件提交到代码仓库,构建镜像时只需要运行已生成的迁移文件即可。
内容的提问来源于stack exchange,提问作者Inon
相关产品推荐
相关产品推荐

