Skip to content

Commit

Permalink
docs: Update README.
Browse files Browse the repository at this point in the history
  • Loading branch information
darkobits committed May 13, 2021
1 parent cdce8de commit d22ae7f
Showing 1 changed file with 140 additions and 93 deletions.
233 changes: 140 additions & 93 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,36 @@
<a href="https://conventionalcommits.org"><img src="https://img.shields.io/static/v1?label=commits&message=conventional&style=flat-square&color=398AFB"></a>
</p>

This package aims to make containerizing a Node project as straightforward as using `npm publish`. It leverages `npm pack` (used internally by `npm publish`) to determine which files are production-relevant and existing standards for determining a project's entrypoint, namely the `"main"` and `"bin"` `package.json` fields.
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 pack` 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.

## Install

Dockerize may be installed globally, though it is recommended that it be installed as a development dependency of an existing project.
Dockerize may be installed globally, though it is recommended that it be installed as a development
dependency of an existing project.

```sh
$ npm i --dev @darkobits/dockerize
```
npm i --dev @darkobits/dockerize
```

You must also have Docker installed on your system with the `docker` command in your `PATH`.

## Use

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](https://docs.docker.com/engine/reference/builder/#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.
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](https://docs.docker.com/engine/reference/builder/#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.

**Example:**

Let's imagine we are developing a web server that we want to containerize. We're using [Babel](https://babeljs.io/) 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:
Let's imagine we are developing a web server that we want to containerize. We're using [Babel](https://babeljs.io/)
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`
Expand All @@ -42,60 +55,88 @@ Let's imagine we are developing a web server that we want to containerize. We're
}
```

To containerize this project, we can run `npm run dockerize`, which will invoke the Dockerize CLI via the above package script.
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](https://nodejs.org). To start our containerized web server, we can run:
This will produce a Docker image with the tag `web-server-demo:0.1.0` using the [current LTS version of Node](https://nodejs.org).
To start our containerized web server, we can run:

```
docker run --interactive --tty web-server-demo:0.1.0
```sh
$ docker run --interactive --tty web-server-demo:0.1.0
```

## Options

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>cwd</code></td><td><code>false</code></td><td><code>process.cwd()</code></td></tr>
</table>
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`
```yml
node-version: '12.1.3'
ubuntu-version: '19.04'
label:
- rainbows=true
- unicorns=true
env:
- FOO=1
push: true
```

### `cwd`

Required: `false`<br>
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`.
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
```sh
$ dockerize ~/projects/spline-reticulator
```

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--dockerfile`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--dockerfile</code></td><td><code>false</code></td><td>See below.</td></tr>
</table>
Required: `false`<br>
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:
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 19.04 image](https://hub.docker.com/_/ubuntu) will be used as a base, which is "minimal" by default and therefore relatively small.
* The [current LTS version of Node](https://nodejs.org) will be installed. (See `--node-version` below.)
* The [Tini](https://github.com/krallin/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
```sh
$ dockerize --dockerfile "../path/to/your/Dockerfile"
```

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--tag`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--tag</code></td><td><code>false</code></td><td>See below.</td></tr>
</table>
Required: `false`<br>
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.
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|
|:--|:--|
Expand All @@ -107,138 +148,143 @@ The default tag format for scoped packages is: `{{packageScope}}/{{packageName}}

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.
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.
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}}"
```sh
$ 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.
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.

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--node-version`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--node-version</code></td><td><code>false</code></td><td>See below.</td></tr>
</table>
Required: `false`<br>
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.
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="12.13.4"
```sh
$ dockerize --node-version="14.15.0"
```

**Note:** This argument is moot when the `--dockerfile` flag is used.

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--ubuntu-version`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--ubuntu-version</code></td><td><code>false</code></td><td><code>20.10</code></td></tr>
</table>
Required: `false`<br>
Default: `20.10`

Ubuntu version to use as a base image. This option supports any valid tag for the [public `ubuntu` image](https://hub.docker.com/_/ubuntu/).

**Example:**

```
dockerize --ubuntu-version="latest"
```sh
$ dockerize --ubuntu-version="latest"
```

**Note:** This argument is moot when the `--dockerfile` flag is used.

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--npmrc`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--npmrc</code></td><td><code>false</code></td><td>N/A</td></tr>
</table>
Required: `false`<br>
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.
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"
```sh
$ dockerize --npmrc="~/.npmrc"
```

**Note:** If an `.npmrc` file is used, it will be deleted from the image once dependencies are installed.
**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.

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--label`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--label</code></td><td><code>false</code></td><td>N/A</td></tr>
</table>
Required: `false`<br>
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.
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"
```sh
$ dockerize --label="foo=bar" --label="baz=qux"
```

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--env`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--env</code></td><td><code>false</code></td><td>N/A</td></tr>
</table>
Required: `false`<br>
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.
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="EDITOR=vim"
```sh
$ dockerize --env="RETICULATE_SPLINES=1"
```

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--extra-args`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--extra-args</code></td><td><code>false</code></td><td>N/A</td></tr>
</table>
Required: `false`<br>
Default: N/A

Any additional arguments to provide to the call to `docker build`. This value should be a single quoted string.
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"
```sh
$ dockerize --extra-args="--force-rm --squash"
```

<a href="#top" title="Back to top"><img src="https://user-images.githubusercontent.com/441546/67830932-d6ab4680-fa99-11e9-9870-bc6d31db5a1b.png"></a>
### `--push`

<table>
<tr><th align="left">Name</th><th align="left">Required</th><th align="left">Default</th></tr>
<tr><td><code>--push</code></td><td><code>false</code></td><td><code>false</code></td></tr>
</table>
Required: `false`<br>
Default: `false`

Whether to call `docker push` after building an image.

## Node API

Dockerize can also be used programmatically. This package's default export is a function that accepts a single options object per the above specification.
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:**

```js
import Dockerize from '@darkobits/dockerize';

await Dockerize({
nodeVersion: '10.14.2',
nodeVersion: '14.15.0',
// These options should use the singular form for their key, but their values may be strings
// or arrays of strings.
label: ['foo=bar', 'baz=qux'],
Expand All @@ -248,9 +294,10 @@ await Dockerize({

## Debugging

This tool respects the `LOG_LEVEL` environment variable. It may be set to `verbose` or `silly` to enable additional logging.
This tool respects the `LOG_LEVEL` environment variable. It may be set to `verbose` or `silly` to enable
additional logging.

<br />
<a href="#top">
<img src="https://user-images.githubusercontent.com/441546/102322726-5e6d4200-3f34-11eb-89f2-c31624ab7488.png" style="max-width: 100%;">
<img src="https://user-images.githubusercontent.com/441546/118062198-4ff04e80-b34b-11eb-87f3-406a345d5526.png" style="max-width: 100%;">
</a>

0 comments on commit d22ae7f

Please sign in to comment.