Skip to content

thiamsantos/shipator

Repository files navigation

Shipator

CI GitHub release Go Report Card License

Inject environment variables into static files at runtime.

Background

The common front-end build tools (like CRA) inject the env vars at build time. This means if we want to deploy the static files in a docker environment, we need to build a different docker image for each environment, as the URL for the server and other values that usually come from an env var will be inlined in the final bundle. This behaviour prevents the docker image to be built once and run anywhere - on any environment (dev, test, staging, prod) - just requiring us to provide the different configuration of each environment.

This project aims to feel this gap by allowing to inject environment variables into static files at runtime using the approach mentioned at the CRA documentation.

Another option would be to serve the application using a Node.js webserver to inject the env vars in each request. Shipator takes a different approach by trying to keep working exclusively with static files in order to leverage high-performance webservers like ngnix to serve the files while enabling us to inject env vars at runtime.

How it works

Shipator will replace a placeholder (like __ENV__) of a targeted static file with the allowed env vars.

It ships with an official docker image that uses OpenResty (a ngnix distribution) to serve the files. Whenever the container starts, it will read all the env vars starting with the prefix defined at SHIPATOR_PREFIX (default REACT_APP), and inject the env vars in the place of the placeholder defined at SHIPATOR_PLACEHOLDER (default __ENV__) of the target file defined at SHIPATOR_TARGET (default /app/shipator/html/index.html). After the replace the ngnix server will be started to serve the static files.

Docker Usage

Note: The following example assumes that your project was generated by CRA however, all the steps can be applied to different setups given a few minor modifications.

  1. Update the public/index.html of your project, inserting the __ENV__ to be injected at runtime, but fallbacking to the build time env vars that CRA provides, so it works locally normally.

Insert the following snippet right before the </head> closing tag.

<script>
  window.ENV = (function() {
    try {
      return __ENV__;
    } catch (e) {
      return {};
    }
  })();
  window.ENV.REACT_APP_SERVER_URL =
    window.ENV.REACT_APP_SERVER_URL || '%REACT_APP_SERVER_URL%';
</script>
  1. Update the rest of the project to get the values from this global variable:
const baseUrl = window.ENV.REACT_APP_SERVER_URL;
  1. Create a Dockerfile using shipator
FROM node:12.16.1-alpine as builder
WORKDIR /app
COPY yarn.lock /app/yarn.lock
COPY package.json /app/package.json
RUN yarn install --frozen-lockfile
COPY . /app
RUN yarn build

FROM Finbits/shipator:1.0.2
COPY --from=builder /app/build /app/shipator/html
  1. Build the docker image.
$ docker build --rm -t my-webapp:latest .
  1. Start the webserver
$ docker run --rm -p 3000:80 -e REACT_APP_SERVER_URL=http://my-api.com my-webapp:latest
  1. Now open your browser at http://localhost:3000.

If you open your dev tools console, and write window.ENV.REACT_APP_SERVER_URL, it will return http://my-api.com.

Note: If you use kubernetes in production the env vars could be placed in a configmap, with different values for each deployment environment.

CLI Usage

You can also use the shipator CLI directly. You can download it on the releases page.

Usage
  $ shipator [options] target

Options
  -placeholder string
        Placeholder in the target (default "__ENV__")
  -prefix string
        Prefix of the env vars to inject (default "REACT_APP")
  -version
        Prints current version

Examples
  $ shipator build/index.html
  $ shipator -prefix REACT_APP -placeholder __ENV__ build/index.html
  $ shipator -placeholder __VARS__ build/index.html
  $ shipator -prefix VUE_APP build/index.html

Changelog

See the changelog.

Contributing

See the contributing file.

License

Copyright 2021 © Finbits.

Shipator source code is released under Apache 2 License.

Check LICENSE file for more information.