tl;dr
Docker のコンテナイメージを AWS の CodePipeline や CodeBuild を介して, コンテナレジストリ (ECR) に push する流れを実装したくて, 色々と調査していましたが, とりあえず, CircleCI で実施してみたらどうなるだろうと思ってドキュメントなどを参考にハンズオンしてみました.
やんなきゃいけないこと
コンテナレジストリにコンテナイメージを push するにあたって, 以下のような流れを実装したいなと考えています.
- Docker イメージをリポジトリに push
- CircleCI にてコンテナイメージをビルド
- ビルドしたイメージに対してテスト
- テストが正常に完了したら ECR に push
今回, 三番目のステップであるビルドイメージのテストは goss と goss を Docker コンテナイメージに対してテストをする為のラッパーである dgoss を利用してテストするように実装しようと思います.
github.com
github.com
やったこと
以下にやったことをまとめてあります.
github.com
超シンプルな Apache が起動するだけの Docker イメージを作成するものです. ファイルの一覧は以下の通りです.
$ tree .
.
├── Dockerfile
├── README.md
├── goss.yaml
└── terraform
├── Makefile
├── main.tf
└── provider.tf
1 directory, 6 files
Dockerfile
前述の通り, Amazon Linux コンテナを利用して, Apache をインストールしているだけのコンテナが作成されます.
FROM amazonlinux
RUN yum install -y httpd && echo 'circleci-docker-test-and-build' > /var/www/html/index.html
goss の詳しい説明については, Github のリポジトリをご一読いただければと思います. テストケースが YAML で書くことができるインフラ構成のテストツールとなります. 類似したツールでは Serverspec が挙げられます. 以下は YAML で書かれたテストケースです.
$ cat goss.yaml
package:
httpd:
installed: true
process:
httpd:
running: true
port:
tcp:80:
listening: true
file:
/var/www/html/index.html:
exists: true
filetype: file
contains:
- "circleci-docker-test-and-build"
Rspec DSL でテストケースを記載する Serverspec とは異なり, Ansible などで馴染み深い YAML でテストケースを記述できるという点が異なりますが, Serverspec との決定的な違いは goss はリモートホストのテストには対応していないという点です. これをネガティブポイントと捉えるかどうかはユースケース次第なので, 必要に応じて使い分けることができればと考えています.
上記のテストケースは実にシンプルで, 以下のような点をテストします.
- httpd パッケージがインストールされていること
- httpd プロセスが起動していること
- 80 番ポートが Listen していること
- /var/www/html/index.html が存在していること,
circleci-docker-test-and-build
という文字列が含まれていること
goss は CircleCI では, 以下のように実行します. ${FULL_IMAGE_NAME}
には, 前段階で docker build した際のコンテナイメージ名が入ります.
dgoss run ${FULL_IMAGE_NAME} /usr/sbin/httpd -DFOREGROUND
例えば, コンテナイメージを test:httpd
でビルドした場合, 以下のように実行してテストを走らせることが出来ます.
$ dgoss run test:httpd /usr/sbin/httpd -DFOREGROUND
INFO: Starting docker container
INFO: Container ID: 101827da
INFO: Sleeping for 0.2
INFO: Container health
PID USER TIME COMMAND
2888 root 0:00 /usr/sbin/httpd -DFOREGROUND
2939 48 0:00 /usr/sbin/httpd -DFOREGROUND
2940 48 0:00 /usr/sbin/httpd -DFOREGROUND
2942 48 0:00 /usr/sbin/httpd -DFOREGROUND
2944 48 0:00 /usr/sbin/httpd -DFOREGROUND
2972 48 0:00 /usr/sbin/httpd -DFOREGROUND
INFO: Running Tests
Process: httpd: running: matches expectation: [true]
File: /var/www/html/index.html: exists: matches expectation: [true]
File: /var/www/html/index.html: filetype: matches expectation: ["file"]
File: /var/www/html/index.html: contains: matches expectation: [circleci-docker-test-and-build]
Port: tcp:80: listening: matches expectation: [true]
Package: httpd: installed: matches expectation: [true]
Total Duration: 0.039s
Count: 6, Failed: 0, Skipped: 0
INFO: Deleting container
.circleci/config.yml
Docker ビルドして, テストして, ECR にログインして, コンテナイメージを push するまでの操作をまとめると以下のような感じになりました.
version: 2
jobs:
build:
machine: true
steps:
- checkout
- run:
name: Setup common environment variables
command: |
echo 'export ECR_REPOSITORY_NAME="${AWS_RESOURCE_NAME_PREFIX}"' >> $BASH_ENV
echo 'export FULL_IMAGE_NAME="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}:${CIRCLE_SHA1}"' >> $BASH_ENV
- run:
name: Setup AWS CLI
command: |
curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip"
unzip awscli-bundle.zip
sudo ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws
- run:
name: Setup goss & dgoss
command: |
curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.6/goss-linux-amd64 -o ${HOME}/bin/goss
chmod +x ${HOME}/bin/goss
export GOSS_PATH=${HOME}/bin/goss
curl -L https://raw.githubusercontent.com/aelsabbahy/goss/master/extras/dgoss/dgoss -o ${HOME}/bin/dgoss
chmod +x ${HOME}/bin/dgoss
- run:
name: Build Image
command: |
docker build -t ${FULL_IMAGE_NAME} .
- run:
name: Run Tests
command: |
dgoss run ${FULL_IMAGE_NAME} /usr/sbin/httpd -DFOREGROUND
- run:
name: Login to AWS ECR
command: eval $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
- run:
name: Push Docker Image
command: |
docker push ${FULL_IMAGE_NAME}
事前に以下のような環境変数を CircleCI のプロジェクトに登録しておく必要があります.
実際に
リポジトリに対して push すると CircleCI によるビルドとテスト, ECR への push が行われます.
いい感じです.
ECR にも意図した通りにコンテナイメージが push されていることが判ります.
$ aws ecr describe-images --repository-name=httpd
{
"imageDetails": [
{
"registryId": "123456789012",
"repositoryName": "httpd",
"imageDigest": "sha256:ae7cefb61f88f132eadc4eb98fa545a0054dd3a2888be26c9da48f29ab21c0b0",
"imageTags": [
"40f82524001fe52644c2cee1ab9b7895572aa94f"
],
"imageSizeInBytes": 142276848,
"imagePushedAt": 1546063334.0
},
{
"registryId": "123456789012",
"repositoryName": "httpd",
"imageDigest": "sha256:9afcd192b4e9c51fc43706d00c755747e890811c367422cb53e69f2071df42d2",
"imageTags": [
"7c92bdaac1c92f0f317f4e5692f5c6833642be48"
],
"imageSizeInBytes": 142276745,
"imagePushedAt": 1545953477.0
},
{
"registryId": "123456789012",
"repositoryName": "httpd",
"imageDigest": "sha256:7ba84149310e448739a2f91e06641a63e8ed37bf9cf3b9991cc8860ba54d25f2",
"imageTags": [
"79697d588b9efb809cc07621f403a63744079e66"
],
"imageSizeInBytes": 142276832,
"imagePushedAt": 1546065921.0
}
]
}
以上
今回は, コンテナイメージをテストしてイメージを push するところまでをハンズオンしましたが, 次回は, もう少し複雑なアプリケーションを使って, ECS や Fargate にデプロイするところまでやってみたいと思います.
参考
circleci.com