今回やること
composer install
で追加する依存パッケージ部分を、 Docker ビルド時のキャッシュにする- Laravel 6 を Docker 化する。その3 – oki2a24 の続き
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.json
とcomposer.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/ .
$
おわりに
全体像は次のようになりました。
キャッシュを使うことでビルド時間を短縮するテクニックは、調べて知りました。キャッシュの仕組みは、公式ドキュメントで解説されています。
- Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント
- Best practices for writing Dockerfiles | Docker Documentation
以上です。