CircleCI で定期的に Docker イメージをビルド
概要
Docker Hub には色々な Docker イメージが公開されていて便利なんですが、なかなか更新されないものもあります。
更新されない一因として手動で誰かがビルドして Docker Hub にプッシュする運用になっているということがあると思います。
そこで CircleCI で定期的にイメージをビルドして Docker Hub にプッシュするというジョブを作って自動化するのをやってみました。
リポジトリはこれです。
https://github.com/bigsleep/haskell-docker
Docker Hub はこれです。
https://hub.docker.com/r/tkaaad97/haskell-docker/
イメージ
https://hub.docker.com/_/haskell/
前にも少しブログに書きましたが haskell のイメージが公開されているのですがあまり更新されていません。
現在最新の GHC バージョンは 8.4.1 のようですが 8.2.1 で止まっています。
OS のバージョンも変わったり色々な依存パッケージも変わったりするので 完全に自動にするのは難しいと思いますがマイナーバージョンの更新ぐらいなら そんなに Dockerfile の内容は変えずにいけるんじゃないかと思います。
このイメージを定期的に新しい ghc バージョンで更新するというのが目標になります。
パッケージ情報の取得
GHC の開発に使われている git リポジトリは公開されていて GitHub にもミラーがあるので ここからリリースの情報を取得することもできると思います。
ただソースからビルドするのはなかなか大変で時間もかかりそうなので Ubuntu 用に公開されているパッケージを使っています。
Packages in “GHC” : GHC : Herbert V. Riedel
Ubuntu用のパッケージは launchpad.net に登録されているようです。
https://launchpad.net/+apidoc/1.0.html#archive
launchpad.net の API もあるようなのでここから情報を取得できそうです。
curl -fs "https://api.launchpad.net/1.0/~hvr/+archive/ubuntu/ghc?ws.op=getPublishedBinaries&distro_arch_series=https://api.launchpad.net/1.0/ubuntu/xenial/amd64&status=Published&order_by_date=true&binary_name=ghc"
これでパッケージ情報が取得できました。
Webhook というのもあってこれも使えるかもしれないんですが CircleCI ではまだ API からビルドを走らせることはできないらしいので上手く利用できないかもしれません。
CircleCI
Continuous Integration and Delivery - CircleCI
CircleCI は CI (継続的インテグレーション) のためのサービスで、開発に伴う色々な作業を自動化することに使うことができます。
他に Travis CI も有名だと思います。Jenkins や GitLab CI などサーバーをホスティングして使うものもあります。
CircleCI は GitHub との連携があって GitHub にアカウントがあれば簡単に試すことができました。
GitHub のプロジェクトのソースに CircleCI の設定ファイルを含めてこれに基づいてビルドやテストを行うようになっているようです。
ある程度は無料でも利用できるので便利そうです。
CircleCI の設定
Configuration Reference - CircleCI
ドキュメントは色々あるんですが読んでもいまいちわからないので 実験用のプロジェクトを作って色々試してみるのがいいような気がします。
version
, jobs
, workflows
というのが一番上の階層にあります。
version
は2を指定します。
jobs
は CI で実行するジョブの内容を書きます。シェルスクリプトなども使えます。
build
という名前のジョブは少し特別扱いされていて workflows
が無い設定では build
ジョブだけが実行されます (Orchestrating Workflows - CircleCI) 。
workflows
はジョブ間の順番やジョブを実行するブランチのフィルタリング、コンテキストなどジョブの付属的な設定を書くようです。
workflows
には triggers
で cron 形式で定期的に実行する設定ができます。
色々試行錯誤して下の設定を作りました。
build
ジョブでは単純にコミットされた Dockerfile を元にイメージをビルドして Docker Hub にプッシュしています。
crawl
のジョブでは lanunchpad.net から最新の ghc パッケージ情報を取得して Dockerfile を生成して github にプッシュするようになっています。
build
ジョブは master ブランチ以外、 crawl
ジョブは master ブランチのみで実行されます。
crawl
ジョブは triggers
を使っていて週三回定期的に実行するようにしています。
ビルドが手元でやるより大分速いので毎日ビルドするのでもいいかもしれません。
version: 2 jobs: build: working_directory: /work docker: - image: docker:18.02.0-ce-git steps: - checkout - setup_remote_docker - run: docker login -u ${DOCKER_USER} -p ${DOCKER_PASS} - run: docker build -t ${DOCKER_USER}/${CIRCLE_PROJECT_REPONAME}:${CIRCLE_BRANCH} . - run: docker push ${DOCKER_USER}/${CIRCLE_PROJECT_REPONAME}:${CIRCLE_BRANCH} - run: docker tag ${DOCKER_USER}/${CIRCLE_PROJECT_REPONAME}:${CIRCLE_BRANCH} ${DOCKER_USER}/${CIRCLE_PROJECT_REPONAME}:latest - run: docker push ${DOCKER_USER}/${CIRCLE_PROJECT_REPONAME}:latest crawl: machine: true working_directory: ~/work steps: - checkout - add_ssh_keys: fingerprints: - "20:ed:11:cf:92:b2:fa:ff:24:a5:00:f3:fe:00:d9:ac" - run: ./scripts/crawl.sh workflows: version: 2 docker-build: jobs: - build: filters: branches: ignore: master tags: ignore: /.*/ scheduled-workflow: triggers: - schedule: cron: "0 0 * * 1,3,5" filters: branches: only: master tags: ignore: /.*/ jobs: - crawl
まとめ
CircleCI を使って Docker イメージのビルドを定期的に行うようにしてみました。 まだ CI 設定作ったところで実際に新しいバージョンがリリースされて更新できるかなどは確認がとれてません。 しばらく続けて動かしてみて様子を見てみます。 例えばプロジェクトの依存ライブラリの新しいバージョンがリリースされていたらビルドしてテストを流してみるなども 似たような感じでできそうかなと思います。