tl;dr
Docker のコンテナイメージを AWS の CodePipeline や CodeBuild を介して, コンテナレジストリ (ECR) に push する流れを実装したくて, 色々と調査していましたが, とりあえず, CircleCI で実施してみたらどうなるだろうと思ってドキュメントなどを参考にハンズオンしてみました.
やんなきゃいけないこと
コンテナレジストリにコンテナイメージを push するにあたって, 以下のような流れを実装したいなと考えています.
- Docker イメージをリポジトリに push
- CircleCI にてコンテナイメージをビルド
- ビルドしたイメージに対してテスト
- テストが正常に完了したら ECR に push
今回, 三番目のステップであるビルドイメージのテストは goss と goss を Docker コンテナイメージに対してテストをする為のラッパーである dgoss を利用してテストするように実装しようと思います.
やったこと
リポジトリ
以下にやったことをまとめてあります.
超シンプルな 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.yaml
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 にデプロイするところまでやってみたいと思います.