5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ubuntu-latest が 26.04 になったら、ECS(arm64)がイメージを pull できなくなった話

5
Last updated at Posted at 2026-11-05

はじめに

GMOコネクトの小倉です。

依存ライブラリを更新する PR をマージしたら、ECS の新しいタスクが起動しなくなりました。アプリのコードも Dockerfile も、ビルドの手順も変えていないのに、です😇

調べてみると、GitHub Actions の ubuntu-latest が 24.04 から 26.04 に切り替わって Docker が 29 になり、push されるイメージに「amd64 用」と記録されるようになったのが原因でした。

原因の特定と、2行で済んだ対処の記録です。

まとめ

  • ランナーが ubuntu-26.04 になり、Docker が 28 から 29 に上がった。push されるイメージが manifest list(複数のイメージをまとめる目次)形式になり、ランナーと同じ linux/amd64 として登録されるようになった
  • 中身は arm64 のバイナリなのに、ECS(arm64)は「arm64 用が見つからない」と判断して pull に失敗する
  • docker build --platform linux/arm64 と、builder の FROM --platform=$BUILDPLATFORM の2行で解消

構成

GitHub Actions(ubuntu-latest / amd64 のランナー)
  └─ docker build → ECR に push
       └─ ECS(arm64)がイメージを pull して起動

Dockerfile はマルチステージです。builder で Go を arm64 向けにクロスコンパイルし、最終ステージは distroless の arm64 イメージにバイナリを載せるだけです。

FROM golang:1.26 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o app .

FROM gcr.io/distroless/static-debian12:latest-arm64
COPY --from=builder /app/app /app
CMD ["/app"]

workflow 側は、プラットフォームを指定せずに docker build して docker push しているだけでした。

- run: |
    docker build -t <registry>/<repo>:<tag> .
    docker push <registry>/<repo>:<tag>

発生した事象

新しいイメージでタスクを起動しようとすると、ECS が次のエラーで止まりました。

CannotPullContainerError: pull image manifest has been retried 7 time(s):
image Manifest does not contain descriptor matching platform 'linux/arm64 v8'

イメージの中に、linux/arm64 向けの情報(descriptor)が見つからないというエラーです。バイナリは arm64 向けにビルドしているので、最初は意味がわかりませんでした。

原因の特定

成功したときと失敗したときの Actions ログを比べる

前回成功したビルドと今回のビルドで、GitHub Actions のログを比べました。

項目 前回(成功) 今回(失敗)
ランナーのイメージ ubuntu-24.04 ubuntu-26.04
Docker 28.0.4 29.4.2
push の出力 manifest(size 3022) manifest list(size 856)
ビルドログ manifest list の出力なし exporting attestation manifest / exporting manifest list が出る

ワークフローは runs-on: ubuntu-latest のままです。変わったのはランナーのイメージでした。GitHub は ubuntu-latest を 2026年10月19日から11月19日にかけて、24.04 から 26.04 へ段階的に切り替えています(GitHub Changelog)。

manifest list になったのは Docker 29 のイメージストアのため

ランナーに入っている Docker は、24.04 が 28.0.4、26.04 が 29.4.2 です(runner-images の Ubuntu 24.04 と Ubuntu 26.04 の Readme)。Docker 29 からは、新規インストールでは containerd イメージストアが既定になりました。

The containerd image store is the default storage backend for Docker Engine 29.0 and later on fresh installations.

containerd image store with Docker Engine

従来のイメージストアは manifest list(Image Index)を扱えません。そのため前回は manifest が1つ push されるだけで、プラットフォームは記録されていませんでした。照合する一覧がないので、ECS はそのまま pull できていました。中身が arm64 なので、起動もできていました。

containerd イメージストアでは、ビルドの来歴情報(attestation)が付き、manifest list 形式で push されます。ビルドは amd64 向けとして実行されていたので(InvalidBaseImagePlatform の警告を参照)、manifest list にはランナーと同じ linux/amd64 として登録されたと考えられます。ECS は manifest list の中から linux/arm64 を探し、見つからずに失敗します。

実は前から警告が出ていた

前回の成功したビルドにも、次の警告が出ていました。

InvalidBaseImagePlatform: Base image gcr.io/distroless/static-debian12:latest-arm64
was pulled with platform "linux/arm64", expected "linux/amd64" for current build

ビルドそのものは amd64 向けとして実行され、最終ステージのベースだけが arm64 だった、という意味です。従来のイメージストアでプラットフォームが記録されなかったので、たまたま動いていただけでした。

対処法

2行の修正

直すのは2か所です。workflow でビルド対象のプラットフォームを指定し、Dockerfile の builder はランナー本来のプラットフォームで動かします。

- docker build -t <registry>/<repo>:<tag> .
+ docker build --platform linux/arm64 -t <registry>/<repo>:<tag> .
- FROM golang:1.26 AS builder
+ FROM --platform=$BUILDPLATFORM golang:1.26 AS builder

$BUILDPLATFORM は、ビルドを実行しているマシン(ここでは amd64 のランナー)のプラットフォームを表す BuildKit の変数です。

これでイメージは linux/arm64 向けとしてビルドされ、ECS(arm64)が pull してタスクを起動できるようになりました。

2行はセットで必要

--platform linux/arm64 だけを付けると、builder も arm64 として動きます。amd64 のランナー上で arm64 の go build を動かすにはエミュレーション(QEMU)が必要で、用意していないランナーではビルドが失敗します。

Go はもともと GOARCH=arm64 でクロスコンパイルしているので、builder は amd64 のまま動かせば十分です。最終ステージには RUN がないので、エミュレーションは一度も発生しません。

runs-on: ubuntu-24.04 に固定する案は採らなかった

比較 ubuntu-24.04 に固定 プラットフォームを明示
修正量 1行 2行
正しいイメージになるか ならない(以前と同じく、たまたま pull できる状態) なる(linux/arm64 向けにビルドされる)
ランナーの廃止後 また壊れる 影響なし
警告 出続ける 解消

固定すれば、すぐに元の状態へ戻せます。ただ、24.04 のランナーが廃止された時点でまた壊れます。そこで、プラットフォームを明示する方を選びました。

教訓

  • ubuntu-latest は、ワークフローを変えなくても中身が変わる。Docker のメジャーバージョンも上がる
  • InvalidBaseImagePlatform の警告は、動いているうちに潰しておく
  • ビルドするマシンと動かすマシンのアーキテクチャが違うなら、--platform で明示する
  • マルチステージのビルドでは、builder を $BUILDPLATFORM で動かしてクロスコンパイルに任せる

最後に

ご一読いただき、ありがとうございました。

弊社では、AWSを使ったサービスの開発や技術支援をはじめ、幅広い支援を行っておりますので、何かありましたらお気軽にお問合せください。

お問合せ: https://gmo-connect.jp/contactus/

5
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?