Beeeat’s log

Beeeat’s log

プログラミングで出くわした知識やツール、日常生活、働き方その他色々なことをメモしていくブログ

「CodeBuild に用意されている Docker イメージ」で AWS CodeBuild 上での docker-compose のインストール作業を省略する

この記事は マイナビ Advent Calendar 2020 の6日目の記事です. 昨日は @task4233 さんの YubiKeyの技術検証を任されたので, 検証用のデモサーバを実装した話 でした. YubiKey があるとより安全になるし,シュッと使えるとなんかカッコいい感じありますよね.


現在関わっているプロダクトでは AWS CodeBuild(以下,CodeBuild) をCI環境として利用し,約1年半が経ちました.

その運用の中で突然動かなくなり,復旧するように修正することが何回かありました.

その復旧作業の中で出てきた改善案の1つとして AWS CodeBuild で docker-compose をインストールする作業があるのですが,今回はそのインストール作業を省略させ,CI環境としてより安定し,実行時間が短縮した話についてまとめようと思います.

改善前の状態

改善前の構成や AWS CodeBuild を導入した話についての詳細はこちらにまとめています🔽.

bake0937.hatenablog.com

上記の記事にある通り改善前は AWS CodeBuild で利用するDockerイメージとして DockerHub にあるdocker/dindという Docker in Docker に対応したDockerイメージで docker-compose をインストールし,テストの実行に必要なDockerイメージをプルしていました.

hub.docker.com

buildspec.ymlとしては以下のような感じです.

version: 0.2
phases:
  install:
    commands:
      - echo install started on `date`
      - apk update
      - apk add --no-cache gcc build-base libffi-dev py-pip python-dev libressl-dev
      - pip install docker-compose
      - docker-compose version
      - pip install awscli && \
      - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay&
      - timeout 15 sh -c "until docker info; do echo .; sleep 1; done"
  pre_build:
    commands:
      - echo pre_build started on `date`
      - echo Logging in to Amazon ECR...
# ↓ここからテストの実行に必要なDockerイメージを ECR からプルする処理やテスト実行の処理が続く
・・・・・・・・・・・

しかし,7行目にあるapk add --no-cache gcc build-base libffi-dev py-pip python-dev libressl-devという処理で以下のような Error で落ちたことを CodeBuild のコンソールで確認しました😿.

[Container] 2020/06/03 04:06:07 Entering phase INSTALL
[Container] 2020/06/03 04:06:07 Running command echo install started on `date`
install started on Wed Jun 3 04:06:07 UTC 2020
[Container] 2020/06/03 04:06:07 Running command apk add --no-cache gcc build-base libffi-dev py-pip python-dev libressl-dev
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
ERROR: unsatisfiable constraints:
  python-dev (missing):
    required by: world[python-dev]
[Container] 2020/06/03 04:06:07 Command did not exit successfully apk add --no-cache gcc build-base libffi-dev py-pip python-dev libressl-dev exit status 1
[Container] 2020/06/03 04:06:07 Phase complete: INSTALL State: FAILED

この時は以下のようにインストールするライブラリを修正するという暫定対応で何とか復旧するようになりました.

version: 0.2
phases:
  install:
    commands:
      - echo install started on `date`
      - apk update
--      - apk add --no-cache gcc build-base libffi-dev py-pip python-dev libressl-dev
++      - apk add --no-cache gcc build-base libffi-dev py-pip python3-dev libressl-dev
      - pip install docker-compose

実は過去にも似たような Error が発生し,対応しております.

bake0937.hatenablog.com

CodeBuild が突然落ちた時,まず CodeBuild 自体の原因(設定など)なのか,buildspec.ymlで実行するコマンド側の原因なのかという切り分けから始めなければならないため大変だった記憶があります(まぁ慣れの問題ではありますが...).

改善方法

改修の内容自体はそこまで大したことがない規模ですが,こうも頻発すると開発業務も止まってしまうため何とかしたいと思っていました.

19.03.14-dindなどバージョンが固定されている Docker イメージに変更しようとも思いましたが,たまたまこちらの記事を見つけました.

qiita.com

どうやら AWS で用意している「standard:2.0」という Docker イメージには docker-compose がインストール済みで,これを使えばbuildspec.ymlにある docker-compose をインストールする処理を省略できそうであることがわかったため以下の方法で試してみました.

①変更する Docker イメージを確認する

まずは「CodeBuild に用意されている Docker イメージ」のドキュメントを確認します. docs.aws.amazon.com

現在用意されている Docker イメージは Amazon Linux 2,Ubuntu 18.04,Windows Server Core 2019のようです. Qiita で見た記事はおそらく Amazon Linux 2 の standard:2.0 かと思いました.

そこで「どの Docker イメージにすれば良いんだろう」という話になりますが,ここに関しては自分なりの考えで各々の環境に合ったもの選ぶでOKだと思いました.

私の場合はローカル開発環境の OS が Ubuntu だったということもあり,環境を合わせるという意味で「Ubuntu standard:4.0」を選択してみました. (今回の変更で apk を実行するコマンドが消えるためおそらく Amazon Linux 2 standard:4.0 でも動くとは思います.)

使用する Docker イメージが決まったらbuildspec.ymlで docker-compose をインストールする処理を削除し,「Ubuntu standard:4.0」に対応する Docker のランタイムバージョンを設定します. 以下の公式ドキュメントに設定例があります.

docs.aws.amazon.com

ここらへんでおそらく気づくのですが,RubyGolang などはドキュメントにランタイムバージョンが記載されているのですが,Docker のランタイムバージョンの記載が見当たりません😇. ここでちょっと焦ったのですが,公式ドキュメントをよく見てみると GitHubリポジトリのリンクがあることがわかります.

github.com

このリポジトリにある「aws-codebuild-docker-images/ubuntu/standard/4.0」ディレクトリのruntimes.yml を見てると,ランタイムバージョンは 18 または 19 が設定できることがわかります.私は現状の最新である 19 を使うことにしました.

②使用する Docker イメージを変更する

使用する Docker イメージが決まったため作業に入ります.まずは AWS Console の CodeBuild のページにアクセスし,対象のビルドプロジェクトの「環境」へアクセスします. そこで以下のように項目を変更し「保存」を押します.

f:id:bake0937:20201206195846p:plain

注:この変更により一時的に CodeBuild が動かなくなる可能性があるため,変更前にチームメンバーへ事前に作業内容の共有もしくは検証用にビルドプロジェクトを作成し,そこで試すことをオススメします.

buildspec.ymlを変更する

次にbuildspec.ymlを以下のように変更します.

version: 0.2
phases:
  install:
--  commands:
--    - echo install started on `date`
--    - apk update
--    - apk add --no-cache gcc build-base libffi-dev py-pip python3-dev libressl-dev
--    - pip install docker-compose
--    - docker-compose version
--    - pip install awscli && \
--    - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay&
--    - timeout 15 sh -c "until docker info; do echo .; sleep 1; done"
++    runtime-versions:
++      docker: 19
  pre_build:
    commands:
      - echo pre_build started on `date`
      - echo Logging in to Amazon ECR...
# ↓ここからテストの実行に必要な Docker イメージを ECR からプルする処理やテスト実行の処理が続く
・・・・・・・・・・・

CodeBuild の Docker イメージは変更済みのため,このbuildspec.ymlを変更するプルリクエストを作成したら CodeBuild のコンソール上で動作を確認できるかと思います. 以下のようにUsing Docker 19が表示され,docker-compose のコマンドが実行されれば成功です.

[Container] 2020/06/05 06:10:47 Waiting for agent ping
[Container] 2020/06/05 06:10:51 Waiting for DOWNLOAD_SOURCE
[Container] 2020/06/05 06:11:06 Phase is DOWNLOAD_SOURCE
[Container] 2020/06/05 06:11:06 CODEBUILD_SRC_DIR=/codebuild/output/src☓☓☓☓☓☓☓☓☓/src/github.com/hoge-organization/fuga-project
[Container] 2020/06/05 06:11:06 YAML location is /codebuild/output/src☓☓☓☓☓☓☓☓☓/src/github.com/hoge-organization/fuga-project/buildspec.yml
[Container] 2020/06/05 06:11:06 No commands found for phase name: install
[Container] 2020/06/05 06:11:06 Processing environment variables
[Container] 2020/06/05 06:11:06 Selecting 'docker' runtime version '19' based on manual selections...
[Container] 2020/06/05 06:11:06 Running command echo "Using Docker 19"
Using Docker 19

# 省略
・・・・・・・・・・・

[Container] 2020/06/05 06:11:08 Running command docker-compose pull
Pulling mysql         ...
Pulling web           ...
Pulling spring        ...
Pulling redis         ...
Pulling s3            ...

# 省略
・・・・・・・・・・・

これでCodeBuild 上で docker-compose をインストールする作業を省略することができました!これにより冒頭にあったような Error の発生が無くなり,より安定しました. さらに実行時間も短縮することができました.(私が試した時は約4〜5分の短縮に成功しました!!)

まとめと所感

今回は久しぶりに CodeBuild にでやってみたことをまとめてみました! 今回紹介した「CodeBuild に用意されている Docker イメージ」を利用して自分で docker-compose インストールしなくても済むようになってとても助かりました.

CodeBuild 導入時はこの Docker イメージに気づかなった(もしくは当時はまだ無かった!?)ず,CircleCI のconfig.ymlのような複数コンテナを指定する方法を CodeBuild でどう実現すれば良いのかでだいぶ悩みましたが,これからはシンプルにdocker-compose pullでテストの実行に必要な Docker イメージをプルしてテストを実行すれば良いので安心ですね!

運用を通して,CodeBuild のCI環境と CircleCI などの CI サービスの仕組みや動きの比較について調べることが多くなり,CI についての興味関心がより高まるようになりました.