🧑‍💻

Laravel + AWS Elastic Beanstalkの環境構築

2021/02/27に公開

Elastic Beanstalkとは?

Elastic Beanstalk(以下EB)は一言で言えばAWSでサーバーを立てる際の初期設定を自動でやってくれるAWSの公式ツールです。

AWSは実際サーバーを立てようと思ったとき、サーバーを複数台構成にして、ロードバランサーも入れて、DNSでルーティングもしなきゃ…という設定をひとつずつやっていくのは結構大変です。ましてサーバーエンジニアでもない開発者であれば、そもそもどうやっていいか分からない場合も多いと思います。
そういったときにEBを使えば、条件を色々と設定するだけであとはわずか数分で自動的に設定してくれます。これはサーバーエンジニアであっても、手間なくミスもなくできるので便利。

今回はこのEBを使ってLaravelをDeployして動作させるところまでをやってみたいと思います。

設定条件

  • サーバー:AWS Elastic Beanstalk(環境設定済み)
  • 公開するプログラム:Laravel

※AWS Elastic Beanstalkの初期設定方法は詳しく書かれている方がたくさんいるので、今回は省略します

EB on Laravelの公式ドキュメント

EBへのLaravelのDeployについてはまさにそれな公式ドキュメントがあります。
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/php-laravel-tutorial.html
じゃあこの通りやればこの記事を読むまでもないな、と思うところですが実はこの↑ドキュメント、「不完全」です。
間違ってはないのですが、実用的な設定がいくつか足りていません。。
公式なのになんなんだという苛立ちを抑えつつ、続きをお読みください。。

とりあえず公式の手順を参考に進めますので、公式ドキュメントと合わせてお読みください。

1.EBの環境作り

公式手順通りでOKです。

2.Laravelのインストール

公式手順通りでいいのですが、既にローカルに用意がある場合はスルーでOKです。

3.EBへのデプロイ

EBでは公開するファイル群をzip圧縮して、AWSコンソール上からzipファイルをアップロードするという手順でデプロイを行います。一般的におそらく以下2パターンがあるかと思います。

a. ローカルファイルをそのままzip圧縮

普通に圧縮する手順です。公式手順ではコマンドで圧縮をしていますがzipになっていればなんでも構いません。ただ少しポイントがあります。

vendorは除外できる

公式でvendorを除外している通り、vendorは除外してしまって構いません。じゃあcomposerのプログラム群はどうすればいいのかと思いますが、実は公式にはどこにも書かれていないのですが、デプロイした時点でcomposer installが自動実行されます。

公式ドキュメントでは

vendor フォルダ内のファイルは…(略)…多くのスペースを使用するだけでなく、アプリケーションを Elastic Beanstalk にデプロイするのに不要です。

と言っているのに、なぜcomposer installが自動実行されることを書かない謎。

b. Gitのリポジトリ内容をZip圧縮

ソースをGit管理している方はほぼこのかたちかなと思います。これなら普通vendorディレクトリもgitignoreで除外していると思うので、除外する操作も不要です。
以下gitコマンドで実行できます。

git archive HEAD --output=xxxxx.zip

HEAD の部分は、タグ名、ブランチ名、コミットID、などが指定できます。
xxxxx.zipの部分が出力するファイル名になります。

4.ドキュメントルートを/publicに変更

公式ドキュメント通りです。通常はサイトルートが直下になっているので、/publicに変更します。

5.DB設定

ドキュメント通りですが、このあたりはそもそも普通は1の手順で行っているのではないかなと思います。

6.完了確認

ここまでできれば、Laravelの初期画面を確認して完了かと思います。
公式ドキュメントも初期画面を確認してめでたしめでたしということで、クローズ方法まで丁寧に解説されています。

公式ドキュメントの不足点

一見すべてOKに見える公式ドキュメントですが、実際運用を考えると必ず行わなければいけない設定がいくつか抜けています。

1.下層ページが開かない

前述したとおり、公式ドキュメントでは初期画面を確認して終わっていますが、実は下層ページが404になり開きません。
LP1ページ構成のサイトのためにLaravelを選択する人はまずいないと思いますので(笑)必ず追加設定が必要になります。

原因としてはnginxやapacheで行う、ルーティングの設定が抜けています。この設定が無いと下層ページはアクセスしたパスそのものを見に行ってしまうのでファイルが存在せず404となります。
EBではnginxで動いていますのでその設定を書き換えます。
EBではサーバー自体の設定も、特定ディレクトリに設定ファイルを置くことで実現できます。(最初はこれに気がつかずAWSコンソール内を探し回ってました)

ローカルのプロジェクト内に下記ディレクトリをつくり、その中に以下に示す内容を記載したファイルを作成します。

/.platform/nginx/conf.d/elasticbeanstalk

※.platformのディレクトリ位置はlaravelのapp,publicディレクトリ等と同階層でプロジェクト直下です。

# path: /.platform/nginx/conf.d/elasticbeanstalk/laravel.conf

location / { 
    try_files $uri $uri/ /index.php?$query_string;
}

ちなみにhttpsへのリダイレクトやパフォーマンスを考慮した実用系だと以下のような感じですね。

# path: /.platform/nginx/conf.d/elasticbeanstalk/laravel.conf

location / {
    if ($http_x_forwarded_proto != https) {
        return 301 https://$host$request_uri;
    }
    try_files $uri $uri/ /index.php?$query_string;
    gzip_static on;
}

このファイルを設置したら、これを含めた公開zipファイルを作り、再びアップロードして公開してOKです。

2.envの切替が考慮されていない

もう1つ実用において決定的な問題が、見出しの通り「envの切替」です。
一般的にローカルで環境を作ってテストして、それを公開する際はenvの環境設定を本番用に切り替えて行うかたちが多いと思いますが、公式ドキュメントはその点が考慮されていません。

対応方法は2パターンあります。

a. envファイルを書き換え

あらかじめ.env.prodというような公開用envファイルを用意しておき、公開フローの中で.envに置き換える手順です。
EBでは公開時の追加作業パターンについても、先ほどのnginxの設定書き換え同様に、特定ディレクトリに設定ファイルを置くことで実現できます。

以下ディレクトリに設定ファイルを設置します。

/.ebextensions/01-setting.config

01-settingの部分は任意の名前を付けられます。設定ファイルを複数置くこともでき、その際は名前のソート順で上から順次実行されるため”01-xxxxx.config”という感じで番号を振っておくと分かりやすいです。

下記内容を記載して保存します。

# /.ebextensions/01-setting.config

container_commands:
  00_copy_env_file:
    command: "mv .env.prod .env"

先の手順と同様に、これを含めた公開zipファイルを作り、再びアップロードして公開します。

b. サーバーの環境変数を設定

おそらくこちらの方が合理的です。.envファイルは置かずに、サーバーの環境偏すとして.envに記載の値を設定します。

これも先の手順と同じく、.ebextensionsにファイルを置く形で設定できます。

# /.ebextensions/01-enviromnent.config

option_settings:
  "aws:elasticbeanstalk:application:environment":
    APP_NAME: SITENAME
    APP_ENV: local
    APP_KEY=base64:xxxxxxxxxx=
    APP_DEBUG=false
    APP_URL=http://aaaa.com
        …

こんな感じで.envに記載のすべてのパラメータを記述します。最初だけそれなりに大変です。

3.migrationされない

EBはcomposer installは何も言わずやってくれるのにmigrationは言わないとやってくれないようです。笑
ということで、やはり.ebextensionsで実行します。

# /.ebextensions/02-migration.config

container_commands:
  01-migrations:
    command: "php artisan migrate --force"

php artisan migrateだけでなく”--force”が付いていますが、これを付けることで「本番環境だけど実行していいの?(yes / no)」という主旨だと思われる英語の親切メッセージをパスすることができます。

また、ここでは新たなファイルにしましたが、01-setting.configの続きとして記載でも構いません。(↓こんな感じ)

# /.ebextensions/01-setting.config

container_commands:
  00_copy_env_file:
    command: "mv .env.prod .env"
  01-migrations:
    command: "php artisan migrate --force"

4.その他設定

とりあえずここまで設定すれば一応実用的な使い方はできますが、.ebextensionsはいろいろな設定ができるので私自身がさらに追加で設定するいつものやつを記載しておきます。

サーバーの時刻設定を日本時間に変更

# /.ebextensions/00-set-timezone.config

commands:
  set_time_zone:
    command: ln -f -s /usr/share/zoneinfo/Japan /etc/localtime

アップロードサイズの変更

# /.ebextensions/change-upload-size.config

files:
    "/etc/php.d/99uploadsize.ini":
        mode: "000644"
        owner: root
        group: root
        content: |
            upload_max_filesize = 32M
            post_max_size = 32M
commands:
    remove_old_ini:
        command: "rm -f /etc/php.d/99uploadsize.ini.bak"

imagickの利用

#/.ebextensions/use-imagick.config

packages:
    yum:
        ImageMagick: []
        ImageMagick-devel: []
 
commands:
    01_install_imagickphp:
        cwd: /tmp
        test: "php -r \"exit(extension_loaded('imagick') ? 1 : 0);\""
        command: |
           wget https://pecl.php.net/get/imagick -O imagick \
            && tar xvzf imagick \
            && cd imagick-* \
            && phpize \
            && ./configure \
            && make \
            && make install \
            && echo extension=imagick.so > /etc/php.d/imagick.ini

サイトルートの設定
※実は最初にAWSコンソールから行ったサイトルートの設定もこれで行うことができます

#/.ebextensions/01-setting.config

option_settings:
  aws:elasticbeanstalk:container:php:phpini:
    document_root: /public

まとめ

設定は以上になります。
わりと手順が長くなってしまいましたが、追加の設定は管理画面で行うものでなくすべてファイルを生成して記載するものなので、基本パターンのファイルを用意しておけばそれをコピペするだけで使い回せます。

優しいのか優しくないのか分からない公式ドキュメントに踊らされた方のお役に立てば幸いです。

Discussion