Strategy for deploying/hosting javascript-based static websites in containers This comes up from time to time in several of our dev teams, without us having figured out the "right" way:

We use a lot of react-based webapplications that "compile" into static websites that are just a few html, js and css files.

However, the "building" of these apps take a number of variables that enable/disable feature flags, configure backend urls, etc.
This means that we cannot "build" a binary in the traditional sense and just apply a config file at deploy-time - the "build" itself needs to have these environment-specific variables set, and thus the only time we can "build" is at deploy-time.

For now we solve this by injecting the required environment variables into the Docker container and run a start cmd along the lines of

npm build &amp;&amp; nginx run


This has a couple of disadvantages:


The build process takes a lot of cpu/memory relative to the run-time requirements of the container. That means we need to scale the container for the build process instead of the run-time requirements - which feels wrong
Build failures are hard to "track". We can use healthchecks in Kubernetes, but if a build takes 2 minutes we still have to wait for 3 mins (1 extra for safety) before we can start testing the container's healthcheck endpoint to see if its alive.
Deployments might take a long time: If we configure Kubernetes to do a "serial" deployment, it will start each pod and wait for the "initialDelay" period of 2-3 minutes before starting the next. This means that we're easily looking at a 10-min deploy time if the deployment is scaled to 3-4 pods.


This all feels very suboptimal to me. I'd be very interested in hearing how the community solves the "build at deploy-time" conundrum with modern javascript webapps.

I realize that for Kubernetes we could use "init-containers" that perform the build, places the artiacts in persistent storage and then have the app containers simply pull from persistent storage during startup, but this still feels more like "bypassing" the problem than solving the root issue.
From my standpoint the best approach would be to:


Separate build process using Jenkins that would build NodeJS project into distribution and wrap it into Docker image
Spin up Docker registry that would accumulate Docker images from Jenkins (this registry should be accessible from Kubernetes cluster)
Move environment variables to Jenkins secrets or use separate tool to collect and combine configurations from external Git repo (we use Spring Cloud Config through REST API to collect json/yml definitions for every application in every environment)


Using Jenkins you can configure continuous delivery system based on generic Pipelines. Possible flow would be:


Developers finish their work in correspondence to GitFlow (latest Pull Request merged into Release branch)
Webhook triggers Jenkins pipeline:


Stage 1: collect environment definition
Stage 2: build NodeJS app using npm
Stage 3: build Nginx Docker image with distribution
Stage 4: push Docker image to Docker registry
Stage 5: deploy/update service in Kubernetes using standard definitions

Notifications send in regard of results


This process might be visualized using Rancher. I can answer your questions in chat.