Search code examples
dockernext.jsdeploymentprismafly

Retrieve fly.io secret DATABASE_URL at build time


I'm trying to deploy a NEXTJS app with Prisma on Fly.io. When provisionning my App, I asked for a Fly Postgres but when building the app, I need to run "npx prisma generate" which fails because DATABASE_URL is not passed at build time:

#21 28.33 error: Environment variable not found: DATABASE_URL.
#21 28.33   -->  schema.prisma:10

I don't know how to fix this, as most of the solutions suggest retrieving the variable via ssh and passing it with --build-arg, but as it is a fly-generated secret, I don't have direct access to it and as my app is not built, I cannot ssh to retrieve it.

Here is my dockerfile:

# base node image
FROM node:16-bullseye-slim as base

# Install openssl for Prisma
RUN apt-get update && apt-get install -y openssl

# Install all node_modules, including dev dependencies
FROM base as deps

RUN mkdir /app
WORKDIR /app

ADD package.json package-lock.json ./
RUN npm install --production=false

# Setup production node_modules
FROM base as production-deps

RUN mkdir /app
WORKDIR /app

COPY --from=deps /app/node_modules /app/node_modules
ADD package.json package-lock.json ./
RUN npm prune --production

# Build the app
FROM base as build

ENV NODE_ENV=production

RUN mkdir /app
WORKDIR /app

COPY --from=deps /app/node_modules /app/node_modules

# If we're using Prisma, uncomment to cache the prisma schema
ADD prisma .
RUN npx prisma generate

ADD . .
RUN echo DATABASE_URL
RUN npm run build

# Finally, build the production image with minimal footprint
FROM base

ENV NODE_ENV=production

RUN mkdir /app
WORKDIR /app

COPY --from=production-deps /app/node_modules /app/node_modules

# Uncomment if using Prisma
COPY --from=build /app/node_modules/.prisma /app/node_modules/.prisma

COPY --from=build /app/build /app/build
COPY --from=build /app/public /app/public
ADD . .

CMD ["npm", "run", "start"]

I'm sure the secret exist as I see it when I run flyctl secrets list


Solution

  • According to to fly.io documentation:

    application environment variables and secrets are not available to builds.

    https://fly.io/docs/reference/configuration/#specify-docker-build-arguments

    Workaround

    You can create a file entrypoint.sh:

    entrypoint.sh

    #!/bin/sh
    
    NODE_ENV=production npm run build
    npm run start
    

    Dockerfile

    
    ...
    
    # Remove CMD ["npm", "run", "start"] and build code above
    
    ENTRYPOINT ./entrypoint.sh
    

    In this case, the npm app is built inside VM. As it is inside VM, you can reach all your secrets.