CodeBuild Localを使ってローカル環境でビルドを試す。

AWSのBlog記事 [Announcing Local Build Support for AWS CodeBuild](https://aws.amazon.com/blogs/devops/announcing-local-build-support-for-aws-codebuild/) を見かけたので、早速CodeBuildを使う前提のプロジェクトをローカル環境でビルドしてみました。

AWSのBlog記事内では、CodeBuild提供の公式Dockerイメージを使う手順が記載されていますが、独自で用意したカスタムDockerイメージを使う手順を説明します。

## 何がうれしいの？

* AWS CodeBuildのビルド設定`buildspec.yml` の試行錯誤をローカルで行える
* `buildspec.yml` の試行錯誤のための無駄コミットをしなくてよくなる
* AWS CodeBuildの1回のビルド料金(数円)を節約できる（笑

## 試した環境

* Ubuntu 16.04
* Docker version 18.03.1-ce

### 追記
MacOS & Docker for Macの環境でも問題なく動作しました！

## 事前準備

プロジェクトに `buildspec.yml` を追加します。
`buildspec.yml` はCodeBuildで使用するビルド手順を記載するファイルです。
CodeBuild Localのための何か特別な記述は一切不要です。

## カスタムビルドイメージを使う場合

公式のビルドイメージは少し古いバージョンだったり、求めているバージョン要件とマッチしない、そもそも言語が存在しないなど、手厚いサポートとは言い難いため、あえて使うことは少ないと思います。
そもそもイメージがubuntuベースなので、イメージサイズがとても大きいです。

まずは自分で作ったビルドイメージを使う場合です。
なお、以下の説明で使っているビルドイメージは、DockerfileをCIサービスでビルドするためのdocker-in-dockerイメージです。

### シェルスクリプトで実行する場合

ローカル環境でCodebuildを動かすシェルスクリプトを作ります。
ビルド対象のプロジェクトのルートに `codebuild-local.sh` を作成します。(名前はなんでもいいです)

```sh:codebuild-local.sh
#!/bin/bash
# スクリプトの絶対パスを取得
SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"

# ビルドに使うイメージを指定 (CodeBuildのEnvironment image に指定するやつです)
BUILD_IMAGE_NAME="gemcook/docker:17.12.1-dind"

# ローカル環境用のCodeBuildのDockerイメージ
docker pull amazon/aws-codebuild-local:latest --disable-content-trust=false

# CodeBuild起動
# IMAGE_NAME: ビルドに使うイメージ
# ARTIFACTS: ビルドの出力のartifactsを出力するディレクトリを絶対パスで指定 (artifacts使ってなくても必須)
# SOURCE: ビルド対象のソースコード 
# (このスクリプトは、ビルド対象のプロジェクトルートに作るので、スクリプトの絶対ディレクトリがソースコードの位置になる)
docker run -it -v /var/run/docker.sock:/var/run/docker.sock -e "IMAGE_NAME=$BUILD_IMAGE_NAME" -e "ARTIFACTS=$SCRIPTPATH/codebuild-local/artifacts" -e "SOURCE=$SCRIPTPATH" amazon/aws-codebuild-local
```

あとは作成したスクリプトファイルを起動するだけです。

```sh
sh ./codebuild-local.sh
```

### Makefileに書く場合

私がよく開発するGo言語の場合、Makefileを書くので、Makefileを作るプロジェクトの場合その中に書いてしまう方がスッキリします。

Makefileに以下を足します。

```Makefile:Makefile

# Makefile内でカレントディレクトリの絶対パスを取得する
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))
# ビルドに使うイメージを指定する
BUILD_IMAGE_NAME="gemcook/docker:17.12.1-dind"

# artifactsの出力先ディレクトリを./codebuild-local/artifacts にしているので .PHONY必須
.PHONY: codebuild-local
codebuild-local:
	docker pull amazon/aws-codebuild-local:latest --disable-content-trust=false
	docker run -it -v /var/run/docker.sock:/var/run/docker.sock -e "IMAGE_NAME=$(BUILD_IMAGE_NAME)" -e "ARTIFACTS=$(CURRENT_DIR)/codebuild-local/artifacts" -e "SOURCE=$(CURRENT_DIR)" amazon/aws-codebuild-local

```

シェルスクリプトの場合とやることは一緒です。

```sh
make codebuild-local
```

## AWS CodeBuild 公式提供のビルドイメージを使う場合

自分のビルドイメージを使う場合に比べ、ひと手間増えます。
カスタムのdocker-in-dockerイメージを使う代わりに、公式のdocker-in-dockerイメージを使う場合はシェルスクリプトを次のようにします。

```sh:codebuild-local.sh
#!/bin/bash

SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
BUILD_IMAGE_NAME="aws/codebuild/docker:17.09.0"

if [ ! -d "aws-codebuild-docker-images" ]; then
    git clone https://github.com/aws/aws-codebuild-docker-images.git
fi
docker build -t $BUILD_IMAGE_NAME ./aws-codebuild-docker-images/ubuntu/docker/17.09.0

docker pull amazon/aws-codebuild-local:latest --disable-content-trust=false

docker run -it -v /var/run/docker.sock:/var/run/docker.sock -e "IMAGE_NAME=$BUILD_IMAGE_NAME" -e "ARTIFACTS=$SCRIPTPATH/codebuild-local/artifacts" -e "SOURCE=$SCRIPTPATH" amazon/aws-codebuild-local
```

カスタムビルドイメージを使う場合に比べて変わったのは、

* https://github.com/aws/aws-codebuild-docker-images をgit cloneしてくる
* 公式イメージをビルドする

だけです。
ビルドする公式イメージは、使う環境によって適宜変更してください。 READMEにイメージ一覧があります。

ちなみに、公式のビルドイメージをビルドするのに10〜20分程度時間がかかります。