@ethical-jobs/dynamic-env
v1.0.1
Published
Helper scripts and documentation for creating Javascript apps with a dynamically deployed environment.
Downloads
483
Readme
JavaScript Dynamic Environment Helper Package
Purpose
This package helps to generate dynamic environment based on the current deployment environment instead of relying on a statically built system that requires a new build for each stage of the dev process. This allows for building once and deploying everywhere.
NOTE: This package will not help you build a dynamic environment for static files deployed on a CDN!
HINT: It's not really dynamic - it's just dynamically generating an environment at boot time for the app to use. So if you change your
env
you'll need to restart your dev or docker container, etc to reinitialise your app's environment.
Further reading
More info can be found here https://github.com/facebook/create-react-app/issues/2353
Kudos
This package is based on the post Krunoslav Banovac (@kunokdev) wrote which can be found here https://medium.freecodecamp.org/how-to-implement-runtime-environment-variables-with-create-react-app-docker-and-nginx-7f9d42a91d70
How it works
This package provides shell scripts that can be incorporated into any javascript project that requires a dynamically set runtime environment at the time of deployment. To achieve this we need to integrate the scripts in this package with the tooling in our apps.
There are 2 scripts which run on the bash
shell.
env-add
Creates an environment variable and sets it's default. It is an interactive script which saves the variable
in .env.example
in the root of you application.
env-gen
Generates the application's environment when required. The default location of the generated file is public/env.js
.
The resulting code is something like the following.
/**
* WARNING: This file is generated by env-gen.sh
* Do not modify this file directly!
*/
window._env_ = {
"APP_DEBUG": "true",
"APP_ENV": "local",
};
Prerequisites
The following command line tools are required to run the scripts and must be installed on deployment hosts.
jq
This tool is used to verify and format JSON documents. Please refer to https://stedolan.github.io/jq/ for downloads and installation instructions for your system.
dotenv-to-json
This tool converts .env
files to JSON representation. It can be installed globally using the following command, for
more information refer to https://www.npmjs.com/package/dotenv-to-json.
yarn global add dotenv-to-json
Installation
This package will be required in your production environment so should be installed in the requirements
section of
package.json
NPM
npm require @ethical-jobs/dynamic-env
Yarn
yarn add @ethical-jobs/dynamic-env
Integrating into your application
Adding variables to .env.example
This file has 2 functions.
- The first is to be an example of the env required by the application.
- The second is to act as a whitelist of which variables are allowed to be exposed in the application.
NOTE: if a variable is not defined in this file it will not appear in your application environment.
To add variables to .env.example
you can use the script in this package env-add
. This script is interactive
and supports base64 encoding if needed.
You are free to manually add variables to .env.example
and they will not be overwritten.
$ env-add
Name of variable: APP_ENV
Default value for variable 'APP_ENV': production
Would you like to base64 encode the value?
1) Yes
2) No
#? 2
Should value be quoted?
1) Yes
2) No
#? 2
APP_ENV=production
Once you have set up your variables in .env.example
you are ready to publish your dynamic env.
Modify index.html
to access your variables.
In the <head>
section of your app add the following script to allow access to your dynamic variables.
<script src="%PUBLIC_URL%/env.js"></script>
This is an example of a create-react-app
setup. Modify for your application's public folder.
Publishing your dynamic environment
The script env-gen
is used to publish your environment when you require it in your app. To do so just run env-gen
in
your app's root directory and it will generate env.js
for you.
Accessing environment variables in your app
To access your environment variables in your app you can now do so with the following syntax.
HINT: this replaces process.env.ENV_VAR
const appEnv = window._env_.ENV_VAR;
Use in development environments
To utilise your dynamic variables in a development environment you need to modify your package.json
scripts section
that starts your dev server. An example would be for the create-react-app
but you can use this in any JavaScript
project.
{
"scripts": {
"dev": "gen-env && react-scripts start"
}
}
Then you can run your development server as per normal.
yarn dev
Use in Docker container
Using Docker for your deployments is where this is really useful. It is also very easy to setup and configure to your own requirements. Below is an example of how you could setup a Dockerfile.
# => Build container
FROM node:alpine as builder
WORKDIR /app
COPY package.json .
COPY yarn.lock .
RUN yarn
COPY . .
RUN yarn build
# => Run container
FROM nginx:alpine
# install node and jq
RUN apk add --no-cache nodejs-current yarn jq
# install global node scripts
RUN yarn global add dotenv-to-json @ethical-jobs/dynamic-env
# Nginx config
RUN rm -rf /etc/nginx/conf.d
COPY conf /etc/nginx
# Static build
COPY --from=builder /app/build /usr/share/nginx/html/
COPY --from=builder /app/.env.example /usr/share/nginx/html/.env.example
# Default port exposure
EXPOSE 80
# Copy .env file and shell script to container
WORKDIR /usr/share/nginx/html
# Add bash
RUN apk add --no-cache bash
ENV ENV_DEST=/usr/share/nginx/html
# Start Nginx server
CMD ["/bin/bash", "-c", "env-gen && nginx -g \"daemon off;\""]
The important sections of this Dockerfile
are:
Install the dependencies.
# install node and jq
RUN apk add --no-cache nodejs-current yarn jq
# install global node scripts
RUN yarn global add dotenv-to-json @ethical-jobs/dynamic-env
Set a different destination folder. In this case our install folder (where our built scripts go).
ENV ENV_DEST=/usr/share/nginx/html
Add env-gen
to your runtime command so when the container starts it generates your environment file.
CMD ["/bin/bash", "-c", "env-gen && nginx -g \"daemon off;\""]
You should modify your config to whatever setup you need.
Use with Docker Compose
An example Docker Compose for local development purposes. Used with the Dockerfile
example above.
version: "3.2"
services:
app:
build:
context: .
image: dynamicenvtest
ports:
- "5000:80"
env_file:
- .env.example
- .env
environment:
- "ENV_DEST=/usr/share/nginx/html/"
Use in Kubernetes
You need to allow Kubernetes to pull in any environment variables you have set in .env.example
. Refer to your host
documentation on how to do this.
.gitignore
Make sure to update your Git ignore with the following.
public/env.js
env.js
.env
.env.generated
env-gen
overridable variables
Set these in your env or as ENV in your Dockerfile or anywhere you need to override the script defaults.
BASE_DIR
sets the base directory of your app. This defaults to.
or current directoryENV_DEST
set theenv.js
final destination. This defaults topublic/
and should be set to wherever your public directory is situatedWHITELIST_FILE
set the name of your whitelist file if different to your example env. This defaults to.env.example
ENV_JS
set this to change the name of your generatedenv.js
file. This defaults toenv.js