Techconative Logo

 Manage Multiple NEXT_PUBLIC Environment Variables at Runtime with Docker

Mon Jan 16 2023

Next JS | Docker | Environmental Variables

Manage Multiple NEXT_PUBLIC Environment Variables at Runtime with Dockerimage

Context

Next.js is definitely a very good solution for making modern web applications. It's fast, simple, and reliable. It works very well also with Docker, you can build a production image with a few lines of Dockerfile, and deploy your app to the world.

However, there is a problem if you follow the below approach!

Let's say,

  • You decided to package your application as docker image.
  • Your image contains the built version of front-end app.
  • You're going to use the same image for all the environments, with the parameters as environment variable.
  • From your code you have referred to certain public variables (*NEXTPUBLIC**) using process.env.<NEXT_PUBLIC_VARIABLE_NAME>.
  • And the referenced variables will not available at build time but only at runtime.

The above approach won't work when you pass the required environment variable while starting the container because with production build (next build) the variables would have been already resolved during the build time and static files would have got generated.

Solution

Well, a quite tricky (and hacky) solution is to do the variable replace directly on runtime as docker image entrypoint!

Let's see an example. Suppose you have to pass some environment variables NEXT_PUBLIC_CONFIG_URL, NEXT_PUBLIC_USER and using it in code like process.env.<NEXT_PUBLIC_VARIABLE_NAME>.

Create an .env.production like this:

NEXT_PUBLIC_CONFIG_URL = APP_NEXT_PUBLIC_CONFIG_URL; NEXT_PUBLIC_USER = APP_NEXT_PUBLIC_USER;

What we can do on the Dockerfile, is something like this:

FROM node:16-alpine WORKDIR /app COPY . . RUN npm i react-scripts --force && npm run build EXPOSE 3000 ENTRYPOINT ["/app/entrypoint.sh"] CMD ["npm", "run", "start"]

The build will be launched with an environment placeholder in this row, so your NEXT_PUBLIC_CONFIG_URL will be temporarily set to a string with value: APP_NEXT_PUBLIC_CONFIG_URL.Same applies for the other environment variables that are configured.

Now let's create a custom entrypoint called entrypoint.sh that will have specific instructions to replace the placeholders with variables set through docker.

#!/bin/sh echo "Check that we have NEXT_PUBLIC_CONFIG_URL vars" test -n "$NEXT_PUBLIC_CONFIG_URL" find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#APP_NEXT_PUBLIC_CONFIG_URL#$NEXT_PUBLIC_CONFIG_URL#g" echo "Check that we have NEXT_PUBLIC_USER vars" test -n "$NEXT_PUBLIC_USER" find /app/.next \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#APP_NEXT_PUBLIC_USER#$NEXT_PUBLIC_USER#g" echo "Starting Nextjs" exec "$@"

When the docker image starts, the entrypoint will replace all the previously set environment placeholders, with the real values, passed by the NEXT_PUBLIC_CONFIG_URL environment variable! Same for all the env variables.

So you can pass your value directly for example in your docker-compose.yml:

version: "3" services: testing-env-variables: build: context: . dockerfile: Dockerfile image: testing-env-variables container_name: testing-env-variables environment: - NEXT_PUBLIC_CONFIG_URL=https:\\test@test.com - NEXT_PUBLIC_USER=test ports: - "3000:3000"

A couple of things to remember

-This is a tricky(rather hacky) solution, so use it if you don't have any other alternative.

We would love to hear from you! Reach us @

info@techconative.com

Techconative Logo

More than software development, our product engineering services goes beyond backlog and emphasizes best outcomes and experiences.