AWS CodeBuild でローカルビルドを通すようにした

## TL;DR

ひとまずこれで疎通できるようなイメージを作り、ビルダーイメージを差し替えてビルドする。
根本解決はAmazon様の`codebuild/local-builds`のイメージ更新待ち。

```Dockerfile filename: Dockerfile
FROM public.ecr.aws/codebuild/local-builds:latest

RUN <<EOT
  for file in '/LocalBuild/agent-resources/docker-compose.yml' '/LocalBuild/agent-resources/docker-compose-mount-src-dir.yml'
  do
    sed -i -e "s/^version: '2'/version: '3'/" ${file}
    sed -i -e "s/BMR:3000/agent:3000/g" ${file}
    sed -i -e "/links:/d" ${file}
    sed -i -e "/agent:BMR/d" ${file}
  done
EOT
```

実行コマンドはこの通り

```bash
# Dockerfile があるディレクトリで実行する
docker build -t local-builds-v3:latest .
# buildspec.yml があるディレクトリで実行する
./codebuild_build.sh -i public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:5.0 -a artifact -l local-builds-v3:latest
```

参考URL: [CodeBuildのローカルビルド実行時の「ERROR: client version 1.22 is too old.… 」への対処方法](https://zenn.dev/nondescript/articles/9fb13a79ddc597)

## 問題

[CodeBuildのAWSドキュメント](https://docs.aws.amazon.com/codebuild/latest/userguide/use-codebuild-agent.html)に例示されたコマンドとスクリプトが正常に動作しない。
以下のようなエラーが出力されて実行できない。

```
ERROR: client version 1.22 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version
```

### 環境

```
OS: Arch Linux
Client:
 Version:           26.1.0
 API version:       1.44 (downgraded from 1.45)
 Go version:        go1.22.2
 Git commit:        9714adc6c7
 Built:             Tue Apr 23 07:59:02 2024
 OS/Arch:           linux/amd64
 Context:           desktop-linux

Server: Docker Desktop 4.28.0 (139021)
 Engine:
  Version:          25.0.3
  API version:      1.44 (minimum version 1.24)
  Go version:       go1.21.6
  Git commit:       f417435
  Built:            Tue Feb  6 21:14:25 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.28
  GitCommit:        ae07eda36dd25f8a1b98dfbf587313b99c0190bb
 runc:
  Version:          1.1.12
  GitCommit:        v1.1.12-0-g51d5e94
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Docker Compose version 2.27.0
```

Client APIバージョンは`1.44`なので、ローカルのDockerを利用してローカルの`docker-compose.yml`を処理する分には正常に動く。

## 原因

`./codebuild_build.sh`がDocker in Docker環境を作成して、ホストのDocker Engineを使って、古い`docker-compose.yml`を実行しているため。
![old_build_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81605/1d307900-5041-0b1e-f02c-da13280295cf.png)

こんな感じで中身を見て `docker-compose.yml` の定義が古いことを確認。

```bash
docker run --entrypoint /bin/bash -it --rm public.ecr.aws/codebuild/local-builds
```

よく使われるこれだと entrypoint が書き変わらずうまくシェルを呼び出せなかった。(
```bash
docker run -it --rm public.ecr.aws/codebuild/local-builds /bin/bash
```

大きな原因としては`version`が古いことと、`services.hoge.links`が正常に動作せず名前解決ができていないことだったため、その部分を修正したブログ記事を参考に修正した。

![new_build_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81605/f30ba33b-9a04-8284-ed49-1f418ccf935e.png)


## 成果物

```Dockerfile
FROM public.ecr.aws/codebuild/local-builds:latest

RUN <<EOT
  for file in '/LocalBuild/agent-resources/docker-compose.yml' '/LocalBuild/agent-resources/docker-compose-mount-src-dir.yml'
  do
    sed -i -e "s/^version: '2'/version: '3'/" ${file}
    sed -i -e "s/BMR:3000/agent:3000/g" ${file}
    sed -i -e "/links:/d" ${file}
    sed -i -e "/agent:BMR/d" ${file}
  done
EOT
```

- `version: '2'`を`version: '3'`に(最近はversion指定いらなくなったらしいね?)
- `links: "agent:BMR"`としてエイリアスを張っていた部分を削除、サービスのホスト名で通信するように修正

```bash
# Dockerfile があるディレクトリで実行する
docker build -t local-builds-v3:latest .
# buildspec.yml があるディレクトリで実行する
./codebuild_build.sh -i public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:5.0 -a artifact -l local-builds-v3:latest
```
./codebuild_build.sh の解説

- `-i`: ビルド環境のイメージ。CodeBuildのイメージと同じものを指定する
- `-a`: 出力ディレクトリ。ビルド結果がzipアーカイブとなって出力される
- `-l`: docker-composeなどを環境によって変化させるコマンド用のイメージ。何も指定されないと`public.ecr.aws/codebuild/local-builds`が指定される

## 感想

ローカルで動作しなくなるイメージをツールチェインに入れるのは怖いなというおはなし。  
ちゃんとメンテしよう。

## 参考URL

 - [CodeBuildのローカルビルド実行時の「ERROR: client version 1.22 is too old.… 」への対処方法](https://zenn.dev/nondescript/articles/9fb13a79ddc597)
 - [Run builds locally with the AWS CodeBuild agent](https://docs.aws.amazon.com/codebuild/latest/userguide/use-codebuild-agent.html)
 - [How to Override Entrypoint Using Docker Run](https://phoenixnap.com/kb/docker-run-override-entrypoint)
 - [docker-composeのclientのversionが古いと言われる](https://qiita.com/tettsu__/items/25743cdd92fd47505bcd)