ziguzagu.org

CircleCI + Docker で ADD によるキャッシュがなるだけ失われないようにする

ADD cpanfile cpanfile.snapshot /app
RUN cd /app && carton install --deployment

などしてコンテナ内に CPAN モジュールを含めておく場合、ローカルリポジトリの cpanfile の mtime が変わるようなことが起きると ADD によるキャッシュはきかず carton やり直すはめになり時間がかかる。

CircleCI で Docker を利用してテストする際、ローカルリポジトリはキャッシュから展開されて clone ではなく pull されるようになっているので、cpanfile に実際の変更がなければ mtime 変わらないが、なぜか変わってしまうことがたまにあって時間がかかってしまうことがあるっぽい。

これは、ADD するファイルの mtime をコミット時の Commit Date に変更して、ファイルの内容に変化がなければ mtime も変わらないようにすることで防ぐことができる。

#!/usr/bin/env bash
set -eu

for file in $*; do
    touch -m -t $(date -d "$(git log -1 --pretty=format:%cd --date=iso $file)" +%Y%m%d%H%M.%S) $file
done

というスクリプトをリポジトリ内に用意しておいて、

checkout:
  post:
    - tools/git-mtime cpanfile cpanfile.snapshot

と docker build する前に ADD するファイルは全部 mtime 変更やっておくとよい。

CircleCI に限った話でもないのでこのスクリプトは PATH のとおってる場所においておくと、

git mtime <file...>

として普段使いもできる(あまり使う機会はない…)。