🏗️
CodeBuildのビルド仕様ファイル(buildspec.yml)をローカルで動作確認
概要
CodeBuildのビルド仕様ファイル(buildspec.yml)の動作確認はローカル環境で実施することが可能です。
CodeBuildは無料利用枠がありますが、動作確認で使ってしまうのももったいないのでローカルでの実行環境を準備してみます。
buildspec.ymlでは、以下を実施します。
- Testinfraとhadolintのインストール
- ECRへのログイン
- hadolintでDockerfileの静的解析
- DockerfileからDockerイメージのビルド
- TestinfraでDockerイメージのテスト
- DocckerイメージをECRへ格納
環境
% docker -v
Docker version 20.10.17, build 100c701
% aws --version
aws-cli/2.7.31 Python/3.9.11 Darwin/21.6.0 exe/x86_64 prompt/off
Docker環境の準備
DockerはMacにDocker Desktopをインストールして使用します。
インストール方法は割愛。
ビルドイメージの取得
ビルド環境用のイメージ取得
docker pullでイメージを取得します。
13.2GBもあります。。。
% docker pull public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:3.0
% docker images | grep amazonlinux2
public.ecr.aws/codebuild/amazonlinux2-x86_64-standard 3.0 3c8ea9e9584d 3 months ago 13.2GB
CodeBuildエージェント用のイメージ取得
再度docker pullを実行します。
% docker pull public.ecr.aws/codebuild/local-builds:latest
% docker images | grep local-builds
public.ecr.aws/codebuild/local-builds latest 7c562345ec69 19 months ago 816MB
CodeBuildエージェント実行用スクリプトの取得
% cd /usr/local/bin
% curl -O https://raw.githubusercontent.com/aws/aws-codebuild-docker-images/master/local_builds/codebuild_build.sh
% chmod +x codebuild_build.sh
% codebuild_build.sh -h
usage: codebuild_build.sh [-i image_name] [-a artifact_output_directory] [options]
Required:
-i Used to specify the customer build container image.
-a Used to specify an artifact output directory.
Options:
-l IMAGE Used to override the default local agent image.
-r Used to specify a report output directory.
-s Used to specify source information. Defaults to the current working directory for primary source.
* First (-s) is for primary source
* Use additional (-s) in <sourceIdentifier>:<sourceLocation> format for secondary source
* For sourceIdentifier, use a value that is fewer than 128 characters and contains only alphanumeric characters and underscores
-c Use the AWS configuration and credentials from your local host. This includes ~/.aws and any AWS_* environment variables.
-p Used to specify the AWS CLI Profile.
-b FILE Used to specify a buildspec override file. Defaults to buildspec.yml in the source directory.
-m Used to mount the source directory to the customer build container directly.
-d Used to run the build container in docker privileged mode.
-e FILE Used to specify a file containing environment variables.
(-e) File format expectations:
* Each line is in VAR=VAL format
* Lines beginning with # are processed as comments and ignored
* Blank lines are ignored
* File can be of type .env or .txt
* There is no special handling of quotation marks, meaning they will be part of the VAL
使用するファイルなど
以下のファイルを使用します。
% tree -aF
./
├── Dockerfile
├── artifacts/
├── buildspec.yml
├── env.local
├── reports/
└── tests/
└── test.py
Dockerfile
今回のビルド対象です。
Dockerfile
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y curl=7.35.0-1ubuntu2.20
buildspec.yml
今回は以下のbuildspec.ymlを使って動作確認をします。
phases/build/commandsではDockerイメージのビルド前にhadolintでDockerfileの静的解析を実施します。
hadolintではinfoレベルは無視したいので、-t warningでwarning以上の解析結果があった場合に失敗としています。
buildspec.yml
version: 0.2
env:
variables:
IMAGE_REPO_NAME: 'testrepo'
phases:
install:
on-failure: ABORT
runtime-versions:
python: 3.9
commands:
- pip install pytest-testinfra==6.8.0
- wget https://github.com/hadolint/hadolint/releases/download/v2.10.0/hadolint-Linux-x86_64
- chmod 755 hadolint-Linux-x86_64
pre_build:
on-failure: ABORT
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
build:
on-failure: ABORT
commands:
- echo Build started on `date`
- IMAGE_TAG=$(echo $CODEBUILD_BUILD_ID | awk -F':' '{print $2}')
- echo Testing the Dockerfile...
- ./hadolint-Linux-x86_64 Dockerfile -t warning
- echo Building the Docker image...
- docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
- docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
post_build:
on-failure: ABORT
commands:
- echo Build completed on `date`
- echo Testing the Docker image...
- py.test --junit-xml=./reports/${IMAGE_TAG}_testinfra_report.xml tests/test.py
- echo Pushing the Docker image...
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
reports:
testinfra-reports:
files:
- '**/*'
base-directory: reports/
file-format: JunitXml
env.local
AWS上のCodeBuildでビルドプロジェクトを作成した場合は、ビルドプロジェクト内で環境変数を設定できます。
今回はローカルで実行するので、その代替としてenv.localに環境変数を定義してビルド時に参照します。
env.local
AWS_DEFAULT_REGION=ap-northeast-1
AWS_ACCOUNT_ID=************(12桁の数字)
test.py
Testinfraで実行するテストの定義です。
test.py
import pytest
import subprocess
import testinfra
@pytest.fixture(scope='session')
def host(request):
docker_id = subprocess.check_output(['docker', 'run', '-d', 'docker/getting-started']).decode().strip()
yield testinfra.get_host("docker://" + docker_id)
subprocess.check_call(['docker', 'rm', '-f', docker_id])
def test_myimage01(host):
assert host.check_output('uname -r') == '5.10.124-linuxkit'
ビルドの実行
codebuild_build.shを実行し、エラーが出力されないことを確認します。
codebuild_build.shには以下の引数を与えます。
引数 | 概要 |
---|---|
-a artifacts | artifactsディレクトリにアーティファクトを出力します。今回はアーティファクトを出力しませんが、必須のため指定します。 |
-c | Dockerを実行するOSの~/.aws/credentialsからaws_access_key_idとaws_secret_access_keyを取得します。 |
-e env.local | env.localファイルから変数を取得します。 |
-i public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:3.0 | ビルド環境用のイメージを指定 |
-m | Dockerを実行するOSのディスクをマウントし、ディスクにDockerコンテナ上での実行結果を書き出せるようにします。 |
-r reports | reportsディレクトリにレポートを出力します。 |
codebuild_build.shの実行後、テスト結果のファイルが作成されることを確認できました。
% codebuild_build.sh -i public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:3.0 -a artifacts -c -e env.local -r reports -m
% ls reports
00000000-0000-0000-0000-000000000000_testinfra_report.xml reports-testinfra-reports.zip
ECRにDockerイメージが格納されました。
% aws ecr describe-images --repository-name testrepo
{
"imageDetails": [
{
"registryId": "************",
"repositoryName": "testrepo",
"imageDigest": "sha256:efea61875494fa0a6471df39a6bd7dccee89b5269d39a26e2a282d4875ccc719",
"imageTags": [
"00000000-0000-0000-0000-000000000000"
],
"imageSizeInBytes": 85701276,
"imagePushedAt": "2022-09-19T09:14:51+09:00",
"imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
"artifactMediaType": "application/vnd.docker.container.image.v1+json"
}
]
}
参考
Discussion