🏗️

CodeBuildのビルド仕様ファイル(buildspec.yml)をローカルで動作確認

2022/09/19に公開

概要

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"
        }
    ]
}

参考

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/use-codebuild-agent.html
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html

Discussion