環境
- laradockで開発しているLaravelプロジェクト
CIで時間かかる処理
- npmパッケージ取得
- composerパッケージ取得
- dockerイメージビルド
キャッシュによる高速化
-
キャッシュの仕組みがある
- CircleCI 2.0からの機能らしい
-
save_cache
- 依存ライブラリ等に名前を付けて、キャッシュを生成できる
-
restore_cache
- 名前を指定してキャッシュを読み出す
- 無ければ何もしない
-
キャッシュの名づけには、パッケージ管理ファイルのチェックサム等を使用する
- シノニムは考えないことにする
npmパッケージ
.circleci/config.yml
- run: cp ./src/package-lock.json ./src/package-lock.json.bak
- restore_cache:
keys:
- npm-v1-{{ checksum "./src/package-lock.json.bak" }}
paths:
- ./src/node_modules
- run:
name: Install JavaScript Packages
command: |
if [ ! -d ./src/node_modules ]; then
pushd ./laradock
docker-compose exec workspace npm install
fi
- save_cache:
key: npm-v1-{{ checksum "./src/package-lock.json.bak" }}
paths:
- ./src/node_modules
package-lock.json
のチェックサムをもってして同一性を検証- ただし、
npm install
でpackage-lock.json
が書き換わるようなのでバックアップを使用している - キャッシュ使用時は
npm install
しない
composerパッケージ
.circleci/config.yml
- run: cp ./src/composer.lock ./src/composer.lock.bak
- restore_cache:
keys:
- composer-v1-{{ checksum "./src/composer.lock.bak" }}
paths:
- ./src/vendor
- run:
name: Install PHP Packages
command: |
if [ ! -d ./src/vendor ]; then
pushd ./laradock
docker-compose exec workspace composer install
fi
- save_cache:
key: composer-v1-{{ checksum "./src/composer.lock.bak" }}
paths:
- ./src/vendor
- おなじ
dockerイメージビルド
.circleci/config.yml
- run:
name: Archive Build Context (for checksum)
command: tar --mtime="2000-01-01 00:00Z" -cvf laradock.tar laradock
- restore_cache:
keys:
- laradock-v1-{{ checksum "./laradock.tar" }}
paths:
- ~/caches/images.tar
- run:
name: Docker Image Rebuild
command: |
if [ ! -f ~/caches/images.tar ]; then
pushd laradock
docker-compose build workspace php-fpm nginx mysql
fi
- run:
name: Save Docker Images
command: |
if [ ! -f ~/caches/images.tar ]; then
mkdir ~/caches
docker image save $(docker image ls --format="{{.Repository}}" | grep laradock_) -o ~/caches/images.tar
fi
- save_cache:
key: laradock-v1-{{ checksum "./laradock.tar" }}
paths:
- ~/caches/images.tar
- run:
name: Load Docker Images
command: docker image load -i ~/caches/images.tar
- run: docker image ls
- 先の例ほど単純ではないので分割
キャッシュ名生成部分
- run:
name: Archive Build Context (for checksum)
command: tar --mtime="2000-01-01 00:00Z" -cvf laradock.tar laradock
- docker-composeのビルドコンテキストは
laradock/
ディレクトリ全体 - CircleCIの
checksum
は単一ファイルにしか対応していない。はず。 - なので
*.tar
に固めてからchecksum
に渡す必要がある - 下記では駄目:
tar -cvf laradock.tar laradock
tar
コマンドは内容物のタイムスタンプを保存する- CircleCIがGitHubからコードをcloneした時刻によってタイムスタンプは変わるため、
laradock.tar
のチェックサムが毎回変わってしまう - ので、タイムスタンプを固定値にする:
tar --mtime="2000-01-01 00:00Z" -cvf laradock.tar laradock
キャッシュ読み出し部分
- restore_cache:
keys:
- laradock-v1-{{ checksum "./laradock.tar" }}
paths:
- ~/caches/images.tar
mkdir ~/caches
はしなくていいみたい
dockerイメージビルド・ファイル書き出し部分
- run:
name: Docker Image Rebuild
command: |
if [ ! -f ~/caches/images.tar ]; then
pushd laradock
docker-compose build workspace php-fpm nginx mysql
fi
- run:
name: Save Docker Images
command: |
if [ ! -f ~/caches/images.tar ]; then
mkdir ~/caches
docker image save $(docker image ls --format="{{.Repository}}" | grep laradock_) -o ~/caches/images.tar
fi
-
キャッシュを読み出せた場合は何もしない
~/caches/images.tar
の存在により判定
docker-compose build
で必要なイメージをビルドする-
laradock_
から始まるイメージのみファイルに書き出すdocker image ls --format="{{.Repository}}"
はイメージ名一覧を得る
- 【issue】
laradock/.env
のCOMPOSE_PROJECT_NAME=laradock
を変えると機能しなくなる
キャッシュ保存
- save_cache:
key: laradock-v1-{{ checksum "./laradock.tar" }}
paths:
- ~/caches/images.tar
- どうってことはない
イメージ読み込み
- run:
name: Load Docker Images
command: docker image load -i ~/caches/images.tar
- run: docker image ls
- キャッシュファイルからイメージ読み込む
- キャッシュミスして1からビルドした場合も通るので効率悪い
- けど判定・分岐が面倒くさい&頻繁なケースではないので手を抜いた
高速化による弊害と対策
docker-compose up -d
でmysqlコンテナ起動後、mysqldの準備完了を待たずして後工程が容赦なく進むようになった- Composeの起動順番を制御
Compose はコンテナの準備が「整う」まで待ちません。 (つまり、特定のアプリケーションが利用可能になるまで待ちません) 単に起動するだけです。
- DBが絡むテストで
SQLSTATE[HY000] [2002] Connection refused
が出てしまうように - wait-for-itを用いてmysqldの準備完了を待つようにした
- run:
name: PHP CI (waiting for the invocation of mysqld)
command: docker-compose exec workspace /root/etc/wait-for-it.sh mysql:3306 -- composer run ci
working_directory: ./laradock