I am facing one big issue at the moment; with a base NextJS app, I try to connect to MongoDB for static generation but the secrets haven’t been populated into the environment variables during the build process, which means I cannot access the database.
I know this works after the build as I have hard coded temporary credentials and logged them to the console after the build, but they are undefined during the build step.
Is this how most NextJS apps work? We don’t (yet) have a way to do builds with your secrets exposed, or in the same network as your apps. But you can build the image locally and pass credentials to it.
If you have environment variables set, run this:
docker built . -t nextjs-app -e DATABASE_URL
This will pass the current DATABASE_URL environment variable through to Docker. You can also set it in the command: DATABASE_URL=mongodb://myserver/db
Then you can deploy the image tag:
flyctl deploy -i nextjs-app
See if that works for you. It would make sense to do builds with the secrets accessible, or have a pre-deploy step, or similar. We have some changes coming to the remote builder that will make this a little easier.
Sorry, I missed out the details about the remote build using NodeJS builtin.
It is used as part of the incremental static generation. NextJS will use the data at build to create the pages, which can also be configured to regenerate as users request the page. Whilst it may not currently be widely adopted - I definitely think there is a case for secrets to be included in the remote builds.
Build the image locally is a good work around for the secrets though - thank you.
Now using this local build my deployment fails and the logs are showing:
UnhandledIoError(Os { code: 8, kind: Other, message: “Exec format error” })
Looks like an error like that can be caused by a missing shebang line at the top of your file (#!/bin/bash for example).
Edit: I think it could also be true if your file is not executable, or if it’s not found. Make sure it’s executable and maybe try an absolute path or prefix with ./? Worth a shot
@jerome
Thanks for your suggestions. Docker is still relatively new to me so I don’t have a custom entrypoint file - I am just using the node:alpine image and CMD from the dockerfile.
That could be the problem, if the next binary isn’t in the path it might throw that error.
Do you have Docker installed locally? The simplest thing to do might be to poke around at the Docker image to see where things are. You can try running your app like this:
I just created a default nextjs app and a new fly project to see if it would work for me without any extra dependencies and it didn’t (repo: https://github.com/melloradamj/fly-next-error)
Could it be that its the Apple M1 version of Docker locally?
Oh! Yes it could be. I wonder if it built the image for arm64. Try flyctl deploy --remote-only which will build with our remote builders running on x86_64.
I’ll try and see if I can fix it for local Docker environments on arm64.
FROM hexpm/elixir:1.10.3-erlang-23.2.7-alpine-3.14.0 AS build
ARG FONT_AWESOME_TOKEN
ENV FONT_AWESOME_TOKEN=${FONT_AWESOME_TOKEN}
[... other things...]
RUN npm run --prefix ./assets build
I think this token would be better used as a secret instead of an env var that lives in the fly.toml file - here’s what I would do (let me know if I’m off-base in what your issue is!).
Some explanation: Secrets set via fly secrets set... are not available at build time, but instead only during run-time of the app (in other words, secrets aren’t set as env vars when running “docker build…”).
To get secrets into the build steps, you can use Docker (BuildKit) secrets.
This means updating your Dockerfile to mount secrets in:
RUN --mount=type=secret,id=font_awesome_token \
echo "$(cat /run/secrets/font_awesome_token)"
You won’t want to echo that secret in reality, but I wanted to show you that the secret gets mounted as a file, and you can get the secret value from that file’s contents
Then when deploying the app, you can add the secrets to be mounted: