くずきのblog

技術とか色々

CircleCI2.0でDocker Composeをキャッシュする

どうも、くずきです。
以前、CircleCI2.0を試しました。

kzkohashi.hatenablog.com

CircleCI2.0を使って見たものの、せっかく色々機能があるのに使えてなかったので、今回はWorkflowsを使ってDocker Composeのキャッシュを利用したいと思います。

目標

  • Workflowsに適応させる
  • Docker Composeをキャッシュする
  • キャッシュしたDocker Composeをテストで利用する

あとはビルドが早くなればいいな〜と思う。

一応環境

  • Laravel
    • 5.5.11
  • PHP
    • 7.1.1
  • Mysql
    • 5.7
  • CircleCI
    • 2.0

CircleCI設定

.circleci/config.ymlの設定

versin: 2
jobs:
  generate_cache:
    machine: true
    steps:
      - checkout
      - restore_cache:
          keys:
            - docker-{{ .Branch }}--{{ checksum ".circleci/config.yml" }}--{{ checksum "docker-compose.yml" }}-{{ checksum "Dockerfile" }}
          paths:
            - ~/caches/images.tar
      - run:
          name: Setup docker
          command: |
            if [ ! -f ~/caches/images.tar ]; then
              docker-compose pull db cache
              docker-compose build app
              mkdir -p ~/caches
              docker save $(docker images | awk 'NR>=2 && ! /^<none>/{print $1}') -o ~/caches/images.tar
            fi
      - save_cache:
          key: docker-{{ .Branch }}--{{ checksum ".circleci/config.yml" }}--{{ checksum "docker-compose.yml" }}-{{ checksum "Dockerfile" }}
          paths:
            - ~/caches/images.tar
  test:
    machine: true
    steps:
      - checkout
      - restore_cache:
          keys:
            - docker-{{ .Branch }}--{{ checksum ".circleci/config.yml" }}--{{ checksum "docker-compose.yml" }}-{{ checksum "Dockerfile" }}
          paths:
            - ~/caches/images.tar
      - run:
          name: docker load
          command: |
            if [[ -e ~/caches/images.tar ]]; then
              docker load -i ~/caches/images.tar
            fi
      - run:
          name: Setup Laravel
          command: |
            docker-compose run app composer install
            cp .env.circleci .env
            docker-compose run app php artisan key:generate
            docker-compose run app php artisan migrate:refresh --seed
      - run:
          name: Run Test
          command: |
            docker-compose run app vendor/bin/phpunit
workflows:
  version: 2
  build_and_test:
    jobs:
      - generate_cache
      - test:
          requires:
            - generate_cache

各設定箇所を簡単に説明。

workflows

jobsに書かれたジョブの実行順序を決めたり、並列化などできる。
本家の画像をパラパラと見れば理解しやすい(英語読まない)。

circleci.com

今回は、generate_cache -> testというジョブの順番で行うようにしてある。

save_cache

pathsで設定した内容をkeyの名前で保存できる。
keyに関しては{{}}を使うことで色々な名前にできて、今回は以下を設定。

  • .Branch
    • ブランチ名ごとにキャッシュ
  • checksum ファイル名
    • 指定したファイル名が変更されるたびにキャッシュ
    • 今回は、dockerファイル周りとcircleciのファイル

restore_cache

save_cacheで指定したkeyで保存したファイルをダウンロードできる。

[タスク] Setup docker

docker-composepullbuildしたイメージを

docker save イメージ名 -o アウトプット先

という形で保存している。
ここは結構詰まったので、後述。

[タスク] docker load

generate_cacheジョブで作ったファイルを、testジョブでrestore_cacheし、
それをdokcer loadで読み込んでいる。

動作結果

以前のビルド 結果: 3分07秒 f:id:kzkohashi:20180128185802j:plain

新しいビルド 結果: 2分52秒 f:id:kzkohashi:20180128185741p:plain

結果あんまり早くならなかった。
原因としては、ジョブを切り替える時間、restore_cacheなどの時間、composer installした内容をキャッシュしていなかったためである。

まあでもかっこよくなったのと、並列化などしやすくなったためよかった。

詰まったところ

キャッシュ名に.circleci/config.ymlを入れてなかった

すごく恥ずかしいんですけど、キャッシュをする際にkey.circleci/config.ymlをいれなかったせいで、.circleci/config.ymlをいくら変更しても前のキャッシュを使用してて全然更新されてなかった。。

docker saveが上手くされてなかった

最初はこのようにsaveしてた。

docker save -o ~/caches/images.tar

これだと、docker loadはできるものの、実際にdokcer-compose runを行う際にキャッシュを使わずに一からPull&Buildをしてしまう。だいぶここにはまった。
docker loadしても、RpositoryTagの名前が<none>になってしまい、Pullする際などに取れないからである。

yoshinorin.net

解決法としては、docker imagesする際に、Repository名を切り出して保存する。

docker save $(docker images | awk 'NR>=2 && ! /^<none>/{print $1}') -o ~/caches/images.tar

qiita.com

ほんと助かりました(ここのコードちょうだいしました・・)。作者様ありがたです。

もう少し良さげなコマンド無いか探して見まする。

ビルドしたDockerFileに名前をつける

docker-compose.yml

  app:
    #image: php:7.1.1-apache
    build: .
    image: app
    container_name: app
    ports:
      - "8000:80"
    volumes:
      - .:/var/www/html
      - ./000-default.conf:/etc/apache2/sites-available/000-default.conf
    depends_on:
      - db
      - cache

http://docs.docker.jp/compose/compose-file.html#build

buildした際に、imageでタグ名をつけとかないとdocker save時に困ります。

まとめ

  • workflowsでかっこよいテストにできる
  • restore_cache, save_cacheを使いこなそう
  • ハマりどころは細かくあるので注意
  • 次は並列化したい(そもそもテストの量増やさないと・・・)