NestJS Runtime Environment Variables
Introduction
Here goes my experience dockerizing a NestJS application. I aimed to dockerize the entire stack for my master project, which included a Frontend built with NestJS. To achieve this, I used docker-compose to specify the required services, and configured environment variables using a .env
file.
Challenge: NestJS and Environment Variables
Initially, I used static values for local development to connect the Frontend to the API service. However, I soon realized that providing the required configuration at runtime was crucial for my project. Furthermore, according to the 12 Factor Application, configuration should be externalized from the application entirely. While it is usually possible to access environment variables in a Node application with process.env.VAR_NAME
, it wasn’t that simple with NestJS.
Solution: Workaround for NestJS
NestJS does a few things differently, such as inlining browser-exposed variables, hiding server runtime environment variables, and doing other custom stuff depending on the component used. To prevent NestJS from inlining the variables at build time, I had to prefix the variables with NEXT_PUBLIC.
The workaround to set environment variables at runtime goes like this:
- Add the
NEXT_PUBLIC
Prefix to the variables you are using in your code. - NestJS creates a build artifact where calls to
const var = process.env.NEXT_PUBLIC_MY_VAR
are substituted with the value, making itconst var = 123
, if the variable was set to 123. - I created an
entrypoint.sh
for my Dockerfile that replaces the values defined in.env
used in my docker-compose file with those found in the runtime environment. - The values are first replaced by NestJS, then by the
entrypoint.sh
script, which may seem hacky. - Now the app should correctly
Replacing Environment Variables at Runtime
Here is the entrypoint.sh
script that I used to replace environment variables:
Problem: Rerunning the Variable Replacement
One caveat is that running the container the first time, and the environment values are replaced in the code, the values are static again. So if you want to update the configuration, you’ll have to reset the containers state back to the image.
You can do this fairly easy by running docker compose pull frontend
.