【序 章】フリマアプリ開発完全ロードマップ【AWS自動デプロイ】

はじめに

添野と申します。プログラミング学習を初めて4か月ほど経過しました。
Railsでメルカリ風フリマアプリを1人で作れたので、ロードマップとして一通りの開発経緯を残します。

序章では、Railsでフリマアプリ開発を行う前にアプリの雛形をAWSへデプロイする方法を解説します。
デプロイには自動デプロイが可能となる便利なgem"capistrano"を使用します。

制作するアプリ

ユーザ登録、商品出品・購入の機能を備えたフリマアプリです。
メルカリ風、というかほぼメルカリです。メルカリを作ります。

こんな感じのWebサイトを作っていきます。
イラスト.png

ちなみに、この規模のアプリは単価50万円ほどで取引されることが多いそうです。
通常納期は30日ほどだと思いますが、慣れてくれば1週間くらいで作れたりします。
この記事を使って、Web開発を極める一助にしていただければ幸いです。

開発環境
OS   : macOS Catalina 10.15.3
DB   : MySQL
Ruby : 2.5.1
Rails: 5.2.4.2

フリマアプリ開発完全ロードマップ

内容 難易度 所要時間 主要技術
序 章 AWS自動デプロイ ★☆☆☆☆ ★★★☆☆ capistrano
第一章 データベース設計 ★☆☆☆☆ ★☆☆☆☆
第二章 マークアップ作業 ★★☆☆☆ ★★★★★
第三章 ユーザ登録/ログイン機能 ★★★★☆ ★★☆☆☆ devise
第四章 商品出品/編集/詳細表示/削除 ★★★★☆ ★★★☆☆ carrierwave
第五章 商品カテゴリ機能 ★★★★★ ★★★☆☆ ancestry
第六章 商品購入機能 ★★★★★ ★★★★☆ Payjp

1.ディレクトリの作成

早速、アプリ開発を始めていきます。
ディレクトリは~/project、アプリ名はfrema-appとして作成します。

【注意】
ここでアプリ名をfrema-app以外にする場合、この後に出てくるアプリ名を全て置換する必要があります。
コピペした時にアプリ名がそのままだとエラーの原因になるのでよく確認して作業することをおすすめします。

1.ターミナルで以下のコマンドを実行

ターミナル(ローカル)
cd projects
rails new frema-app -d mysql
cd frema-app
rails db:create
git init
rails s

2.以下のアドレスでRailsトップページの表示を確認
http://localhost:3000/

スクリーンショット 2020-04-15 13.38.59.png
これが出てくればOKです。

2.レポジトリの作成

今回はGithub Desktopを使用します。
「レポジトリって??」という人はこれを読んでください

1.以下の動画の通りにローカルレポジトリを登録
640b82fbebc36162eb698984f32cb6e7.gif
2.Publish repositoryを実行してリモートリポジトリを登録
3.コミット名にinitial commitと入力してコミット後にPublish branch
044a06cb071f67574df13b922270356d.gif

3.デプロイ設定

アプリを作り込む前にデプロイしましょう。
インフラは全部最初にやってしまった方がいいです。

1. ここでアカウント作成
2. サービスをクリック
3. EC2をクリック
スクリーンショット 2020-04-15 14.06.26.png
4.インスタンスの作成をクリック
スクリーンショット 2020-04-15 14.19.51.png
5. Amazon Linux AMI選択 ※Amazon Linux 2 AMIではないので注意
スクリーンショット 2020-04-15 14.20.59.png
6. 作成と確認をクリック
スクリーンショット 2020-04-15 14.26.31.png

7.起動をクリック
スクリーンショット 2020-04-15 14.27.16.png

8.新しいキーペアの作成を選択
9.キーペア名frema-appと入力
10.キーペアのダウンロードをクリック
11.インスタンスの作成をクリック
スクリーンショット 2020-04-15 14.46.21.png

12.インスタンスをクリック
13.インスタンスIDをコピーしてメモに保存
スクリーンショット 2020-04-15 14.50.40.png

14.Elastic IPをクリック
15.新しいアドレスの割り当てをクリック
スクリーンショット 2020-04-15 14.53.49.png
16.割り当てをクリック
スクリーンショット 2020-04-15 14.55.00.png
17.Elastic IPをコピーしてメモに保存
18.閉じるをクリック
スクリーンショット 2020-04-15 14.56.37.png
19.アクションをクリック
20.アクションの関連付けをクリック
スクリーンショット 2020-04-15 15.01.11.png

21.インスタンスメモしたインスタンスIDを選択して入力
22.関連付けをクリック
スクリーンショット 2020-04-15 15.04.45.png

23.閉じるをクリック
スクリーンショット 2020-04-15 15.24.18.png

24.インスタンスをクリック
25.メモしたインスタンスIDと一致するものをクリック
26.セキュリティグループの欄からlaunch-wizard(数字)をクリック
スクリーンショット 2020-04-15 15.26.18.png
27.インバウンドをクリック
28.編集をクリック
スクリーンショット 2020-04-15 15.29.13.png
29.ルールの追加をクリック
30.タイプHTTPを選択
31.保存をクリック
スクリーンショット 2020-04-17 10.59.08.png

32.ターミナルで以下を実行

ターミナル(ローカル)
cd ~
mkdir ~/.ssh
mv Downloads/frema-app.pem .ssh/
cd .ssh/
chmod 600 frema-app.pem
ssh -i frema-app.pem ec2-user@18.181.6.140

ssh -i frema-app.pem ec2-user@18.181.6.14018.181.6.140は、メモしたElastic IPに置き換えて下さい

Are you sure you want to continue connecting (yes/no)?と出力されるので、yesと入力してEnterです。


この辺りで一旦休憩したくなりそうですが、この章の最後までは休憩せずに進めるのがおすすめです
なぜなら、この辺の退屈な作業を早々に終わらせると、後々の作業がかなり楽しくなるからです。


33.EC2ターミナルで以下をすべて実行
深く考える必要はありません。全てをコピペEnterです。

ターミナル(ec2-user)
sudo yum -y update
sudo yum -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel libcurl libcurl-devel curl
sudo curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
sudo yum -y install nodejs
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv 
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile 
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
source .bash_profile
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv rehash
rbenv install 2.5.1
rbenv global 2.5.1
rbenv rehash
sudo yum -y install mysql56-server mysql56-devel mysql56
sudo yum update
sudo service mysqld start

34.EC2ターミナルで以下のPASSWORDを任意のパスワードに書き換えて実行

ターミナル(ex2-user)
sudo /usr/libexec/mysql56/mysqladmin -u root password 'PASSWORD'

コピペで実行するとパスワードが「PASSWORD」になるので注意。

35.ターミナルで以下を実行し、上記で設定したパスワードを入力

ターミナル(ex2-user)
mysql -u root -p
# mysqlが起動するので、exitと入力して終了する
exit

36.EC2ターミナルで以下を実行

ターミナル(ex2-user)
ssh-keygen -t rsa -b 4096

Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):という表示で止まるので、Enterを3回押します。

37.EC2ターミナルで以下を実行

ターミナル(ex2-user)
cat ~/.ssh/id_rsa.pub

長い文字列が出てくるので、コピーしておきます。

38.ここからgithubにアクセス

39.New SSH keyをクリック
image.png

40.Titleに適当な名前、Keyにコピーした長い文字列をペーストしAdd SSH keyをクリック
スクリーンショット 2020-04-15 16.35.51.png

41.EC2ターミナルで以下のコマンドを実行

ターミナル(ex2-user)
ssh -T git@github.com
// yesで進める

ここでHi!という陽気な挨拶とともに、Githubのユーザ名が表示されれば連携成功です。

42.Gemfileに以下を追記し、ローカルでbundle install

Gemfile
group :production do
  gem 'unicorn', '5.4.1'
end

group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end

# 以下は末尾に追記
gem 'pry-rails'
gem 'haml-rails'
gem 'erb2haml'
ターミナル(ローカル)
bundle install
rails haml:replace_erbs
bundle exec cap install

43.Capfileを以下のように書き換え

Capfile
require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

44.config/deploy/production.rbを以下のように書き換え

production.rb
server '18.181.6.140', user: 'ec2-user', roles: %w{app db web}

18.181.6.140という文字列(Elastic IP)はご自身のものに置き換えて下さい。

45.config/deproy.rbを以下のように書き換える

deproy.rb
lock '3.13.0'
set :application, 'frema-app'
set :repo_url,  'git@github.com:Fumiya-Soeno/frema-app.git'
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')
set :rbenv_type, :user
set :rbenv_ruby, '2.5.1'
set :ssh_options, auth_methods: ['publickey'], keys: ['~/.ssh/frema-app.pem'] 
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end

1行目のlock '3.13.0'はcapistranoのバージョンに合わせて書き換えて下さい。バージョンはGemfile.lockに以下のような形で書いてあります。

Gemfile.lock
〜(省略)〜
builder (3.2.4)
byebug (11.1.1)
capistrano (3.13.0) // これです
  airbrussh (>= 1.0.0)
  i18n
  rake (>= 10.0.0)
〜(省略)〜

3行目のset :repo_url, 'git@github.com:Fumiya-Soeno/frema-app.git'も書き換えが必要です。Fumiya-Soeno/frema-appの部分を、ご自身のリモートリポジトリのGithub上でのパスに置き換えて下さい。

スクリーンショット 2020-04-15 17.53.00.png

46.config/unicorn.rbを新規作成し、以下のように編集

unicorn.rb
app_path = File.expand_path('../../../', __FILE__)
worker_processes 1
working_directory "#{app_path}/current"
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"
timeout 60
preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true
check_client_connection false
run_once = true
before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&
    ActiveRecord::Base.connection.disconnect!
  if run_once
    run_once = false
  end
  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end
after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end

47.config/environments/production.rbの以下の行を探し、コメントアウト

production.rb
  # config.assets.js_compressor = :uglifier

48.EC2ターミナルで以下を実行

ターミナル(ec2-user)
sudo mkdir /var/www/
sudo chown ec2-user /var/www/
sudo yum -y install nginx
sudo vim /etc/nginx/conf.d/rails.conf

49.vimで以下のようにファイルを編集

rails.conf
upstream app_server {
  server unix:/var/www/frema-app/shared/tmp/sockets/unicorn.sock;
}
server {
  listen 80;
  server_name 18.181.6.140;
  client_max_body_size 2g;
  root /var/www/frema-app/current/public;
  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    root   /var/www/frema-app/current/public;
  }
  try_files $uri/index.html $uri @unicorn;
  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }
  error_page 500 502 503 504 /500.html;
}

挿入はiキー、終了はescキー:wqと入力→Enterキーです。
6行目にserver_name 18.181.6.140;とありますが、
ここはご自身のElasticIPを入れて下さい。

50.EC2ターミナルで以下を実行

ターミナル(ec2-user)
cd /var/lib
sudo chmod -R 775 nginx  
cd /var/www/

51.これまでの変更をmasterにプッシュ
今回はGithub Desktopで行います。
2b876403a386161e1efa69a0ba06871f.gif

52.アプリをEC2にクローン

ターミナル(ec2-user)
cd /var/www/
git clone https://github.com/Fumiya-Soeno/frema-app.git

2行目Fumiya-Soenoの部分はご自身のGithubユーザ名を入れて下さい。
コマンド入力後、Githubユーザ名とパスワードを要求されるので入力して下さい。

53.EC2ターミナルで以下のコマンドを実行

ターミナル(ec2-user)
cd ~
sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
sudo chmod 600 /swapfile1
sudo mkswap /swapfile1
sudo swapon /swapfile1
sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'

54.ローカルで以下のコマンドを実行

cd projects/frema-app/
bundler -v
// 出力 Bundler version 2.1.4

このとき出力された 2.1.4のような数字をコピーしておきます。

55.EC2ターミナルで以下を実行

ターミナル(ec2-user)
cd /var/www/frema-app
gem install bundler -v 2.1.4
bundle install
// 結構時間がかかります(3分くらい)。ここで一瞬休憩しましょう。

2.1.4のところに上でコピーした数字をペーストです。

55.EC2ターミナルで以下を実行

ターミナル(ec2-user)
rake secret

長い文字列が出力されるので、コピーします。

ターミナル(ec2-user)
sudo vim /etc/environment

vimが起動するので下記のように編集します。

/etc/environment
DATABASE_PASSWORD=PASSWORD
SECRET_KEY_BASE=先程コピーした長い文字列

1行目の=の後のPASSWORDにはmysqlで設定したパスワードを書いておきましょう。

56.EC2ターミナルからexitしてログインし直す

ターミナル(ec2-user)
exit
↓ログアウトされるので、下記を実行してec2にログインし直す
ssh -i frema-app.pem ec2-user@18.181.6.140

18.181.6.140の部分はご自身のElasticIPに置き換えます。

57.config/database.ymlを修正
Railsのコードを一部修正です。
produbtion:と記述のある部分を以下のように書き換えます。

database.yml
production:
  <<: *default
  database: frema-app_production
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

58.変更をmasterにプッシュ
Github Desktopで行います。
092c518f7e2443fd89983b5d34e2dc43.gif

59.EC2ターミナルで以下を実行

ターミナル(ec2-user)
cd /var/www/frema-app/
git pull origin master
sudo service mysqld start
sudo service nginx start
rails db:create RAILS_ENV=production
rails db:migrate RAILS_ENV=production
rails assets:precompile RAILS_ENV=production

60.ローカルで以下を実行

ターミナル(ローカル)
cd ~/.ssh/
ssh-add -K  ~/.ssh/frema-app.pem

61.表示用のトップページを作成

ターミナル(ローカル)
cd ~/projects/frema-app/  
rails g controller products
routes.rb
Rails.application.routes.draw do
  $date = Time.now.in_time_zone('Tokyo').to_s
  root "products#index"
  resources :products, only: :index
end

app/views/products/index.html.hamlを作成して適当に文字を配置

index.html.haml
下記の時間にデプロイが成功しました
%br
= $date

app/assets/stylesheets/application.css
app/assets/stylesheets/application.scssにrenameして、適当なCSSを書く

application.scss
body{
  background-color: #f5f5f5;
}

62.変更をmasterにプッシュ
63.ターミナル(ローカル)で以下を実行

ターミナル(ローカル)
bundle exec cap production deploy  

お疲れ様でした。ひとまずここで自動デプロイまで設定完了です。
下記のアドレスを、ご自身のElasticIPに置き換えたものにしてアクセスして下さい。

http://18.181.6.140/

上記コマンドでエラーで止まる場合は、ここに書いてあることを何かしら飛ばしている可能性が高いです。確認してみて、解決できなければ、エラーコードや起きている現象をググって解決しましょう。

無事成功していれば、下記のようにproducts#indexが表示できます。
背景が若干グレーがかっていれば、CSSの適用にも成功しています。
これでようやく、開発のスタートラインに立つことができました。

スクリーンショット 2020-04-17 11.13.50.png

お疲れ様でした。ここまでが序章になります。
ここからようやくアプリ制作に入っていきます。頑張りましょう!

第一章 データベース設計に続きます。

内容 難易度 所要時間 主要技術
序 章 AWS自動デプロイ ★☆☆☆☆ ★★★☆☆ capistrano
第一章 データベース設計 ★☆☆☆☆ ★☆☆☆☆
第二章 マークアップ作業 ★★☆☆☆ ★★★★★
第三章 ユーザ登録/ログイン機能 ★★★★☆ ★★☆☆☆ devise
第四章 商品出品/編集/詳細表示/削除 ★★★★☆ ★★★☆☆ carrierwave
第五章 商品カテゴリ機能 ★★★★★ ★★★☆☆ ancestry
第六章 商品購入機能 ★★★★★ ★★★★☆ Payjp

あとがき

この記事のここをもっと解説してほしい!などありましたら、コメント欄でお伝えください。
また、コメント欄での暴言や誹謗中傷の書き込み等はご遠慮ください。凹むので。

いつも記事を読んで頂いている皆さま、LGTMを押していただいている皆さま、本当にありがとうございます!!
有益な記事を執筆するモチベーションに繋がりますので、この記事が役に立ったなと思って頂けたら、
是非LGTMボタンのクリックSNSでのシェアをよろしくお願いします。


添野文哉(@enjoy_omame)
https://twitter.com/enjoy_omame

enjoy_omame
TECH CAMPというスクール出身です。 Rails系男子。hamlとjQueryが好きです。
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
コメント
この記事にコメントはありません。
あなたもコメントしてみませんか :)
すでにアカウントを持っている方は
ユーザーは見つかりませんでした