Dockerize aims to make containerizing a Node project as straightforward as using npm publish
.
No Dockerfile
required.
This project uses idiomatic standards (ie: "files"
, "main"
, "bin"
in package.json
) to determine
which files in a project are production-relevant. It uses npm-packlist
under the hood, which is what npm publish
uses to create package tarballs. It uses sane defaults and
adheres to best practices for containerizing Node applications, but remains configurable for those with
highly specific use cases.
Dockerize may be installed globally, though it is recommended that it be installed as a development dependency of an existing project.
$ npm i --dev @darkobits/dockerize
You must also have Docker installed on your system with the docker
command in your $PATH
.
Dockerize uses a project's package.json
to infer which files should be included in images and which
file to use as the image's entrypoint.
By default, it will use the first (or only) "bin"
value, if present. Otherwise, it will use "main"
.
All files enumerated in "files"
will be included in the image. To produce a list of exactly what files
will be added to images, run npm pack --dry-run
.
Example:
Let's imagine we are developing a web server that we want to containerize. We're using Babel
to transpile our source files to a dist
folder in our project root. This project's package.json
(sans dependencies) may look like the following:
package.json
{
"name": "web-server-demo",
"version": "0.1.0",
"files": [
"dist"
],
"main": "dist/server.js",
"scripts": {
"dockerize": "dockerize"
}
}
To containerize this project, we can run npm run dockerize
, which will invoke the Dockerize CLI via
the above package script.
This will produce a Docker image with the tag web-server-demo:0.1.0
using the current LTS version of Node.
To start our containerized web server, we can run:
$ docker run --interactive --tty web-server-demo:0.1.0
Dockerize accepts the following named arguments, which may be set via command-line flags or via a configuration file, which may be any of the following:
Name | Format |
---|---|
.dockerize.json |
JSON |
.dockerize.yml |
YAML |
dockerize.config.js |
JavaScript |
Example:
.dockerize.yml
node-version: '12.1.3'
ubuntu-version: '22.04'
label:
- rainbows=true
- unicorns=true
env:
- FOO=1
push: true
Required: false
Default: process.cwd()
This is a positional argument when using the CLI and a named option when using the API.
Root of the project to containerize. This argument works just like docker build
's first positional
argument. This directory should contain a package.json
.
Example:
$ dockerize ~/projects/spline-reticulator
Required: false
Default: See below.
Optional path to a custom Dockerfile
to use. If not provided, Dockerize will look for a Dockerfile
in the root of the build context (see cwd
argument above). If the build context does not contain a
Dockerfile
, Dockerize will programmatically generate one for you with the following properties:
- The Ubuntu 22.04 image will be used as a base for stage 1.
- The distroless base image is used for stage 2, producing a very compact image.
- The current LTS version of Node will be installed. (See
--node-version
below.) - The Tini process manager will be installed and configured to ensure proper handling of POSIX signals. This is considered a best practice when using Node in Docker.
Example:
$ dockerize --dockerfile "../path/to/your/Dockerfile"
Required: false
Default: See below.
Tag to use for the image.
Dockerize will inspect package.json
and extract the name
and version
fields. It will then remove
any leading @
, and split the name into its scope (if applicable) and base name components. These
tokens are then used to construct the image's name, and are also available to the user to create a
custom tag format using these data.
Token | Value |
---|---|
{{packageName}} |
Non-scope segment of name from package.json . |
{{packageScope}} |
Scope segment of name from package.json , sans @ . |
{{packageVersion}} |
version from package.json . |
The default tag format for scoped packages is: {{packageScope}}/{{packageName}}:{{packageVersion}}
.
The default tag format for un-scoped packages is: {{packageName}}:{{packageVersion}}
.
When using the tag
argument, you may include these tokens and Dockerize will replace them with their
appropriate values.
Example:
Suppose we are Dockerizing version 1.2.3
of a package named @acmeco/spline-reticulator
which we want
to push to a custom Docker registry, hub.acmeco.com
. The default image name that would be generated
for this package would be acmeco/spline-reticulator:1.2.3
, and a docker push
of this image would
assume it should be pushed to the public Docker registry.
Instead, we can pass the following tag
argument:
$ dockerize --tag="hub.acmeco.com/{{packageName}}:{{packageVersion}}"
Which will produce an image named hub.acmeco.com/spline-reticulator:1.2.3
. Notice that we don't need
our package scope in this image name since we are publishing to our own private registry. Leveraging a
custom tag format let's us accomplish this.
Required: false
Default: LTS
By default, Dockerize will use the current LTS version of Node. The LTS, or Long-Term Support version of Node provides the best balance of modern language features and stability. If your project requires a specific Node version, you may provide it using this flag.
Example:
$ dockerize --node-version="14.15.0"
Note This argument is moot when the
--dockerfile
flag is used.
Required: false
Default: 20.10
Ubuntu version to use as a base image. This option supports any valid tag for the public ubuntu
image.
Example:
$ dockerize --ubuntu-version="latest"
Note This argument is moot when the
--dockerfile
flag is used.
Required: false
Default: N/A
If your project has production dependencies that are installed from private registries or otherwise
require authorization, NPM will need to be configured using an .npmrc
file. Most of the time, this
file will not be present in the build context and will therefore not be available when npm install
is
called when building the image. If your project requires an .npmrc
file in order to install
dependencies, you may provide a path to this file using this argument.
Example:
$ dockerize --npmrc="~/.npmrc"
Note If an
.npmrc
file is used, it will be deleted from the image once dependencies are installed.
Note This argument is moot when the
--dockerfile
flag is used.
Required: false
Default: N/A
Apply one or more labels to the image. This argument works just like docker build
's --label
argument, and may be used multiple times to apply multiple labels. Quoting each value when using this
argument is recommended.
Example:
$ dockerize --label="foo=bar" --label="baz=qux"
Required: false
Default: N/A
Set one or more environment variables in the image. This argument works just like docker build
's
--env
argument, and may be used multiple times to apply multiple environment variables. Quoting each
value when using this argument is recommended.
Example:
$ dockerize --env="RETICULATE_SPLINES=1"
Note This argument is moot when the
--dockerfile
flag is used.
Required: false
Default: N/A
Any additional arguments to provide to the call to docker build
. This value should be a single quoted
string.
Example:
$ dockerize --extra-args="--force-rm --squash"
Required: false
Default: false
Whether to call docker push
after building an image.
Dockerize can also be used programmatically. This package's default export is a function that accepts a single options object per the above specification.
Example:
import Dockerize from '@darkobits/dockerize';
await Dockerize({
cwd: './my-project',
nodeVersion: '16.13.1',
labels: [
'foo=bar',
'baz=qux',
'kittens=true'
],
env: [
'NODE_ENV=production'
]
});
This tool respects the LOG_LEVEL
environment variable. It may be set to verbose
or silly
to enable
additional logging.