steebchen / prisma-client-go

Prisma Client Go is an auto-generated and fully type-safe database client
https://goprisma.org
Apache License 2.0
2.15k stars 96 forks source link

"no binary found" using Docker example #1268

Open mjlangan opened 6 months ago

mjlangan commented 6 months ago

I'm trying to package my application into a Docker image following the guide here: https://goprisma.org/docs/reference/deploy/docker#optimized-dockerfile

The image builds fine, but when I run I get (pardon the JSON-formatted log output):

{"level":"fatal","msg":"error connecting to database: ensure: no binary found","time":"2024-05-03T01:12:54Z"}

I did check for other issues and know this isn't the first issue about this error, but in my case:

Dockerfile looks like this:

FROM golang:1.22.2 as build

WORKDIR /src

# Copy the dependency files and download deps
COPY go.mod go.sum ./
RUN go mod download

# prefetch the prisma binaries, so that they will be cached and not downloaded on each change
RUN go run github.com/steebchen/prisma-client-go prefetch

# copy over everything and rely on dockerignore to filter out the junk
# See https://github.com/docker/docs/issues/14609
COPY ./ ./

# re-run the Prisma generator because it does some magic
ENV PRISMA_GENERATOR_CLIENT go run github.com/steebchen/prisma-client-go
RUN go run github.com/steebchen/prisma-client-go generate

# build the binary for Linux
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o app .

# generate the dotenv file
RUN <<EOF cat >> .env

... config-like stuff goes here

EOF

# build the deployment image
FROM scratch

# copy over SSL certificates, so that we can make HTTPS requests
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

# copy over the  binary and the .env
COPY --from=build src/app /app
COPY --from=build src/.env /.env

ENTRYPOINT ["/app", "server"]

.dockerignore is filtering out stuff like IDE files, the .git folder, locally-built app binaries on the dev's machine, etc., but I'm also running the generator again so that should be getting whatever binary I need for Linux, right?

steebchen commented 6 months ago

You are probably on an arm Mac, right? I can reproduce, I'll have to look closer into it

mjlangan commented 6 months ago

You are probably on an arm Mac, right? I can reproduce, I'll have to look closer into it

Intel Mac, actually. Though I have teammates with ARM machines.

I forgot to add a step after re-generating the client within the Dockerfile where I move the package to another location (the schema file comes from a git submodule) I added the generated Prisma files to my .dockerignore and included the step to copy them into the right place, and now I get a different error (progress!)

{"level":"fatal","msg":"error connecting to database: ensure: version check failed: fork/exec /tmp/prisma/binaries/engines/473ed3124229e22d881cb7addf559799debae1ab/unpacked/v2/prisma-query-engine-debian-openssl-3.0.x: no such file or directory","time":"2024-05-03T07:37:54Z"}

I think I recall something about a/tmp folder in another issue, I'll keep poking at this on my end too.

For reference, the "generate" portion of my dockerfile now looks like:

ENV PRISMA_GENERATOR_CLIENT go run github.com/steebchen/prisma-client-go
RUN go run github.com/steebchen/prisma-client-go generate
RUN cp ./prisma/db/* ./database/db
RUN rm -rf ./prisma/db
mjlangan commented 6 months ago

Inspecting the filesystem within the build stage shows I got something generated under /tmp/prisma-binaries, but this path does not match what my application says it's looking for, either.

ls -al
total 16
drwxrwxrwt 1 root root 4096 May  3 07:37 .
drwxr-xr-x 1 root root 4096 May  3 18:29 ..
drwxr-xr-x 1 root root 4096 May  3 00:36 prisma-binaries
cd prisma-binaries
ls -al
total 47052
drwxr-xr-x 1 root root     4096 May  3 00:36 .
drwxrwxrwt 1 root root     4096 May  3 07:37 ..
-rwxr-xr-x 1 root root 22857424 May  3 07:29 prisma-query-engine-linux-static-x64
-rwxr-xr-x 1 root root 25307344 May  3 07:29 prisma-schema-engine-linux-static-x64
steebchen commented 6 months ago

Interesting, as on my M1 mac it actually uses the arm64 binary and there's a different error. Thanks for the report though, I'll have to look closer into it when I have some time. For now as a temporary workaround please use a single-stage build then it will work fine

e-sarpong commented 3 months ago

Any updates on this issue?

Satont commented 1 month ago

I experiencing the same thing i guess with multi-stage.

Got error on start:

ensure: version check failed: fork/exec /tmp/prisma/binaries/engines/69d742ee20b815d88e17e54db4a2a7a3b30324e3/unpacked/v2/prisma-query-engine-debian-openssl-3.0.x: no such file or directory

Single stage working, but size of it is huge, 1.7gb, which kind of unacceptable for me.

steebchen commented 1 month ago

yeah it is definitely still an issue, let me look into this this weekend

Sarps commented 1 month ago

I was able to fix it. And I created a gist for the fix here.

https://gist.github.com/Sarps/ebba88ea89306032a7024b68eda07405

steebchen commented 1 month ago

Yeah this is an ok temp solution, thanks! but I will have to fix the core issue

Alynva commented 1 week ago

I'm having the same problem deploying to AWS Lambda (binary runtime).

What did worked for me as a workaround is setting the missing PRISMA_INTERNAL_QUERY_ENGINE_PATH env variable with the path of the unpacked binary that I got printing the env variable value on the first run of the lambda. It seans that it keeps the content of /tmp but resets the env vars for subsequents requests.

Maybe a check here, could fix it (at least for my case where the file exists but its path is unknown to the engine):

https://github.com/steebchen/prisma-client-go/blob/67c12ec6753f7278ea59ba56e9f3b294839fdd3a/binaries/unpack/unpack.go#L38-L41

So it sets the variable before returning...

I also had to do a little trick to get the values of my .env to be loaded before the client loads, by creating a package with a init function that gets imported in my main.go (before anything that imports the prisma client) as 'no-op'. I called github.com/joho/godotenv.Load(), but I guess just importing github.com/joho/godotenv/autoload as 'no-op' in the main instead of creating this package would work too. I'm not experienced with Go, but I noticed that the autogenerated client doesn't import it with autoload:

https://github.com/steebchen/prisma-client-go/blob/67c12ec6753f7278ea59ba56e9f3b294839fdd3a/generator/templates/_header.gotpl#L14-L15

Could it be the cause of https://github.com/steebchen/prisma-client-go/issues/1245 ? I also had the warning about DATABASE_URL, and I don't get it now.

steebchen commented 1 day ago

Oh that is super interesting @Alynva, thank you so much for bringing that up. This is actually a bug in the Go client. I think there might be a better solution to this, but for now I have added the fix you suggested to set the env var again (https://github.com/steebchen/prisma-client-go/pull/1409). Thanks so much for this detailed report and help, this is incredibly valuable!

steebchen commented 1 day ago

Regarding the env, I thought about it a lot but mostly I came to the conclusion that I don't want to run any env stuff on behalf of the user; ideally they should set the database url with flags (although there is a known bug with that which I haven't figured out yet :/)...

steebchen commented 1 day ago

This fix is released in v0.34.0. Not sure if that also fixes the original docker issue here