Rails アプリを Docker で稼動させる際に、 Gemfile と Gemfile.lock を先に ADD して bundle install してからアプリケーション全体を ADD することで、 bundle install の結果をキャッシュする手法はよく知られています。
ADD Gemfile /app/Gemfile.lock
ADD Gemfile /app/Gemfile
WORKDIR /apps
RUN bundle -j4
ADD . /app
こういうやつ。
ところがこの手法は Jenkins のように毎回リポジトリが clean にチェックアウトされる環境では全く無効です。
何故なら、 Docker は ADD するファイルが更新されているかどうかを、ファイルの中身そのものではなく、タイムスタンプなどのメタデータで確認しているからです。 git checkout とかされちゃうとタイムスタンプが書き換えられてファイルが更新されたと判定されて毎回 bundle install されてしまいます。
これでは毎回 docker build に物凄く時間がかかってしまう。
ですが先に述べた通り、 Docker ではファイルの更新をメタデータで管理しているので、 docker build の前に毎回
touch -t 201412121212.12 Gemfile
touch -t 201412121212.12 Gemfile.lock
してしまえば問題ないです。 Gemfile や Gemfile.lock が実際に更新されている場合はファイルサイズなど他の要素も変わりますから、大丈夫です。 Gemfile 以外にも ADD しているものがあり、 ADD をなるべくキャッシュしたいという場合は、それらも touch してしまいましょう。
これにより Jenkins 上で高速に docker build 出来るようになって生活が豊かになります。