今回は「Ruby on Rails」で作成したWebアプリケーションをAWSのサービス「Elastic Beanstalk」でデプロイするまでの手順について紹介していきたいと思います。

デプロイ方法についてはすでに色々なサイトで解説されていますが、情報が古かったりして自分の環境では上手く動かなったり、UIの変更によってわかりにくかったりする部分も多々あったので、この記事を書いている2020年現在に通用したプロセスをそのまま残していくつもりです。

人それぞれ環境は違いますから、もしかすると全く参考にならない可能性もあります。その点はご了承ください。

途中で何度もエラーが発生する事もしたので、それらの対応についても掲載しておきます。もし同じようなエラーに遭遇された場合は参考にしてみてください。

Elastic Beanstalkとは

そもそもの話、Elastic Beanstalkとは一体何なのか?

僕もAWSの学習を始めてから日が浅いため、ぶっちゃけハッキリとはわかっていないというのが実際のところですが、ざっくり言ってしまうと

「ソースコードさえ渡してくれればインフラ周りの準備は全部こっちがやってあげるよー」

といった感じのサービスだと実際に使ってみる中で感じました。

 

「PaaS(パース)」と言えば良いのでしょうか。お馴染みのHerokuみたいな感じですね。ただ、個人的にはElastic Beanstalkの方が全然難しかったです。何せ情報量が少ない…。

 

通常、AWSを使ってアプリをデプロイしようと思ったら「VPCを作って、サブネットを作って、セキュリティグループを作って、EC2を設置して、NginxやUnicornの設定をして~」なんてプログラミング初学者にとってはまさに意味不明な手順を踏まなければいけませんが、Elastic Beanstalkではそういったものを省略して全て自動で用意してくれます。

 

参照記事:世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで

(こちらの記事を読めばいかに面倒かわかるはず。)

 

そのため、一からインフラの事を学びたいという方には向かないかもしれませんが、なるべく手短にサクッとアプリをデプロイしたい人にはぜひ使ってみて欲しいです。

 

ちなみに、Beanstalkというのは「豆の木」といった意味があるんだとか。読み方は「ビーンスターク」。僕はずっと「ビーンズトーク(豆の会話って一体何ぞ…?)」だと思っていたので、つい恥をかくところでした。

 

 

ビーンスターク【beanstalk】

豆の茎。また、英国民話「ジャックと豆の木」で主人公が手に入れた、一晩で大木のように成長する豆の木のこと。

出典:デジタル大辞泉(小学館)

前提環境

自分の場合は下記のような環境で作業を行いました。

  • Ruby: 2.6.3
  • Rails: 5.2.4
  • masOS: High Sierra(バージョン 10.13.6)

 

デプロイするアプリはこちら(https://github.com/kazama1209/ramen-quest

※僕が就活用に作ったポートフォリオです。ただ単に使い方の勉強をしたい場合、上のリポジトリからクローンしてこれから説明する通りに手を動かせば全く同じ結果になると思います。

実際の手順

ではさっそく手を動かしていきましょう。

 

今回、自分がElastic Beanstalkへのデプロイに挑戦する上で参考にした記事は次の通り。

 

大まかな流れとしてはこれらの指示に従いつつ、残念ながら自身の環境で上手くいかない部分については独自の対処を行いました。

なお、上の記事内で既に詳しく解説していただいている部分についてはわざわざ深く掘り下げるつもりは無いので、こちらの記事と同時に開きながら読み進めるとよりスムーズにいくと思います。

IAMユーザーの作成

作業を行うためのIAMユーザーを作成し、アクセスキーとシークレットアクセスキーを忘れないようにメモしておきます。(.csvファイルをダウンロードして保管しておくとより安心)

EB CLI をインストール

自身のターミナルでElastic Beanstalkを操作するために、「EB CLI」というツールをインストールします。

インストール

$ brew install awsebcli
==> Downloading https://homebrew.bintray.com/bottles/aws-elasticbeanstalk-3.9.0.sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring aws-elasticbeanstalk-3.9.0.sierra.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
/usr/local/etc/bash_completion.d
==> Summary
/usr/local/Cellar/aws-elasticbeanstalk/3.9.0: 1,540 files, 31M
バージョン確認
$ eb --version
EB CLI 3.16.0 (Python 3.8.1)

 

各種キー設定(※IAMユーザー作成時に発行されたものを入力)
 
$ aws configure
AWS Access Key ID [None]: *********
AWS Secret Access Key [None]: **********************
Default region name [None]: ap-northeast-1
Default output format [None]: json

 

ちゃんと設定できるか心配な方は次のコマンドを入力する事で確認できます。

 
$ cat ~/.aws/config
$ cat ~/.aws/credentials

 

デプロイ用アプリケーションのセットアップ

EB CLIのインストールが済んだら、次は実際にデプロイするアプリケーションのリポジトリ内へ入り、セットアップを行っていきます。対話形式で進んでいくので、聞かれた事に対し自分で回答を入力していきましょう。

※人によって聞かれる項目や選択肢が異なる可能性もあります。

 

リポジトリ内へ移動
 
$ cd 自分のアプリ 

 

初期セットアップ
$ eb init
Select a default region
1) us-east-1 : US East (N. Virginia)
2) us-west-1 : US West (N. California)
3) us-west-2 : US West (Oregon)
4) eu-west-1 : EU (Ireland)
5) eu-central-1 : EU (Frankfurt)
6) ap-south-1 : Asia Pacific (Mumbai)
7) ap-southeast-1 : Asia Pacific (Singapore)
8) ap-southeast-2 : Asia Pacific (Sydney)
9) ap-northeast-1 : Asia Pacific (Tokyo)
10) ap-northeast-2 : Asia Pacific (Seoul)
11) sa-east-1 : South America (Sao Paulo)
12) cn-north-1 : China (Beijing)
13) cn-northwest-1 : China (Ningxia)
14) us-east-2 : US East (Ohio)
15) ca-central-1 : Canada (Central)
16) eu-west-2 : EU (London)
17) eu-west-3 : EU (Paris)
18) eu-north-1 : EU (Stockholm)
19) ap-east-1 : Asia Pacific (Hong Kong)
20) me-south-1 : Middle East (Bahrain)
(default is 3): 9 ※今回は東京リージョンを選択。

Enter Application Name
(default is "リポジトリ名"): ※任意の名前を入力。何もせずエンターを押すとリポジトリ名で作成される。 
Application リポジトリ名 has been created.

It appears you are using Ruby. Is this correct?
(Y/n): Y ※Rubyを使用しているかどうか聞かれているのでYes。

Select a platform version.
1) Ruby 2.6 (Passenger Standalone)
2) Ruby 2.6 (Puma)
3) Ruby 2.5 (Passenger Standalone)
4) Ruby 2.5 (Puma)
5) Ruby 2.4 (Passenger Standalone)
6) Ruby 2.4 (Puma)
7) Ruby 2.3 (Passenger Standalone)
8) Ruby 2.3 (Puma)
9) Ruby 2.2 (Passenger Standalone)
10) Ruby 2.2 (Puma)
11) Ruby 2.1 (Passenger Standalone)
12) Ruby 2.1 (Puma)
13) Ruby 2.0 (Passenger Standalone)
14) Ruby 2.0 (Puma)
15) Ruby 1.9.3
(default is 1): 2
Do you wish to continue with CodeCommit? (y/N) (default is n): n
Do you want to set up SSH for your instances?
(Y/n): Y ※この辺は自分に合ったものを選択する。

Select a keypair.
1) hoge
2) foo
3) bar
4) [ Create new KeyPair ]
(default is 4): 1 ※過去に自分が作ったキーペアの中から選ぶか、新たに作成する。

 

設定を確認
 
$cat .elasticbeanstalk/config.yml
branch-defaults:
  master:
    environment: null
    group_suffix: null
global:
  application_name: リポジトリ名
  branch: null
  default_ec2_keyname: キー名
  default_platform: Ruby 2.6 (Puma)
  default_region: ap-northeast-1
  include_git_submodules: true
  instance_profile: null
  platform_name: null
  platform_version: null
  profile: null
  repository: null
  sc: git
  workspace_type: Application

 

先ほどの「eb init」後、ルートディレクトリに「.elasticbeanstalk/config.yml」というファイルが生成されているので中身を確認しておきましょう。それぞれが何を意味しているのか自分もぶっちゃけ良くわかりませんが、特に問題無かったのでそのまま進みます。

EC2の作成

次に、AWS上にアプリをデプロイするための環境である「EC2」を作成していきます。EC2と聞くと苦手意識を持たれる方もいるかもしれませんが、ここでは特に難しい操作も無く「eb create」というコマンドを叩けばOK。

 

デプロイするための環境を構築
 $ eb create
Enter Environment Name
(default is ramen-quest-dev): ※特に希望が無ければ空のままエンターキー。
Enter DNS CNAME prefix
(default is ramen-quest): こちらも上と同様。

Select a load balancer type
1) classic
2) application
3) network
(default is 2): 1

Would you like to enable Spot Fleet requests for this environment?
(y/N): N
Creating application version archive "app-9c74-200106_043901".
Uploading: [##################################################] 100% Done...
... (中略) ...

 

するとこんな感じでアプリケーション環境の構築が始まるので、完了するまでしばらく待ちます。

 

エラー発生
2020-01-05 19:41:43    INFO    Command execution completed on all instances. Summary: [Successful: 0, Failed: 1].
2020-01-05 19:42:47    ERROR   Create environment operation is complete, but with errors. For more information, see troubleshooting documentation.
                                
ERROR: ServiceError - Create environment operation is complete, but with errors. For more information, see troubleshooting documentation.

 

数分後、画面を見てみるとまさかのエラー。処理自体は終わったものの、どこかで不具合が生じているようです。

 

 

Elastic Beanstalkのダッシュボードを確認してみると、明らかにエラーだとわかる赤色に染まっていました。

 

$ eb logs

 

慌てずにまずはログを確認。

 

 

/var/log/eb-activity.log
 
  + '[' -d /var/app/ondeck/vendor/cache ']'
  + bundle install
  /opt/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems.rb:284:in `find_spec_for_exe': Could not find 'bundler' (2.0.2) required by your /var/app/ondeck/Gemfile.lock. (Gem::GemNotFoundException)
  To update to the latest version installed on your system, run `bundle update --bundler`.
  To install the missing version, run `gem install bundler:2.0.2`
  	from /opt/rubies/ruby-2.6.5/lib/ruby/site_ruby/2.6.0/rubygems.rb:303:in `activate_bin_path'
  	from /opt/rubies/ruby-2.6.5/bin/bundle:23:in `<main>' (Executor::NonZeroExitStatus)

 

Elastic Beanstalkはソースコードをアップした際、自動で「bundle install」を実行してくれるそうなのですが、どうやらエラー文を読んでみると「bundler:2.0.2」が無いと怒られている様子。

 

ググってみた結果、「.ebextensions」という隠れディレクトリをルートに作成し、「.conifg」を拡張子とするYMLもしくはJSON形式のファイルを置く事で、デプロイ前後に実行するコマンドやファイルを追加するための設定を行う事ができるそうです。

 

参照記事

 

.ebextensions/00_yarn.configを追加
files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/09_yarn.sh" :
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      set -xe

      EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
      EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
      EB_APP_USER=$(/opt/elasticbeanstalk/bin/get-config container -k app_user)
      EB_SUPPORT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k support_dir)

      . $EB_SUPPORT_DIR/envvars
      . $EB_SCRIPT_DIR/use-app-ruby.sh

      # Install nodejs
      echo "install nodejs"
      curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash -
      yum -y install nodejs
      echo "install yarn"
      # install yarn
      wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo;
      yum -y install yarn;

      # yarn install
      cd $EB_APP_STAGING_DIR
      yarn install --ignore-engines

      # mkdir /home/webapp
      mkdir -p /home/webapp
      chown webapp:webapp /home/webapp
      chmod 700 /home/webapp

 

.ebextensions/01_options.configを追加
option_settings:
  aws:elasticbeanstalk:environment:
    LoadBalancerType: application
  aws:autoscaling:launchconfiguration:
    InstanceType: t3.small
    # The additional security group
    # refer: https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/configuration-files/aws-provided/security-configuration/securitygroup-addexisting.config
    SecurityGroups: default
  # aws:elasticbeanstalk:application:environment: {}

packages:
  yum:
    htop: []
    strace: []

files:
  # https://stackoverflow.com/a/55378320/3090068
  #
  # Runs before `./10_bundle_install.sh`:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/09_gem_install_bundler.sh" :
    mode: "000775"
    owner: root
    group: users
    content: |
      #!/usr/bin/env bash

      EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
      EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
      . $EB_SCRIPT_DIR/use-app-ruby.sh

      cd $EB_APP_STAGING_DIR
      echo "Installing compatible bundler"
      gem install bundler -v 2.0.2

commands:
  01-set_timezone:
    command: |
      cp /usr/share/zoneinfo/Japan /etc/localtime
      echo 'ZONE="Asia/Tokyo"' &amp;gt; /etc/sysconfig/clock
      echo 'UTC=false' &amp;gt; /etc/sysconfig/clock

 

正直、内容が高度に感じて何が書かれているのか良く分からない部分もありますが、とりあえず言われた通り「.ebextensions」を作成し、その中に各種「.config」ファイルをコピペで置いてみました。

bundler以外にyarnのインストールに関するファイルも作成してあります。

 

再度デプロイ

.ebextensionsを追加したところで、再度デプロイし直したいと思います。ただ、その前にgit commitしておくのを忘れずに。

 
$ git add .
$ git commit -m '[Add] ebextensions'
 

 

先ほどすでに「eb create」を行っているので、2回目以降は「eb deploy」を使っていきます。

 

 
$ eb deploy
Creating application version archive "app-072b-200106_055431".
Uploading: [##################################################] 100% Done...
2020-01-05 20:55:18    INFO    Environment update is starting.
... (中略) ...

 

これまた多少の時間がかかるので待ちます。

 

またしてもエラー発生(Rubyのバージョン関連)
+ '[' -d /var/app/ondeck/vendor/cache ']'
  + bundle install
  Don't run Bundler as root. Bundler can ask for sudo if it is needed, and
  installing your bundle as root will break this application for all non-root
  users on this machine.
  Your Ruby version is 2.6.5, but your Gemfile specified 2.6.3 (Executor::NonZeroExitStatus)

 

数分後、画面を確認してみるとまたしてもエラー。ただ、内容が少し変わっています。これはつまり、先に進んでいるという事。ポジティブに考えて進んでいきましょう。

ざっくり読んでみると「あなたの環境におけるRubyのバージョンは2.6.5なのに、Gemfileには2.6.3が記述されてますよ」的な事を言われているぽいですね。

 

EC2内のRubyのバージョンを確認
$ eb ssh
[ec2-user@ip-000-00-0-000 ~] $ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]

 

「eb ssh」でEC2内へログインし、Rubyのバージョンを確認してみると確かに2.6.5になっていました。

 

GemfileのRubyのバージョンを変更
$ vi Gemfile

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.5'

 

 

再度デプロイ
 
$ git add .
$ git commit -m '[Modify] update Ruby version'
$ eb deploy

 

忘れずに「git commit」した後、再度「eb deploy」。

 

3回目のエラー発生(マスターキー関連)
Missing encryption key to decrypt file with. Ask your team for your master key and write it to /var/app/ondeck/config/master.key or put it in the ENV['RAILS_MASTER_KEY']. (Executor::NonZeroExitStatus)

 

ん~、なかなか思うようにいかない。またしてもエラー発生です。

「マスターキーが無いよ」と言われてしまっています。自分の場合「.gitignore」でmaster.keyをgitの管理対象から外してしまっているため、上手く読み込めていないと思われます。

 

まぁこれに関してはすぐに解決できそうですね。

 

環境変数をセット
$ eb setenv RAILS_MASTER_KEY='マスターキーの中身'

 

「eb setenv」コマンドでmaster.keyの中身を環境変数として設定すればOKです。

※もし他にも環境変数を使用している場合、ここで一気にセットしてしまうと後が楽になります。

 

再度デプロイ
 
$ eb deploy

 

一刻も早くデプロイできる事を夢見て再度「eb deploy」を叩きます。

 

4回目のエラー発生(MySQL関連)
+ cd /var/app/ondeck
  + su -s /bin/bash -c 'bundle exec /opt/elasticbeanstalk/support/scripts/check-for-rake-task.rb db:migrate' webapp
  + '[' false = true ']'
  + su -s /bin/bash -c 'leader_only bundle exec rake db:migrate' webapp
  rake aborted!
  Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
  /opt/rubies/ruby-2.6.5/bin/bundle:23:in `load'
  /opt/rubies/ruby-2.6.5/bin/bundle:23:in `&amp;lt;main&amp;gt;'
  Tasks: TOP =&amp;gt; db:migrate
  (See full trace by running task with --trace) (Executor::NonZeroExitStatus)

 

しかし残念ながらまたエラー発生。今度はMySQLと接続ができないと怒られています。それもそのはず、そういえばまだデータベースを作成していません。

冒頭でElastic Beanstalkを使えばインフラの準備は不要と言いましたが、データベースは自分で用意する必要があるみたいですね。

 

RDSを作成

データベースに関してはAWSが提供しているRDSを利用します。ダッシュボードの「設定」から最下部にある「データベースの変更」をクリック。

 

お好みの設定にして「適用」をクリックしましょう。

 

「RDS」→「データベース」のところにインスタンスが作成されていれば成功です。

 

詳細画面に記載されている「エンドポイント」は後ほど使う事になるのでメモしておいてください。

 

config/database.ymlを編集
 
$ vi config/database.yml
... (中略) ...
production:
  &amp;amp;lt;&amp;amp;lt;: *default
  adapter: mysql2
  encoding: utf8
  database: &lt;%= ENV['RDS_DB_NAME'] %&gt;
  host: &lt;%= ENV['RDS_HOST_NAME'] %&gt;
  username: &lt;%= ENV['RDS_USER_NAME'] %&gt;
  password: &lt;%= ENV['RDS_PASSWORD'] %&gt;
  port: 3306

 

「config/database.yml」のproduction部分を編集します。

 

$ git add .
$ git commit -m '[Modify] config/database.yml'

 

環境変数をセット
$ eb setenv RDS_DB_NAME=ebdb RDS_HOST_NAME='エンドポイント' RDS_USER_NAME='ユーザー名' RDS_PASSWORD='パスワード'

 

忘れずに環境変数もセットしておきましょう。なお、Elastic Beanstalkで作成したRDSのデータベース名はデフォルトで「ebdb」になるようです。

 

再度デプロイ
 
$ eb deploy

 

デプロイ成功

長い戦いがようやく終わり、デプロイ成功です。ヘルスチェックにも合格して緑色になっています。

 

実際にアクセス

 $ eb open 

 

しかし、ここでまたもや問題発生。「eb open」でページにアクセスしてみると「このサイトにアクセスできません」との文字が…。

 

 
$ eb ssh 
[ec2-user@ip-000-00-0-000 ~] $ cd /var/app/current
[ec2-user@ip-000-00-0-000 current]$ ls
Gemfile       README.md     app     config.ru  log           public  storage  yarn-error.log
Gemfile.lock  README_EN.md  bin     db         node_modules  spec    tmp      yarn.lock
Procfile      Rakefile      config  lib        package.json  static  vendor

 

「/var/app/current」内にしっかりと各種ファイルが入っているので、デプロイ自体は上手くいっているはずなのですが。

ログを見ても特にヒントは見当たりません。というより、サーバー自体にアクセスが届いていないみたいで、ログが途切れてしまっています。これじゃ何の不具合が起きているのかもわからない…。

ここからまた長い旅が始まります。

 

キャッシュを削除してみた

「ElasticBeanstalk デプロイ後 このサイトにアクセスできません」という単純なキーワードから始まり、色々調べてみたのですが、一向にそれらしい回答はでてきませんでした。

ただ、この種のエラーが起きた場合の基本的な問題解決方法として、Cookieやキャッシュを削除すると良いかもといったものがあります。

参照記事:「このサイトにアクセスできません」の解決&対処法

 

「まさかそんなシンプルな方法で…」と半信半疑でしたが、これがまさかの正解。

ついにアクセスできるようになりました!

 

しかし、なぜかCSSが反映されていない様子。

 

 $ eb ssh 
[ec2-user@ip-000-00-0-000 ~] $ cd /var/app/current/pubcic/assets
[ec2-user@ip-000-00-0-000 current]$ ls 
...........jpg
... (中略) ...

 

「pubcic/assets」内を見る限り、様々なファイルが存在するので「bundle exec rake assets:precompile RAILS_ENV=production」は上手くいっているはずです。画像も表示されていますし。

 

config/environments/production.rb内の「config.assets.debug = true」をfalse へ変更
 $ vi <span class="sc_title">config/environments/production.rb</span>
Rails.application.configure do
... (中略) ...
config.assets.debug = true # falseへ変更
... (中略) ...
end

 

おそらくconfig関連で何かミスがあると踏み、検索開始。するとこんな記事を発見。

参照記事:Railsはassetsに注意しろ

 

こちら参考にconfig/environments/production.rb内の「config.assets.debug = true」をfalse へ変更してみました。trueになっていると、application.css/jsと個別のファイルの二重読み込みがされて上手く作動しない事があるようです。

 

CSSが無事に反映される

ついにそれらしい感じになりました。CSSも反映されてデプロイ完了です。

 

感想

「Elastic Beanstalkを使えばめちゃくちゃ簡単にデプロイできるよ~」なんて言われていますが、個人的にはかなり苦戦してしまいました。

僕の環境や設定が悪かったというのもあるかもしれません。エラーの連続でかなり疲労困憊状態…。

 

とはいえ、基本的にはしっかりとログを読んで、解決策をググれば何とか対応できると思います。発生するエラーは人それぞれ違うと思うので、必ずしもこの記事があなたにとって役に立つかはわかりませんが、一つでもヒントになれば幸いです。

おすすめの記事