ローカルビルドが成功した Bazel ビルドは、ローカルビルドに影響しない制限や要件のために、リモートで実行すると失敗することがあります。このようなエラーの最も一般的な原因については、リモート実行での Bazel ルールの適応をご覧ください。
このページでは、リモート実行と同等の制限をビルドに設定する Docker サンドボックス機能を使用して、リモート実行で発生する最も一般的な問題を特定して解決する方法について説明します。これにより、リモート実行サービスを必要とせずにビルドのトラブルシューティングを行うことができます。
Docker サンドボックス機能は、次のようにリモート実行の制限を模倣しています。
ビルド アクションをツールチェーン コンテナ内で実行します。コンテナ化されたリモート実行をサポートするサービスを介して、同じツールチェーン コンテナを使用してローカルとリモートでビルドを実行できます。
余分なデータはコンテナの境界を越えません。明示的に宣言された入出力は、関連するビルド アクションが正常に完了した後にのみ、コンテナの入出力が行われます。
各アクションは新しいコンテナで実行されます。生成されたビルド アクションごとに新しいコンテナが作成されます。
これらの問題のトラブルシューティングを行うには、次のいずれかの方法を使用します。
ネイティブでのトラブルシューティングこの方法を使用すると、Bazel とそのビルド アクションがローカルマシンでネイティブに実行されます。Docker サンドボックス機能を使用すると、ビルドにリモート実行と同等の制限が課されます。ただし、この方法ではローカルツール、状態、ビルドへのデータ漏洩は検出されず、リモート実行で問題が発生します。
Docker コンテナでのトラブルシューティング。この方法を使用すると、Bazel とそのビルド アクションが Docker コンテナ内で実行されるため、ローカルマシンからビルドにリークされるツール、状態、データを検出できます。また、リモート実行の場合と同等の制限を適用できます。このメソッドは、ビルドの一部が失敗した場合でも、ビルドに関する分析情報を提供します。この方法は試験運用版であり、正式にはサポートされていません。
Prerequisites
トラブルシューティングを開始する前に、以下を行います(まだ行っていない場合)。
- 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 --define=EXECUTOR=remote
build:docker-sandbox --experimental_docker_verbose
build:docker-sandbox --experimental_enable_docker_sandbox
ルールに追加のツールが必要な場合は、次の手順を行います。
Dockerfile を使用してツールをインストールし、イメージをビルドして、カスタム Docker コンテナを作成します。
上記の
--experimental_docker_image
フラグの値をカスタム コンテナ イメージの名前に置き換えます。
ネイティブのトラブルシューティング
この方法では、ローカルマシンで Bazel とそのすべてのビルド アクションが直接実行されるため、リモートでビルドしても成功したかどうかを確実に確認できます。
ただし、この方法では、特に構成スタイルの WORKSPACE ルールを使用している場合は、ローカルにインストールされたツール、バイナリ、データがビルドにリークする可能性があります。このようなリークにより、リモート実行で問題が発生します。検出するには、ネイティブでトラブルシューティングに加えて、Docker コンテナでのトラブルシューティングが必要です。
ステップ 1: ビルドを実行する
ビルドを実行する Bazel コマンドに
--config=docker-sandbox
フラグを追加します。例:bazel --bazelrc=.bazelrc build --config=docker-sandbox target
ビルドを実行し、完了するまで待ちます。Docker サンドボックス機能により、ビルドの実行速度は通常の 4 倍になります。
次のエラーが発生することがあります。
ERROR: 'docker' is an invalid value for docker spawn strategy.
その場合は、--experimental_docker_verbose
フラグを使用してビルドを再度実行します。このフラグは、詳細エラー メッセージを有効にします。このエラーは通常、Docker のインストールが正しくないか、現在のユーザー アカウントで実行するための権限がないことが原因です。詳細については、Docker のドキュメントをご覧ください。問題が解決しない場合は、Docker コンテナでのトラブルシューティングに進みます。
ステップ 2: 検出された問題を解決する
よくある問題とその回避策を以下に示します。
Bazel runfiles ツリーで参照されるファイル、ツール、バイナリ、リソースがありません。影響を受けるターゲットのすべての依存関係が明示的に宣言されていることを確認します。詳細については、暗黙的な依存関係の管理をご覧ください。
絶対パスまたは
PATH
変数によって参照されるファイル、ツール、バイナリ、リソースがない。必要なすべてのツールがツールチェーン コンテナにインストールされていることを確認し、ツールチェーン ルールを使用して、欠落しているリソースを指す依存関係を適切に宣言します。詳細については、ツールチェーン ルールを使用したビルドツールの呼び出しをご覧ください。バイナリ実行が失敗します。ビルドルールの一つが、実行環境(Docker コンテナ)と互換性のないバイナリを参照することです。詳細については、プラットフォーム依存のバイナリの管理をご覧ください。問題を解決できない場合は、bazel-discuss@google.com にお問い合わせください。
@local-jdk
のファイルがないか、エラーが発生する。ローカルマシンの Java バイナリと互換性のないビルドがリークされています。ルールとターゲットでは、@local_jdk
ではなくjava_toolchain
を使用します。ご不明な点がある場合は bazel-discuss@google.com にお問い合わせください。その他のエラー。サポートが必要な場合は、bazel-discuss@google.com にお問い合わせください。
Docker コンテナでのトラブルシューティング
この方法では、Bazel はホスト Docker コンテナ内で実行され、Bazel のビルド アクションは Docker サンドボックス機能によって生成された個々のツールチェーン コンテナ内で実行されます。サンドボックスでは、ビルド アクションごとに新しいツールチェーン コンテナが生成され、各ツールチェーン コンテナでは 1 つのアクションのみが実行されます。
この方法では、ホスト環境にインストールされているツールをより細かく制御できます。ビルドの実行とビルド アクションの実行を切り離し、インストール済みのツールを最小限に保つことで、ビルドがローカル実行環境に依存しているかどうかを確認できます。
ステップ 1: コンテナをビルドする
Docker コンテナを作成し、最小限のビルドツールで Bazel をインストールする
Dockerfile
を作成します。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
にあります。
このコマンドは、ツールチェーン コンテナとして使用される rbe-ubuntu16-04
コンテナと互換性のないバイナリを含む debian:stretch
ベースコンテナから意図的に起動します。ローカル環境のバイナリがツールチェーン コンテナにリークされている場合、ビルドエラーが発生します。
ステップ 3: コンテナをテストする
Docker コンテナ内から次のコマンドを実行してテストします。
docker ps
bazel version
ステップ 4: ビルドを実行する
次のようにビルドを実行します。出力ユーザーは root であるため、Bazel が実行されているホストコンテナ、Bazel のビルド アクションが実行されている Docker サンドボックス機能によって生成されたツールチェーン コンテナ、ホストとアクション コンテナが実行されているローカルマシンから同じ絶対パスでアクセスできるディレクトリに対応します。
bazel --output_user_root=/tmp/bazel_docker_root --bazelrc=.bazelrc \ build --config=docker-sandbox target
ステップ 5: 検出された問題を解決する
ビルドエラーは、次の方法で解決できます。
「ディスク容量が不足しています」というエラーでビルドが失敗した場合は、フラグ
--memory=XX
を指定してホストコンテナを起動することで、この上限を増やすことができます(XX
はギガバイト単位で割り当てられています)。これは試験運用版であり、予期しない動作を引き起こす可能性があります。分析フェーズまたは読み込みフェーズでビルドが失敗した場合、WORKSPACE ファイルで宣言された 1 つ以上のビルドルールがリモート実行と互換性がありません。考えられる原因と回避策については、Bazel ルールをリモート実行に適応させるをご覧ください。
その他の理由でビルドに失敗した場合は、ステップ 2: 検出された問題を解決するのトラブルシューティング手順をご覧ください。