A Docker base image for NodeJS apps.
Your app must contain three files in its root:
package.json
yarn.lock
.npmrc
(can be blank)
And you must pass a docker build arg called RANCH_BUILD_ENV
. (see below)
Create a Dockerfile
in your app's root:
FROM goodeggs/ranch-baseimage-nodejs:latest
# the rest is handled by ONBUILD instructions.
And the most basic build:
$ docker build --build-arg 'RANCH_BUILD_ENV={}' .
The secret sauce here is to embrace Docker image layer caching behavior. By adding package.json
, npm-shrinkwrap.json
, and .npmrc
in a separate instruction, we will skip the entire npm install
routine unless one of those files has changed. (or the docker build cache is empty)
Your app runs as root inside the container. The reason is a shortcoming of Docker: COPY
and ADD
instructions do not respect USER
instructions, they always add files with root
as the owner. If we then RUN chown -R app:app /app
, we end up with an entire new Docker layer and double the resulting image size. This is unacceptable.
There is hope that Docker will address this, but work is frozen until they split the builder out. See docker/docker#13600 and the Dockerfile syntax section of Docker's roadmap for more details.
You can pass a list of environment variables encoded as a JSON object in a docker build arg called RANCH_BUILD_ENV
. A normal use of this is to pass a private NPM repository token for use during the npm install
step. It can be the empty string but you must pass it or docker will throw.
$ docker build --build-arg 'RANCH_BUILD_ENV={"NPM_AUTH":"sekret"}' .
During docker build
, the engines.node
and engines.npm
properties will be read out of your package.json
file, and the appropriate versions (including semver resolution) will be installed.
The included start
command takes a process name and parses /app/Procfile
. eg start web
would find the line in your Procfile that starts with web:
, and execute that command.
A cool feature inherited from the Heroku NodeJS Buildpack, the included entrypoint
command will detect available memory (using cgroups), read the WEB_MEMORY
environment variable set by you, and export a WEB_CONCURRENCY
variable useful for things like NodeJS's cluster module.
Both the entrypoint
and the start
commands export reasonable values for the DYNO
environment variable, mirroring a useful behavior of Heroku. Instead of dyno index (eg web.1
), we export the container hostname (eg web.abcd3fg
).