CircleCI 上で aws-ecr Orb を使った docker build がコケて悩んだ話

こんにちは、 フォーカセル開発チーム所属の id:hano_tea です。

弊チームではアプリケーションを AWS ECR, ECS を利用して稼働させており、デプロイには CircleCI を利用しているのですが、 先日 CircleCI 周りの設定を見直した際に謎のエラーが発生、ビルドがコケて少しハマってしまいました :sob:

エラーメッセージから原因の特定がやや難しいタイプの問題で、同様の現象に遭遇したという記事、情報も特に見当たらなかったため、 記事として原因と対応方法を書き留めておこうと思います。

TL;DR

  • aws-ecr Orb v8 から Multi-arch build がサポートされ、 docker buildx が使われるようになりました
  • 環境によって docker buildx が使えないことがあり、その場合分かりづらいエラーを吐いてビルドがコケます
  • circleci は古いイメージなので cimg リポジトリのイメージを使うようにしましょう

発生した現象

一言で言うと、「aws-ecr Orb のバージョンを v6.12.2 から v8.2.1 に上げたらビルドが変なコケ方をするようになった」です。

改修前の設定

改修前の .circleci/config.yml は以下のような状態になっていました。 (必要最低限の設定だけにしたものを掲載しています)

version: 2.1

orbs:
  aws-ecr: circleci/aws-ecr@6.12.2

jobs:
  build-image:
    docker:
      - image: circleci/golang:1.17.2
    steps:
      - checkout
      - setup_remote_docker
      - aws-ecr/build-and-push-image:
          repo: "invalid-ecr-build-sample"

workflows:
  main:
    jobs:
      - build-image:
          context: 
            - test

設定内容をざっくりまとめると、

  • aws-ecr Orb のバージョンは 6.12.2
  • 実行環境は Docker, circleci/golang:1.17.2
  • aws-ecr/build-and-push-image コマンドで Docker イメージをビルド、プッシュする

という感じになっています。

当然ですが、こちらの設定は改修前にデプロイに利用していたため、特に問題なくビルドが通ります。

ビルドがコケた設定

上述の設定に対し、 aws-ecr Orb のバージョンアップをするような以下の修正を加えました。

diff --git a/.circleci/config.yml b/.circleci/config.yml
index aa4031d..b306256 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,7 +1,7 @@
 version: 2.1
 
 orbs:
-  aws-ecr: circleci/aws-ecr@6.12.2
+  aws-ecr: circleci/aws-ecr@8.2.1
 
 jobs:
   build-image:

この状態で CI を走らせると aws-ecr/build-and-push-image が以下のようなエラーを出してコケます。 (全部書くと量が多いので一部抜粋)

...(前略)...

+ docker buildx build -f ./Dockerfile -t *************************************************/invalid-ecr-build-sample:latest --platform linux/amd64 --progress plain --push .
unknown shorthand flag: 'f' in -f
See 'docker --help'.

Usage:  docker [OPTIONS] COMMAND

...(中略)...

Exited with code exit status 125
CircleCI received exit code 125

unknown shorthand flag: 'f' in -f というエラーメッセージが出ています。 f フラグがない?というイマイチよく分からないエラーです。

当然ながら docker build でも docker buildx build でも -f フラグは存在し、 Docker ファイルを指定するためのものになっているので、 f フラグが無いと言われても…としばらく途方に暮れていました。

解決策

様々な調査を経て、結局以下のようにすれば良いということがわかりました。

diff --git a/.circleci/config.yml b/.circleci/config.yml
index aa4031d..f1fe0c4 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,12 +1,12 @@
 version: 2.1
 
 orbs:
-  aws-ecr: circleci/aws-ecr@6.12.2
+  aws-ecr: circleci/aws-ecr@8.2.1
 
 jobs:
   build-image:
     docker:
-      - image: circleci/golang:1.17.2
+      - image: cimg/go:1.17.2
     steps:
       - checkout
       - setup_remote_docker

何が変わったかというと、「実行環境となる Docker イメージ」が変わっています。

元々 circleci リポジトリの Go 用イメージを使っていましたが、 それを cimg リポジトリの Go 用イメージを使うようにしています。

原因

ざっくり言うと、

という2つが組み合わさった結果発生したものでした。

CircleCI の docker image と buildx

CircleCI 上で buildx を使う際の資料としては以下の公式ブログ記事がありました。

https://support.circleci.com/hc/ja/articles/360058095471-Remote-Docker-%E3%81%A7-Buildx-%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E3%81%84

色々書いてありますが、記事の末尾あたりに以下のような記述があります。

もし、私たちの cimg イメージ以外の docker イメージを使用している場合は、そのイメージ内で buildx が使用可能であることを確認する必要があることに注意してください。

buildx を使う場合は cimg 系のイメージを使うか、あるいは buildx が使えることがわかっているイメージを使わないと今回と同じようにハマる可能性が高そうです。

同じ CircleCI 公式イメージではありますが、 circleci 系イメージだと buildx は対応していなさそうなので注意しましょう。

ちなみに cimg は2020年初め頃に出た次世代イメージと呼ばれているもので、 circleci はそれ以前からある古いイメージです。

https://circleci.com/blog/announcing-our-next-generation-convenience-images-smaller-faster-more-deterministic/

今わざわざ circleci 系イメージを新規に使う理由はおそらく無いので、特段の事情がなければ cimg を使うのが良さそうです。

まとめ

というわけで、 aws-ecr Orb をアップデートしたら謎エラーが発生してハマったというお話でした。

原因自体は分かってしまえば簡単な話…でしたが、エラーメッセージから原因を推測するのが難しく、調査に結構な時間を使ってしまったのが辛いところです……


アプリケーションで使っているライブラリ、言語のバージョンアップは意識しやすいですが、 CI 上の環境についても日頃から意識して、こまめなメンテナンスやアップデートをしていかなければ…と思う出来事でした。