简体   繁体   English

使用 Prisma Dockerize NextJS 应用程序

[英]Dockerize NextJS Application with Prisma

I have created a NextJS application, to connect to the database I use Prisma.我创建了一个 NextJS 应用程序,以连接到我使用 Prisma 的数据库。 When I start the application on my computer everything works.当我在计算机上启动该应用程序时,一切正常。 Unfortunately, I get error messages when I try to run the application in a Docker container.不幸的是,当我尝试在 Docker 容器中运行应用程序时收到错误消息。 The container can be created and started.可以创建并启动容器。 The start page of the application can also be shown (there are no database queries there yet).也可以显示应用程序的起始页(那里还没有数据库查询)。 However, when I click on the first page where there is a database query I get error code 500 - Initial Server Error and the following error message in the console:但是,当我单击有数据库查询的第一页时,我收到错误代码 500 - Initial Server Error 和控制台中的以下错误消息:

PrismaClientInitializationError: Unknown PRISMA_QUERY_ENGINE_LIBRARY undefined. Possible binaryTargets: darwin, darwin-arm64, debian-openssl-1.0.x, debian-openssl-1.1.x, rhel-openssl-1.0.x, rhel-openssl-1.1.x, linux-arm64-openssl-1.1.x, linux-arm64-openssl-1.0.x, linux-arm-openssl-1.1.x, linux-arm-openssl-1.0.x, linux-musl, linux-nixos, windows, freebsd11, freebsd12, openbsd, netbsd, arm, native or a path to the query engine library.
You may have to run prisma generate for your changes to take effect.
    at cb (/usr/src/node_modules/@prisma/client/runtime/index.js:38689:17)
    at async getServerSideProps (/usr/src/.next/server/pages/admin/admin.js:199:20)
    at async Object.renderToHTML (/usr/src/node_modules/next/dist/server/render.js:428:24)
    at async doRender (/usr/src/node_modules/next/dist/server/next-server.js:1144:38)
    at async /usr/src/node_modules/next/dist/server/next-server.js:1236:28
    at async /usr/src/node_modules/next/dist/server/response-cache.js:64:36 {
  clientVersion: '3.6.0',
  errorCode: undefined
}

My Dockerfile:我的 Dockerfile:

# Dockerfile

# base image
FROM node:16-alpine3.12

# create & set working directory
RUN mkdir -p /usr/src
WORKDIR /usr/src

# copy source files
COPY . /usr/src

COPY package*.json ./
COPY prisma ./prisma/

# install dependencies
RUN npm install

COPY . .

# start app
RUN npm run build
EXPOSE 3000
CMD npm run start

My docker-compose.yaml:我的 docker-compose.yaml:

version: "3"

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: web
    restart: always
    volumes:
      - ./:/usr/src/app
    ports:
      - "3000:3000"
    env_file:
      - .env

My package.json:我的 package.json:

{
    "name": "supermarket",
    "version": "0.1.0",
    "private": true,
    "scripts": {
        "dev": "next dev",
        "build": "next build",
        "start": "next start",
        "lint": "next lint"
    },
    "prisma": {
        "schema": "prisma/schema.prisma"
      },
    "dependencies": {
        "@prisma/client": "^3.6.0",
        "axios": "^0.22.0",
        "cookie": "^0.4.1",
        "next": "latest",
        "nodemailer": "^6.6.5",
        "react": "17.0.2",
        "react-cookie": "^4.1.1",
        "react-dom": "17.0.2"
    },
    "devDependencies": {
        "eslint": "7.32.0",
        "eslint-config-next": "11.1.2",
        "prisma": "^3.6.0"
    }
}

I have been having a similar issue, which I have just solved.我一直有一个类似的问题,我刚刚解决了。

I think what you need to do is change the last block in your docker file to this我认为您需要做的是将 docker 文件中的最后一个块更改为此

# start app
RUN npm run build
RUN npx prism generate
EXPOSE 3000
CMD npm run start

I think that will solve your issue.我认为这将解决您的问题。

I've found the error.我发现了错误。 I think it's a problem with the M1 Chip.我认为这是M1芯片的问题。 I changed node:16-alpine3.12 to node:lts and added some commands to the Dockerfile which looks like this now:我将node:16-alpine3.12更改为node:lts :lts 并向 Dockerfile 添加了一些命令,现在看起来像这样:

# base image
FROM node:lts

# create & set working directory
RUN mkdir -p /usr/src
WORKDIR /usr/src

# copy source files
COPY . /usr/src

COPY package*.json ./
COPY prisma ./prisma/

RUN apt-get -qy update && apt-get -qy install openssl

# install dependencies
RUN npm install

RUN npm install @prisma/client

COPY . .
RUN npx prisma generate --schema ./prisma/schema.prisma
# start app
RUN npm run build
EXPOSE 3000
CMD npm run start

I hope this can also help other people我希望这也可以帮助其他人


I had a luck this way:我有这样的运气:

FROM node:17-slim as dependencies


# set working directory
WORKDIR /usr/src/app

# Copy package and lockfile
COPY package.json ./
COPY yarn.lock ./
COPY prisma ./prisma/
RUN apt-get -qy update && apt-get -qy install openssl

# install dependencies
RUN yarn --frozen-lockfile

COPY . .

# ---- Build ----
FROM dependencies as build
# install all dependencies

# build project
RUN yarn build

# ---- Release ----
FROM dependencies as release
# copy build
COPY --from=build /usr/src/app/.next ./.next
COPY --from=build /usr/src/app/public ./public

# dont run as root
USER node

# expose and set port number to 3000
EXPOSE 3000
ENV PORT 3000

# enable run as production
ENV NODE_ENV=production

# start app
CMD ["yarn", "start"]

I've found this solution with some workarounds: https://gist.github.com/malteneuss/a7fafae22ea81e778654f72c16fe58d3 In short:我发现这个解决方案有一些解决方法: https://gist.github.com/malteneuss/a7fafae22ea81e778654f72c16fe58d3简而言之:

# Dockerfile

...
FROM node:16-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npx prisma generate                   # <---important to support Prisma query engine in Alpine Linux in final image
RUN npm run build

# Production image, copy all the files and run next
FROM node:16-alpine AS runner
WORKDIR /app
...
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --chown=nextjs:nodejs prisma ./prisma/                # <---important to support Prisma DB migrations in bootstrap.sh
COPY --chown=nextjs:nodejs bootstrap.sh ./
...
CMD ["./bootstrap.sh"]

This Dockerfile is based on the official Nextjs with Docker example project and adapted to include Prisma.这个 Dockerfile 基于带有 Docker 示例项目的官方 Nextjs,并适用于包括 Prisma。 To run migrations on app start we can add a bash script that does so:要在应用启动时运行迁移,我们可以添加一个 bash 脚本来执行此操作:

# bootstrap.sh

#!/bin/sh
# Run migrations
DATABASE_URL="postgres://postgres:postgres@db:5432/appdb?sslmode=disable" npx prisma migrate deploy
# start app
DATABASE_URL="postgres://postgres:postgres@db:5432/workler?sslmode=disable" node server.js

Unfortunately, we need to explicitly set the DATABASE_URL here, otherwise migrations don't work, because Prisma can't find the environment variable (eg from a docker-compose file).不幸的是,我们需要在这里显式设置 DATABASE_URL,否则迁移将不起作用,因为 Prisma 无法找到环境变量(例如,从 docker-compose 文件)。 And last but not least, because Alpine Linux base image uses a Musl C-library, the Prisma client has to be compiled in the builder image against that.最后但同样重要的是,因为 Alpine Linux 基础镜像使用了 Musl C 库,所以 Prisma 客户端必须在构建器镜像中针对它进行编译。 So, to get the correct version, we need to add this info to Prisma's schema.prisma file:因此,为了获得正确的版本,我们需要将此信息添加到 Prisma 的schema.prisma文件中:

# schema.prisma

generator client {
  provider = "prisma-client-js"
  binaryTargets = ["native", "linux-musl"] # <---- important to support Prisma Query engine in Alpine linux, otherwise "PrismaClientInitializationError2 [PrismaClientInitializationError]: Query engine binary for current platform "linux-musl" could not be found."
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM