使用Docker部署时NestJS无法连接MySQL数据库问题排查
问题分析与解决方案
核心问题1:数据库HOST配置冲突
你的demo-api文件夹内的.env文件中DB_HOST=localhost,这会覆盖docker-compose.yml中设置的DB_HOST=mysqldb。在Docker容器环境下,localhost指向容器自身,而非MySQL服务容器,导致无法连接到mysqldb服务。
修复方式:
- 删除
demo-api文件夹内.env中的DB_HOST、DB_USER、DB_PASSWORD、DB_NAME、DB_PORT配置项,让容器优先使用docker-compose.yml中传递的环境变量。 - 或者修改
demo-api的.env中DB_HOST=mysqldb,保持与Docker网络配置一致。
核心问题2:MySQL服务未就绪时NestJS提前启动
depends_on仅保证容器启动顺序,不确保MySQL服务完全初始化完成。NestJS启动时MySQL可能还在初始化,导致连接失败。
修复方式:
方式一:添加启动等待脚本
在demo-api的Dockerfile中集成wait-for-it脚本,确保MySQL就绪后再启动NestJS:
- 将
wait-for-it.sh脚本复制到demo-api目录 - 调整Dockerfile内容:
# 基础镜像 FROM node:18-alpine # 复制脚本 COPY wait-for-it.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/wait-for-it.sh # 工作目录 WORKDIR /app # 复制依赖文件并安装 COPY package*.json ./ RUN npm install # 复制项目文件 COPY . . # 构建项目 RUN npm run build # 暴露端口 EXPOSE 8080 # 启动命令,等待MySQL就绪 CMD ["wait-for-it.sh", "mysqldb:3306", "--", "npm", "run", "start:prod"]
方式二:添加数据库连接重试机制
在TypeORM配置中增加重试参数,让NestJS自动重试连接:
const DBModule = TypeOrmModule.forRootAsync({ useFactory: async () => ({ type: process.env.DB_TYPE as any, host: process.env.DB_HOST, port: parseInt(process.env.DB_PORT), username: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, entities: entities, synchronize: true, retryAttempts: 10, // 最大重试次数 retryDelay: 3000, // 每次重试间隔3秒 }), });
docker-compose.yml优化点
目前配置无语法错误,但可补充完善MySQL用户配置(非强制,但保持配置完整性):
mysqldb: # ...原有配置 environment: - MYSQL_ROOT_PASSWORD=$MYSQLDB_ROOT_PASSWORD - MYSQL_DATABASE=$MYSQLDB_DATABASE - MYSQL_USER=$MYSQLDB_USER # 新增:对应根.env中的MYSQLDB_USER - MYSQL_PASSWORD=$MYSQLDB_ROOT_PASSWORD # 新增:为该用户设置密码
验证步骤
- 停止并清理现有容器与卷:
docker-compose down -v - 重新构建并启动服务:
docker-compose up --build - 查看
demo-api日志确认连接状态:docker logs <demo-api-container-id>
内容的提问来源于stack exchange,提问作者Fahad Amin
相关产品推荐
相关产品推荐

