Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query engine library for current platform "linux-musl" could not be found in Docker #16901

Closed
jclaessens97 opened this issue Dec 19, 2022 · 25 comments
Assignees
Labels
bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. kind/bug A reported bug. team/schema Issue for team Schema. topic: bundler topic: engine download topic: engine-not-found topic: esbuild

Comments

@jclaessens97
Copy link

jclaessens97 commented Dec 19, 2022

Whenever I try to run my docker container on AWS App Runner I get the following:

image

image

When running my docker container locally it just works. I'm running the docker on AWS on amd64, while on my laptop it's arm64 (m1 mac).

# Base
FROM --platform=linux/amd64 app/base:latest as base


# Build
FROM --platform=linux/amd64 node:18-alpine as api-builder
WORKDIR /usr/src/app

RUN apk add --no-cache libc6-compat
RUN apk update
RUN npm install -g turbo

COPY --from=base /usr/src/app /usr/src/app/
RUN turbo prune --scope=@app/api --docker


# Production image
FROM --platform=linux/amd64 node:18-alpine as api-runner
WORKDIR /usr/src/app

RUN apk add --no-cache libc6-compat
RUN apk add --update --no-cache openssl1.1-compat
RUN apk update
RUN npm install -g pnpm@7.17.0
RUN npm install -g npkill

COPY --from=api-builder /usr/src/app/out/pnpm*.yaml ./
COPY --from=api-builder /usr/src/app/out/json .
RUN pnpm install --frozen-lockfile

COPY --from=api-builder /usr/src/app/out/full .
RUN pnpm turbo run db:generate
RUN pnpm turbo run build --filter=@app/api...

RUN npkill
RUN pnpm install --offline --prod

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 runner
RUN chown -R runner:nodejs ./apps/api/build
USER runner

WORKDIR /usr/src/app/apps/api
ENTRYPOINT [ "node", "build/server.js" ]
@barryhagan
Copy link

Change node:18-alpine to node:18-alpine3.16 in your dockerfile for now.

Alpine 3.17 moved to OpenSSL 3.0 and that is now the tagged version for 18-alpine.

Alternatively, install the openssl1.1-compat package with 3.17.

Prisma on Alpine w/ OpenSSL 3.0 is not ready yet: #16553

@jclaessens97
Copy link
Author

jclaessens97 commented Dec 19, 2022

Hi, thanks for your answer. I've tried the solutions proposed in the tagged discussion. First I got indeed an error about openSSL, but after I tried both node:18-alpine3.16 and installing apk add openssl1.1-compat and even using node:18-buster and node:18, I still get the same errors.

Even after explicity specifying the binaryTargets it keeps throwing errors.

Not sure if it's still related to that openSSL package, or something else is wrong here.

I also have to note that I saw somewhere that installing libc6-compat can cause unexpected behaviour, but I need it installed to make turbo work under alpine.

image

@jclaessens97
Copy link
Author

jclaessens97 commented Dec 20, 2022

I also tested building on github actions just now (of which I'm sure it's the same architecture as where I deploy the app), and I get exactly the same error. So now I'm not even sure that it's architecture related...

@jkomyno jkomyno self-assigned this Dec 21, 2022
@jkomyno jkomyno added bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. team/schema Issue for team Schema. topic: engine download kind/bug A reported bug. labels Dec 21, 2022
@jclaessens97
Copy link
Author

jclaessens97 commented Dec 21, 2022

TL;DR

I did some more research, and to me it seems that it's looking for the 'query engine library' in the wrong location.

Context

I use a pnpm workspace with turbo. At first I noticed when opening a terminal in the docker, not everything was there. For example on my local machine I have @prisma in the root node_modules, but because of the prune (I think) it wasn't there.

Next I tried building the docker without pruning, and the binary engine was there in the root node_modules for linux-musl-openssl3.x.so.node. However I found it in the @prisma/engines folder, while when believing the message it's not looking there.

These are the places Prisma look:

/usr/src/app/.prisma/client
/usr/src/app/node_modules/.pnpm/@prisma+client@4.8.0_prisma@4.8.0/node_modules/@prisma/client
/usr/src/app/apps/api
/usr/src/app/apps/api/build
/usr/src/app/apps/api/build
/tmp/prisma-engines
/usr/src/app/apps/api/build

The location I'm referring to when I mean @prisma/engines, I mean this one:
/usr/src/app/node_modules/.pnpm/@prisma+client@4.8.0_prisma@4.8.0/node_modules/@prisma/client

When I physically check in terminal inside the docker I can find the engine lib but it's not at that location, it's here:
/usr/src/app/node_modules/.pnpm/@prisma+client@4.8.0_prisma@4.8.0/node_modules/@prisma/engines

But it's not looking there.

When diving deeper into these engine locations, I found an environment variable that can be set for where to find each binary, including the missing libquery the error is about (as far as I can understand). Find the docs here.

I found the environment variable PRISMA_QUERY_ENGINE_LIBRARY that you can set to specify the 'query engine library' location. I understand correctly, this should normally only be used when you download or build these binaries yourself, not for the "auto downloaded" engines by Prisma.

Though I tried setting it to /usr/src/app/node_modules/.pnpm/@prisma+client@4.8.0_prisma@4.8.0/node_modules/@prisma/engines/libquery_engine-linux-musl-openssl-3.0.x.so.node to match the exact location of where I found the binary when looking into the docker with the terminal.

Now I'm stuck again. I've set the environment variable, double checked it's effectively set, but still it doesn't seem to look at that location. Maybe it does, but at least the issue remains the same, and the location of the environment variable isn't added to the list Prisma prints out where it's looking.

EDIT:

In the meantime I also tried adding a symbolic link that points the first location where Prisma looks /usr/src/app/apps/api/build/libquery_engine-linux-musl-openssl-3.0.x.so.node to the above location in the @prisma/engines folder.

@jkomyno
Copy link
Contributor

jkomyno commented Dec 21, 2022

Hi @jclaessens97, can you please share your schema.prisma with us?

It looks like you've modified the binaryTargets attribute in your schema, which may cause Prisma to download a different engine library/binary than the ones it's supposed to.

I've also tried running prisma (both the CLI and the Client) on a machine that mirrors your system configuration:

  • MacBook with M1 CPU (arm64 architecture)
  • Docker image using Linux Alpine 3.17 (amd64 emulated architecture)
  • OpenSSL 3.0.x
  • libc6-compat installed

but I can see that the query engine library downloaded is called libquery_engine-linux-musl-openssl-3.0.x.so.node (verified via prisma -v).

@jclaessens97
Copy link
Author

jclaessens97 commented Dec 21, 2022

Hi @jkomyno,

I've indeed tried with modifying binaryTargets, but even without that set or with just native set, nothing seem to change. I've tried it with setting it manually as follows:

binaryTargets = ["native", "debian-openssl-1.1.x", "debian-openssl-3.0.x", "linux-musl", "linux-musl-openssl-3.0.x"].

I can't post my full schema, but the generator/datasource blocks looks like this:

generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native", "debian-openssl-1.1.x", "debian-openssl-3.0.x", "linux-musl", "linux-musl-openssl-3.0.x"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

My prisma -v inside the built docker looks like this:

image

The error happens during client initialization, the first time I try to execute a query. Not during build/generate stage.

@jkomyno
Copy link
Contributor

jkomyno commented Dec 21, 2022

@jclaessens97 can you please copy your project in another folder, replacing your private schema with

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgres"
  url      = env("DATABASE_URL")
}

model SomeUser {
  id   Int      @id
  post Post[]
}

model Post {
  id     Int      @id
  user   SomeUser @relation(fields: [userId], references: [id])
  userId Int
}

and trying again to initialise the Client with prisma@4.8.0?

You may use a Client seed file like the following:

// ./prisma/seed.ts

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {

  /* truncate tables */
  await prisma.post.deleteMany()
  await prisma.someUser.deleteMany()

  // create users
  const N_USERS = 2
  const userIds = Array.from({ length: N_USERS }, (_, i) => i + 1)

  // create posts per user
  const N_POSTS_PER_USER = 100
  const postsToCreate = Array.from({ length: N_USERS * N_POSTS_PER_USER }, (_, i) => ({
    id: i + 1,
    userId: Math.floor(i / N_POSTS_PER_USER) + 1
  }))

  console.log('creating users...')
  await prisma.someUser.createMany({
    data: userIds.map((id) => ({ id })),
  })

  console.log('creating posts...')
  await prisma.post.createMany({
    data: postsToCreate,
  })
}

main()
  .finally(() => {
    prisma.$disconnect()
  })

which, when paired with a package.json like

{
  "name": "@prisma/linux-alpine-3.17-x64-openssl-1.1.x",
  "version": "1.0.0",
  "license": "ISC",
  "dependencies": {
    "@prisma/client": "4.8.0"
  },
  "prisma": {
    "seed": "pnpm ts-node ./prisma/seed.ts"
  },
  "devDependencies": {
    "@types/node": "^18.0.0",
    "prisma": "4.8.0",
    "ts-node": "^10.8.1",
    "typescript": "^4.9.3"
  }
}

can be run via pnpm prisma db push and pnpm prisma db seed.

@jcamden
Copy link

jcamden commented Dec 21, 2022

FWIW, I ran into this problem running docker-compose locally with node:16-alpine. Thanks @barryhagan for pointing out the changes to latest Alpine. I decided to bump to 18 but pin to 3.16 as you suggested: node:18-alpine3.16 That worked for me.

@jclaessens97
Copy link
Author

jclaessens97 commented Dec 22, 2022

@jkomyno, I've looked into trying the repro you suggested and tested it both locally and on AWS.

Both seem to work fine on v4.8.0. Now I'll try to add stuff to the repro until I can really reproduce it.
I'm thinking about pnpm, turbo or something related to #15292

@jcamden I've tried pinning both 3.16, 3.17 (as of 4.8.0 you can again use alpine 3.17 without openssl1.1-compat install). I think my issue is something else.

@jclaessens97
Copy link
Author

jclaessens97 commented Dec 22, 2022

I was just able to reproduce it also outside of Docker, however it might be related to my build step and there is no "actual" prisma issue related to the engine not being found, but rather a very confusing error message.

I've pushed my reproduction (built on @jkomyno's proposed repro) to github: https://github.com/jclaessens97/prisma-repro

My guess is that when building with esbuild (I also have to add the postBuild step to place the schema in my build folder, otherwise it's complaining it can't find the schema), that some files are getting moved around (or not) and that it tries to reach some nescessary files using some sort of relative path.

However, I'm not sure which files, where I'm going wrong and how to fix it. On the other side if this IS the case (still not 100%), then I think Prisma can benefit from more clearer error messages 😄

EDIT: added expected repro output
image

@jkomyno
Copy link
Contributor

jkomyno commented Dec 22, 2022

Thanks for your repro @jclaessens97, this will be absolutely helpful for understanding this problem on our end!

@jclaessens97
Copy link
Author

@jkomyno no worries, anything to help 😄

I think it might simply be fixed by not using bundle: true in esbuild.ts. At least, I got the repro working by doing that (and removing the postBuild hook). Testing my application again at the moment.

@jclaessens97
Copy link
Author

@jkomyno, I think I need bundling because otherwise my path aliases won't be resolved correctly in esbuild.

I think it should be possible since I found this page in the docs. However I'm not sure what to manually copy and where to, do you have any pointers for that maybe?

@jclaessens97
Copy link
Author

I've removed my path aliases for now to work around that. It seems to be working now 🙏

I think it still might be a good thing to have troubleshooting somewhere in the docs with a few steps people can try?
Small list I came up with from this issue and related issues:

  • Clear cache
  • binaryTargets
  • Check bundling:
    • no bundling
    • bundling but copy static files to the right location (maybe add example on the module bundling page?)
  • Refer to the alpine docker issues

I think that will save you guys a lot of new issues related to this topic 😅

For me you can close this issue!

@Jolg42 Jolg42 added topic: engine-not-found topic: bundler topic: esbuild bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. and removed bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. labels Dec 22, 2022
@ali-shabani
Copy link

I had the same problem and struggled with it for a day. I want to share my experience with those looking for a solution if their setup is like mine.
I'm using Turborepo, and I keep my Prisma in its related package as the Turborepo documentation suggests.

I tried to bundle my app using tsup, first I got an issue with finding the schema file, then after copying it to my build folder, I got the query engine platform error. by setting skipNodeModulesBundle: true in tsup config my problem has been solved.

@jkomyno
Copy link
Contributor

jkomyno commented Jan 3, 2023

Closing this as the issue has a clear solution here.
Currently, Prisma Client might not work out of the box with some bundlers, if you encounter such a case, please create an issue, as we want to improve on this area.

jyecusch added a commit to nitrictech/cli that referenced this issue May 22, 2023
We may remove these fixes in future and allow developers to resolve
these issues themselves through custom docker files. For now though,
they have no impact on projects that aren't running prisma.

Related issues can be found here:
- prisma/docs#4365
- prisma/prisma#16901 (comment)
@zach-betz-hln
Copy link

I was able to resolve this after a bit of poking around. More info below.

Was getting this error after a docker run (it built fine):

Prisma Client could not locate the Query Engine for runtime "linux-musl-arm64-openssl-3.0.x".\n\nThis is likely caused by a bundler that has not copied "libquery_engine-linux-musl-arm64-openssl-3.0.x.so.node" next to the resulting bundle.\nEnsure that "libquery_engine-linux-musl-arm64-openssl-3.0.x.so.node" has been copied next to the bundle or in "dist".\n\nWe would appreciate if you could take the time to share some information with us.\nPlease help us by answering a few questions: https://pris.ly/engine-not-found-bundler-investigation\n\nThe following locations have been searched:\n /home/node/app/dist\n /home/node/app\n /home/node/app/node_modules/@prisma/client\n /home/.prisma/client\n /tmp/prisma-engines

Some info on my local setup:

Build command is:

yarn run ncc build src/index.ts -o dist

Dockerfile is:

Dockerfile
FROM node:18.16-alpine3.17 AS builder

ARG NODE_ENV=production

ARG GH_NODE_AUTH_TOKEN

WORKDIR /home/node/app

# Git is used in later scripts
# Other packages needed for ARM chip if building image locally. For example, on Apple M1
# See https://github.com/parcel-bundler/watcher/issues/102#issuecomment-1229125545
RUN apk add --no-cache \
    git \
    make \
    clang \
    build-base \
    python3

# Enable yarn
RUN corepack enable

COPY . .

# Install packages
RUN yarn install --immutable --immutable-cache

# Run unit tests
RUN CI=true yarn test

# Do production build
RUN yarn run build

FROM node:18.16-alpine3.17 AS final

ENV NODE_ENV=production
ENV TZ=America/New_York

WORKDIR /home/node/app

# Tini is a container init system
# See https://github.com/krallin/tini
RUN apk add --no-cache tini

# Fix permissions
RUN chown node: /sbin
RUN chown node: /usr/local/bin

USER node

# Only copy needed files
COPY --from=builder --chown=node:node /home/node/app/dist /home/node/app/dist
COPY --from=builder --chown=node:node /home/node/app/generatedInfo.json /home/node/app/generatedInfo.json
COPY --from=builder --chown=node:node /home/node/app/schema.graphql /home/node/app/schema.graphql

EXPOSE 4001

ENTRYPOINT [ "/sbin/tini", "--" ]

CMD [ "node", "/home/node/app/dist/index.js" ]

To fix, had to specify the engineType to my prisma/schema.prisma:

generator client {
  provider   = "prisma-client-js"
  engineType = "binary"
}

See https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#configuring-the-query-engine

@jkomyno
Copy link
Contributor

jkomyno commented Jun 29, 2023

Hi @zach-betz-hln, what if you remove ncc from your Docker pipeline and leave the default engineType ("library") in your Prisma schema? Looks like this may be an ncc issue not supporting Node.js addons created via napi.rs

@zach-betz-hln
Copy link

Hi @jkomyno - Sure enough, if I change my build command to a plain yarn run tsc, then change the engineType back to "library", it works.

Though, I'm satisfied with my current ncc + engineType = "binary" setup, since it allows me to only copy the necessary output files into my final Docker image, resulting in a smaller image 🤷‍♂️

@iamprakashom
Copy link

Adding below line in schema.prisma worked like a charm.

binaryTargets = ["native", "linux-musl-openssl-3.0.x"]

@Viktorlvkl
Copy link

At schema.prisma file add:

generator client {
  provider = "prisma-client-js"
  binaryTargets = ["native","linux-musl"]
}

After that, run npx prisma generate

@gabo71096
Copy link

In my situation, I checked the node_modules/.prisma/client folder and I realized that I had a windows .dll instead of the libquery_engine-debian-openssl-3.0.x.so.node file, I think it was caused because I run yarn prisma generate outside of the container, and then the app went insane. Apparently running the prisma generate command manually, ignored the binaryTargets, and replaced the file with a windows option.
After removing the folder node_modules, running yarn again on the host, and rebuilding the container, it finally worked.

@zach-betz-hln
Copy link

@gabo71096 if it helps, yarn version 4 has config options for os which you can tweak the pull the Windows and Linux binaries.

@gabo71096
Copy link

@gabo71096 if it helps, yarn version 4 has config options for os which you can tweak the pull the Windows and Linux binaries.

Thanks! I had no idea... Cheers!

@adamspotlite
Copy link

After circling on this page for 3+ hours, for anyone using nextjs, this solved my issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. kind/bug A reported bug. team/schema Issue for team Schema. topic: bundler topic: engine download topic: engine-not-found topic: esbuild
Projects
None yet
Development

No branches or pull requests