This is an updated fork of jshmrtn/s2i-nodejs-nginx, that builds on their incredible work - thank you jshmrtn! 🤘
# The repository containing the static application you'd like to build
export REPO_URL=https://github.com/evanshortiss/s2i-nodejs-nginx-example
# Name for the resulting image tag
export OUTPUT_IMAGE_NAME=nginx-webapp-runner
# Build the specified repo using the latest Node.js version,
# and serve it using the latest NGINX available in Alpine linux
s2i build $REPO_URL quay.io/evanshortiss/s2i-nodejs-nginx:latest $OUTPUT_IMAGE_NAME
This image provides a convenient way to build web application containers. The tradeoff is that the resulting container is a little bloated with Python, g++, Node.js etc. If you want leaner production grade containers you should consider a Multi-Stage Build or OpenShift Chained Builds.
When used in conjunction with s2i (source-to-image), it bundles the source code for a webapp that is built using Node.js tools, and produces a runnable container image that serves the content using NGINX.
The process is illustrated in the diagram below:
The text in the parentheses below are available image tag names.
- Node.js 16 and NGINX 1.18 (16-nginx1.18 / latest)
- Node.js 16 and NGINX 1.16 (16-nginx1.16)
- Node.js 14 and NGINX 1.18 (14-nginx1.18)
- Node.js 14 and NGINX 1.16 (14-nginx1.16)
- Node.js 12 and NGINX 1.18 (12-nginx1.18)
- Node.js 12 and NGINX 1.16 (12-nginx1.16)
- Node.js 10 and NGINX 1.18 (10-nginx1.18)
- Node.js 10 and NGINX 1.16 (10-nginx1.16)
Each of these is available at quay.io/evanshortiss/s2i-nodejs-nginx
in the format quay.io/evanshortiss/s2i-nodejs-nginx:14-nginx1.18
.
Minor Node.js versions cannot be specified. Each tag is built using the Node.js
Alpine base images from Docker Hub, e.g 14-alpine
.
The web application being built using this builder must:
- Contain a
build
entry in thescripts
section of the package.json - The
build
script must produce a dist/ folder (alternative directory can be specified using aBUILD_OUTPUT_DIR
environment variable) in the root of the repository (it can be added to .gitignore) - An index.html must be at the root of the dist/ folder
- All other static assets must be included in the dist/ relative to index.html
A sample application that satisfies these requirements can be found here.
If the builder detects a yarn.lock in your repository it will use yarn instead of npm to install dependencies and execute the build script in your package.json.
You need to install s2i
and Docker before running the s2i build
command below to generate a container image.
# Node.js version used for building the app, and NGINX the version for serving
export BUILDER_VERSION=14-nginx1.18
# The repository containing the application you'd like to build
export REPO_URL=https://github.com/evanshortiss/s2i-nodejs-nginx-example
# Name for the resulting image tag
export OUTPUT_IMAGE_NAME=nginx-webapp-runner
s2i build $REPO_URL quay.io/evanshortiss/s2i-nodejs-nginx:$BUILDER_VERSION $OUTPUT_IMAGE_NAME
This will produce a container named nginx-webapp-runner
that can be started
via docker run -p 8080:8080 nginx-webapp-runner
.
With the OpenShift CLI (oc
)
you can deploy the static site using the following command:
# Node.js version to use for building the application (does not support minor versions)
export BUILDER_VERSION=14-nginx1.16
# The repository containing the application you'd like to build
export REPO_URL=https://github.com/evanshortiss/s2i-nodejs-nginx-example
oc new-app quay.io/evanshortiss/s2i-nodejs-nginx:$BUILDER_VERSION~$REPO_URL
This will create a BuildConfig and the other necessary API Objects on your OpenShift instance to build the application via source-to-image and deploy it.
The out of the box configuration does the following:
- Listens on port 8080
- Serves dist/index.html for the
/
route - Applies GZIP compression to text-based assets larger than 1000 bytes
- Logs at INFO level to stdout
- Includes NGINX default mime type mappings
Set these during an s2i build using the --env
flag, or on the BuildConfig in OpenShift:
- BUILD_OUTPUT_DIR (default:
dist
):- Tells the build image where
npm run build
places assets. - For example, if using Create React App you need to set
BUILD_OUTPUT_DIR=build
. - With Webpack you might use a custom output directory, so you set
BUILD_OUTPUT_DIR=my-custom-dir
- Tells the build image where
These can be set when running the built container. Currently none are supported.
You can add your custom nginx.conf
to the container. While assembling, the builder looks for a nginx.conf file in your project .s2i/nginx
directory. If there is a nginx.conf
present at .s2i/nginx/nginx.conf
, it will copy all contents of the .s2i/nginx/
directory and put it into the target images /opt/app-root/etc
directory. There the custom nginx.conf file will be used.
You can include files in your custom configuration. This is useful if you have many configuration files. If you provide the builder with a custom nginx.conf file in your projects .s2i/nginx/
directory, all other files inside .s2i/nginx/
will be copied along as well. So you could for example include a file with mime types in your custom nginx.conf. Add the file .s2i/nginx/mime.types
to your project and include it like this:
include /opt/app-root/etc/mime.types;
The builder can add basic auth to the container for you. All you need to do is to set some environment variables.
Note: These must be set on the OpenShift BuildConfig
BASICAUTH_USERNAME
- the username used for basic auth.BASICAUTH_PASSWORD
- the password used for basic auth.BASICAUTH_TITLE
- the title used for basic auth.
If you'd like to contribute, then being able to test locally is a must. Here are some helpful commands to get running locally:
This will produce a builder image that uses Node.js 14 and NGINX 1.18:
export NODE_VERSION=14
export NGINX_VERSION=1.18
# Must set the APK_REPO to 3.12 find NGINX 1.18
export APK_REPO=http://dl-cdn.alpinelinux.org/alpine/v3.10/main
docker build . -f alpine.Dockerfile \
--build-arg NODE_VERSION=$NODE_VERSION \
--build-arg NGINX_VERSION=$NGINX_VERSION \
--build-arg APK_REPO=$APK_REPO \
-t s2i-webapp-builder
To use NGINX 1.16, change the NGINX_VERSION
and APK_REPO
variables:
export NODE_VERSION=14
export NGINX_VERSION=1.16
# Set the APK_REPO to 3.10 find NGINX 1.16, or 3.12 for NGINX 1.18
export APK_REPO=http://dl-cdn.alpinelinux.org/alpine/v3.12/main
docker build . -f alpine.Dockerfile \
--build-arg NODE_VERSION=$NODE_VERSION \
--build-arg NGINX_VERSION=$NGINX_VERSION \
--build-arg APK_REPO=$APK_REPO \
-t s2i-webapp-builder
# The repository that s2i should clone and build
export REPO_URL="<the repo you want to build>"
# The BUILD_OUTPUT_DIR needs to be set to "build" if the application in
# REPO_URL uses react-scripts build. Otherwise, change it according to your
# custom output directory, e.g dist
export BUILD_OUTPUT_DIR=build
# Perform an s2i build.
s2i build $REPO_URL --env BUILD_OUTPUT_DIR=$BUILD_OUTPUT_DIR s2i-webapp-builder s2i-webapp-runner
# Run the resulting image and expose it on port 8080
docker run -f --rm --name webapp -p 8080:8080 s2i-webapp-runner