Laravel+mixのAWS Elastic Beanstalk環境を自動ビルド設定する
はじめに
AWSのElasticBeanstalk環境をカスタマイズするように.ebextensionsを使用して設定するという方法があります。
毎回のデプロイが自動になるためデプロイ作業の時間が短縮でき、ミスも少なくなります。
動機
今回、フロントをLaravel Mixでアセットビルドとコンパイルし、設定ファイルにコードを数行追加するだけでセットアップするため、アプリケーションのアップロード時にwebpackビルドを実行したいと考えました。
しかし、Elastic Beanstalkのアプリケーション環境は、PHPプラットフォームを採用しますが、composer install
は自動で実行されるものの、nodejsはインストールされておらず、npm install
やnpm run dev
なども自動では実行されません。
そこで、webpackビルドを行うために必要なnodejsのインストール〜webpackビルドの実行までを行えるように、Elastic Beanstalk環境をカスタマイズすることにしました。
本来であれば、CodeCommit/CodeBuild/CodeDeployをCodePipelineで繋げてデプロイを自動化するのが理想なのですが、開発しつつデプロイを繰り返すという様な手返しの良さを実現したく、.ebextensionsを使用して組み込む事にしました。
Laravel Mixを使う理由
Laravel Mixは、webpackのAPIラッパーです。
文法は洗練されていて簡単に使用できます。
バージョン管理、ホットリロード、アセットビルドとコンパイルは、設定ファイルにコードを数行追加するだけでセットアップできます。
アプリケーション環境
- PHP 8.0 running on 64bit Amazon Linux 2/3.3.14 (PHPプラットフォーム)
- Composer version 2.3.7
- nodejs v14.19.3
- npm 8.12.2
事前準備
- Laravelプロジェクト導入(もちろん終わっている前提)
- ElasticBeanstalk環境の初期化(もちろん終わっている前提)
作業
ついでに、Laravelやcomposerの環境設定もきっちりやります。
- composer環境
- composerの最新版をインストール
- composerのオプション設定
- webpackビルドを行うために必要な作業
- nodejsのインストール
- npmの最新版をインストール
- laravelプロジェクトのクリーンアップ
- npm install
- npm run prod(dev)
Linux サーバーでのソフトウェアのカスタマイズ
設定ファイルは、アプリケーションが実行している Linux サーバーに影響する次のキーをサポートしています。
詳しくは、公式ドキュメントを確認して下さい。
.ebextensionsの各種ファイル
プロジェクトのの下に「.ebextensions」というフォルダを作成して、設定ファイル作成します。
カテゴリ毎に、ファイルを分けても構いませんが、設定ファイルはアルファベット順に実行されます。
PROJECT_ROOT/.ebextensions/01_setup.config
たとえば、.ebextensions/01run.config は .ebextensions/02do.config の前に実行します。
詳しくは、公式ドキュメントを確認して下さい。
今回使うのは、コマンドとコンテナコマンドの2つ
-
コマンド
commands キーを使用すると、EC2 インスタンスでコマンドを実行できます。このコマンドは、アプリケーションとウェブサーバーがセットアップされ、アプリケーションバージョンファイルが抽出される前に実行されます。
指定されたコマンドはルートユーザーとして実行され、名前のアルファベット順に処理されます。デフォルトでは、コマンドはルートディレクトリで実行します。別のディレクトリからコマンドを実行するには、cwd オプションを使用します。 -
コンテナコマンド
container_commands キーを使用して、アプリケーションのソースコードに影響するコマンドを実行できます。コンテナコマンドは、アプリケーションおよびウェブサーバーが設定され、アプリケーションバージョンアーカイブが抽出された後、アプリケーションバージョンがデプロイされる前に実行されます。コンテナ以外のコマンドと他のカスタマイズオペレーションは、アプリケーションソースコードが抽出される前に実行されます。
指定されたコマンドはルートユーザーとして実行され、名前のアルファベット順に処理されます。コンテナコマンドは、ソースコードがアプリケーションサーバーにデプロイされる前に抽出されたステージングディレクトリから実行されます。コンテナコマンドを使用してステージングディレクトリにあるソースコードに対して行うすべての変更は、ソースが最終的な場所にデプロイされる際に含まれます。
leader_only を使用して、1 つのインスタンスでコマンドを実行するか、テストコマンドが test と評価される場合のみコマンドを実行するよう true を設定できます。リーダー専用コンテナコマンドは、環境の作成およびデプロイ中のみ実行されます。他のコマンドやサーバーカスタマイズオペレーションは、インスタンスがプロビジョニングまたは更新されるたびに実行されます。リーダー専用コンテナコマンドは、AMI ID やインスタンスタイプの変更などの起動設定の変更によって実行されることはありません。
今回の設定ファイルの内容
このバージョンのPHPプラットフォームでは、
/var/app/staging/ – ここで、アプリケーションのソースコードがデプロイ中に処理され
次に
/var/app/current/ – ここで、アプリケーションのソースコードが処理後に実行されます。
最終的には、/var/www/htmlは、/var/app/currentのシンボリックリンクになっていました。
commands:
# composerの最新版をインストール
01_updateComposer:
command: export COMPOSER_HOME=/root && /usr/bin/composer.phar self-update
# nodejsのリポジトリをインストール
10_getNodeRepo:
command: "curl --silent --location https://rpm.nodesource.com/setup_14.x | bash -"
# nodejsをインストール
11_installNode:
command: "yum install -y nodejs"
# npmの最新版をインストール
12_updateNpm:
command: "npm install npm -g"
# コンテナコマンドが実行されるカレントディレクトリは、/var/app/stagingです。
container_commands:
# laravelプロジェクトのクリーンアップ
20_config_clear:
command: "php artisan config:clear"
leader_only: true
21_cache_clear:
command: "php artisan cache:clear"
# Viewをキャッシュ
# tailwindcssをビルドしたい場合は、これを行っておかないと全てのスタイルがビルドされません。
# 使用しているスタイルのみをcssへ追加しようとしますが、直接bladeファイルを捜索しているのではなく
# view cacheから探す様になっているようです。
22_view_cache:
command: "php artisan view:cache"
# npm installで、node_modulesディレクトリやnpm run prod(dev)での成果物を書き込む権限を
# 一旦、ec2-userに持たせます。
30_permissions:
# fix permissions on the Laravel app folder
command: 'chown -R ec2-user:ec2-user .'
31_npm_install_command:
command: 'sudo -u ec2-user npm install'
32_npm_run_command:
# tailwindもbuildされます。
command: 'sudo -u ec2-user npm run prod'
# 規定のユーザに戻します。
33_permissions:
# fix permissions on the Laravel app folder
command: 'chown -R webapp:webapp .'
Containerコマンドとして実行できないものはshファイルにします。
実行
あとは、いつも通りzipに含めて、アップロードすれば実行されます。
ちなみに、コマンド系のログは/var/log/cfn-init-cmd.log
で確認する事ができます。
[ec2-user@ip-xxx-xxx-xxx-xxx ~]$ ls -l /var/log/
total 1328
drwx------ 3 root root 17 Jun 18 03:19 amazon
-rw------- 1 root root 9950 Jun 18 11:31 boot.log
-rw------- 1 root utmp 9216 Jun 18 11:50 btmp
-rw-r--r-- 1 root root 9741 Jun 18 11:55 cfn-hup.log
-rw-r--r-- 1 root root 19501 Jun 18 03:22 cfn-init-cmd.log
-rw-r--r-- 1 root root 2496 Jun 18 03:22 cfn-init.log
-rw-r--r-- 1 root root 687822 Jun 18 11:55 cfn-wire.log
drwxr-x--- 2 chrony chrony 6 Jun 18 03:19 chrony
-rw-r--r-- 1 root root 95892 Jun 18 03:19 cloud-init.log
-rw-r----- 1 root root 2527 Jun 18 03:19 cloud-init-output.log
-rw------- 1 root root 24458 Jun 18 11:50 cron
-rw-r--r-- 1 root root 26946 Jun 18 03:19 dmesg
-rw-r--r-- 1 root root 0 Jun 18 03:19 eb-cfn-init-call.log
-rw-r--r-- 1 root root 51175 Jun 18 03:19 eb-cfn-init.log
-rw-r--r-- 1 root root 0 Jun 18 04:01 eb-engine.log
-rw-r--r-- 1 root root 0 Jun 18 03:20 eb-hooks.log
-rw-r--r-- 1 root root 73863 Jun 18 11:50 eb-publish.log
drwxr-xr-x 3 healthd healthd 39 Jun 18 03:21 healthd
drwxr-xr-x 3 root root 21 Jun 18 03:19 httpd
-rw------- 1 root root 208 Jun 18 03:19 maillog
-rw------- 1 root root 205130 Jun 18 11:54 messages
drwxr-xr-x 4 nginx nginx 71 Jun 18 03:22 nginx
drwxr-xr-x 2 webapp webapp 23 Jun 18 03:22 php-fpm
drwxr-xr-x 2 root root 40 Jun 18 04:01 rotated
drwxr-xr-x 2 root root 43 Jun 18 08:53 sa
-rw------- 1 root root 14557 Jun 18 11:51 secure
-rw-rw-r-- 1 root utmp 3072 Jun 18 11:51 wtmp
drwxr-xr-x 2 xray xray 6 Mar 29 15:21 xray
-rw------- 1 root root 63 Jun 18 03:20 yum.log
以上です。
補足
以下のコマンドを実行するようにしていますが、先にcomposer install
が実行されvender
ディレクトリ以下にautoload.php
などが作成されている必要があります。
出典バンドルに依存関係を含めるによると
Elastic Beanstalk がインスタンスで vendor フォルダを検出した場合、composer.json ファイルは (存在する場合でも) 無視されます。アプリケーションは vendor フォルダから依存関係を使用します。
と記載がありましたので、アップロードするzipに最初からvendorが含まれていると、composer install
が省略されてしまうようですので、注意が必要ですね・・・
php artisan config:clear