2通りのやり方がある。pull/cache-from を使う方法と、save/load を使う方法。
手元のプロジェクトだと前者の方がだいぶ速い。
1. pull/cache-from を使う方法
version: 2
jobs:
build:
machine: true
environment:
- DOCKER_IMAGE_REPO: your-private-repository
working_directory: ~/your-repo
steps:
- checkout
- # ...必要に応じて ecr login など
- run: docker pull $DOCKER_IMAGE_REPO:latest
- run: docker build -t circleci --cache-from $DOCKER_IMAGE_REPO:latest .
- run: docker tag circleci $DOCKER_IMAGE_REPO:latest
- run: docker push $DOCKER_IMAGE_REPO:latest
既存の latest イメージを pull して、ビルド時に --cache-from として指定する。
このオプションは Docker 1.13 で追加された もので、以前は pull したイメージをキャッシュとして利用する手段が存在しなかった。
CircleCI 1.0 では Docker 1.10 の独自拡張版を利用していたが、CircleCI 2.0 で Docker のバージョンが新しくなったため可能となった。
イメージサイズは 800 MB 程度だが、pull に 4 分かかる。0 からビルドするよりは速いので許容できる。
2. save/load を使う方法
.circleci/config.yml
にこんな内容を書けば良い。
version: 2
jobs:
build:
machine: true
working_directory: ~/my-repo
steps:
- checkout
# 1. キャッシュリストア
- restore_cache:
keys:
- my-docker-cache-{{ .Branch }}
- my-docker-cache
# 2. キャッシュイメージ読み込み
- run: if test -d ~/cache; then docker load -i ~/cache/image.tar; fi
# 3. ビルド
- run: docker build -t my-image .
# 4. イメージ書き出し
- run: mkdir -p ~/cache && docker save -o ~/cache/image.tar my-image $(docker history -q my-image | tail -n +2 | grep -v \<missing\> | tr '\n' ' ')
# 5. キャッシュ保存
- save_cache:
key: my-docker-cache-{{ .Branch }}-{{ checksum "~/cache/image.tar" }}
paths:
- ~/cache
ビルド終了時に docker save
でイメージの 全レイヤをまとめて tar に保存し、CircleCI のキャッシュ機構を使って tar を保存する。
ビルド開始時に前回のキャッシュ (tar) をリストアし、docker load
でロードしてやれば良い。
Docker 1.10 にはイメージのキャッシュをファイルからロードする手段が存在しない。そのため CircleCI 1.0 ではビルド間でキャッシュを持ち越せなかった。(参考: CircleCI で Docker ビルドキャッシュができない理由)
また、Docker ビルド環境にキャッシュファイルを渡すため、 executor type は machine でなければいけない。
Restore(CircleCI Cache), docker load, docker save, Save(CircleCI Cache) それぞれで地味に時間がかかる。
備考
docker save/load
を明示的に書かずにキャッシュ効かせる方法も用意されているが、2017/04 現在特別に申請された一部のリポジトリのみ有効であり、将来的には有料オプションになるかもしれないらしい。 (https://circleci.com/docs/2.0/docker-layer-caching/)
参考
- save/load の詳細: https://github.com/moby/moby/issues/20316#issuecomment-221289631
- 全レイヤをまとめて保存するワンライナー: https://github.com/moby/moby/issues/20316#issuecomment-221388885