Laravel 6 を Docker 化する。その 4 。 PHP 依存パッケージのダウンロードをキャッシュ

今回やること

vendor/ 以下を Docker ビルド時のコンテキストに含めないようにする

composer install 時に追加される依存パッケージを配置する vendor/ ディレクトリを、 Docker ビルド時に Docker ホストからコピーされる対象となるコンテキストに含めないようにします。

このために、 .dockerignore ファイルを作り、そこに含めないようにする対象を記述します。今後のことも考えて、 .gitignore をコピーしてその内容を元に作りました。結果、 .gitignore そのままとしました。

.dockerignore

/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
.env
.env.backup
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log

これで docker build 時のコンテキストのコピーを、 47.72MB から 782.3kB へと減らすことができました♪コンテキストのコピー、 Sending build context to Docker daemon の時間も、体感できるほど短くすることができました♪

composer install で追加する依存パッケージ部分を、 Docker ビルド時のキャッシュにする

vendor/ をコンテキストに含めないようにしましたので、 Docker ビルド時に、 composer install し、 vendor/ を作らねばなりません。

この際、開発時の効率が上がるための工夫をしました。 Laravel アプリの開発は、コントローラー等のロジックを書く時間が大半です。これに比べて、依存パッケージを追加・削除する内容を書く時間は少なくなります。

ですので、 依存パッケージの追加に関わるファイルのみのコピーと依存パッケージの追加部分を Docker ビルド時に分離し、この部分をキャッシュできれば、 Docker ビルド時に毎回依存パッケージをダウンロードして追加する時間を節約できます。

これを実現するために、 Dockerfile を次のように修正しました。

  • composer コンテナを使い、そこで composer install や他の Laravel アプリのセットアップ作業を行うようにした。 Docker のマルチステージビルド。
  • まずはじめに、 composer install に必要なのは composer.jsoncomposer.lock のみなのでこれをコピーする。
  • 次に composer install を実行する。この時、オートローダーと composer スクリプトの実行はせず、依存パッケージのダウンロードのみを行う。
  • 次に、 Laravel アプリのコードを全てコピーする。
  • 次に、 オートローダーの実行と、 composer install 時に本来実行されるはずだった composer スクリプトを実行する。
  • Docker ビルドの最後に、 composer コンテナを使用して作成したビルド成果物を Laravel アプリを実行するコンテナにコピーする。
$ git diff Dockerfile
diff --git a/Dockerfile b/Dockerfile
index 99043e4..717fa5c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,3 +1,11 @@
+FROM composer:1.9 AS build
+COPY --chown=www-data:www-data ./composer.json ./composer.lock ./
+RUN composer install --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress --no-suggest --no-interaction
+COPY --chown=www-data:www-data . .
+RUN composer dump-autoload \
+  && composer run-script post-root-package-install \
+  && composer run-script post-create-project-cmd
+
 FROM php:7.3-apache

 ARG TZ=Asia/Tokyo
@@ -19,4 +27,4 @@ ENV APACHE_DOCUMENT_ROOT /var/www/html/public
 RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
 RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

-COPY --chown=www-data:www-data . .
+COPY --from=build --chown=www-data:www-data ./app/ .
$

おわりに

全体像は次のようになりました。

キャッシュを使うことでビルド時間を短縮するテクニックは、調べて知りました。キャッシュの仕組みは、公式ドキュメントで解説されています。

以上です。

コメントを残す

コメントを残す