Slide 1

Slide 1 text

マルチアーキテクチャ対応の コンテナイメージを ちゃんと理解して使いこなす 株式会社 WFS 駒﨑 拓斗

Slide 2

Slide 2 text

駒﨑 拓斗 組み込みソフトウェア開発会社を経て 2012 年にグリー株式会社 (現:グリーホールディングス株式会社)へ入社。開発基盤やクラ ウドインフラの構築、運用に横断的に携わる。 2023 年からは株式会社WFS にて『アナザーエデン』『ヘブン バーンズレッド』のバックエンド、運用基盤の開発に従事。 株式会社 WFS リードエンジニア 2

Slide 3

Slide 3 text

アジェンダ ● 背景 ● コンテナイメージのマルチアーキテクチャ対応とは ● マルチアーキテクチャ対応のためのビルド実例 3

Slide 4

Slide 4 text

背景 : 身近になった ARM アーキテクチャ ● x86 中心だったサーバサイドでも ARM が広がりを見せている ● AWS, Google Cloud での身近な ARM トピック ○ 2018/11 AWS re:Invent にて ARM ベースプロセッサ Graviton 発表 ○ 2020/06 AWS Tokyo リージョンで Graviton2 が利用可能に ○ 2023/02 AWS Tokyo リージョンで Graviton3 が利用可能に ○ 2024/12 AWS Tokyo リージョンで Graviton4 が利用可能に ○ 2024/04 Google Cloud Next にて ARM ベースプロセッサ Axion 発表 ○ 2025/春頃 Tokyo リージョン GKE で Axion ベース VM ノードが利用可能に 4

Slide 5

Slide 5 text

背景 : 身近になった ARM アーキテクチャ ● ARM PC の普及 ○ サーバサイド & ローカル PC で同じイメージをエミュレーションなしで実行したい ○ Apple silicon Mac での将来的な x86 エミュレーション提供の不透明さ ● x86 / ARM どちらでも利用可能なコンテナイメージが求められる 5 Single-platform images Multi-platform image

Slide 6

Slide 6 text

WFS サーバサイド開発の CPU 近況 ● 開発者 PC ○ Mac (Apple silicon) & Windows (Intel & AMD) 混在 ● 現行ゲームサービスのゲーム API サーバ ○ 基本的に x86_64 のみ ● 非ゲーム API サーバ、開発環境 ○ x86_64 & ARM 混在 ● 新規開発向けゲームサーバ ○ x86_64 & ARM 混在 6

Slide 7

Slide 7 text

ただし書き ● マルチアーキテクチャとは題しつつも ○ x86_64, ARM の 2つを対象にして話します ■ x86_64 はコード中で amd64 と記載するケースがあります ● 本スライド中では基本的に同義です ■ ARM はコード中で arm64 と記載するケースがあります ○ 他のアーキテクチャについても外れる話ではないです ● コンテナは Linux コンテナのみを扱います 7

Slide 8

Slide 8 text

ところで? それぞれの矢印でどんなコンテナイメージがやりとりされている? 8 $ docker pull \ hello-world:latest ARM PC x86 PC $ docker pull \ hello-world:latest $ docker tag \ hello-world:latest \ foobar/hello-world:latest $ docker push \ foobar/hello-world:latest foobar server (registry) ??

Slide 9

Slide 9 text

コンテナイメージの マルチアーキテクチャ対応とはなにか 9

Slide 10

Slide 10 text

マルチアーキテクチャ対応のコンテナイメージとは それぞれのアーキテクチャ向けのイメージへの参照が列挙されている イメージインデックス (マニフェストリストとも) 10 https://docs.docker.com/build/building/multi-platform/

Slide 11

Slide 11 text

コンテナイメージの構造 ● OCI (Open Container Initiative) イメージフォーマット仕様にしたがう ○ マニフェストおよびファイルシステムレイ ヤー、コンフィグ等によって構成されるこ とを規定する仕様 11 https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md https://github.com/opencontainers/image-spec/blob/v1.1.1/spec.md ● ファイルとして出力する際の仕様もある => OCI イメージレイアウト仕様 ● docker image save などで出力可能 ○ 例 docker image save alpine:latest | tar xf -C dir/ blobs/ sha256/ ... index.json oci-layout

Slide 12

Slide 12 text

レジストリ コンテナイメージの構造 (デフォルメ) イメージの名前は何を指すか? 通常は以下のどちらかを参照して使っている ● ファイル実体を持ち実行可能なもの ● メタデータだけを持ち、 そこから実行可能なイメージを参照するもの 12 実行可能なイメージ ファイルシステム メタデータ (image.manifest) インデックス メタデータ (image.index) 実行可能なイメージ ファイルシステム メタデータ (image.manifest) 実行可能なイメージ ファイルシステム メタデータ (image.manifest) インデックス メタデータ (image.index) 実行可能なイメージ ファイルシステム メタデータ (image.manifest) ※ いずれも仕様上は広義のイメージですが、 本スライドでは前者をイメージ、 後者をインデックスと呼ぶようにします

Slide 13

Slide 13 text

マルチアーキテクチャ対応するには ● 各アーキテクチャ向けのイメージを作成 ● イメージインデックスを作成 ○ manifests にそれぞれへの参照を含める ■ platform ごと ○ ユーザに参照してもらうためのタグをつける (latest, v2, 1.2.3-alpine, etc.) 13 { "mediaType": "application/vnd.oci. image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.oci. image.manifest.v1+json", "digest": "sha256:", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:", "platform": { "architecture": "arm64", "os": "linux", "variant": "v8" } } ] } インデックス メタデータ (image.index) ... ... $ docker pull \ hello-world:latest tags: latest

Slide 14

Slide 14 text

基本的なコマンドを使った作りかた ● 各アーキテクチャ向けのイメージを作成し push ○ ( 図をいれる ) ○ ( レジストリの状態の画像 ) ○ ○ ○ ● イメージインデックスを作成 14 # ARM ホストで $ docker build . \ -t someregistry/myapp:0.1.0-arm64 $ docker push \ someregistry/myapp:0.1.0-arm64 # x86_64 ホストで $ docker build . \ -t someregistry/myapp:0.1.0-amd64 $ docker push \ someregistry/myapp:0.1.0-amd64 # Usage: docker manifest create MANIFEST_LIST MANIFEST [MANIFEST...] $ docker manifest create \ someregistry/myapp:0.1.0 \ someregistry/myapp:0.1.0-arm64 \ someregistry/myapp:0.1.0-amd64

Slide 15

Slide 15 text

基本的なコマンドを使った作りかた 15

Slide 16

Slide 16 text

より便利なコマンド ● 実用的にはもっとイージーに作成可能 ● 例 : docker buildx ○ 各アーキテクチャ向けにビルドしてインデックス作成し push ○ 内容確認 16 $ docker buildx build . \ --platform=linux/amd64,linux/arm64 \ -t someregistry/myapp:0.2.0 \ --push $ docker buildx imagetools inspect someregistry/myapp:0.2.0 Name: someregistry/myapp:0.2.0 MediaType: application/vnd.oci.image.index.v1+json Digest: sha256:c86a1c628af0e47bf09b4c2ad49c68797fa7908822fc16c284f8a52ecf6a2f9c Manifests: Name: someregistry/myapp:0.2.0@sha256:8c8aa16... MediaType: application/vnd.oci.image.manifest.v1+json Platform: linux/amd64 Name: someregistry/myapp:0.2.0@sha256:7aded20... MediaType: application/vnd.oci.image.manifest.v1+json Platform: linux/arm64 ...

Slide 17

Slide 17 text

※ 注: build の挙動が異なる場合があります ● 前述の docker コマンドによるビルド出力は環境により異なります ○ 2025/09 現在、Docker Desktop では自動的にイメージインデックス+イメージのビルド 結果が得られます (設定依存) ■ その場合に単一のイメージとしてビルドするには 17 $ docker build . \ --provenance=false \ -t someregistry/myapp:0.1.0-arm64

Slide 18

Slide 18 text

※ 注: イメージインデックス非対応の環境もあります ● コンテナ実行環境によってはインデックス経由の参照に非対応 ● AWS Lambda をコンテナイメージで動かす場合 ○ 単一イメージにのみ対応 ( 2025/09 現在 ) https://docs.aws.amazon.com/lambda/latest/dg/nodejs-image.html 18

Slide 19

Slide 19 text

中間まとめ ● コンテナイメージのマルチアーキテクチャ対応は、 各アーキテクチャごとのイメージをたばねた イメージインデックス(マニフェストリスト) によって実現される 19

Slide 20

Slide 20 text

ビルド実例 20

Slide 21

Slide 21 text

アーキテクチャ別イメージをどのようにビルドするか 選択肢 ● 単一ホスト上でエミュレーションしてビルド ○ まずはこれを検討 ● アーキテクチャ別にホストを用意してビルド ○ エミュレーション環境利用が困難、またはビルド時間に問題があれば ● クロスコンパイルによるバイナリ生成 ○ (本発表では割愛 ) golang シングルバイナリのイメージ等 21

Slide 22

Slide 22 text

エミュレーションによるビルド ローカル PC の例 ※一時的な作業や検証向けに。 Docker Desktop, Podman Desktop : デフォルトでエミュレーション利用可能 docker-ce : QEMU, buildx-plugin の導入で利用可能 22 $ docker buildx build . \ --platform=linux/amd64,linux/arm64 \ -t someregistry/myapp:0.3.0 \ --push $ podman build . \ --platform=linux/amd64,linux/arm64 \ --manifest someregistry/myapp:0.3.0 \ $ podman manifest push \ someregistry/myapp:0.3.0

Slide 23

Slide 23 text

エミュレーションによるビルド GitHub Actions の例 標準 GitHub Hosted ランナーで setup actions を利用 管理コストも低く、広く使われてい ると思われる 23 jobs: build: runs-on: ubuntu-latest steps: ... - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 ... - name: Build and push uses: docker/build-push-action@v6 with: platforms: linux/amd64,linux/arm64 push: true tags: xxx

Slide 24

Slide 24 text

エミュレーションよしあし ● ビルド環境、ワークフローの管理が簡単 ● 計算コストが高い場合にパフォーマンス悪化が顕著 ○ 問題となった事例: PHP gRPC 拡張のインストール ■ もともと時間のかかる処理だったが QEMU 環境でより顕著に ■ GitHub Actions, on: ubuntu-latest (x86) ● Build linux/amd64: 約10分~ ● Build linux/arm64: 約250分~ 24 RUN ... && pecl install grpc-1.x.x 関連: 弊社 藤田によるブログ記事 Github ActionsでCloud Spanner対応のPHPイメージをビルドするための工夫|株式会社 WFS https://note.com/wfs_blog/n/na6adcf9c454f

Slide 25

Slide 25 text

アーキテクチャごとに別ホストでビルド docker buildx の例 ● builder にリモートホストを登録可能 ● 対象アーキテクチャごとに 使ってほしいホストを指定する ● push する場合はリモートから registry に疎通可能である必要あり ● ローカル書き出しは非サポート (2025/09 現在) 25 $ docker buildx create \ --name multi-node-builder \ --node local \ --platform linux/arm64,linux/arm $ docker buildx create \ --name multi-node-builder \ --append \ --node remote-x86 \ --platform linux/amd64,linux/386 \ ssh://remote-builder-host $ docker buildx use multi-node-builder $ docker buildx build . \ --platform=linux/amd64,linux/arm64 \ -t someregistry/myapp:0.3.0 \ --push

Slide 26

Slide 26 text

アーキテクチャごとに別ホストでビルド GitHub Actions の例 ● x86 用は標準ランナーで ● ARM 用には Self-Hosted ランナー or GitHub Hosted ランナー を使う ● GitHub Hosted ランナーは制限あり ○ public レポ ○ Enterprise or Team プラン ■ org 毎に Large Runner として明示的に追加 ● それぞれのビルド後に イメージインデックスを作成する ○ docker buildx imagetools create \ xxx:latest-amd64 \ xxx:latest-arm64 \ --tag xxx:latest 26 jobs: build-x86: runs-on: ubuntu-latest steps: ... - name: Build amd64 uses: docker/build-push-action@v6 with: platforms: linux/amd64 push: true tags: xxx:latest-amd64 build-arm: # Self-hosted runner または org で Large Runner 登録 runs-on: ubuntu-your-arm-runner steps: ... - name: Build arm64 uses: docker/build-push-action@v6 with: platforms: linux/arm64 push: true tags: xxx:latest-arm64

Slide 27

Slide 27 text

アーキテクチャごとに別ホストでビルド GitHub Actions から AWS CodeBuildの例 ● runs-on: codebuild- で AWS CodeBuild をランナーとして利用可能 27 jobs: build-codebuild-x86: runs-on: codebuild-my-x86-prj-${{ github.run_id }}-${{ github.run_attempt }} steps: ... build-codebuild-arm: runs-on: codebuild-my-arm-prj-${{ github.run_id }}-${{ github.run_attempt }} steps: ... --- # または jobs: build-codebuild: runs-on: - codebuild-my-prj-${{ github.run_id }}-${{ github.run_attempt }} image: arm-3.0 instance-size: small steps: ...

Slide 28

Slide 28 text

アーキテクチャごとに別ホストでビルド AWS CodePipeline + CodeBuild の例 ● イメージビルド用とインデックス用の CodeBuild プロジェクトと buildspec を用意 ● AWS のマネージド機能で完結可能 28

Slide 29

Slide 29 text

まとめ ● コンテナイメージのマルチアーキテクチャ対応 ○ 各アーキテクチャごとのイメージをたばねた イメージインデックス(マニフェストリスト) によって実現される ● アーキテクチャの異なるイメージをビルドするには ○ エミュレーション or ○ ネイティブ環境でそれぞれビルドし、インデックスで束ねる ● GitHub Actions, AWS を中心とした CI 例の紹介 ○ 基本手順は同じ ■ イメージ作成 => インデックス作成 29

Slide 30

Slide 30 text

ご清聴ありがとうございました 30

Slide 31

Slide 31 text

No content