CircleCI 2.0 では Docker ビルドキャッシュが効く

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 のバージョンが新しくなったため可能となった。

jobtalk_cf-recommend__102_-_CircleCI.png

イメージサイズは 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 でなければいけない。

jobtalk_cf-recommend__87_-_CircleCI.png

Restore(CircleCI Cache), docker load, docker save, Save(CircleCI Cache) それぞれで地味に時間がかかる。

備考

docker save/load を明示的に書かずにキャッシュ効かせる方法も用意されているが、2017/04 現在特別に申請された一部のリポジトリのみ有効であり、将来的には有料オプションになるかもしれないらしい。 (https://circleci.com/docs/2.0/docker-layer-caching/)

参考

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.