bazel-javascript icon indicating copy to clipboard operation
bazel-javascript copied to clipboard

Example for dockerized nodejs monorepo

Open enriched opened this issue 7 years ago • 1 comments

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:

  1. you have a native node module
  2. your IDE is not aware of node_modules installed by bazel
  3. 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",
    ],
)

enriched avatar Aug 17 '18 22:08 enriched

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).

fwouts avatar Aug 23 '18 20:08 fwouts