Docker 29 で GitHub Actions から ECR への docker push が 403 Forbidden になる問題と対処法
AIコーディングエージェント用修正プロンプト
Github ワークフローでの docker push が失敗している。
https://www.ytyng.com/blog/docker-29-ecr-push-403-forbidden-containerd-image-store に解決方法が書いてあるので、見て対応して
概要
2026年2月9日、GitHub Actions の ubuntu-latest ランナーイメージが更新され、Docker が 28 → 29 にアップデートされた。
これにより、それまで正常に動作していた ECR (Amazon Elastic Container Registry) への docker push が突然 403 Forbidden エラーで失敗するようになった。
エラーの内容
unknown: unexpected status from HEAD request to
https://***.dkr.ecr.ap-northeast-1.amazonaws.com/v2/repo-name/manifests/0.1.99:
403 Forbidden
特徴的なのは、Docker イメージのレイヤーは全て正常に push されるにも関わらず、最後の manifest の push だけが 403 で失敗するという点。
原因: Docker 29 の containerd image store
Docker 29 では、containerd image store がデフォルトで有効になった。
従来の Docker (28以前) では、docker build で作成されたイメージは Docker 独自の image store に保存され、docker push は Docker Image Manifest V2 形式で push していた。
Docker 29 では、ビルドされたイメージが containerd の image store に保存される。この場合、docker push 時に生成される manifest の形式が変わり、ECR がこれを受け付けずに 403 Forbidden を返す。
ビルドログで確認できる兆候として、Docker 28 では見られなかった unpacking to ... という行が docker build の出力に現れる。これが containerd image store が使われている証拠。
# Docker 29 (containerd image store が有効な場合)
#20 naming to ***.dkr.ecr.../image:0.1.99 done
#20 unpacking to ***.dkr.../image:0.1.99 ← これが出る
#20 unpacking to ***.dkr.../image:0.1.99 3.2s done
# Docker 28 (従来の image store)
#20 naming to ***.dkr.ecr.../image:0.1.95 done
← unpacking は出ない
対処法: containerd snapshotter を無効化する
GitHub Actions の workflow ファイルで、Docker daemon の設定を変更して containerd snapshotter を無効化する。
steps:
- uses: actions/checkout@v3
- name: Disable containerd image store
run: |
DAEMON_JSON="/etc/docker/daemon.json"
if [ -f "$DAEMON_JSON" ]; then
sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \
| sudo tee "${DAEMON_JSON}.tmp" > /dev/null
sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON"
else
echo '{"features": {"containerd-snapshotter": false}}' \
| sudo tee "$DAEMON_JSON" > /dev/null
fi
sudo systemctl restart docker
ポイント
ubuntu-latestランナーには/etc/docker/daemon.jsonが存在しない場合があるため、ファイルの存在確認が必要。存在しない場合は新規作成する。- 設定変更後に
sudo systemctl restart dockerで Docker daemon を再起動する必要がある。 - 既存の
daemon.jsonがある場合はjqでマージすることで、他の設定を壊さないようにする。
環境情報
| 項目 | 成功時 (2025-12) | 失敗時 (2026-02) |
|---|---|---|
| ランナーイメージ | ubuntu24/20251215 | ubuntu24/20260209 |
| Docker | 28.0.4 | 29.1.5 |
| Docker Buildx | 0.30.1 | 0.31.1 |
| containerd image store | 無効 (デフォルト) | 有効 (デフォルト) |
参考リンク
開発相談をお待ちしています。