Docker容器内PrismaORM PostgreSQL创建迁移失败问题
Docker构建NestJS+Prisma+PostgreSQL应用时数据库连接失败
执行npx prisma migrate dev --name init时报错:Can't reach database server at postgres:5432
相关配置文件
docker-compose.yml
version: "3.8" services: api: build: dockerfile: Dockerfile context: . depends_on: - postgres env_file: - ./.env ports: - "8080:5000" postgres: image: postgres:10.4 ports: - "5432:5432" environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: db volumes: - ./postgres-data:/var/lib/postgresql/data env_file: - ./.env
Dockerfile
FROM node:16 WORKDIR /qmessanger/src/server COPY package*.json ./ COPY prisma ./prisma/ COPY .env ./ COPY . . RUN npm install RUN npm run build RUN npx prisma generate RUN npx prisma migrate dev --name init EXPOSE 8080 CMD [ "node", "dist/main" ]
.env配置
DATABASE_URL="postgresql://user:password@postgres:5432/db" POSTGRES_HOST=postgres POSTGRES_PORT=5432 POSTGRES_USER=user POSTGRES_PASSWORD=password POSTGRES_DB=db
Prisma配置
generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") }
问题根源
- 构建阶段无法访问postgres服务:Docker镜像构建时(
RUN指令执行阶段),postgres容器还未启动,depends_on只控制容器启动顺序,和镜像构建流程无关。 - 错误使用迁移命令:
prisma migrate dev是开发环境命令,依赖本地开发环境和运行中的数据库,不应该嵌入到镜像构建步骤里。
修复方案
1. 调整Dockerfile,移除构建阶段的migrate命令
删除RUN npx prisma migrate dev --name init,调整后Dockerfile:
FROM node:16 WORKDIR /qmessanger/src/server COPY package*.json ./ COPY prisma ./prisma/ COPY .env ./ COPY . . RUN npm install RUN npm run build RUN npx prisma generate EXPOSE 8080 CMD [ "node", "dist/main" ]
2. 选择合适的迁移执行时机
方案一:容器启动时自动执行生产环境迁移
修改CMD指令,先执行生产环境迁移命令再启动服务,适合测试/生产环境:
CMD ["sh", "-c", "npx prisma migrate deploy && node dist/main"]
注:
prisma migrate deploy只会执行未应用的迁移,是生产环境专用命令,不会生成开发相关文件。
方案二:本地提前完成开发迁移(仅开发环境)
本地启动postgres服务后,先在项目根目录执行npx prisma migrate dev --name init完成迁移,再构建Docker镜像,镜像构建只需要保留prisma generate生成客户端代码即可。
3. 确保postgres服务完全就绪
添加健康检查,避免api容器在postgres未初始化完成时尝试连接:
修改docker-compose.yml中的postgres服务:
postgres: image: postgres:10.4 ports: - "5432:5432" environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: db volumes: - ./postgres-data:/var/lib/postgresql/data env_file: - ./.env healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d db"] interval: 5s timeout: 5s retries: 5
同时修改api服务的depends_on,等待postgres健康检查通过:
api: build: dockerfile: Dockerfile context: . depends_on: postgres: condition: service_healthy env_file: - ./.env ports: - "8080:5000"
4. 验证配置正确性
当前.env中的DATABASE_URL使用postgres作为主机名,和docker-compose中postgres服务名称一致,配置无需修改。
内容的提问来源于stack exchange,提问作者QueezZ
相关产品推荐
相关产品推荐

