ElasticBeanstalkを使ってRailsをデプロイする

# ElasticBeanstalkを使ってRailsをデプロイする

- OS: macOS High Sierra
- Version: 10.13.5

## 1. AWSのアカウントを作る
// TODO

## 2. ローカル環境の設定

- AWS系

```
$ brew update
$ brew install awscli
$ brew install aws-elasticbeanstalk
```

- Docker系

```
$ brew install docker
$ brew cask install docker
$ open -a docker // dockerの起動

$ sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.21.2, build 1719ceb
```


## 3. Railsプロジェクトの作成
```
$ mkdir eb-sample
$ cd eb-sample
$ touch Dockerfile
$ touch docker-compose.yml
$ touch Gemfile
```

`Dockerfile`

```dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp
```

`docker-compose.yml`

```yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

`Gemfile`

```
source 'https://rubygems.org'
gem 'rails', '5.2.0'
```

- Railsプロジェクトの作成
- 権限設定
- ビルド

```
$ docker-compose run web rails new . --force --database=postgresql
$ sudo chown -R $USER:$USER .
$ docker-compose build
```

DB設定を変更(`config/database.yml`)

```yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test
```

```
$ docker-compose run web rake db:create
$ docker-compose up 
$ open localhost:3000
```

```
$ git add .
$ git commit -m "add rails setting"
```

## 4. ElasticBeanstalkへのデプロイ

```
$ aws configure --profile [AWSアカウント(`~/.aws/config`に登録済み)]
```

```
$ eb init eb-sample --platform docker --keyname aws-eb 
$ eb create eb-sample-dev 

INFO: Successfully built aws_beanstalk/staging-app
ERROR: No EXPOSE directive found in Dockerfile, abort deployment
ERROR: [Instance: i-0849603a39b46935b] Command failed on instance. Return code: 1 Output: No EXPOSE directive found in Dockerfile, abort deployment.
```

ここまででRailsプロジェクトの作成が完了、ただこのままでは以下の問題があるためエラーが発生する

- Dockerコンテナの公開ポートが指定されてない
- DB連携がされていない
- マイグレーションのような初期処理が実行されてない


ここからはこれらの問題を解消する。

### Dockerコンテナの公開ポートが指定されてない

Dockerfileに以下を追記

```
...

EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
```

```
$ git add .
$ git commit -m "add docker expose port"
$ eb deploy 
INFO: New application version was deployed to running EC2 instances.
INFO: Environment update completed successfully.

$ eb open // デプロイしたプロジェクトのURLを開く
```

### DB連携がされていない

ElasticBeanstalkのコンソール画面を開き
設定 > データベース(変更) をクリック

- エンジン: postgres
- ユーザー名: postgres
- パスワード: XXXX(好きなパスワード)

を設定(初期設定にしばらくかかるので待機)

次に `config/database.yml` を更新

```yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: <%= ENV.fetch("RDS_HOSTNAME") { "db" } %>
  username: <%= ENV.fetch("RDS_USERNAME") { "postgres" } %>
  password: <%= ENV.fetch("RDS_PASSWORD") { "" } %>
  port: <%= ENV.fetch("RDS_PORT") { "5432" } %>
  pool: 5

development:
  <<: *default
  database: <%= ENV['RDS_DB_NAME'] { "myapp_development" } %>

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: <%= ENV['RDS_DB_NAME'] %>
```

```
$ git add .
$ git commit -m "update database setting for eb"
$ eb deploy
$ eb open
```

開いたページで `Yay! You’re on Rails!` が表示されていれば成功。

### マイグレーションのような初期処理が実行されてない

ここまででRailsのトップ画面の表示には成功した。
ただこのままではDBへのアクセスが必要なページは表示できない

試しにTodoモデルを追加して確認してみる

```
$ docker-compose run web rails g scaffold todo title:string completed:boolean
$ docker-compose run web rake db:migrate
$ docker-compose up -d 
$ http://localhost:3000/todos
```

```
$ git add .
$ git commit -m "add todo model"
$ eb deploy 

INFO: Environment update completed successfully.
```

`eb open` で開いてみると、、、
`ActiveRecord::PendingMigrationError` と表示されている.

ここからはこのエラーの解消を行う.

`dockerfile` を変更

```
...

ADD start.sh /myapp/bin/start.sh
RUN chmod +x /myapp/bin/start.sh
EXPOSE 3000
CMD ["bin/start.sh"]
```

`start.sh` ファイルを追加

```
#!/bin/bash
bundle exec rake db:migrate
bundle exec rake assets:precompile
bundle exec rails server
```

このようにする事でDockerの起動時にマイグレーション処理などを実行する事ができる

```
$ git add .
$ git commit -m "update dockerfile"
$ eb deploy
$ eb open
```

開いたページでエラーがなく `/todos` を開ければ成功

# まとめ
以上の処理でElasticBeanstalkを使いRailsプロジェクトをデプロイする事ができた。
この他に実際にサービスをリリースするにはドメインの割当や、TLSの設定、可用性の検証などが必要になるがElasticBeanstalkを使う事でAWSでのデプロイ作業を効率化でき、VPCやEC2のような具体的なサービス構成を意識する事なくHerokuを使うような感覚で進められた。

# 参考
- [aws cli install mac](https://qiita.com/maimai-swap/items/999eb69b7a4420d6ab64)
- [Elastic BeanstalkでRailsアプリ](https://qiita.com/s-jcs/items/dd830f5eaa759e08c928)
- [Install Docker Compose](https://docs.docker.com/compose/install/#install-compose)
- [最速！MacでRuby on Rails環境構築](https://qiita.com/narikei/items/cd029911597cdc71c516)
- [Quickstart: Compose and Rails](https://docs.docker.com/compose/rails/)
- [AWS CLIのプロファイルを切り替えてebコマンドで既存ElasticBeanstalk Applicationにアクセスする](https://dev.classmethod.jp/etc/aws-eb-multi-profile/)
- [Rails on DockerをElastic Beanstalkにデプロイする](https://dev.classmethod.jp/cloud/aws/deploy-rails-on-docker-to-elasticbeanstalk/)