Manage Multiple NEXT_PUBLIC Environment Variables at Runtime with Docker
Mon Jan 16 2023
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,
process.env.<NEXT_PUBLIC_VARIABLE_NAME>
.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.
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"
-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