Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DockerCIビルドを一歩先へ Buildkitを運用前提で試食してみた / Docker ci with buildkit

DockerCIビルドを一歩先へ Buildkitを運用前提で試食してみた / Docker ci with buildkit

Dd276c4366435466f92c96ffb09a1bbb?s=128

Hiroki Tanaka

June 14, 2019
Tweet

More Decks by Hiroki Tanaka

Other Decks in Programming

Transcript

  1. DockerCIビルドを 一歩先へ Buildkitを 運用前提で 試食してみた 2019/06/14 タナカヒロキ @dabits

  2. 自己紹介 { id: ‘dabits’, name: ‘タナカヒロキ’, company: ‘株式会社エイチームライフスタイル’, division: ‘CTO室

    (like a SRE)’, hobby: ‘アニソンDJ’, }
  3. None
  4. 前回のあらすじ

  5. この数ヶ月、 KPIにCI/CDの時間を設定して ビルドの高速化を してきました。

  6. その一環でDocker buildの チューニングを 行ってきました。

  7. multi stage buildを使って やっと早くなってきたぞ!

  8. そんなとき

  9. DockerCon ‘19でとある発表が

  10. https://www.slideshare.net/Docker/dcsf19-dockerfile-best-practices

  11. https://www.slideshare.net/Docker/dcsf19-dockerfile-best-practices

  12. 今まで調べたこと 全部書いてあるやんけ

  13. 今からビルドを早くしたい人

  14. https://www.slideshare.net/Docker/dcsf19-dockerfile-best-practices

  15. 絶対読んだ方がいいですよ! 全部詰まってます!

  16. というお話でした。

  17. その次の改善ポイント

  18. 昨年発表された 「Buildkit」を使った高速化

  19. https://docs.google.com/presentation/d/1fy_xBVY15fNEOs0 DbuY79wKmp_POBBHAeZaGCUNQi-M/edit#slide=id.g3b87 b4748c_0_0

  20. が、今回のお話です。

  21. None
  22. Buildkit導入対象 • Ruby on rails • Assets precompileを使っている • Webpacker

    compileも使っている(移行期間中, 併用期)
  23. 早速Buildkit対応 していきましょう

  24. None
  25. Buildkitでの高速化ポイント • 並列ビルド ◦ multi stage buildになっていれば空気を読んで並列に • キャッシュマウント ◦

    RUNの頭に--mount-type=cache,target=/hoge command...と書くと該当のディレクトリをマウントして キャッシュしてくれる
  26. 今回の並列ビルド対象 • 1つ目のペア : bundle install vs yarn install •

    2つ目のペア : assets precompile vs webpack compile
  27. 今回のキャッシュマウント対象 • apk install • bundle install • yarn install

    • assets precompile • webpack compile
  28. None
  29. bundleとyarnの 並列インストール

  30. FROM ruby:2.5.5-alpine3.8 as builder RUN apk update && apk upgrade

    && \ apk add --no-cache git mysql-dev nodejs nodejs-npm libxml2-dev imagemagick-dev && \ npm install -g yarn WORKDIR /app COPY Gemfile Gemfile.lock ./ RUN bundle install -j4 --without development test deployment COPY package.json yarn.lock ./ RUN yarn install --production --frozen-lockfile
  31. # syntax = docker/dockerfile:experimental FROM ruby:2.5.5-alpine3.8 as base-builder RUN apk

    update && apk upgrade && \ apk add --no-cache git mysql-dev nodejs nodejs-npm libxml2-dev imagemagick-dev && \ npm install -g yarn WORKDIR /app FROM base-builder as bundle-builder COPY Gemfile Gemfile.lock ./ RUN bundle install -j4 --without development test deployment FROM base-builder as yarn-builder COPY package.json yarn.lock ./ RUN yarn install --production --frozen-lockfile
  32. assetsとwebpackの 並列コンパイル

  33. ... COPY ./app/assets /app/app/assets RUN bundle exec rails assets:precompile ...

    COPY frontend ./frontend RUN yarn run webpack --config config/webpack/production.js
  34. FROM base-builder as modules-builder COPY --from=bundle-builder /app/Gemfile /app/Gemfile.lock ./ COPY

    --from=yarn-builder /app/package.json /app/yarn.lock ./ FROM modules-builder as assets-builder ... COPY ./app/assets /app/app/assets RUN bundle exec rails assets:precompile FROM modules-builder as webpack-builder ... COPY frontend ./frontend RUN yarn run webpack --config config/webpack/production.js
  35. FROM ruby:2.5.5-alpine3.8 as release … COPY --from=builder /app/vendor/bundle/ /app/vendor/bundle/

  36. FROM ruby:2.5.5-alpine3.8 as release … COPY --from=modules-builder /app/vendor/bundle /app/vendor/bundle COPY

    --from=webpack-builder /app/public /app/public COPY --from=assets-builder /app/public /app/public
  37. キャッシュマウント

  38. ... RUN apk update && apk upgrade && \ apk

    add --no-cache git mysql-dev nodejs nodejs-npm libxml2-dev imagemagick-dev && \ npm install -g yarn WORKDIR /app
  39. ... RUN --mount=type=cache,target=/var/cache/apk \ apk update && apk upgrade &&

    \ apk add --no-cache git mysql-dev nodejs nodejs-npm libxml2-dev imagemagick-dev && \ npm install -g yarn WORKDIR /app
  40. ... FROM base-builder as bundle-builder COPY Gemfile Gemfile.lock ./ RUN

    bundle install -j4 --without development test deployment FROM base-builder as yarn-builder COPY package.json yarn.lock ./ RUN yarn install --production --frozen-lockfile
  41. ... FROM base-builder as bundle-builder COPY Gemfile Gemfile.lock ./ RUN

    --mount=type=cache,target=/app/tmp \ bundle install --path=/app/tmp/bundle -j4 --without development test deployment FROM base-builder as yarn-builder COPY package.json yarn.lock ./ RUN --mount=type=cache,target=/app/tmp \ --mount=type=cache,target=/usr/local/share/.cache/yarn \ yarn install --modules-folder=/app/tmp/node_modules --production --frozen-lockfile
  42. FROM base-builder as modules-builder COPY --from=bundle-builder /app/Gemfile /app/Gemfile.lock ./ COPY

    --from=yarn-builder /app/package.json /app/yarn.lock ./
  43. FROM base-builder as modules-builder COPY --from=bundle-builder /app/Gemfile /app/Gemfile.lock ./ COPY

    --from=yarn-builder /app/package.json /app/yarn.lock ./ RUN --mount=type=cache,target=/app/tmp \ mkdir -p /app/vendor && \ cp -r /app/tmp/bundle /app/vendor/bundle && \ cp -r /app/tmp/node_modules /app/node_modules
  44. .. COPY ./app/assets /app/app/assets RUN bundle exec rails assets:precompile ...

    COPY frontend ./frontend RUN yarn run webpack --config config/webpack/production.js
  45. .. COPY ./app/assets /app/app/assets RUN --mount=type=cache,target=/app/tmp \ mkdir -p /app/tmp/assets

    /app/public && mv /app/tmp/assets /app/public/assets && \ bundle exec rails assets:precompile && \ cp -r /app/public/assets /app/tmp/assets ... COPY frontend ./frontend RUN --mount=type=cache,target=/app/tmp \ mkdir -p /app/tmp/packs /app/public && mv /app/tmp/packs /app/public/packs && \ yarn run webpack --config config/webpack/production.js && \ cp -r /app/public/packs /app/tmp/packs
  46. 結果

  47. 結果 • Dockerfile : 約140行! • ビルド時間 ◦ 初回フルビルド :

    853s→683s (x1.25 Faster) ◦ packageを追加 : 844s→294s (x2.87 Faster) ◦ assetsのみを更新 : 482s→208s (x2.32 Faster) ※AWS EC2 t3.small : 2Core, Memory 2GB, Swap 4GBで検証
  48. ここまでが ローカル上でのお話

  49. いかにしてCIに組み込むか

  50. CIに組み込む際のポイント • Docker layer cacheを保持できること ◦ buildkitは--cache-fromが使えない ◦ docker layer

    cacheに頼らざるを得ない • mountしたデータを保持できること ◦ dindで都度立ち上げるとmountデータが消えてしまう
  51. 考えうる選択肢 • dockerdを共通で使う・・・✗ ◦ 並列で複数サービスのビルドが走ると詰まる • dindの/var/lib/dockerを保持させる・・・✗ ◦ 実装が大変すぎる •

    buildkit対応しているクラウドサービスを使う・・・△ ◦ AWS:cacheが途中でexpire, GCP:非対応, CircleCIなら
  52. うちはGitlab-CIを使っているので

  53. 諦めました

  54. みんなどうしてるんだろう?

  55. 今後試してみようと思うこと • 1サービス1dockerdをCI用に立てたままにする ◦ pros : 手軽にキャッシュを保持できる ◦ cons :

    サービス増えるたびにdockerd増やすの...? • Buildkitを捨ててGCP+Kanikoにする ◦ pros : CI周りの面倒なことを考えなくて済む ◦ cons : 並列vsKanikoの最適化はどれだけ差があるか?
  56. と、この資料 書いている途中に

  57. https://medium.com/nttlabs/buildkit-on-kubernetes-d37a0 3150192

  58. 事例出てきたやんけ

  59. NTT須田さんいつも ありがとうございます!

  60. None
  61. まとめ • Buildkitでビルドを高速化するには ◦ 並列ビルド+キャッシュマウント • CIのフローに組み込むには ◦ 規模が小さければdockerd使い回しでOK ◦

    規模が大きければお金払うor実装する必要ありかも • Dockerfile Best Practices はバイブル • 最近のBuildkit事情はNTT須田さんの資料をみる
  62. ありがとうございました

  63. Any Questions?