Docker环境下NestJS应用无法连接MySQL数据库求助
NestJS容器无法连接MySQL容器的排查与解决
问题背景
开发基于NestJS的应用,使用Docker Compose容器化部署,后端容器始终无法连接MySQL容器,报错:
Error: P1001: Can't reach the database server at `demo-tracker-mysql`:`3306`
已配置depends_on(含健康检查依赖)、同网络,MySQL容器外部可通过Workbench正常连接,容器状态显示健康。
相关配置文件
docker-compose.yml
version: "3" services: frontend: build: context: ./demo-tracker-frontend command: ["npm", "start"] ports: - "3000:3000" depends_on: - backend networks: - network backend: build: context: ./demo-tracker-backend command: ["sh", "-c", "npx prisma migrate deploy && npm run start:migrate:prod"] ports: - "3001:3000" volumes: - ./demo-tracker-backend:/app_backend depends_on: mysql: condition: service_healthy environment: DATABASE_URL: "mysql://root:#password@demo-tracker-mysql:3306/demo_tracker_mysql?connect_timeout=300" networks: - network mysql: build: context: ./mysql environment: MYSQL_ROOT_PASSWORD: #password MYSQL_DATABASE: demo_tracker_mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 30s retries: 20 ports: - "3306:3306" networks: - network networks: network:
MySQL Dockerfile
FROM mysql:latest HEALTHCHECK --interval=5s --timeout=30s \ CMD mysqladmin ping -h localhost ENV MYSQL_ROOT_PASSWORD=passbackendtrackerword ENV MYSQL_DATABASE=demo_tracker_mysql EXPOSE 3306 CMD ["mysqld"]
NestJS后端Dockerfile
FROM node:18.17.1 WORKDIR /app_backend COPY ./package*.json ./ COPY prisma ./prisma/ RUN npm install RUN npx prisma generate COPY ./ . RUN npm run build EXPOSE 3001 CMD ["npm", "run", "start:migrate:prod"]
排查与修复步骤
1. 修正密码一致性与URL编码
- 你的MySQL Dockerfile中设置的root密码是
passbackendtrackerword,但docker-compose中覆盖为#password,两者不一致,需统一。 - 若使用含特殊字符的密码(比如
#),必须进行URL编码,#的编码为%23,修改后端的DATABASE_URL:
建议优先使用无特殊字符的密码,避免编码问题。DATABASE_URL: "mysql://root:%23password@demo-tracker-mysql:3306/demo_tracker_mysql?connect_timeout=300"
2. 让MySQL监听所有网卡
MySQL默认仅绑定localhost,导致容器内其他服务无法访问。修改MySQL的启动参数:
- 在MySQL Dockerfile中修改CMD:
确保MySQL监听容器内所有IP地址,而非仅本地回环。CMD ["mysqld", "--bind-address=0.0.0.0"]
3. 强化MySQL健康检查
当前健康检查仅验证服务启动,未确认数据库可正常查询。修改docker-compose中mysql服务的健康检查:
healthcheck: test: ["CMD", "mysql", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}", "-e", "SELECT 1;", "${MYSQL_DATABASE}"] timeout: 30s retries: 20 interval: 5s
确保数据库完全就绪后,后端才开始启动。
4. 验证容器间网络连通性
进入后端容器,手动测试MySQL连接:
# 进入后端容器 docker exec -it <backend容器名称> bash # 安装MySQL客户端(若未预装) apt update && apt install -y mysql-client # 测试连接 mysql -h demo-tracker-mysql -u root -p<你的密码> demo_tracker_mysql
若连接失败,说明网络或MySQL配置存在问题;若成功,则排查Prisma配置。
5. 确认Prisma配置正确性
- 检查
prisma/schema.prisma中的数据源配置:datasource db { provider = "mysql" url = env("DATABASE_URL") } - 由于后端挂载了本地目录,需确认容器内
node_modules/@prisma/client未被本地文件覆盖,可删除容器内的node_modules后重新安装生成:docker exec -it <backend容器名称> bash rm -rf node_modules && npm install && npx prisma generate
总结
最可能的问题是密码不一致+特殊字符未编码,或MySQL仅监听localhost。优先修正密码与URL编码,调整MySQL绑定地址,基本可解决连接问题。
内容的提问来源于stack exchange,提问作者Mohammad Kazemzadeh
相关产品推荐
相关产品推荐

