CicleCIでDockerイメージを再利用する - かまたま日記3
こちらの記事の最新版です。 現在CircleCIはバージョン2で、Docker Layer Cachingという機能がありますが、残念ながら追加のフィーが必要です。というわけで、会社とかで使っててフィーを払える方はそちらを使うとして、個人のOSS活動などで払うのが厳しい方用に普通にCircleCI 2.0のファイルのキャッシュ機能を使った方法を解説します*1
前回に比べて以下の点が変わっています
- GoのようにMulti stage buildを使って多段ビルドを行う前提 (最初のビルドのステージは
as buider
でbuilderという名前がついてます) - Docker image を完全に再利用はしないで中間イメージを再利用する (
docker build
は毎回やる) docker save
後のtarファイルを更にgzに圧縮してリストアの時間短縮を図る
注意として、自分の環境では、数百メガのキャッシュをload cacheとsave cacheするので2~3分かかるのでキャッシュを使うことによって、それ以上短縮出来なければ、総時間は変わらないか悪くなる可能性もあります。
1. キャッシュ用のディレクトリとキャッシュキーを決める
ここではディレクトリは /home/circleci/docker-cache
、キャッシュキーは毎回変えたいので {{ .Branch }}-{{ .Revision }}
を使います
- restore_cache: keys: - v1-docker-{{ .Branch }}-{{ .Revision }} - v1-docker-{{ .Branch }}- - v1-docker- - save_cache: paths: - "/home/circleci/docker-cache" key: v1-docker-{{ .Branch }}-{{ .Revision }}
2. イメージをビルドする
今回は builder
のイメージを取っておきたいので、builderの部分は別にビルドしてbuilerタグを付けています。
IMAGE_NAME=my_app CACHE_FROM="--cache-from ${IMAGE_NAME}:builder --cache-from ${IMAGE_NAME}" docker build --pull ${CACHE_FROM} --target builder -t ${IMAGE_NAME}:builder . docker build --pull ${CACHE_FROM} -t ${IMAGE_NAME} .
3. イメージを保存する
docker save
で保存するイメージを docker history
コマンドで取得します。 builder
を取ってるのがミソです。
mkdir -p /home/circleci/docker-cache image_ids=$(docker history -q my_app:builder | grep -v '<missing>') docker save ${image_ids} | gzip > ${DOCKER_CACHE_FILE}
4. イメージを展開する
Gzip化しているのでgunzipコマンドで解答して docker load
に渡します
if [ -f /home/circleci/docker-cache/image.tar.gz ]; then gunzip -c /home/circleci/docker-cache/image.tar.gz | docker load fi
全体
キャッシュファイルのパスを変数に入れて、以下のような感じになります。関係ない部分*2は略してます。
version: 2 jobs: build: environment: DOCKER_CACHE_FILE: /home/circleci/docker-cache/image.tar.gz steps: - checkout - restore_cache: keys: - v1-docker-{{ .Branch }}-{{ .Revision }} - v1-docker-{{ .Branch }}- - v1-docker- - run: | name: Load Docker cache command: | if [ -f ${DOCKER_CACHE_FILE} ]; then gunzip -c ${DOCKER_CACHE_FILE} | docker load fi - run: | name: Docker build command: | IMAGE_NAME=my_app CACHE_FROM="--cache-from ${IMAGE_NAME}:builder --cache-from ${IMAGE_NAME}" docker build --pull ${CACHE_FROM} --target builder -t ${IMAGE_NAME}:builder . docker build --pull ${CACHE_FROM} -t ${IMAGE_NAME} . - run: name: Save Docker cache command: | mkdir -p $(dirname ${DOCKER_CACHE_FILE}) image_ids=$(docker history -q my_app:${t} | grep -v '<missing>') docker save ${image_ids} | gzip > ${DOCKER_CACHE_FILE} - save_cache: paths: - ${DOCKER_CACHE_FILE} key: v1-docker-{{ .Branch }}-{{ .Revision }}