在本地构建成功的 Bazel 构建在远程执行时可能会失败,这是因为远程执行存在一些 不会影响本地构建的限制和要求。如需了解此类失败的最常见 原因,请参阅为远程执行调整 Bazel 规则。
本页面介绍了如何使用 Docker 沙盒功能识别和解决远程执行时出现的最常见问题。Docker 沙盒功能对构建施加的限制与远程执行的限制相同。这样,您无需使用远程执行服务即可排查构建问题。
Docker 沙盒功能会模拟远程执行的限制,如下所示:
构建操作在工具链容器中执行。您可以使用相同的 工具链容器在本地和远程运行构建,前提是您使用支持容器化远程执行的服务 。
没有无关数据会跨越容器边界。只有明确 声明的输入和输出才会进入和离开容器,并且只有在关联的构建操作成功完成后才会发生这种情况。
每个操作都在新的容器中执行。系统会为每个生成的构建操作创建一个新的唯一容器。
您可以使用以下任一方法来排查这些问题:
以原生方式进行问题排查。使用此方法, Bazel 及其构建操作会在本地计算机上以原生方式运行。Docker 沙盒功能对构建施加的限制与远程 执行的限制相同。但是,此方法不会检测到本地工具、状态和 数据泄露到构建中,而这些泄露会导致远程执行出现问题。
在 Docker 容器中进行问题排查。 使用此方法时,Bazel 及其构建操作会在 Docker 容器内运行, 除了施加与远程执行相同的限制之外,此方法还可让您检测到从本地 计算机泄露到构建中的工具、状态和数据。即使部分构建失败,此方法也能让您深入了解您的 构建。此方法处于实验阶段 未获得正式支持。
前提条件
在开始问题排查之前,请先执行以下操作(如果尚未执行):
- 安装 Docker 并配置运行它所需的权限。
- 安装 Bazel 0.14.1 或更高版本。早期版本不支持 Docker 沙盒功能。
- 按照此处的说明,将 bazel-toolchains
代码库(固定到最新发布版本)添加到构建的
WORKSPACE文件中。 - 将标志添加到
.bazelrc文件以启用该功能。如果 Bazel 项目的根目录中不存在该文件,请在 该目录中创建该文件。以下标志 是参考示例。请参阅 bazel-toolchains 代码库中的最新.bazelrc文件,并复制其中定义的标志的值以用于配置docker-sandbox。
# Docker Sandbox Mode
build:docker-sandbox --host_javabase=<...>
build:docker-sandbox --javabase=<...>
build:docker-sandbox --crosstool_top=<...>
build:docker-sandbox --experimental_docker_image=<...>
build:docker-sandbox --spawn_strategy=docker --strategy=Javac=docker --genrule_strategy=docker
build:docker-sandbox --experimental_docker_verbose
build:docker-sandbox --experimental_enable_docker_sandbox
如果您的规则需要其他工具,请执行以下操作:
使用 Dockerfile 安装工具并在本地 构建 映像,以创建自定义 Docker 容器。
将上面的
--experimental_docker_image标志的值替换为 自定义容器映像的名称。
以原生方式进行问题排查
此方法直接在本地 计算机上执行 Bazel 及其所有构建操作,是一种可靠的方法,可用于确认您的构建在远程执行时是否会成功 。
但是,使用此方法时,本地安装的工具、二进制文件和数据可能会泄露 到构建中,尤其是在构建使用配置样式的 WORKSPACE 规则时。 此类泄露会导致远程执行出现问题;如需检测到这些泄露,除了以原生方式进行问题排查之外 ,还需在 Docker 容器中进行问题排查。
第 1 步:运行构建
将
--config=docker-sandbox标志添加到执行 构建的 Bazel 命令中。例如:bazel --bazelrc=.bazelrc build --config=docker-sandbox target运行构建并等待其完成。由于 Docker 沙盒功能,构建的运行速度将比正常速度慢四 倍。
您可能会遇到以下错误:
ERROR: 'docker' is an invalid value for docker spawn strategy.
如果遇到此错误,请使用 --experimental_docker_verbose 标志再次运行构建。
此标志会启用详细的错误消息。此错误通常是由
Docker 安装错误或当前用户账号缺少执行权限所致。如需了解详情,请参阅 Docker 文档
。如果问题仍然存在,请跳至在 Docker 容器中进行问题排查。
第 2 步:解决检测到的问题
以下是最常见的问题及其解决方法。
Bazel 运行文件树引用的文件、工具、二进制文件或资源 缺失。.确认受影响目标的所有依赖项都已 明确声明。如需了解详情,请参阅 管理隐式依赖项 。
绝对路径或
PATH变量引用的文件、工具、二进制文件或资源缺失。确认所有必需的工具都安装在 工具链容器中,并使用 工具链规则 正确 声明指向缺失资源的依赖项。如需了解详情,请参阅 通过工具链规则调用构建工具 。二进制文件执行失败。其中一个构建规则引用了与执行环境(Docker 容器)不兼容的二进制文件 。如需了解详情,请参阅 管理平台相关的二进制文件 。如果您无法解决此问题,请与 bazel-discuss@google.com 联系以获取帮助。
@local-jdk中的文件缺失或导致错误。本地计算机上的 Java 二进制文件 泄露到构建中,但与 构建不兼容。请在规则和目标中使用java_toolchain,而不是@local_jdk。如果您需要更多帮助,请与 bazel-discuss@google.com 联系。其他错误。请与 bazel-discuss@google.com 联系以获取帮助。
在 Docker 容器中进行问题排查
使用此方法时,Bazel 在宿主 Docker 容器内运行,而 Bazel 的构建 操作在 Docker 沙盒功能生成的各个工具链容器内执行。沙盒会为每个 构建操作生成一个全新的工具链容器,并且每个工具链容器中仅执行一个操作。
此方法可更精细地控制宿主 环境中安装的工具。通过将构建的执行与其 构建操作的执行分开,并将安装的工具保持在最低限度,您可以验证 构建是否对本地执行环境有任何依赖项。
第 1 步:构建容器
创建一个
Dockerfile,用于创建 Docker 容器并安装 Bazel 及最少的一组构建工具:FROM debian:stretch RUN apt-get update && apt-get install -y apt-transport-https curl software-properties-common git gcc gnupg2 g++ openjdk-8-jdk-headless python-dev zip wget vim RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" RUN apt-get update && apt-get install -y docker-ce RUN wget https://releases.bazel.build/<latest Bazel version>/release/bazel-<latest Bazel version>-installer-linux-x86_64.sh -O ./bazel-installer.sh && chmod 755 ./bazel-installer.sh RUN ./bazel-installer.sh将容器构建为
bazel_container:docker build -t bazel_container - < Dockerfile
第 2 步:启动容器
使用以下命令启动 Docker 容器。在该命令中, 将路径替换为您要构建的宿主机上的源代码路径。
docker run -it \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp:/tmp \
-v your source code directory:/src \
-w /src \
bazel_container \
/bin/bash此命令以 root 身份运行容器,同时映射 Docker 套接字并装载
/tmp目录。这样一来,Bazel 能够生成其他 Docker 容器,还可以
使用 /tmp 下的目录与这些容器共享文件。您的源代码位于容器内的 /src 中。
该命令有意从 debian:stretch 基本容器开始,该容器
包含与用作
工具链容器的 rbe-ubuntu16-04 容器不兼容的二进制文件。如果本地环境中的二进制文件泄露到
工具链容器中,则会导致构建错误。
第 3 步:测试容器
在 Docker 容器内运行以下命令以对其进行测试:
docker psbazel version
第 4 步:运行构建
按如下所示运行构建。输出用户是 root,以便它对应于 可以通过以下位置访问(通过同一绝对路径)的目录:运行 Bazel 的宿主 容器内部、由 Docker 沙盒功能生成的运行 Bazel 构建操作的工具链容器,以及运行宿主容器和操作容器的本地 计算机。
bazel --output_user_root=/tmp/bazel_docker_root --bazelrc=.bazelrc \ build --config=docker-sandbox target第 5 步:解决检测到的问题
您可以按如下方式解决构建失败问题:
如果构建因“磁盘空间不足”错误而失败,您可以使用标志
--memory=XX启动宿主容器来增加此 限制,其中XX是分配的磁盘空间(以 GB 为单位)。此方法处于实验阶段,可能会 导致不可预测的行为。如果构建在分析或加载阶段失败,则表明 WORKSPACE 文件中声明的一个或多个构建规则与 远程执行不兼容。如需了解可能的原因和解决方法,请参阅为远程执行调整 Bazel 规则 。
如果构建因任何其他原因而失败,请参阅第 2 步:解决检测到的问题中的问题排查步骤。