blob: cefc41e5fe201550334a030920c52374a5e64c96 [file] [log] [blame] [view]
# An example for rules_js + rules_docker
The `js_image_layer` rule returns `tar` artifacts, suitable to include in the `tars` attribute of the `container_image` rule from rules_docker.
You can `bazel run` the target to get the image to load into your Docker daemon.
See the [rules_docker documentation](https://github.com/bazelbuild/rules_docker/blob/a8aff4076f75c4dfb39bd768dd9870b5d263e70d/README.md#using-with-docker-locally)
> Like all lang_image rules in rules_docker, the nodejs_image rule has different behavior under `bazel run` where the container is booted and executes.
For an example using rules_oci rather than rules_docker, see the js_image_oci folder next to this one.
## Fine-grained layering
`js_image_layer` is a macro that yields two tar files `app.tar` and `node_modules.tar`. While `app.tar` contains first-party sources, `node_modules.tar` contains all third-party dependencies.
This speeds up developer change-build-push cycle by allowing build and push of only what has changed.
For instance, when a new third-party dependency is added, then only `node_modules.tar` will change and one will only have to push changes to dependencies.
On the other hand, if the application code is changed, then only `app.tar` will be updated and pushed.
### dive <image>
```
│ Layers ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Cmp Size Command
118 MB FROM 27d8bf01e7ea3c5
78 MB bazel build ...
97 kB bazel build ...
0 B #(nop) ADD file:64c455af1bb18ff2c202a244e058b6e5ac147b89410ed36edc5e29f4b6f02c5d in /
│ Image Details ├───────────────────────────────────────────────────────────────────────────────────────────
Image name: localhost/bazel:image
Total Image size: 196 MB
Potential wasted space: 0 B
Image efficiency score: 100 %
```
As seen in the [dive](https://github.com/wagoodman/dive) output the largest layer is our base image which is `118 MB` followed by `78 MB` which is the dependencies and finally `97 kB` which is the app itself.
Additionally, we get a `100%` efficiency score which means there are no duplicate or `whiteout` files to waste space.
## Selecting the right NodeJS interpreter
By default `js_binary` gets the nodejs interpreter for the host platform. However, this is not the case when including the js_binary in container_image thanks to transitions. See [#3373](https://github.com/bazelbuild/rules_nodejs/pull/3373) and [#1963](https://github.com/bazelbuild/rules_docker/pull/1963) for how this works.
Toolchain selection is controlled by `operating_system` and `architecture` attribute on `container_image` which is `linux/amd64` by default.
NodeJS interpreter for a different platform can be obtained by changing `operating_system` and `architecture`.
Here is what the final image looks like when the platform is `linux/arm64`
```
app
|-- main.sh
|-- main.sh.runfiles
| |-- __main__
| | |-- main.sh
| | |-- node_modules
| | | `-- chalk -> /app/main.sh.runfiles/__main__/node_modules/.aspect_rules_js/chalk@4.1.2/node_modules/chalk
| | `-- src
| | |-- ascii.art
| | `-- main.js
| |-- aspect_rules_js
| | `-- js
| | `-- private
| | `-- node-patches
| | |-- fs.cjs
| | `-- register.cjs
| |-- bazel_tools
| | `-- tools
| | `-- bash
| | `-- runfiles
| | `-- runfiles.bash
| `-- nodejs_linux_arm64
| `-- bin
| `-- nodejs
| `-- bin
| `-- node
`-- main_.sh
17 directories, 9 files
```