skaffoldでBuildKitを有効にする

Docker 18.09で正式にリリースされたBuildKit。これを有効にして`docker build`を実行するとこれまでよりセキュアかつ並列化のおかげでビルド時間を短くすることが可能になります。

今回は、skaffoldとBuildKitの簡単な紹介と、そのBuildKitをskaffoldというCLIツールを使用した場合に有効化する方法と速度差を記載します。

# skaffold？
Kubernetesを使った開発がしやすくなるGoogle謹製のコマンドラインツール。簡単に説明すると、ソースコードをウォッチして、変更があればビルドしKuberntesクラスターにあげてくれるというところまでを自動でやってくれるツールになります。

より詳しく知りたい場合、こちらの記事が詳しいです。

[Kubernetesの開発環境で困っているならskaffoldを使え](https://qiita.com/tomoyamachi/items/660bd7bb3afff8340307)



# BuildKit？
冒頭でも簡単に触れていますが、これまでよりもセキュアかつ高速でのビルドが可能になるdockerのイメージビルダーです。Docker 18.06ではexperimentalでしたが、18.09で正式に導入されました。

Buildkitに関してはこちらの資料が詳しいです。

<iframe src="//www.slideshare.net/slideshow/embed_code/key/h0XoR27B5RmR1c" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/AkihiroSuda/buildkit" title="BuildKitによる高速でセキュアなイメージビルド" target="_blank">BuildKitによる高速でセキュアなイメージビルド</a> </strong> from <strong><a href="https://www.slideshare.net/AkihiroSuda" target="_blank">AkihiroSuda</a></strong> </div>

# skaffoldで有効にする

Kubernetesを使った開発で、skaffoldを使っているのであれば、 skaffoldでもBuildKitを有効にしてビルド時間を高速化したくなると思います。CLI上で `export DOCKER_BUILDKIT=1`と打つだけで通常の`docker build`ではBuildKitが有効になるのですが、skaffoldではskaffold.yamlでの設定が必要になります。

設定は簡単で、設定ファイルがすでにあれば一行追加するだけでいけます。

```yaml:skaffold.yaml
apiVersion: skaffold/v1beta3
kind: Config
build:
  tagPolicy:
    sha256: {}
  artifacts:
  - image: sample-app/app-dev
  local:
    useBuildkit: true ← これ
deploy:
  kubectl:
    manifests:
    - kubernetes/app/*
```

https://github.com/GoogleContainerTools/skaffold/blob/master/examples/annotated-skaffold.yaml#L101

注意点としては、`apiVersion` が古いと使えません。僕個人の環境でいうと、半年ちょっと前くらいに入れたskaffoldだとバージョンが`v1alpha2`となっていて古かったため、使うことができませんでした。

また、`apiVersion`を上げた場合書き方が多少変わってしまっている箇所もあるため、その場合は少し修正を加える必要が出てきます。

https://github.com/ryosukes/laravel-k8s-sample/commit/913f08485e5accc4867707023e7daae6a71134df

まだ使用したことがない方であれば、最新バージョンを使うことで有効にできるかと思いますのでそのまま最新版をお使いください。

# 実際に使ってみてどうか

このDockerファイルを使い、有効/無効な場合でどれくらい速度に差が出るか確認してみました。

```dockerfile:Dockerfile
FROM node:9.2

COPY . /var/laravel

WORKDIR /var/laravel

RUN npm install \
  && npm rebuild node-sass \
  && npm run production

RUN rm -rf ./node_modules

FROM php:7.2-fpm-alpine

# install libraries
RUN apk upgrade --update \
    && apk add \
       git \
       zlib-dev \
       nginx \
    && docker-php-ext-install pdo_mysql zip \
    && mkdir /run/nginx

# install composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
  && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
  && php -r "unlink('composer-setup.php');"

ENV COMPOSER_ALLOW_SUPERUSER 1

# setting up apps
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY --from=0 /var/laravel /var/www/laravel
WORKDIR /var/www/laravel

# install php libraries && compile laravel mix
RUN composer install --no-dev

RUN find ./vendor -iname tests -type d | xargs rm -rf \
    && find ./vendor -iname tests -type d | xargs rm -rf

COPY ./run.sh /usr/local/bin/run.sh

RUN chown nginx:nginx storage/logs \
    && sed -i 's/www-data/nginx/g' /usr/local/etc/php-fpm.d/www.conf \
    && chown -R nginx:nginx storage/framework \
    && cp .env.example .env \
    && php artisan key:generate \
    && mkdir -p  /usr/share/nginx \
    && ln -s /var/www/public /usr/share/nginx/html \
    && chmod +x /usr/local/bin/run.sh

CMD ["run.sh"]
```

https://raw.githubusercontent.com/ryosukes/laravel-k8s-sample/master/Dockerfile

無効にした状態で実行した場合と有効にした場合とでは2分近くビルド時間に差が出ました。実際に試して出た数字は下記。だいぶ速度に差が出ています。（余談ですが、そもそもこれだけ時間かかっているのは、Multi-stage Buildでnpmやcomposer installをインストールから実行まで行っているのと、最適化を行っていないため）

| 無効   | 有効   |
| ---- | ---- |
| 4m58s | 2m37s |

# さいごに

もし試してみたい、という方がいましたら、Laravel on Kubernetesなサンプルアプリを用意してあるので試してみて貰えればと思います。

https://github.com/ryosukes/laravel-k8s-sample