Laravel+VuejsのAWS Elastic Beanstalk環境自動設定する方法

#はじめに

AWSのElasticBeanstalk環境をカスタマイズするように.ebextensions使用して設定するという方法はあります。
インタネットで調べてみたらEBのLAMP環境やNode環境の設定する手順はいっぱい出てくるはずです。その手順の通りに実施すれば、毎回のデプロイは自動になるためく担当者はデプロイ作業の時間が縮小でき、伴ってミスも少なくなります。

```
$eb deploy #実行するだけで良い
```

今回のプロジェクトはフロントがVueJSでバックはLaravelなったし、検証環境はAWSのElasticBeanstalkに決まりましたからデプロイ手間縮小するため.ebextensionのスクリプト使って自動させることにしました。単位的なLAMP設定手順それともNodeJS設定手順はありますがLaravelはすでにVueJS含んでいますからLaravel+VueJS合わせる環境設定手順をメモして共有しておきます。

#事前準備

## Laravel導入

ローカル環境にはComposer+NodeJS(npm)がすでに導入されたという全店を踏まえてLaravelプロジェクト導入いたします。

```
composer global require laravel/installer

```

上のコマンド実行すればLaravelはグローバル的に導入されます。テストプロジェクトは下記のコマンドで新規します。

```
laravel new TestProject
```

この段階に行けばLaravelの1番簡単なプロジェクトは作成完了しました。以下のコマンドでサーバー動かしてWebBrowserひらけばサンプルのページは表示されるようになるはずです。

```
php artisan serve #http://localhost:8000開いてみてください

```
次まして、作成したプロジェクトのフォルダの内容確認して **package.json** ファイル開いてみてください。

```package.json
{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.18",
        "bootstrap": "^4.1.0",
        "cross-env": "^5.1",
        "jquery": "^3.2",
        "laravel-mix": "^4.0.7",
        "lodash": "^4.17.5",
        "popper.js": "^1.12",
        "resolve-url-loader": "2.3.1",
        "sass": "^1.20.1",
        "sass-loader": "7.*",
        "vue": "^2.5.17", 
    },
}
```

ご覧の通り、VueJSは既存値として追加されました。そういうことで残りの作業は簡単です。

```
npm install
```
** 注意点： 上記のコマンドは実行せず、「npm run dev」など実行したらエラーとなります。なぜかというとnode_modulesのフォルダはまだなくてプロジェクトに必要なライブラリーも導入されていない状態わけです。
## ElasticBeanstalk環境の初期化

ソースコード圧縮してAWSコンソルでアップして手動的なデプロイには本投稿読むのは必要ないですが今回の著者の主意に使いたいのが「EB CLI」いわゆる「ElasticBeanstalk CommandLineInterface」なので、EB CLIはすでに導入された前提とします。

ここまで行けば下記のコマンドでEBへのデプロイは簡単のです。

```
$cd TestProject
$eb init 
$eb deploy
``` 
※ [Elastic Beanstalk への Laravel アプリケーションのデプロイ](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/php-laravel-tutorial.html)

# ebextensionのファイル

プロジェクトのの下に「.ebextensions」というフォルダは作成して下記の３ファイル作成して置く

```
.￥ebextensions￥01_setup.config
.￥ebextensions￥02_env_settings.config
.￥ebextensions￥03_installations.config
```

## 01_setup.config

```
packages:
    yum:
        git: []
# Set composer folder for this command and update
commands:
   01_updateComposer:
      command: export COMPOSER_HOME=/root && /usr/bin/composer.phar self-update
   02_node_install:
        cwd: /tmp
        test: '[ ! -f /usr/bin/node ] && echo "node not installed"'
        command: 'yum install -y nodejs --enablerepo=epel'
   03_npm_install:
        cwd: /tmp
        test: '[ ! -f /usr/bin/npm ] && echo "npm not installed"'
        command: 'curl -L http://npmjs.org/install.sh | sh'
   04_node_update:
        cwd: /tmp
        test: '[ ! -f /usr/bin/n ] && echo "node not updated"'
        command: 'npm install -g n && n stable'
option_settings:
   # Add environment variable to set composer home folder
   - namespace: aws:elasticbeanstalk:application:environment
     option_name: COMPOSER_HOME
     value: /root

   # update php.ini file with new document root and specific composer --no-dev
   - namespace: aws:elasticbeanstalk:container:php:phpini
     option_name: document_root
     value: /public
   - namespace: aws:elasticbeanstalk:container:php:phpini
     option_name: composer_options
     value: --no-dev --no-interaction --prefer-dist --optimize-autoloader
#container_commands:
#   01_optimize:
#      command: "/usr/bin/composer.phar dump-autoload --optimize"

```
コマンドは自己説明的なものなのでさらに説明するのは必要がありませんと思いますが簡単にいうと下記の作業するようにスクリプト書きました

- Gitインストール
- Composer更新 (※EB環境作成する時にPHP環境に指定すればComposerはすでに導入されます）
- npm インストールされたかどうか確認してなければインストールする
- npm更新
- option_settingsのところに注意すべきなところは以下でLaravelのRootFolderは/publicになるからです。

```
   - namespace: aws:elasticbeanstalk:container:php:phpini
     option_name: document_root
     value: /public
```
## 02_env_settings.config

本ファイルはなくてもいいですが、ここでやりたいのは.envファイルS3から取得するのです。
.envファイルは不可視で色々敏感的な情報含んでいるからgitへアップロードするべきではないのでS3で保管すればいいではないかと著者はそう思っています。S3のPolicyで指定したEC2しかからアクセスできないように設定すれば安全ですね。処理流れは大体そうなります
①.envファイルをS3から取得する
②取得したファイルは/tmpに暫定的に保存する
③デプロイする際に/tmpからデプロイ用のフォルダーに移動し.envにリネームする。

※S3のPolicy設定は欲しい方々はコメントすれば個別に共有します。

```
Resources:
  AWSEBAutoScalingGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    Metadata:
      AWS::CloudFormation::Authentication:
        S3AccessCred:
          type: "S3"
          roleName: "aws-elasticbeanstalk-ec2-role"
          buckets: "test-settings"

files:
  "/tmp/test.env":
    mode: "000777"
    owner: root
    group: root
    source: https://s3-ap-northeast-1.amazonaws.com/test-settings/test.env
    authentication: S3AccessCred

container_commands:
  00_move_staging_env:
    command: "mv /tmp/test.env /var/app/ondeck/.env"
```

## 03_installation.config

```
container_commands:
   09_config:
      command: "php artisan config:clear"
      cwd: "/var/app/ondeck"
      leader_only: true
   10_migrate:
      command: "php artisan migrate --force"
      cwd: "/var/app/ondeck"
      leader_only: true
   11_seed:
      command: "php artisan db:seed --force"
      cwd: "/var/app/ondeck"
      leader_only: true
   12_cache:
      command: "php artisan cache:clear"
      cwd: "/var/app/ondeck"
   14_permissions:
      # fix permissions on the Laravel app folder
      command: "chmod 777 -R /var/app/ondeck"
      cwd: "/var/app/ondeck"

files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/49_change_permissions.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      sudo chown -R ec2-user:ec2-user /var/app/ondeck/

  "/opt/elasticbeanstalk/hooks/appdeploy/pre/50_npm.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      cd /var/app/ondeck/
      npm install && npm run dev

  "/opt/elasticbeanstalk/hooks/appdeploy/post/99_make_storage_writable.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      echo "Making /storage writeable..."
      chmod -R 777 /var/app/current/storage

      if [ ! -f /var/app/current/storage/logs/laravel.log ]; then
          echo "Creating /storage/logs/laravel.log..."
          touch /var/app/current/storage/logs/laravel.log
          chown webapp:webapp /var/app/current/storage/logs/laravel.log
      fi

      if [ ! -d /var/app/current/public/storage ]; then
          echo "Creating /public/storage symlink..."
          ln -s /var/app/current/storage/app/public /var/app/current/public/storage
      fi

  "/opt/elasticbeanstalk/tasks/publishlogs.d/laravel-logs.conf":
    mode: "000755"
    owner: root
    group: root
    content: |
      /var/app/current/storage/logs/*.log

```

導入前後実行しなければならないコマンドの定義です。Containerコマンドとして実行できないものはshファイルにします。そのまま使えばいいと思います。検証環境ですから「npm run dev」で実行するようにしていますが本番の場合「npm run production」に変更して下さい。

以上です。