prisma: Precompiled engine files for `aarch64-unknown-linux-musl` target (Alpine Linux on ARM, e.g. M1)

Problem

Right now you can’t use Prisma on Docker alpine on M1 mac as it requires aarch64-unknown-linux-musl binaries. As M1 will see more adoption, people will run into this frequently.

Suggested solution

Provide precompiled binaries for aarch64-unknown-linux-musl target like we have precompiled binaries for x86-linux-musl

Alternatives

  1. Ask user to compile the binary themselves
  2. Document use node:lts instead of node:lts-alpine which is not ideal.

Additional context

https://github.com/prisma/prisma/issues/7755

Naming as unknown is intended like that, see more information internally: https://prisma-company.slack.com/archives/C016KUHB1R6/p1627469574008300?thread_ts=1626873669.001400&cid=C016KUHB1R6

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 77
  • Comments: 77 (16 by maintainers)

Commits related to this issue

Most upvoted comments

This could be “solved” by using docker build --platform linux/arm64 see this article

Hi everyone! Native support for Alpine Linux on ARM64 CPUs is now merged and will be released in Prisma 4.10.0 on Tuesday. You shouldn’t need any workarounds like running the image in emulation or building the engines yourselves starting with 4.10.0. Please let us know if you have any feedback!

Yeah, this has become an issue for our engineers using M1s - is there any indication as to whether this item is any sort of priority?

nobody assigned on this? it would be great to get prisma working without sucking my entire m1 pro battery in 3h because of the x86 emulation inefficiency 😕

Hopefully this will help in the interim:

FROM rust:1.58.1-alpine3.14 as prisma
ENV RUSTFLAGS="-C target-feature=-crt-static"
RUN apk --no-cache add openssl direnv git musl-dev openssl-dev build-base perl protoc
RUN git clone --depth=1 --branch=3.9.0 https://github.com/prisma/prisma-engines.git /prisma && cd /prisma
RUN cargo build --release --jobs 1

FROM node:16.14.0-alpine3.14
WORKDIR /src
ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine \
  PRISMA_MIGRATION_ENGINE_BINARY=/prisma-engines/migration-engine \
  PRISMA_INTROSPECTION_ENGINE_BINARY=/prisma-engines/introspection-engine \
  PRISMA_FMT_BINARY=/prisma-engines/prisma-fmt \
  PRISMA_CLI_QUERY_ENGINE_TYPE=binary \
  PRISMA_CLIENT_ENGINE_TYPE=binary
COPY --from=prisma /prisma/target/release/query-engine /prisma/target/release/migration-engine /prisma/target/release/introspection-engine /prisma/target/release/prisma-fmt /prisma-engines/
COPY . /src
RUN cd src && yarn install

We have this in our radar and hope to work on a solution soon, sadly, thanks to the way our build process work and the complexities of cross compilation and MUSL we cannot give yet a release date for this feature, sorry. I will keep posted and update when this is done and available.

# syntax=docker/dockerfile:1

FROM node:18-slim

RUN apt-get update
RUN apt-get install -y openssl

ARG NODE_ENV=production
ENV NODE_ENV $NODE_ENV

WORKDIR /app

COPY ["package.json", "package-lock.json", "./"]

RUN npm install --production

COPY . .

RUN npx prisma generate

RUN npm run build

CMD ["node", "dist/main"]

Here is what I have working on M1 @exsesx

How can we help get this prioritised?

Any update on this?

Any plan or timeline to support this?

We published an image because of how long it takes to build the prisma binaries, will make the workaround faster:

FROM positivly/prisma-binaries:latest as prisma
FROM node:16.13.2-alpine

## Your normal build steps here

# Set prisma environment:
ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine \
  PRISMA_MIGRATION_ENGINE_BINARY=/prisma-engines/migration-engine \
  PRISMA_INTROSPECTION_ENGINE_BINARY=/prisma-engines/introspection-engine \
  PRISMA_FMT_BINARY=/prisma-engines/prisma-fmt \
  PRISMA_CLI_QUERY_ENGINE_TYPE=binary \
  PRISMA_CLIENT_ENGINE_TYPE=binary
COPY --from=prisma /prisma-engines/query-engine /prisma-engines/migration-engine /prisma-engines/introspection-engine /prisma-engines/prisma-fmt /prisma-engines/

what can we do to help? Our org security policy prevents us to use node lts or slim and alpine is the only option.

Hey everyone, Alberto from Prisma here. Please notice that this issue is about providing compiled Prisma engines for Linux images using the musl C standard library on aarch64 / arm64 architectures. This could be particularly useful to users on macOS with M1/M2 CPUs running Docker images based on Linux Alpine.

While we’re working on our end to support this natively, most of you can already overcome this problem by using Docker Buildx, which supports a custom --platform flag.

For example, given an example Dockerfile like

# Dockerfile for running Prisma on Linux Alpine 3.17+

# change with the Node.js version of your choice
ARG NODE_VERSION="18.12.1"

# change with the Linux Alpine version of your choice
ARG ALPINE_VERSION="3.17"

FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS base

# install OpenSSL 1.1.x, needed for Linux Alpine 3.17+
RUN apk update \
  && apk add openssl1.1-compat

ENV DATABASE_URL ""
WORKDIR /app

# install your project dependencies
COPY package.json ./
RUN npm i

# copy your project files and Prisma schema
COPY . ./

RUN npx prisma version

you can build it with

docker buildx build --load -f Dockerfile --platform=linux/amd64 . -t prisma-linux-node-alpine-3.17-x64

which acts as if you’re running Docker on an x86_64 architecture.

Note:

  • in recent Docker versions, Buildkit is already activated, so you may try omiting buildx from the command above, like so:
docker build --load -f Dockerfile --platform=linux/amd64 . -t prisma-linux-node-alpine-3.17-x64

@zackdotcomputer, @bb-centrum, please refer to https://github.com/prisma/prisma/issues/16553#issuecomment-1353302617 for a working solution to the problems you’ve mentioned.

TL/DR, you have two choices:

  • Use a Node.js Docker image based on Alpine 3.16, like node:alpine3.16, node:lts-alpine3.16, node:18.12.1-alpine3.16 (encouraged)

  • Install OpenSSL 1.1.x via the openssl1.1-compat package, e.g., by adding

    RUN apk add --update --no-cache openssl1.1-compat
    

    to your Dockerfile before installing Prisma

Notes:

  • we recommend you to always pin Docker images to a specific version, to ensure reproducible builds
  • we’ve noticed some comments in similar issues suggesting to install libc / libc6-compat on Linux Alpine to fix the problem. Please DON’T do this, as it could cause other unexpected errors.

My workaround is just to rely on node:xx-slim instead of node:xx-alpine.

What can I do to help get support for this implemented?

I got this working on 4.4.0 with the following dockerfile:

FROM rust:1.64.0-alpine3.16 as prisma
ARG PRISMA_VERSION=4.4.0
ENV RUSTFLAGS="-C target-feature=-crt-static"
RUN apk --no-cache add openssl direnv git musl-dev openssl-dev build-base perl protoc
RUN git clone --depth=1 --branch=${PRISMA_VERSION} https://github.com/prisma/prisma-engines.git /prisma && cd /prisma
WORKDIR /prisma
RUN cargo build --release

# Configure and Install Release Dependencies
FROM node:16-alpine AS deps
ARG NPM_TOKEN
WORKDIR /app

# Prisma Support
RUN apk --no-cache add openssl
COPY --from=prisma /prisma/target/release/query-engine /prisma/target/release/migration-engine /prisma/target/release/introspection-engine /prisma/target/release/prisma-fmt /prisma-engines/
ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine PRISMA_MIGRATION_ENGINE_BINARY=/prisma-engines/migration-engine PRISMA_INTROSPECTION_ENGINE_BINARY=/prisma-engines/introspection-engine PRISMA_FMT_BINARY=/prisma-engines/prisma-fmt PRISMA_CLI_QUERY_ENGINE_TYPE=binary PRISMA_CLIENT_ENGINE_TYPE=binary PRISMA_CLI_BINARY_TARGETS=linux-arm64-openssl-1.1.x

...

@csulit you can do it like this:

version: "3.9"
services:
  api:
    platform: linux/amd64
    ports:
      - 4000:4000

@jkomyno Small suggestion as it seems many people are running into this issue (alpine is popular). Maybe there is a way to detect alpine is being run and for Prisma to give a nice error message.

@ateethk thank you!

I was also able to get this working on M1 Mac by using the node:18-slim image and installing OpenSSL.

@brizandrew Keystone depends on "@prisma/client": "3.12.0" while positivly/prisma-binaries:latest only works with 3.9.

amd64/node:16-alpine

Yeah, emulating amd64 is working. Luckily M1 is so fast it doesn’t matter all that much. One can do this in the docker-compose.yml also/instead:

  myservice:
    build: .
    depends_on:
      - db
    platform: "linux/amd64"

Thanks @aleccool213, we’re tracking the idea of improving the error messages in https://github.com/prisma/prisma/issues/16970, which we’m working on. A first big step in that direction is preparing several different scenarios where Prisma can be installed and run. (You can take a sneak peek in here ☺️)

I’m maintaining Docker images for cross compile: https://github.com/orgs/napi-rs/packages/container/package/napi-rs%2Fnodejs-rust. The ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine is for compile aarch64-unknown-linux-musl target, see https://github.com/napi-rs/package-template/blob/main/.github/workflows/CI.yaml#L79 for example.

I tested this yesterday and works like a charm, error message is also clear finally 😃 Updates I made to make it work: package.json

"@prisma/client": "^4.10.0-dev.81",
"prisma": "^4.10.0-dev.81",

Dockerfile

-FROM node:16-alpine3.16 AS build
+FROM node:18-alpine3.17 AS build
+
+RUN apk add --update --no-cache openssl1.1-compat

schema.prisma

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

Just fyi - in my case, it seems we were building docker images on different architecture then running them, hence I had to add a binary target. Also, we wanted to upgrade node to 18, which was failing before, and without a clear error message I didn’t wanted to invest time in playing with building it FROM prisma source.

So thanks @aqrln 😃 great update

Hey everyone, Alberto from Prisma here. Please notice that this issue is about providing compiled Prisma engines for Linux images using the musl C standard library on aarch64 / arm64 architectures. This could be particularly useful to users on macOS with M1/M2 CPUs running Docker images based on Linux Alpine.

While we’re working on our end to support this natively, most of you can already overcome this problem by using Docker Buildx, which supports a custom --platform flag.

For example, given an example Dockerfile like

# Dockerfile for running Prisma on Linux Alpine 3.17+

# change with the Node.js version of your choice
ARG NODE_VERSION="18.12.1"

# change with the Linux Alpine version of your choice
ARG ALPINE_VERSION="3.17"

FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} AS base

# install OpenSSL 1.1.x, needed for Linux Alpine 3.17+
RUN apk update \
  && apk add openssl1.1-compat

ENV DATABASE_URL ""
WORKDIR /app

# install your project dependencies
COPY package.json ./
RUN npm i

# copy your project files and Prisma schema
COPY . ./

RUN npx prisma version

you can build it with

docker buildx build --load -f Dockerfile --platform=linux/amd64 . -t prisma-linux-node-alpine-3.17-x64

which acts as if you’re running Docker on an x86_64 architecture.

@zackdotcomputer, @bb-centrum, please refer to #16553 (comment) for a working solution to the problems you’ve mentioned.

TL/DR, you have two choices:

* Use a Node.js Docker image based on Alpine 3.16, like `node:alpine3.16`, `node:lts-alpine3.16`, `node:18.12.1-alpine3.16` (encouraged)

* Install OpenSSL 1.1.x via the `openssl1.1-compat` package, e.g., by adding
  ```dockerfile
  RUN apk add --update --no-cache openssl1.1-compat
  ```
  
  
      
        
      
  
        
      
  
      
    
  to your Dockerfile before installing Prisma

Notes:

* we recommend you to **always** pin Docker images to a specific version, to ensure reproducible builds

* we've noticed some comments in similar issues suggesting to install `libc` / `libc6-compat` on Linux Alpine to fix the problem. Please **DON'T** do this, as it could cause other unexpected errors.

Thanks for the detailed response but running docker buildx build --load -f Dockerfile --platform=linux/amd64 won’t help if you’re trying to build an image to run on arm64 e.g. a M1 Mac or Raspberry Pi in my case.

It will help if you want to build an x86 image on arm64 hardware.

I’m getting the same result as @ggohierroy with a similar Dockerfile:

FROM rust:1.58.1-alpine3.14 as prisma
ENV RUSTFLAGS="-C target-feature=-crt-static"
RUN apk --no-cache add openssl direnv git musl-dev openssl-dev build-base perl protoc
RUN git clone --depth=1 --branch=3.9.0 https://github.com/prisma/prisma-engines.git /prisma && cd /prisma
WORKDIR /prisma
RUN cargo build --release

FROM node:16.14.0-alpine3.14

WORKDIR /usr/src/app

ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine \
  PRISMA_MIGRATION_ENGINE_BINARY=/prisma-engines/migration-engine \
  PRISMA_INTROSPECTION_ENGINE_BINARY=/prisma-engines/introspection-engine \
  PRISMA_FMT_BINARY=/prisma-engines/prisma-fmt \
  PRISMA_CLI_QUERY_ENGINE_TYPE=binary \
  PRISMA_CLIENT_ENGINE_TYPE=binary
COPY --from=prisma /prisma/target/release/query-engine /prisma/target/release/migration-engine /prisma/target/release/introspection-engine /prisma/target/release/prisma-fmt /prisma-engines/
COPY . /usr/src/app/

COPY ["package.json", "yarn.lock", "tsconfig.json", ".env", "next.config.js", "postcss.config.js", "tailwind.config.js", "./" ]

RUN apk add --no-cache git

RUN cd /usr/src/app && yarn install

COPY ./public ./public
COPY ./src ./src

RUN yarn prisma generate

EXPOSE 3000

CMD yarn dev

Error:

 => ERROR [stage-1 10/10] RUN yarn prisma generate                                                                                       0.7s
------
 > [stage-1 10/10] RUN yarn prisma generate:
#22 0.323 yarn run v1.22.17
#22 0.352 $ /usr/src/app/node_modules/.bin/prisma generate
#22 0.638 Environment variables loaded from .env
#22 0.641 Prisma schema loaded from prisma/schema.prisma
#22 0.705 Error: Unknown binary target linux-arm64-openssl-undefined in generator client.
#22 0.705 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
#22 0.723 error Command failed with exit code 1.
#22 0.724 info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
------
executor failed running [/bin/sh -c yarn prisma generate]: exit code: 1

and I definitely do not have any binaryTargets specified in my Prisma.schema:

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

This is my Dockerfile right now, but it still fails with the same error when npx prisma generate is run

Error: Unknown binary target linux-arm64-openssl-undefined in generator client.

FROM rust:1.58.1-alpine3.14 as prisma ENV RUSTFLAGS=“-C target-feature=-crt-static” RUN apk --no-cache add openssl direnv git musl-dev openssl-dev build-base perl protoc RUN git clone --depth=1 --branch=3.9.0 https://github.com/prisma/prisma-engines.git /prisma WORKDIR /prisma RUN cargo build --release --jobs 1

FROM node:16.14.0-alpine3.14 WORKDIR /app ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine
PRISMA_MIGRATION_ENGINE_BINARY=/prisma-engines/migration-engine
PRISMA_INTROSPECTION_ENGINE_BINARY=/prisma-engines/introspection-engine
PRISMA_FMT_BINARY=/prisma-engines/prisma-fmt
PRISMA_CLI_QUERY_ENGINE_TYPE=binary
PRISMA_CLIENT_ENGINE_TYPE=binary COPY --from=prisma /prisma/target/release/query-engine /prisma/target/release/migration-engine /prisma/target/release/introspection-engine /prisma/target/release/prisma-fmt /prisma-engines/

RUN apk add --no-cache libc6-compat WORKDIR /app

COPY package.json package-lock.json ./ RUN npm ci

COPY . /app

EXPOSE 3000

RUN npx prisma generate

CMD [“npm”, “run”, “dev”]

Hi @ggohierroy

Also, I’m getting a could not find Cargo.toml in / or any parent directory Is there anything I can read to understand a little better what is going on and how to make it work?

This should be fixed if you replace line 5:

RUN cargo build --release --jobs 1

With:

WORKDIR /prisma
RUN cargo build --release

(also removed --jobs 1 as per comment above to make it run faster)

I use amd64/node:16-alpine image in the case of M1 Mac. But, this solution can not solve the essential problem.

@Sakub did you regenerate the client after that? If it doesn’t help, please open a new issue with reproduction, or a new discussion if you don’t think you’re hitting a bug and just need help. This issue is already fixed and is unrelated to your problem, and posting here sends an email to more than 50 people that were subscribed to it.

Hey @bb-centrum, re:

But from your message arm64 is not supported?

Prisma natively supports arm64 for most Linux distros, but not for Linux Alpine. If you need to run Prisma on a Docker container running on e.g. Raspberry Pi, please use node:18-slim or node:lts-slim as a base image (which runs on Linux Debian Bullseye and uses openssl-1.1.x).

If you really want to keep Linux Alpine, please use Docker Buildx --platform as detailed in this comment. Thank you!

Hey @bb-centrum sorry - added an edit above to clarify that this is a specific additional issue for Alpine and needs to be done in addition to sorting out the arm64 vs amd64 issues.

The latest version of Alpine includes only openssl 3.x, which appears to be incompatible with Prisma’s usage - as pointed out in this comment.

I was able to fix this issue without downgrading alpine, adding the platform emulation flag, or abandoning alpine in favor of vanilla debian. In my case, adding RUN apk add --update --no-cache openssl1.1-compat to the start of my Dockerfile fixed the issue.

EDIT: This is not the only issue with using Prisma on M1 macs inside of an Alpine docker container. This is just one of the issues present and a new one at that which might be the culprit if you have had your build suddenly break like mine did.

I’m using node:18-alipine, upgraded from prisma 3.14 to 4.3.1 and now I experience the same issue…

PS: I’m not running this via compose - but deploy image to AWS ECS (fargate) and it doesn’t want to work there

We published an image because of how long it takes to build the prisma binaries, will make the workaround faster:

FROM positivly/prisma-binaries:latest as prisma
FROM node:16.13.2-alpine

## Your normal build steps here

# Set prisma environment:
ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine \
  PRISMA_MIGRATION_ENGINE_BINARY=/prisma-engines/migration-engine \
  PRISMA_INTROSPECTION_ENGINE_BINARY=/prisma-engines/introspection-engine \
  PRISMA_FMT_BINARY=/prisma-engines/prisma-fmt \
  PRISMA_CLI_QUERY_ENGINE_TYPE=binary \
  PRISMA_CLIENT_ENGINE_TYPE=binary
COPY --from=prisma /prisma-engines/query-engine /prisma-engines/migration-engine /prisma-engines/introspection-engine /prisma-engines/prisma-fmt /prisma-engines/

Could you share the Dockerfile source code, please? The latest tag scares us a bit ahah!

Thanks for sharing this pre-built binaries!

It is similar to what was posted above:

FROM rust:1.59-alpine as prisma

ENV RUSTFLAGS="-C target-feature=-crt-static"

RUN apk --no-cache add openssl direnv git musl-dev openssl-dev build-base perl protoc
RUN git clone --depth=1 --branch=3.12.0 https://github.com/prisma/prisma-engines.git /prisma && cd /prisma

WORKDIR /prisma

RUN cargo build --release

FROM scratch

COPY --from=prisma /prisma/target/release/query-engine /prisma/target/release/migration-engine /prisma/target/release/introspection-engine /prisma/target/release/prisma-fmt /prisma-engines/

Built with docker buildx build --platform=linux/amd64,linux/arm64 --push -t positivly/prisma-binaries:latest -f Dockerfile.prisma .

For some reason I couldn’t get the build to work on an intel machine, on an M1 it builds for both platforms but the cross compilation takes forever.

Thanks @bbedward, is it correct that those binaries are for Prisma 3.9 specifically? And openssl still needs to be installed?

Here is an example for Next.js, resulting in a 170 Mb image (61Mb compressed).

FROM positivly/prisma-binaries:latest as prisma

# Install migration engine to run prisma generate
FROM node:16.13.2-alpine as builder
RUN apk add --no-cache libc6-compat openssl openssl-dev
COPY --from=prisma /prisma-engines/query-engine /prisma-engines/migration-engine /prisma-engines/
ENV NEXT_TELEMETRY_DISABLED 1
ENV NO_UPDATE_NOTIFIER true
ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine \
  PRISMA_MIGRATION_ENGINE_BINARY=/prisma-engines/migration-engine \
  PRISMA_CLI_QUERY_ENGINE_TYPE=binary \
  PRISMA_CLIENT_ENGINE_TYPE=binary
WORKDIR /app
COPY package.json yarn.lock .npmrc .
RUN yarn --frozen-lockfile
COPY . .
RUN yarn prisma generate && yarn build
# Save some space if copying the complete node_modules
# RUN yarn prisma generate && yarn build && yarn --prod && rm -rf ./node_modules/@prisma/engines/*engine* 

# Only needs query engine
FROM node:16.13.2-alpine as release
RUN apk add --no-cache libc6-compat openssl openssl-dev
COPY --from=prisma /prisma-engines/query-engine /prisma-engines/
ENV CHECKPOINT_DISABLE 1
ENV NEXT_TELEMETRY_DISABLED 1
ENV NODE_ENV production
ENV NO_UPDATE_NOTIFIER true
ENV PORT 3000
ENV PRISMA_HIDE_UPDATE_MESSAGE 1
ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine \
  PRISMA_CLI_QUERY_ENGINE_TYPE=binary \
  PRISMA_CLIENT_ENGINE_TYPE=binary
WORKDIR /app

COPY --from=builder /app/next.config.js .
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

EXPOSE 3000

CMD ["node", "server.js"]

Yes they are built from prisma-engine 3.9, and openssl is required still (openssl-dev should not be needed, though)

@ggohierroy the error sounds like you added "linux-arm64-openssl-undefined" to binaryTargets in your schema.prisma.

@aqrln Hi, nothing like that in my schema file. It’s just the one from the tutorial for NextJS + Prisma.

@aqrln ahh that’s probably it. I couldn’t get the so lib to load so I just switched to the binary, let me try that change.