VISASQ Dev Blog

ビザスク開発ブログ

アプリケーションのビルドを高速化した話

はじめに

こんにちは!基盤チームの高畑です。

最近異常なほど暑いですが、そんな中車のフロントガラスの油膜とりをしていたら軽度の熱中症のような感じになり久々に頭から水を被りました。 こんな暑さの中洗車とかするもんではありませんね、皆さんも熱中症にはくれぐれもお気をつけください。

ビザスクではアプリケーションのビルド・デプロイする際に Cloud Build を利用しています。これまで Cloud Build のなかで kaniko を利用してビルドを行ってきたのですが、なんと 2025/06/03 に Public Archive されてしまいました。

github.com

そこで、kaniko でのビルドをやめて buildx (BuildKit) / docker-container driver でのビルドに置き換えをし、その結果ビルド速度が改善したのでご紹介をしたいと思います。

kaniko ビルドの問題点

2020 年頃から、Cloud Build でレイヤーキャッシュを効かせるために kaniko を利用し始めましたが、

  • kaniko の設計上の問題からか multi-stage build の記述はできるが、実際には並列ビルドされない問題
  • サイズの大きいイメージをビルドしようとすると kaniko のメモリ消費量が増えて OOM Killer が走る時がある
  • 前述したとおり kaniko のリポジトリアーカイブされて今後アップデートやメンテナンスが行われなくなった
    • GCP 公式のドキュメントからも kaniko に関する記述が削除されつつある

といった問題が生まれてきました。

ビルド〜デプロイまでの時間に関しても、レイヤーキャッシュがうまく利用できている状態で 6〜8 分ほど、キャッシュが利用できなかった場合には 10 分を余裕で超えてくるといった状態でした。

  - id: BuildAppImages
    # see kaniko https://cloud.google.com/cloud-build/docs/kaniko-cache?hl=ja
    name: ${_CLOUD_BUILDER_KANIKO_IMAGE}
    args:
      - --cache=true
      - --cache-ttl=48h
      - --context=/workspace
      - --dockerfile=path/to/Dockerfile
      - --destination=${_APP_DOCKER_IMAGE_URL}:${TAG_NAME}
      - --destination=${_APP_DOCKER_IMAGE_URL}:latest
      - --build-arg=STAGE=${_STAGE}
      - --build-arg=PORT=${_PORT}
    volumes:
      - name: "ssh"
        path: /root/.ssh
    waitFor: ["-"]

docker buildx / docker-container driver への置き換え

標準で利用される driver は docker(Docker デーモンにバンドルされたもの) で、--cache-to のオプションが利用できず Artifact Registry へビルドキャッシュを保存する type=registry も利用できません。

Build drivers

docs.docker.com

そのため、buildx で docker-container driver を作成し、その後のビルドに利用をしています。

ビルドの際に docker build ではなく docker buildx build --push とすることで

  • docker buildx create --use で driver をいちいち指定せずとも良い
  • docker push でビルド済みイメージの push をしなくても良い

というメリットがありますが、生成されるビルドイメージがプラットフォームごとに生成されて見通しが良くないので docker build を利用しています(正直好みだとは思いますが)。

ビルド済みイメージ

steps:
...
  - id: SetupCustomDockerBuilder
    name: "docker"
    args:
      - buildx
      - create
      - --name=container
      - --driver=docker-container
    waitFor: ["-"]

  - id: BuildAppImages
    name: "docker"
    args:
      - build
      - --ssh=default=/root/.ssh/id_github
      - --cache-to=type=registry,ref=${_APP_DOCKER_IMAGE_URL}:cache,mode=max
      - --cache-from=type=registry,ref=${_APP_DOCKER_IMAGE_URL}:cache
      - --builder=container
      - --build-arg=STAGE=${_STAGE}
      - --build-arg=PORT=${_PORT}
      - --tag=${_APP_DOCKER_IMAGE_URL}:latest
      - --tag=${_APP_DOCKER_IMAGE_URL}:${TAG_NAME}
      - --file=/path/to/Dockerfile
      - --load
      - .
    volumes:
      - name: "ssh"
        path: /root/.ssh
    waitFor:
      - SetupCustomDockerBuilder

  - id: PushAppImages
    name: "docker"
    args:
      - push
      - -a
      - ${_APP_DOCKER_IMAGE_URL}
    waitFor:
      - BuildAppImages
...

また、上記以外にも

  • 利用できるステップでは gcr.io/cloud-builders/* のイメージを積極的に利用する
    • これにより、ベースイメージの pull 時間が無くなる
    • gcr.io/cloud-builders/docker を利用したかったのですが、含まれる docker のバージョンが結構遅れていて --cache-to/from のオプションが利用できなかったため docker のイメージを指定しています
  • これまで Secret Manager から機密情報を取得する際に gcloud コマンドを利用していたところを Cloud Build の標準機能での取得に置き換える
  • ビルドマシンタイプの変更

などの細かい調整を行っています。

結果

これらの変更により、アプリケーションのビルドがキャッシュが効いていない状態で 3 分程度、キャッシュが効いている状態で 1 分程度になりました。

その他のビルドステップ(コンテナのデプロイまで含め)全体で見ても、3 分前後で完了するまでに速度改善がされました。

置き換え後

ビルド時間

おわりに

いかがでしたでしょうか。アプリケーションのビルド時間は開発生産性に大きく関与していくることでもあり、高速化が図れてとても良かったと思っています。

ぜひ皆さんも同じような問題を抱えていたら参考になると幸いです!

ビザスクではエンジニアの仲間を募集しています! 少しでもビザスク開発組織にご興味を持たれた方は、ぜひ一度カジュアルにお話ししましょう! developer-recruit.visasq.works