初学者がRailsで作ったポートフォリオをAWSへデプロイするまでの記録

エンジニアへ転職するために[こちらの記事](https://qiita.com/naoki_mochizuki/items/f795fe3e661a3349a7ce)を参考にして
ポートフォリオをAWSへデプロイすることが出来たので、それまでにやったことを出会ったエラーを紹介しつつ、振り返っていきたいと思います。

ポートフォリオをAWSにデプロイしてみたい、
AWSへデプロイするまで何を準備すれば良いのかわからない
という方のお役に立てれば幸いです。

ちなみにこの記事はEC2へログインするところから始まります。

# EC2へログインする

EC2インスタンスを作成した時に、キーペアをダウンロードしてるはずなので
それを使ってログインしていきます。

あ、ちなみに今回デプロイしたアプリ名はlovekitchenなるものなので
各々アプリ名の部分は変更してくださいね。

```
$ mv Downloads/lovekitchen.pem .ssh/
$ cd .ssh/
$ chmod 400 lovekitchen.pem
$ ssh -i lovekitchen.pem ec2-user@パブリックIP
```

`yes`と入力すれば変なアスキーアートが表示されてログイン完了です。

# 管理ユーザー作成

```
sudo adduser tatsuya
sudo passwd tatsuya
(# パスワードの登録)
sudo vi visudo
(# 設定を編集)
```
ここからはVIMを使っての編集になります。
まず`i`を押してINSERTモードにして下さい。

```
## Allow root to run any commands anywhere
root ALL=(ALL)    ALL
(この下に)
chiroru ALL=(ALL)   ALL
```

そしてこんな感じで編集したら、　`esc`キーを押して、`:wq`で上書き保存します。
完了したら

```
[ec2-user] sudo su - tatsuya
```

これでユーザー名が変わってると思います。
以降このユーザーで作業を行なっていきます。

そして一旦ログアウトして、次はローカル環境で作業します。

```
[tatsuya] exit
[ec2-user] exit
[.ssh] ssh-keygen -t rsa
(公開鍵の名前を入力してエンター)
(空のままエンターを２回)
[.ssh] vi config
(INSERT)
______________________________________
Host lovekitchen_key_rsa
  Hostname パブリックIP
  Port 22
  User tatsuya
  IdentityFile ~/.ssh/lovekitchen_key_rsa
______________________________________
[.ssh] cat アプリ名_key_rsa.pub
(ssh-rsaからlocalまでをコピー)
```
ここから再びサーバー側の作業となります。

```
[.ssh] ssh -i lovekitchen.pem ec2-user@パブリックIP
[ec2-user] sudo su - tatsuya
[tatsuya] mkdir .ssh
[tatsuya] chmod 700 .ssh
[tatsuya] cd .ssh
[tatsuya] vi authorized_keys
__________________________
さっきコピーした鍵をペースト
__________________________
[tatsuya] exit
[ec2-user] exit
[.ssh] ssh lovekitchen_key_rsa
```

これでログインできればユーザーの設定は完了！
最後に`ec2-user`ではログイン出来ないようにします。

```
[tatsuya] sudo vi /etc/ssh/sshd_config
_______________________________
DenyUsers ec2-user
(ec2-userではログイン出来ない)
_______________________________
[tatsuya] sudo service sshd reload
(設定を反映)
[tatsuya] exit
[.ssh] ssh -i アプリ名.pem ec2-user@パブリックIP

ec2-user@パブリックIP: Permission denied (publickey).
と表示されればOK!
```
これで諸々の準備は完了したので
これからはいよいよプラグインをインストールしたり
アプリをGithubからcloneしたりしていきます。


# 環境構築編

## unicornのインストール

ここはローカル環境での作業となります。

```ruby:Gemfile
group :production do
    gem 'unicorn'
end
```

```
$ bundle install
```

次は `unicorn` の設定ファイルを作成し、編集して行きます。

```ruby:config/unicorn.conf.rb
$worker  = 2
$timeout = 30
$app_dir = "/var/www/projects/アプリ名"
$listen  = File.expand_path 'tmp/sockets/.unicorn.sock', $app_dir
$pid     = File.expand_path 'tmp/pids/unicorn.pid', $app_dir
$std_log = File.expand_path 'log/unicorn.log', $app_dir
# set config
worker_processes  $worker
working_directory $app_dir
stderr_path $std_log
stdout_path $std_log
timeout $timeout
listen  $listen
pid $pid
# loading booster
preload_app true
# before starting processes
before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
  old_pid = "#{server.config[:pid]}.oldbin"
  if old_pid != server.pid
    begin
      Process.kill "QUIT", File.read(old_pid).to_i
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end
end
# after finishing processes
after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
```

## database.ymlを編集

```ruby:config/database.yml
production:
  <<: *default
  database: lovekitchen_production
  username: root
  password:
```

リポジトリへ反映させて行きます。

```
$ git add .
$ git commit
$ git push origin master
```

## Nginxのインストール

```
[tatsuya] sudo yum update
(サーバーをアップデート)
[tatsuya] sudo yum install -y nginx
(Nginxをインストール)
[tatsuya] sudo /etc/init.d/nginx start
(起動確認)
[tatsuya] sudo chkconfig nginx on
(自動起動を設定)
```

## 作業用ディレクトリの作成

```
[tatsuya] cd /
[tatsuya| /] sudo chown tatsuya var
[tatsuya| /] cd var
[tatsuya| var] sudo mkdir www
[tatsuya| var] sudo chown tatsuya www
[tatsuya| var] cd www
[tatsuya| www] sudo mkdir projects
[tatsuya| www] sudo chown tatsuya projects
```

## プラグインをインストール

*この中に後々問題となるプラグインが含まれてます(泣)

```
[tatsuya] sudo yum install git make gcc-c++ patch openssl-devel libyaml-devel libffi-devel libicu-devel libxml2 libxslt libxml2-devel libxslt-devel zlib-devel readline-devel mysql mysql-server mysql-devel ImageMagick ImageMagick-devel epel-release

```
Node.js 6xをインストール

```
[tatsuya] curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
```

yarnをインストール

```
[tatsuya] sudo npm install yarn -g
```

rbenvをインストール

```
[tatsuya] git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
[tatsuya] echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
[tatsuya] echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
[tatsuya] source ~/.bash_profile
```

ruby-buildをインストール

```
[tatsuya] git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
[tatsuya] rbenv rehash
```

rubyをインストール

```
[tatsuya] rbenv install -v 2.5.3
[tatsuya] rbenv global 2.5.3
[tatsuya] rbenv rehash
[tatsuya] ruby -v
```

ここも特に問題なかったです。
rubyがちゃんとインストールされた時はホッとしました。
とにかくコマンド一つ実行するだけでドキドキでしたよもう。

# Githubと連携

ここからGithubと連携して、そして自分のアプリをさっき作ったディレクトリにクローンしていきます。

```
[tatsuya| ~] vi .gitconfig
-----------------------------------
[user]
  name (gitに登録した名前)
  email (gitに登録したメールアドレス)

[color]
  ui = true

[url "github:"]
  InsteadOf = https://github.com/
  InsteadOf = git@github.com:
-----------------------------------
[tatsuya| ~] chmod 700 .ssh
[tatsuya| ~] cd .ssh
[tatsuya| .ssh] ssh-keygen -t rsa
[tatsuya| .ssh] vi config
-----------------------------------
Host github
  Hostname github.com
  User git
  IdentityFile ~/.ssh/aws_git_rsa
-----------------------------------
[tatsuya| .ssh] chmod 600 config
[tatsuya| .ssh] cat aws_git_rsa.pub

```
このコピーした公開鍵をGithubへアップして行きます。
まずGithubの右上にあるアカウントメニューから `Settings`へ進んで下さい。
<img width="1282" alt="スクリーンショット 2019-03-30 22.21.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/254048/c887f02f-9fb2-f0c9-002a-bc00bc4e6a02.png">
次はこちらの `SSH and GPG Keys` へ進みます。
<img width="810" alt="スクリーンショット 2019-03-30 22.22.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/254048/8e2f78ea-0ea6-e9f7-0cfa-092a4b188d6f.png">

```
[Title] aws_git_rsa
[Key] さっきコピーしたaws_git_rsa.pub
```

これで `Add SSH Key` で完了！
ちゃんと接続出来ているか確認しましょう。

```
[tatsuya| .ssh] ssh -T github
Hi tatsuya! You've successfully authenticated, but GitHub does not provide shell access.
```

こんな感じでメッセージが返ってきます。

そして、いよいよクローンです！

```
[tatsuya| .ssh] cd /var/www/projects
[tatsuya| projects] git clone git@github.com:machamp0714/love_kitchen.git
```

ここで初めてエラーが表示されました。
本当はこう入力しないとダメみたいです。

```
[tatsuya| projects] git clone github:machamp0714/love_kitchen.git
[tatsuya| projects] ls
love_kitchen
```
これでクローンも無事完了しました！

# Gemをインストール

お次は、 `bundler` をインストールします。
この時、Gemfile.lockに記載されている `bundler` のバージョンと合わせました。

```
bundlerをインストール
[tatsuya| projects] gem install bundler -v 1.7.1
Gemfileを作成
[tatsuya| projects] bundle init
Gemfileを編集
[tatsuya| projects] vi Gemfile
-------------------------------
*コメントアウトを外して、versionを記載
gem "rails", '5.2.2'

-------------------------------
[tatsuya| projects] bundle install --path vendor/bundle --jobs=4
[tatsuya| projects] bundle exec rails -v
# Rails 5.2.2
```

次はクローンしたディレクトリへ移動してgemをインストールして行きます。
 
```
[tatsuya| projects] cd love_kitchen
[tatsuya| love_kitchen] bundle install --path vendor/bundle
```

するとここで次のエラーが出現。。。

```
/home/tatsuya/.rbenv/versions/2.5.3/bin/ruby -r ./siteconf20190321-31332-65ucq1.rb extconf.rb
checking for gcc... yes
checking for Magick-config... yes
checking for outdated ImageMagick version (<= 6.8.9)... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers. Check the mkmf.log file for more details. You may
need configuration options.

Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/home/tatsuya/.rbenv/versions/2.5.3/bin/$(RUBY_BASE_NAME)

To see why this extension failed to compile, please check the mkmf.log which can be found here:

/var/www/projects/love_kitchen/vendor/bundle/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/rmagick-3.0.0/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /var/www/projects/love_kitchen/vendor/bundle/ruby/2.5.0/gems/rmagick-3.0.0 for inspection.
Results logged to /var/www/projects/love_kitchen/vendor/bundle/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/rmagick-3.0.0/gem_make.out

An error occurred while installing rmagick (3.0.0), and Bundler cannot continue.
Make sure that gem install rmagick -v '3.0.0' --source 'https://rubygems.org/' succeeds before bundling.

In Gemfile:
rmagick
```


エラー文を見る限りどうも `rmagick` をインストールすることが出来ないようです。
ローカル環境でインストールした際も同じようなエラーが出たので、これもversion関連が
原因だろうなと思い、この時はすぐに解決できると思っていました。

ですが、ここで問題発生。
そもそも、AmazonLinuxのyum標準リポジトリにあるImageMagickのversionは一番新しいやつが6.7.8と古く、
ここで欲しいのはversionが6.8.9以上の物なので、ImageMagickのversionを新しいものにするというシンプルな
解決策を実行することが出来ません。

色々調べた結果、yum先生とremi先生のお力を借りればImageMagick6系の最新版をインストール出来るみたいなので
こちらを試してみました。ちなみに、 `rmagick`はImageMagickのversionを7系にしてしまうと使えないので注意してください。

## remiリポジトリを追加

```
[tatsuya] rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
```

## CentOS-Baseリポジトリを追加

```
[tatsuya] vi /etc/yum.repos.d/CentOS-Base.repo
--------------------------------------------------------------------------
[base]
name=CentOS-6 - Base
mirrorlist=http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
--------------------------------------------------------------------------
```

## 古いパッケージを削除

```
[tatsuya] yum remove -y libtiff
[tatsuya] yum remove -y ImageMagick ImageMagick-devel
```

## ImageMagick6系の最新版をインストール

```
[tatsuya] yum install -y libtiff --enablerepo=remi,epel,base --disablerepo=amzn-main
[tatsuya] yum install -y ImageMagick6 ImageMagick6-devel ImageMagick6-libs --enablerepo=remi,epel,base
[tatsuya] yum install -y libwebp libwebp-devel --enablerepo=epel --disablerepo=amzn-main
[tatsuya] yum install -y ImageMagick6 ImageMagick6-devel ImageMagick6-libs --enablerepo=remi,epel,base
```

これで欲しいversionのImageMagickがインストール出来たので,もう一度 `bundle install` を実行します。

```
[tatsuya| love_kitchen] bundle install --path vendor/bundle
```

これでインストール完了です。
僕の環境の場合、このエラーだけしか生じませんでした。

# nginxの設定

次は、nginxの設定ファイルを作成し、編集して行きます。

```
[tatsuya| love_kitchen] sudo vi /etc/nginx/conf.d/アプリ名.conf
----------------------------------------------------------------------
upstream unicorn_server {
    server unix:/var/www/projects/love_kitchen/tmp/sockets/.unicorn.sock
    fail_timeout=0;
}
server {
    listen 80;
    client_max_body_size 4G;
    server_name IPアドレス;
    keepalive_timeout 5;
    # Location of our static files
    root /var/www/projects/love_kitchen/public;
    location ~ ^/assets/ {
        root /var/www/projects/love_kitchen/public;
    }
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        if (!-f $request_filename) {
            proxy_pass http://unicorn_server;
            break;
        }
    }
    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /var/www/projects/love_kitchen/public;
    }
}
アプリ名や、IPアドレスはご自身の環境に合わせてください。
----------------------------------------------------------------------
nginxを再起動
[tatsuya| love_kitchen] sudo service nginx restart
権限を設定
[tatsuya| love_kitchen] sudo chmod -R 775 /var/lib/nginx
mysqlを起動
[tatsuya| love_kitchen] sudo service mysqld start
マイグレーションを実行
[tatsuya| love_kitchen] bundle exec rails db:migration RAILS_ENV=production

Missing encryption key to decrypt file with. Ask your team for your master key and write it to /xxx/my-app/config/master.key or put it in the ENV['RAILS_MASTER_KEY'].
Exiting
```

マイグレーションを実行しようとしたら、こんなエラーが出ました。
どうもconfig/master.keyがないので怒られてるみたいです。

そういえば `master.key` は、 `.gitignore` に記載されていてリポジトリには反映されないのを思い出しました。
というわけで、ローカル環境で `master.key` の中身をコピーして、本番環境の方にも `master.key` ファイルを作成してあげます。

```
[tatsuya| love_kitchen] vi config/master.key
----------------------------------
自分のアプリのconfig/master.keyをコピペ
----------------------------------
[tatsuya| love_kitchen] bundle exec rails db:migration RAILS_ENV=production
```

これで全ての準備が完了しました。
あとはrailsアプリを起動するだけです。

# railsアプリを起動する

```
railsアプリをプリコンパイル
[tatsuya| love_kitchen] bundle exec assets:precompile RAILS_ENV=production
nginxを再起動
[tatsuya| love_kitchen] sudo service nginx restart
unicornを起動
[tatsuya| love_kitchen] bundle exec unicorn_rails -c /var/www/projects/love_kitchen/config/unicorn.conf.rb -D -E production

Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
```

unicornを起動するコマンドを入力するとこんなエラーが出ました。
`mysql.sock` の場所がおかしいのでしょうか。

```
mysql.sockの場所を調べる
[tatsuya| love_kitchen] mysql_config --socket

/var/lib/mysql/mysql.sock
```

`/var/lib/mysql.sock` にあることが判明したので、
database.ymlを編集します。

```
[tatsuya| love_kitchen] vi config/database.yml
------------------------------------------------
production:
  <<: *default
  database: love_kitchen_production
  username: root
  password:
  socket: /var/lib/mysql/mysql.sock
------------------------------------------------
再びunicornを起動
[tatsuya| love_kitchen] bundle exec unicorn_rails -c /var/www/projects/love_kitchen/config/unicorn.conf.rb -D -E production
bundler: failed to load command: unicorn_rails
```

お次はこんなエラーが。。。。。。。。。
`unicorn_rails` の他に、 `unicorn` コマンドもあるみたいなので、そちらを試してみることに。

```
[tatsuya| love_kitchen] bundle exec unicorn -c /var/www/projects/love_kitchen/config/unicorn.conf.rb -D -E production
[tatsuya| love_kitchen] ps -ef | grep unicorn | grep -v grep
プロセスが３行表示される
```

これでようやっと行けたかな？と思い、ブラウザに直接IPアドレスを入力！

```
http://IPアドレス
```

遂にRailsアプリが起動しました!!!!!

ここまで来るのに丸一日かかってしまいましたが、挑戦してホント良かったです。
今は取り敢えずデプロイしました、みたいな感じなのでこれからちゃんと勉強して行きたいですね。

## 参考にした記事

[世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/f795fe3e661a3349a7ce)

ホントに素晴らしい記事ありがとうございます。