Friday I/O です。
株式会社ワムウでは、毎週金曜日は 興味がある事柄に取り組み、その成果を何らかの形でアウトプットする日 としております。
前回記事のおさらい
前回の記事は こちら
CircleCI で Docker Compose を使用して環境のビルドからテストまで任せましょう、便利だね、という内容でした。
ですが Dockerイメージのプル・ビルドに時間がかかる というのが問題点としてありました。
今回のゴール
CircleCIが提供しているcache機能を利用してDockerのイメージ群をキャッシュ化し、ジョブの実行時間を短くしよう
アプリケーションの構成
前回の記事と同様です。
項目 | 名称 | バージョン |
---|---|---|
Language | PHP | 7.1 |
Framework | Laravel | 5.4 |
DB | MySQL | 5.7 |
大まかな処理の流れ
- キャッシュを作成するジョブ
- Docker イメージをプル・ビルドする
- サーバに存在するDockerイメージをキャッシュ化(キャッシュが既に存在する場合スキップ)
- キャッシュしたファイルをCircleCiに保存
- テストを実行するジョブ
- キャッシュしたファイルをCircleCiから読み出す
- Dockerイメージのロード
- Docker Compose からテスト実行
結果
---
version: 2
jobs:
generate_cache:
machine: true
steps:
- checkout
- restore_cache:
key: docker-{{ checksum ".circleci/config.yml" }}-{{ checksum "docker-compose.yml" }}-{{ checksum "Dockerfile" }}
paths: ~/caches/images.tar
- run:
name: Check cache file, if not exists then pull images and generate cache.
command: |
if [ ! -f ~/caches/images.tar ]; then
docker-compose pull sample-mysql
docker-compose build
mkdir -p ~/caches
docker save $(docker images | awk 'NR>=2 && ! /^<none>/{print $1}') -o ~/caches/images.tar
fi
- save_cache:
key: docker-{{ checksum ".circleci/config.yml" }}-{{ checksum "docker-compose.yml" }}-{{ checksum "Dockerfile" }}
paths: ~/caches/images.tar
test:
machine: true
steps:
- checkout
- restore_cache:
key: docker-{{ checksum ".circleci/config.yml" }}-{{ checksum "docker-compose.yml" }}-{{ checksum "Dockerfile" }}
paths: ~/caches/images.tar
- run:
name: Load Docker images
command: docker load -i ~/caches/images.tar
- run:
name: Run tests
command: |
docker-compose run --rm sample-laravel-app /bin/bash -c '\
cp .env.example .env && \
composer install --no-interaction && \
php artisan key:generate && \
./artisan migrate:refresh && \
./vendor/bin/phpunit -c phpunit.circle.xml'
workflows:
version: 2
build:
jobs:
- generate_cache
- test:
requires:
- generate_cache
上記yaml についてのポイント
CircleCi の機能で workflows
という機能と restore_cache
save_cache
という機能を使用しています。
- workflows 公式ドキュメント
ジョブをシーケンシャルに実行する仕組み
上記のyaml の場合generate_cache
,test
の順でジョブを実行する - restore_cache, save_cache 公式ドキュメント
キーバリューでファイルの保存を扱ってくれる仕組み
キー名には任意のファイルのチェックサムを利用できる
一度作成したキーに対する値(ファイル)は残り続ける。(いつ削除されるのか不明なので詳しい方は教えてください。)
作っていて詰まったところ
docker save
というコマンドでイメージ群をtarファイル化しています。
docker save -o ~/caches/images.tar
のみの場合、Repository名が無いイメージとしてtarファイルが生成されるらしく、気がつくのに時間がかかりました。
そのファイルを docker load
後、 docker-compose run
をしても対象のイメージが無いので、イメージのPull が始まりキャッシュしたのに何で?状態でした。
docker save
周りの疑問はこちらの記事 に助けられまた。
実際のジョブ実行時間について
以下に画像を添付します。
- 一枚目がキャッシュ化対応前(前記事)のビルド
- 二枚目が未キャッシュ時のビルド(本記事の内容)
- 三枚目がキャッシュ済時のビルド(本記事の内容)
1 と 3 を比べて 1の方が(キャッシュ化対応前
の方が)早かった。。。
扱うイメージが少ないのでキャッシュ化の恩恵が薄い、workflows
でジョブを分けているのでその分時間がかかるのが原因かもしれません。
あまり込み入った環境でない限りキャッシュする必要は無さそう。
案件で扱った時はビルドが 約2分早くなった のが個人的観測値です。(もちろん制作する規模・環境によりますが)
こんなやり方もあるんだと参考までに。
サンプルのGithub のリポジトリはこちら