designetwork

ネットワークを軸としたIT技術メモ

CI/CD for CI/CDs Dockerイメージの継続的最新化 with ConcourseCI

CI/CD Advent Calendar 2019 の 7日目

qiita.com

数日前に書いた記事のQiita向け調整版です。

AWS CLI on Alpine Docker Image 自動更新ビルド with Concourse - designetwork

ConcourseでのAWS関連作業用コンテナとして、AWS CLIのDocker Imageをビルドする。ビルドにはConcourse CIを使用することで継続的に更新し続ける仕組みを作る。

最終的な成果物としてのDocker Imageはこちら daichi703n/awscli

使い慣れているConcourseで仕組みを作ることができたので、他ツールのDocker Imageにも展開していきたい。

※試験的な実装部分も多いため、改善点等ありましたらご指摘ください。

モチベーション

  • Concourseで各種Docker Imageを使用する際に、できるだけ最新にしておきたい。
  • パッケージだけでなく、ベースイメージも基本的に最新にしておきたい。
  • Docker HubのリポジトリでPull数の多いリポジトリでも未更新が多く悩ましい...
  • 最新Docker Imageがいわゆる腐ってる状態で使えなくなるケースがある。
  • Kubernetesなどの環境向けにDocker Image自動更新の仕組みを作っておきたい。

アーキテクチャ

全体の構成は以下の通り。

DockerHub (ベースイメージ)、パッケージ (PyPIリポジトリ) を監視し、新しいリリースがあったら取り込んでビルド・テスト・プッシュする。

更新検知

更新のトリガーは以下の2つ

  • PyPI awscli Release
  • DockerHub alpine:latest

Concourseでそれぞれ以下のresourceを使用して監視する。

github.com

github.com

Concourse Pipeline実装

作成したConcourse Pipelineはこちら

github.com

Job分割

Concourseでは大きく3つのJobに分けてPipelineを実装した。

  • detect, build, push(dev release)
  • test
  • push(latest & tags), git commit(master & version tag)

1つのJobの中でtaskを分けて同様実装も可能だが、パイプラインっぽさ重視で分けた。疎結合なので他への展開もしやすいはず。

Detect, Build, Push

Detectでは、Concourseの各種Resource(DockerHub, GitHub, PyPI)を使用して新規バージョンのリリースを検知する。

最新バージョンを検知したら、Dockerfileに従って最新候補のDocker Image(develop)をビルドする。

ビルドが正常に完了したら、developタグでDocker ImageをDockerHubにpushする。

Test

ここを充実させるのが重要項目のひとつでもある。developとしてビルドしたイメージが期待通り動作することをテストする。docker-test.sh として保証動作のテストをシェルスクリプトで作成する。テスト失敗時はここで終了し、latestは据え置きなので、自動・定常運用への影響は発生しない。

awscliに関しては以下のテストを実装している。

Test Command Note
aws --version
aws ec2 describe-instances
aws ec2 run-instances
aws ec2 terminate-instances
aws s3 ls
aws s3 mb
aws s3 cp local s3://xxx
aws s3 cp s3://xxx local
aws s3 rb

Push, Git Commit

Testがパスしたら、各種タグを設定しDockerHubにプッシュする。latestに関してはDockerHubとGitHubの連携による自動ビルドを使用する。

version name(Tag) Static/Dynamic meaning
latest Dynamic Latest Build (with latest awscli & alpine version) (Automated Build by Docker Hub)
x.x Dynamic AWS CLI minor version (with latest alpine version)
x.x.x Dynamic AWS CLI patch version (with latest alpine version)
x.x.x-alpinex.x.x Static AWS CLI patch version (with all alpine patch version)

GitHub Commitはsemver resourceを使用して運用することもできるが、今回は手動(shellスクリプト)による実装とした。

  • Git Commit
    • Update versions file
    • Tagging version
    • Merge to master

DockerHub - GitHub連携時のバージョン環境変数

Dockerfile自体は汎用的にするために、awscliのバージョンを環境変数定義+ARG, --build-argで設定している。DockerHubが自動的にイメージをビルドする際にも同様の設定が必要となるため、hooks/build (https://github.com/daichi703n/docker-awscli/blob/master/awscli/hooks/build) を使用して、versionsに書き出したバージョン記載ファイルから読み込むよう、Dockerビルドコマンドを上書きしている。

Docker in Docker構成

ConcourseのTaskの中でDockerを扱う場合は、Docker in Dockerの構成となる。こちらを参考にdocker-lib.shを実装し動作できているが、仕様を理解できていない部分が多い...

github.com

TODO

  • 脆弱性診断
  • task shellを別ファイルにする
  • docker pullなどはresourceでできるのでは?
  • REPOSITORY LINKS を使えば自動的にbase imageを追従してくれるかも

まとめ - CI/CD for CI/CDs Dockerイメージの継続的最新化 with ConcourseCI

パッケージ・ベースイメージの更新を検知して、Docker Imageをビルド・テストするConcourseパイプラインを作成した。数日稼働させてみて正常に動作することを確認できている。

これからも各種ツールの同様パイプラインを整備していきたい。