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

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:
    CMD ["mysqld", "--bind-address=0.0.0.0"]
    
    确保MySQL监听容器内所有IP地址,而非仅本地回环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:23:17