Elastic BeanstalkでRailsアプリ


この記事は[Gunosy Advent Calendar 2017](https://qiita.com/advent-calendar/2017/gunosy)の12日目の記事です。
昨日は@k_7016さんの 「Service Worker触ってみた」 でした。

こんにちは、@k_7016と同じ広告技術部で普段はRuby Railsで開発している、
サンドバーグ(@s-jcs)です。

周りの記事を見ると結構ガッツリとコーディングしているのが多いとは思いましたので、
**逆に**コードをなるべく書かずに手っ取り早くウェブアプリを作ることについて書こうかと思いました。

そこで、最近自分がよく使うAWSの **Elastic Beanstalk** を使った Rails 5 のウェブアプリのつくり方をざっくり紹介します。

## **Elastic Beanstalk?**


![image.png](https://qiita-image-store.s3.amazonaws.com/0/58439/9007a17d-eb85-65cf-7cf6-f9f8420bffbb.png)


AWSの言葉を借りると、Elastic Beanstalkは単純に 「クラウドでウェブアプリケーションをデプロイおよび管理」 するサービスです。

「それってどこまでを管理してくれるの？」

ウェブアプリを走らせる上で基本的に必要なもの大体管理してくれます。
大体を具体的に言うと、
対応している下記のウェブアプリケーションかサービスが
`Java、.NET、PHP、Node.js、Python、Ruby、Go、Docker`
下記のどれかのウェブサーバを通して動く状態までを用意し
`Apache、Nginx、Passenger、IIS`
オートスケーリングやアプリケーションの状態モニタリングまでを管理してくれます。
ウェブアプリケーションを動かすうえで必要なredisなどのインスタンスや、DB (mysql/postgresql) のインスタンスももちろん Elastic Beanstalk上で管理可能（別途用意したものをあとで繋ぎ込むことも）！

## **ではでは、始めましょう**

まず最初に必要なもは...**AWSのアカウントです。**
ない方はいっぺん作ったほうがいいかもしれません（t2.microなどは新規ユーザ一年無料などなど）

基本的なセットアップはMacOS前提で話します。

AWSのアカウント作ったあとは AWSのCLIを入れます
*[AWS CLI pip経由のインストール](http://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/eb-cli3-install.html) *

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

次にRailsアプリの作成 (postgresでなくてもいいよ)

```
$ **rvm/rbenv などのrubyバージョン管理は簡略**
$ gem install rails -v 5.1.4
$ rails new railsapp -d postgresql
$ cd railsapp
$ git init && git add -A && git commit -m "Initial Commit!"
```

以下は自由ですが、画面に何か出したい場合 scaffold で適当にmodel/controllerなどを用意

```
$ rails g scaffold message subject body:text
$ rails db:migrate
$ git add .
$ git commit -am "Messages追加"
$ git push
```

Railsアプリ作成後、Elastic Beanstalkをinitializeします

```
$ eb init

Select a default region <-- リージョン選択
9) ap-northeast-1 : Asia Pacific (Tokyo)

Select an application to use <-- ElasticBeanstalkでのアプリを選択（新規作成）
1)[ Create new Application ]

Enter Application Name <-- アプリの名前入力（未入力だと rails new した時の名前）
(default is "railsapp"):
Application railsapp has been created.

It appears you are using Ruby. Is this correct? <-- Rubyつかってる？はいΣ(´∀｀；)
(y/n): y

Select a platform version. <-- Rubyバージョン指定
1) Ruby 2.4 (Puma)

Note: Elastic Beanstalk now supports AWS CodeCommit; 
a fully-managed source control service. 
To learn more, see Docs: https://aws.amazon.com/codecommit/
Do you wish to continue with CodeCommit?  <-- AWSが提供するgithubっぽいの使う？ 
(y/N) (default is n): n

Do you want to set up SSH for your instances? <-- インスタンス用のSSH発行する？
(y/n): y

Select a keypair. <-- key-pair 選択
1) [ Create new KeyPair ]
(default is 1): 1
```

eb initが正常終了すると .elasticbeanstalkなどのファイルが作成されてるので、、
commitして最後に **eb create production** でelastic beanstalkの環境作成をする 

```
$ git commit -am "Post EB init"
$ eb create prd
```

「ん、、環境作成？」

はい、環境作成です。createしている間は elastic beanstalkが
`loadbalancers`,`security group`,`EC2インスタンス`などを**全部**作ってくれてます。
ちょっと時間がかかるので、お茶を飲みながらのんびり待ってください。

セットアップが完了したら

```
$ eb status
```

で環境のステータスがすぐに確認できます！

## その後の設定

init後早速deployなどがfailしている可能性があるのですが、
その際は `eb logs` で rails app logs, nginx access logs, setup logs
が確認できます！

初期設定の状態で以下の用なエラーがでるかもしれません、、

### **サーバーに接続できない**

```
  + su -s /bin/bash -c 'leader_only bundle exec rake db:migrate' webapp
  `/home/webapp` is not a directory.
  Bundler will use `/tmp/bundler/home/webapp' as your home directory temporarily.
  rake aborted!
  PG::ConnectionBad: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
  /opt/rubies/ruby-2.4.2/bin/bundle:23:in `load'
  /opt/rubies/ruby-2.4.2/bin/bundle:23:in `<main>'
  Tasks: TOP => db:migrate
  (See full trace by running task with --trace) (Executor::NonZeroExitStatus)
```
この場合 db:migrate 実行時、
DBが見つからないようなので、これまた Elastic Beanstalkの AWS Console、
`Configuration` > `Data Tier` で新しいRDSインスタンスを作成

作成したらすぐに環境がupdateされ始めるので待ちです

### **Secrets/Envの設定がない**

実際にRailsを動かすには
Elastic BeanstalkでRails用にENVの設定とsecretsの設定が以下のように必要

```
$ eb setenv SECRET_KEY_BASE=$(rails secret)
INFO: Environment update is starting.
INFO: Updating environment production's configuration settings.
INFO: Environment health has transitioned from Ok to Info. 
Configuration update in progress. 1 out of 1 instance 
completed (running for xx seconds).
INFO: Successfully deployed new configuration to environment.
```

### **production DBの設定が足りてない**
Elastic BeanstalkでRDSインスタンスを管理している場合それらの値はENVに保持されるので
database.ymlに設定を忘れぜずに

```
production:
    <<: *default
    adapter: postgresql
    encoding: unicode
    database: <%= ENV['RDS_DB_NAME'] %>
    username: <%= ENV['RDS_USERNAME'] %>
    password: <%= ENV['RDS_PASSWORD'] %>
    host: <%= ENV['RDS_HOSTNAME'] %>
    port: <%= ENV['RDS_PORT'] %>
```

## すべて他うまく行けば...

`deploy`コマンドで作った環境最新できます

```
$ eb deploy
```

この時点でAWSConsoleのElasticBeanstalkのページは全部緑色のはず...

messagesのscaffoldを作った場合AWS Consoleのelastic beanstalkにある URL + '/messages'
をすれば。。。
`http://production.xxxxxxx.ap-northeast-1.elasticbeanstalk.com/messages`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/58439/3a7fa6ec-6eb7-78af-a8a2-bedf8a0d8fe4.png)

やったー

## まとめ

Railsの初期設定の違いですぐにデプロイできない時もありますが、
基本的には　`eb deploy` > `eb logs` で、どの段階で落ちたかがすぐに確認でき、Debugしやすいはず！
ほかのよくある問題は基本的には local で rails s で確認できる問題が多いかと！

今回のElastic Beanstalkの説明を見てわかると思いますが、AWSでのめんどくさい security-group, ELB, RDS / EC2 instances作成・スケール周りがかなり自動化され楽になります。

小さいインスタンスだけで遊び半分で軽くアプリを作ってみるのはどうでしょう

## 参考資料

[How to setup and deploy a Rails 5...](https://hackernoon.com/how-to-setup-and-deploy-a-rails-5-app-on-aws-beanstalk-with-postgresql-redis-and-more-88a38355f1ea)
[Deploying a Rails Application to Elastic Beanstalk](http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_Ruby_rails.html)
[Deploying a Rails 5 App using Elastic Beanstalk](https://medium.com/@jameshamann/deploying-rails-5-app-using-elastic-beanstalk-and-postgresql-8ca19bc7648a)