bazel-javascript
bazel-javascript copied to clipboard
Example for dockerized nodejs monorepo
I am trying to use Bazel to develop dockerized nodejs apps on a local kubernetes cluster.
Seems like the Bazel way is to compile all sources and dependencies down into a single js file and then add that to the container. That seems to work fairly well till:
- you have a native node module
- your IDE is not aware of node_modules installed by bazel
- your IDE is not aware of bazel dependencies (the ts language server is not aware of bazel deps from ts_library targets)
I am not sure how to solve issue 1 yet. Figuring out which of your node modules are native seems difficult, and then creating a docker image that has them compiled with the correct toolchain seems like something that Bazel isn't all that good at yet.
Issue 2 can be solved by running a yarn install at the workspace root as long as everyone is willing to put all npm dependencies in the package.json at the repo root.
The only way to solve issue 3 seems to be to use path mapping or project references in your tsconfig.json file.
I would really appreciate an example of a monorepo that produces nodejs docker images from someone more experienced in Bazel. Bonus points if it can use something like skaffold for quick development iteration.
Currently, for a dockerized nodejs app I am using something like:
./WORKSPACE
git_repository(
name = "bazel_javascript",
remote = "https://github.com/zenclabs/bazel-javascript.git",
tag = "0.0.23",
)
git_repository(
name = "build_bazel_rules_nodejs",
remote = "https://github.com/bazelbuild/rules_nodejs.git",
tag = "0.10.0",
)
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
node_repositories(
package_json = [],
)
load(
"@io_bazel_rules_docker//container:container.bzl",
"container_pull",
container_repositories = "repositories",
)
container_repositories()
container_pull(
name = "node_alpine_image",
registry = "index.docker.io",
repository = "library/node",
tag = "8.11.3-alpine",
)
./BUILD.bazel
package(default_visibility = ["//visibility:public"])
exports_files(["tsconfig.json"])
load("@bazel_javascript//:defs.bzl", "npm_packages")
npm_packages(
name = "packages",
package_json = ":package.json",
yarn_lock = ":yarn.lock",
)
./libs/shared-package/BUILD.bazel
package(default_visibility = ["//visibility:public"])
load("@bazel_javascript//:defs.bzl", "ts_library")
ts_library(
name = "shared-package"
srcs = glob("**/*.ts")
tsconfig = "//:tsconfig.json"
)
./services/base-image/BUILD.bazel
package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_push")
## The Backend Base Image
container_image(
name = "service",
base = "@node_alpine_image//image:image",
labels = {
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "MyCompany",
"org.label-schema.url": "http://my-company.com/",
"org.label-schema.vcs-url": "https://github.com/MyCompany/this-repo",
"org.label-schema.vcs-ref": "{GIT_COMMIT}",
},
stamp = True,
workdir = "/app",
)
./services/my-service/BUILD.bazel
package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_push")
container_image(
name = "image",
base = "//services/base-image:service",
data_path = ".",
directory = "/app",
files = [
"//services/my-service/server",
],
labels = {
"org.label-schema.vcs-ref": "{GIT_COMMIT}",
},
stamp = True,
)
container_push(
name = "publish",
format = "Docker",
image = ":image",
registry = "my.repo.com",
repository = "my-service",
stamp = True,
tag = "{BUILD_USER}",
)
./services/my-service/server/BUILD.bazel
load("@bazel_javascript//:defs.bzl", "ts_library")
ts_library(
name = "server_lib",
srcs = glob(["**/*.ts"]),
tsconfig = "//:tsconfig.json",
deps = [
"//:packages",
"//libs/shared-package",
],
)
I've just published v0.0.24 which should work with the example in 721c617.
Let's keep this issue open as the approach is still quite suboptimal (running npm rebuild on container launch, and not at build time).