Building a docker formatted container image for a Node.js application
There are 2 main strategies for building an image for a Node.js Application. The most common strategy is simply using a Dockerfile
with a base image of something like FROM node:4-onbuild
. Then do a docker build
. This will produce an image with your application in it, ready to be run. This strategy is known as the Docker
strategy in an OpenShift BuildConfig.
Another strategy is using the s2i
tool for taking the application source from a repository and producing the image. A typical command would be.s2i build git@github.com/me/myrepo.git bucharestgold/centos7-s2i-nodejs:latest myapp.
With this strategy, there is no explicit Dockerfile
. It is known as the Source
strategy in an OpenShift BuildConfig.
Alternatives to npm
Both of these strategies will install any Node dependencies using the npm
tool. However, there are other tools available for managing dependencies in Node.js applications. Yarn is one such tool that has gained popularity due to the speed of dependency installation and locking mechanism for dependency versions.
To use Yarn for installation of dependencies with an s2i strategy, the s2i builder image needs a couple of modifications. The first change is to install the Yarn binary. For these examples, the CentOS s2i builder image maintained at https://github.com/bucharest-gold/centos7-s2i-nodejs will be used. Installing the Yarn binary is a simple enough change to contrib/etc/install_node.sh
.
# Install yarn npm install -g yarn -s &>/dev/null
The second change is to use Yarn when installing Node.js dependencies. Since Yarn is not the official dependency install tool, it would be nice to use npm by default and allow developers to choose Yarn if they wanted. An environment variable can help with that. Developers may also want to pass additional flags to Yarn. This change to s2i/assemble
will allow both scenarios:
if [ ! -z "$YARN_ENABLED" ]; then echo "---> Using 'yarn install' with YARN_ARGS" yarn install $YARN_ARGS else echo "---> Using 'npm install'" npm install -s fi
Doing a make all
will produce create a new s2i builder image with above changes.
S2I builder in action with Yarn
Environment variables can be passed to s2i
with the -e
flag. The following command uses Yarn to install dependencies:
s2i build -e "YARN_ENABLED=true" git@github.com:david-martin/nodejs-ex docker.io/bucharestgold/centos7-s2i-nodejs:latest myapp ---> Installing application source ---> Building your Node application from source ---> Using 'yarn install' with YARN_ARGS yarn install v0.24.5 [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages... Done in 1.79s.
Using it in OpenShift
To use it in OpenShift, there are 2 small changes to your BuildConfig. The first is to tell it to use a different s2i build image. Then configure it to use Yarn by setting an environment variable.
strategy: type: Source sourceStrategy: from: kind: DockerImage name: 'bucharestgold/centos7-s2i-nodejs:latest' env: - name: YARN_ENABLED value: 'true'
Trigger a build using the oc build
command, and the build logs will look similar to above. That's all there is to it. You can extend on this idea to allow other dependency management or installation tools to be used.
Links
- CentOS s2i builder image, with Yarn support - https://hub.docker.com/r/bucharestgold/centos7-s2i-nodejs/
- Pull Request where Yarn support was added - https://github.com/bucharest-gold/centos7-s2i-nodejs/pull/2
- Sample Node.js Application with a Yarn lock file - https://github.com/david-martin/nodejs-ex