
はじめに
GitHub Actionsを使ってマルチアーキテクチャ(x86_64とarm64)のDockerコンテナイメージをビルドする際、無料枠のGitHubランナーだけでは効率的に処理できない問題に直面しました。特にARM64向けのビルドが大きなボトルネックとなっていましたが、Ubicloudの自前ランナーを導入することで劇的に改善できたので、その方法を共有します。
問題: QEMUを使ったクロスビルドの限界
これまで私は、matrixを用いて並行ビルドを実施していました。GitHub Actionsの無料枠では x86_64(amd64)のランナーしか提供されていないため、arm64向けのDockerイメージビルドには QEMU を使ったクロスビルドを行っていました。
しかし、ISC Keaのイメージをビルドする場合、amd64は20分程度で完了する一方、arm64は2時間以上かかってしまい、GitHub Actionsのランナー無料枠を急速に消費してしまう状況でした(もちろん私のDockerfileに改善の余地があるかもしれません)。
解決策: Ubicloudの自前ランナーを導入
そこで、GitHub Actionsの無料枠に頼らず、自前のランナーを用意してamd64とarm64のDockerイメージを効率的に作成することにしました。AWS CodeBuildやBuildjetなどのサービスも検討しましたが、価格面で優位だったUbicloudを採用することにしました。
Ubicloudとは?
Ubicloudは「オープンで自由、ポータブルなクラウド」を標榜するサービスです。公式サイトには以下のように説明されています:
※なお、本記事ではUbicloudの登録作業やGitHub Actionsとの連携設定などの基本セットアップについては割愛します。詳細は公式ドキュメントをご参照ください。
Ubicloudは、オープンで自由、そしてポータブルなクラウドです。Linux が独自OSに対するオルタナティブであるように、パブリッククラウドプロバイダーに対するオルタナティブと考えてください。
UbicloudはHetzner、Leaseweb、Latitude.shなどのベアメタルインスタンスをリースするプロバイダー上でインフラストラクチャー・アズ・ア・サービス(IaaS)機能を提供します。マネージドサービスとしても利用可能です。
マネージドサービスで使用するベアメタルインスタンスの低コストにより、私たちはその低価格をお客様に還元し、クラウドコストを3〜10倍削減できます。
重要なポイントとして、Ubicloudは GitHub Actions との連携もサポートしています。詳細は公式ドキュメントで確認できます。
Ubicloudの料金体系
Ubicloudの料金体系は以下の通りです:
Linux x64
YAML runner tag | vCPU | Memory | Price |
---|---|---|---|
ubicloud-standard-2 | 2 | 8GB | $0.0008/min |
ubicloud-standard-4 | 4 | 16GB | $0.0016/min |
ubicloud-standard-8 | 8 | 32GB | $0.0032/min |
ubicloud-standard-16 | 16 | 64GB | $0.0064/min |
ubicloud-standard-30 | 30 | 120GB | $0.0120/min |
Linux arm64
YAML runner tag | vCPU | Memory | Price |
---|---|---|---|
ubicloud-standard-2-arm | 2 | 6GB | $0.0008/min |
ubicloud-standard-4-arm | 4 | 12GB | $0.0016/min |
ubicloud-standard-8-arm | 8 | 24GB | $0.0032/min |
ubicloud-standard-16-arm | 16 | 48GB | $0.0064/min |
ubicloud-standard-30-arm | 30 | 90GB | $0.0120/min |
今回のarm64ビルド用に、デフォルトの ubicloud-standard-2-arm
を選択しました。
GitHub Actionsワークフローの変更点
ワークフローファイルの主な変更点は以下の2つです:
- ランナーの条件分岐:
runs-on: ${{ matrix.platform == 'linux/amd64' && 'ubuntu-latest' || 'ubicloud-standard-2-arm' }}
- matrix.platformが
linux/amd64
の場合はubuntu-latest
を使用 - それ以外(arm64の場合)は
ubicloud-standard-2-arm
を使用
- matrix.platformが
- QEMUセットアップの条件付き実行:
- name: Set up QEMU if: matrix.platform == 'linux/arm64' && runner.arch == 'X64' uses: docker/[email protected]
- amd64ランナーでarm64イメージをビルドする場合にのみQEMUをセットアップ
- Ubicloudの ARM runnerを使う場合は、ネイティブarm64環境なのでQEMUは不要
- uses: docker/build-push-action@v6
のキャッシュ部分を公式ドキュメント通りに修正:
変更差分
diff -ur .github/workflows/docker-build.yml.20250326 .github/workflows/docker-build.yml
--- .github/workflows/docker-build.yml.20250326 2025-03-27 21:48:36.859477231 +0900
+++ .github/workflows/docker-build.yml 2025-03-27 22:56:05.274661165 +0900
@@ -63,12 +63,12 @@
build:
needs: prepare
if: needs.prepare.outputs.directories != '[]'
- runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform: [linux/amd64, linux/arm64]
directory: ${{ fromJson(needs.prepare.outputs.directories) }}
+ runs-on: ${{ matrix.platform == 'linux/amd64' && 'ubuntu-latest' || 'ubicloud-standard-2-arm' }}
steps:
- name: Checkout repository
@@ -103,7 +103,10 @@
echo "suffix=arm64" >> $GITHUB_OUTPUT
fi
+ # QEMU setup is only needed for AMD64 runners building ARM64 images
+ # For native ARM64 runners, we can skip this step
- name: Set up QEMU
+ if: matrix.platform == 'linux/arm64' && runner.arch == 'X64'
uses: docker/[email protected]
with:
image: tonistiigi/binfmt:qemu-v8.1.5
@@ -133,7 +136,7 @@
build-args: |
VERSION=${{ steps.set-version.outputs.release_version }}
cache-from: type=gha
- cache-to: type=gha,mode=max
+ cache-to: type=gha
outputs: type=image,name=${{ secrets.DOCKER_USERNAME }}/${{ steps.image-name.outputs.image_name }},push-by-digest=true,name-canonical=true
- name: Export digest
なお、QEMU関連の設定はやや冗長なので、より単純化することも可能です。
ubicloudにてrunnerが起動したことを確認

結果と費用対効果
実際に実行してみた結果:
- QEMUでのクロスビルド: 2時間以上
- Ubicloudネイティブランナー: 約40分
大幅な時間短縮に成功しました!

費用面では、80分ほど利用して(1回目の実行が失敗したのは内緒です)約0.07ドル(日本円で約10円)の支出でした。GitHub Actionsの無料枠の消費を抑えつつ、ビルド時間も短縮できるため、非常に費用対効果が高いと言えます。
まとめ
GitHub ActionsでマルチアーキテクチャのDockerイメージをビルドする際、特にarm64向けビルドではUbicloudの自前ランナーを活用することで、ビルド時間を大幅に短縮でき、かつコストも抑えられることがわかりました。
私個人のISC Keaのイメージビルドでは、2時間以上かかっていた処理が40分程度に短縮され、費用も非常に安価で済みました。GitHub Actionsでコンテナイメージのクロスビルドをする際、特にarm64のビルド時間が長くなりがちな場合に、GitHub Actionsの無料枠を使い切ってしまう前に自前ランナーに切り替えることで、ビルド時間を大幅に短縮しつつ、課金額も最小限に抑えられるため、ビルドの高速化と費用のバランスを取りたい方には特におすすめの方法です。
追記:2025/04/01
今更ながら2025年1月16日に組織以外で、パブリックなレポジトリであれば使用できるarm64なrunnerがGithubから出ていたみたいです。