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

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

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

Hiroki Tanaka

June 14, 2019
Tweet

More Decks by Hiroki Tanaka

Other Decks in Programming

Transcript

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

    RUNの頭に--mount-type=cache,target=/hoge command...と書くと該当のディレクトリをマウントして キャッシュしてくれる
  2. 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
  3. # 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
  4. ... COPY ./app/assets /app/app/assets RUN bundle exec rails assets:precompile ...

    COPY frontend ./frontend RUN yarn run webpack --config config/webpack/production.js
  5. 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
  6. 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
  7. ... 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
  8. ... 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
  9. ... 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
  10. ... 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
  11. 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
  12. .. COPY ./app/assets /app/app/assets RUN bundle exec rails assets:precompile ...

    COPY frontend ./frontend RUN yarn run webpack --config config/webpack/production.js
  13. .. 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
  14. 結果 • 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で検証
  15. CIに組み込む際のポイント • Docker layer cacheを保持できること ◦ buildkitは--cache-fromが使えない ◦ docker layer

    cacheに頼らざるを得ない • mountしたデータを保持できること ◦ dindで都度立ち上げるとmountデータが消えてしまう
  16. 今後試してみようと思うこと • 1サービス1dockerdをCI用に立てたままにする ◦ pros : 手軽にキャッシュを保持できる ◦ cons :

    サービス増えるたびにdockerd増やすの...? • Buildkitを捨ててGCP+Kanikoにする ◦ pros : CI周りの面倒なことを考えなくて済む ◦ cons : 並列vsKanikoの最適化はどれだけ差があるか?
  17. まとめ • Buildkitでビルドを高速化するには ◦ 並列ビルド+キャッシュマウント • CIのフローに組み込むには ◦ 規模が小さければdockerd使い回しでOK ◦

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