docker - Bazel Monorepo - 如何仅重建和发布更改的 Docker 镜像?

标签 docker kubernetes google-kubernetes-engine bazel monorepo

客观的

我有一个 monorepo 设置,其中包含越来越多的服务。当我部署应用程序时,我运行一个命令,每个服务都将被重建,最终的 Docker 镜像将被发布。
但是随着服务数量的增加,重建所有服务所需的时间越来越长,尽管只对其中的几个进行了更改。

为什么我的设置重建了所有 Docker 镜像,尽管只有少数镜像发生了变化?我的目标是仅重建和发布实际更改的图像。

细节

我正在使用 Bazel 来构建我的 Docker 镜像,因此在我的项目的根目录中有一个 BUILD包含我要部署时运行的目标的文件。只是k8s_objects的合集,其中包括每项服务:

load("@io_bazel_rules_k8s//k8s:objects.bzl", "k8s_objects")
k8s_objects(
    name = "kubernetes_deployment",
    objects = [
        "//services/service1",
        "//services/service2",
        "//services/service3",
        "//services/service4",
        # ...
    ]
)

同样有一个 BUILD首先从所有源文件创建一个 Typescript 库的每个服务的文件,然后创建 Node.Js 图像,最后将图像传递给 Kubernetes 对象:

load("@npm_bazel_typescript//:index.bzl", "ts_library")
ts_library(
    name = "lib",
    srcs = glob(
        include = ["**/*.ts"],
        exclude = ["**/*.spec.ts"]
    ),
    deps = [
      "//packages/package1",
      "//packages/package2",
      "//packages/package3",
    ],
)

load("@io_bazel_rules_docker//nodejs:image.bzl", "nodejs_image")
nodejs_image(
    name = "image",
    data = [":lib", "//:package.json"],
    entry_point = ":index.ts",
)

load("@k8s_deploy//:defaults.bzl", "k8s_deploy")
k8s_object(
  name = "service",
  template = ":service.yaml",
  kind = "deployment",
  cluster = "my-cluster"
  images = {
    "gcr.io/project/service:latest": ":image"
  },
)

请注意,Typescript 库还依赖于一些包,这些包在重新部署时也应考虑在内!

要部署,我运行 bazel run :kubernetes_deployment.apply
最初我决定选择 Bazel 的一个原因是因为我认为它只能处理构建变化的服务本身。但显然情况并非如此,或者我的设置在某些方面有问题。

如果您需要更详细地了解该项目,可以在此处查看:https://github.com/flolude/cents-ideas

最佳答案

看起来 Bazel repo 本身做了类似的事情:

https://github.com/bazelbuild/bazel/blob/ef0f8e61b5d3a139016c53bf04361a8e9a09e9ab/scripts/ci/ci.sh

粗略的步骤是:

  • 计算改变的文件列表
  • 使用文件列表并找到它们的依赖项(例如,bazel 查询 kind(.*_binary, rdeps(//..., set(file1.txt file2.txt))) 将找到所有依赖于 file1.txtfile2.txt 的二进制目标)
  • 构建/测试目标列表

  • 您需要根据需要调整此脚本(例如,确保它找到 docker 图像目标)

    要找出目标的类型,您可以使用 bazel query //... --output label_kind
    编辑:
    对任何想要进入这个兔子洞的人发出一点警告(特别是如果你绝对不想错过 CI 中的测试):

    你需要考虑:
  • 删除的文件/构建文件(依赖于它们的人)
  • 请注意,移动的文件 == 已删除 + 已添加
  • 您也不能查询不再存在的文件/构建的反向 deps!
  • 修改后的 BUILD 文件(为了安全起见,确保构建了 BUILD 中所有目标的所有反向 deps)

  • 我认为沿着这条路线走下去有很多复杂性(如果可能的话)。使用远程缓存和 --subcommands 依靠 Bazel 本身找出发生了什么变化可能不太容易出错。来计算需要执行哪些副作用。

    关于docker - Bazel Monorepo - 如何仅重建和发布更改的 Docker 镜像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60279671/

    相关文章:

    nginx - Docker 不会附加到图像

    linux - 如何将STDIN发送到docker进程

    postgresql - Kubernetes - PostgreSQL 的持久存储

    kubernetes - 仅从一个状态集的一个Pod中选择服务

    docker - 在 docker 中禁用交互模式

    docker - 如何在 docker 中安装全局 npm 依赖项?

    kubernetes - kubernetes kubelet 是 DaemonSet 吗?

    kubernetes - 在 GKE 上部署 Airflow 的最佳方式和生产级别是什么?

    Kubernetes Pod 与 Google Cloud 中的部署

    docker - 如何将 Container VM 上的 docker 容器与 list 链接?