Laravel アプリケーションを、 Circle CI 経由で AWS ElasticBeanstalk に自動デプロイ

Laravel で作っているアプリケーションのデプロイ自動化に成功した。

プルリクをマージしたら、勝手にEBにデプロイしてくれる。

設定は飛ばして、作成したファイルのみ記載する。

# 概要

- Laravel 5.1
- PHP 7.0

![deploy.png](https://qiita-image-store.s3.amazonaws.com/0/103885/2222a750-4677-443a-47b3-8a1a82168c1a.png)


# Circle CI 関連の設定

Circle CI 内のコンテナで実行すること、またデプロイブランチの設定

```yaml:circle.yml
machine:
  timezone: Asia/Tokyo
  php:
    version: 7.0.4
  environment:
    APP_ENV: testing
    APP_KEY: base64:***************/*******************=
deployment:
  develop:
    branch: develop
    commands:
      - bash ./ci/setup-eb.sh
      - bash ./ci/deploy-circle.sh dev
  production:
    branch: master
    commands:
      - bash ./ci/setup-eb.sh
      - bash ./ci/deploy-circle.sh production
```

EBの設定。アクセスキーは環境変数で与えるため、Circle CI 側で設定しておく。

```bash:ci/setup-eb.sh
#!/bin/bash

set -xue

sudo apt-get install -y python-dev
pip install awsebcli

mkdir /home/ubuntu/.aws
touch /home/ubuntu/.aws/config
chmod 600 /home/ubuntu/.aws/config
echo "[profile eb-cli]" > /home/ubuntu/.aws/config
echo "aws_access_key_id=$AWS_ACCESS_KEY_ID" >> /home/ubuntu/.aws/config
echo "aws_secret_access_key=$AWS_SECRET_ACCESS_KEY" >> /home/ubuntu/.aws/config
```

デプロイシェル。

`eb deploy` で、プロジェクトに現在あるファイルをそのままEBのコンテナに持っていく。
下手にデプロイツールを使うより、 `eb deploy` した方が良い。理由は

- ダウンタイム無し
- オートスケールなどで複数のインスタンスで動いている場合、全てのインスタンスにデプロイしてくれる

```bash:ci/deploy-circle.sh
#!/bin/bash
# Usage: bash ci/deploy-circle.sh [dev|production]

set -xeu

# Ensure this script is executed in Circle CI
echo $CIRCLE_SHA1

deploy_env=$1

if [ ${deploy_env} = 'dev' ] ; then
    eb use ****_dev
    cp .env.dev .env
elif [ ${deploy_env} = 'production' ] ; then
    eb use ****_prod
    cp .env.production .env
fi

gulp --production

eb deploy
```

ここはポリシー次第だが、私の会社では `.env` ファイルをリポジトリに含めているため、上記のスクリプトにしている。

```bash:tree
project
  |- .env.example
  |- .env.dev
  `- .env.production
```

`.ebignore` に `.gitignore` と同じような記法で、 `eb deploy` で含めたくないファイルを指定できる。
デプロイ時間を短縮するのに大事。

```bash:.ebignore
bin
docker
.elasticbeanstalk
.env.*
*.bak
.git
node_modules
tests
tags

# Elastic Beanstalk Files
.elasticbeanstalk/*
```

# EBの設定

EBのリージョンなどの設定。

```yaml:.elasticbeanstalk/config.yml
branch-defaults:
  develop:
    environment: ****

global:
  application_name: ****
  default_ec2_keyname: ****
  default_platform: arn:aws:elasticbeanstalk:ap-northeast-1::platform/PHP 7.0 running
    on 64bit Amazon Linux/2.3.0
  default_region: ap-northeast-1
  instance_profile: null
  platform_name: null
  platform_version: null
  profile: eb-cli
  sc: git
  workspace_type: Application
```

EBのコンテナ内でデプロイのタイミングで行うコマンド。
Apacheを利用している場合。

```yaml:.ebextensions/deploy.config
container_commands:
  01-artisan:
    command: |
      sudo php artisan clear-compiled
      sudo php artisan optimize
      sudo php artisan config:cache
      sudo php artisan view:clear
      php artisan migrate
files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/99_make_storage_writable.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      sudo chmod -R 700 /var/app/current/storage
      sudo chmod -R 700 /var/app/current/public
      sudo chmod -R 700 /var/app/current/bootstrap/cache/services.json
      sudo php /var/app/current/artisan clear-compiled
      sudo php /var/app/current/artisan optimize
      sudo php /var/app/current/artisan config:cache
      sudo php /var/app/current/artisan route:cache
      sudo php /var/app/current/artisan view:clear
  "/etc/httpd/conf.d/ssl_rewrite.conf":
      mode: "000644"
      owner: root
      group: root
      content: |
          RewriteEngine On
          <If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
          RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
          </If>
```

ここで結構はまった。

`01-artisan` でキャッシュを消しておかないと、 Circle CI 以外からデプロイする場合に設定がおかしくなるので注意。