Externalise and Configure Frontend Environment Variables on Kubernetes
GitHub Project for reference.
Vue’s way for handling env variables…
Vue taught us that we can specify different env variables for different env modes by placing different files in our project root.
Sample project to illustrate different .env files.
Development env (npm run serve): .env.development configs used
Production env (npm run build, serve -s dist): .env.production configs used
The problem occurs when we:
(1) Do not want to build using prod variables in dev env;
(2) Only want to bring our build folder into prod env; We do not want to bring every god-damn file into prod!
(3) Just want to do a minor config change; In a micro-service (MS) world we live in today, most of the times we do not have control over MSs we use. If an endpoint of a MS is being renamed, we do not want to redeploy our app…
2. Reference to these variables in your code (Change process.env to window)
3. Create shell scripts and edit Dockerfile to generate new env-config.js file at each build.
4. Add env variables in K8 yaml for new containers.
1. Read config from env-config.js
2. Reference to variables across your Vue code
Before moving on, test out on your app on devt mode — npm run serve/dev.
You should see that your app is reading variables defined in env-config.js.
You can choose to delete .env, .env.development, .env.production files.
We chose to keep .env file to store configs such as long strings that seldom change (i.e. tooltip descriptions).
After ensuring that your app is working fine, we want automate the creation of env-config.js file when we build and dockerise our project.
3. Create shell scripts (generate_env-config.sh, docker_entrypoint.sh) and edit Dockerfile to generate new env-config.js file at the start of each build.
Contains pre-defined env configs. This script takes env config values, assign them to env variables and creates our env-config.js file.
Line 1: Executes generate_env-config.sh and outputs env-config.js to build folder.
Line 2: Serves our build folder.
Don’t jump! This Dockerfile was written using multi-stage builds to reduce our Docker image size. With multi-stage builds, instead of manually building the image twice and maintaining multiple Dockerfiles, we just have to build our Docker image once using 1 Dockerfile.
Note: Multi-stage builds are only introduced in Docker 17.06.
Line 1–7: Install dependencies & build project that outputs build folder (dist)
Line 10–16: Copy only the build folder & shell scripts to new Docker image. Next, install serve to host the project later. Makes the shell scripts executable. Expose the port and run docker_entry.sh script which creates the env-config.js in the build folder and host the project on port 5000.
docker build -t vue-env-sample:1 .
docker run -p 5000:5000 -e VUE_APP_FOO="docker_foo" vue-env-sample:1
Now you can try building and running image. Inject an env variable to the container, you will be able to see your env variable being injected.
4. Add env configs in K8 yaml for new containers.
This step is pretty easy after you’ve got your Docker image working. Add the env configs accordingly and you can start scaling your app on K8.
Few months ago, I wrote a Medium post on how you can externalise your Spring Boot environment variables on Kubernetes. Friends reached out and taught me how we can apply to the frontend too.
A BIG THANK YOU to my developer friends!