Ruby on Rails アプリをAWSにアップするまで

Webアプリ初心者がはじめてrailsアプリをAWSへアップするまでの作成日記
作成中のサイト
https://www.drink-app.club/

  • ID:admin
  • pass:test0108

https://github.com/katsun0921/drink-app-rb

参考サイト

@iwaseasahi さんのページを参照すればだいたいAWSへのアップはいける

はまったところ

ruby2.5.0でやったらDeviseでSyntaxErrorとなった。

バグらしいので修正が必要だった

SyntaxError: /.../devise-3.5.5/app/controllers/devise/sessions_controller.rb:5: syntax error, unexpected '{', expecting keyword_end
...ter only: [:create, :destroy] { request.env["devise.skip_tim...

ここをコードを修正

prepend_before_filter only: [:create, :destroy] { request.env["devise.skip_timeout"] = true }
prepend_before_filter(only: [:create, :destroy]) { request.env["devise.skip_timeout"] = true }

nginxでrestartが反映されない?

修正ファイルをgit hubからpull したら、反映されずというかDNSが切れた
なぜ?
どうやらnginxだとrestartではなくreloadだとうまくいく
http://abyssluke.hatenablog.com/entry/2015/12/11/203707

sudo nginx service reload

でうまくいかなかったらreload

sudo nginx -s reload

develop環境だと画像が表示されるのに、producton環境だと画像が表示されなくなった?

ローカル環境でのvagrantだと画像は、表示されるのにAWSにアップしたら表示されない?
assets/images 配下に画像をおいていた

background: url(/assets/images/hoge.jpg)

この書き方だとパスの書き方が間違っていたっぽい

https://qiita.com/wadako111/items/03bc00d914e62243a511

このページを参考にして画像をpublicへ変更したら解決

/public/images/

に画像をおいて画像パスを変更

background: url(/images/images/hoge.jpg)

assetsにあるcssは変更したらプリコンパイルを忘れず

bundle exec rake assets:precompile RAILS_ENV=production

続きを読む

awsの記事一覧

Amazon Linux + Nginx、CertbotでLet’s Encryptを使ってみる |無料でSSL対応 · 7981. 2017-12-31. 【初心者・独学者向け】Ruby On Railsでrake db:seedで初期データを投入する · Posdb. 2017-12-31. rake aborted! NoMethodError: undefined method `inet’ · Git. 2017-12-29. プログラミングした内容をgit push … 続きを読む

DBなしのRails5アプリを最短でAmazon EC2上に構築して公開する

データベースにAmazon DynamoDBを使ったRailsアプリを作りたいと思い、とりあえずDBなしのRailsアプリを最短でEC2で公開するにはどうしたらいいかをやってみました。

前提

下準備

下記の記事が非常に分かりやすかったです。

(下準備編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
↑これは全て完了させます。

(DB・サーバー構築編)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
↑ここではDBは使わないので、「8.EC2インスタンスの作成」から最後までを完了させます。

ユーザー作成

(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
↑この記事の「8.EC2へのログイン」まで終わらせる。

nginxのインストールと起動テスト

一度、この時点でnginxのインストールと起動を行い、ブラウザからアクセスしてデフォルトのページが表示されるかどうかを確認します。

最初からインストールされている全パッケージのアップデート

$ sudo yum update

nginxのインストール

$ sudo yum install nginx
$ nginx -v

nginxの起動

$ sudo service nginx start

起動後、EC2インスタンスのパブリックDNS or 割り当てたElastic IPにブラウザからアクセスして、下記のページが表示されることを確認します。

スクリーンショット 2017-12-29 16.36.03.png

環境構築

必要なもののインストール

$ sudo yum install make patch git gcc openssl-devel gcc-c++  epel-release
  • make: makeコマンド
  • patch: patchコマンド
  • git: gitコマンド(gitからクローンしたりするために必要)
  • gcc: Rubyをインストールするために必要
  • openssl-devel:Rubyをインストールために必要
  • gcc-c++: Nodeモジュールのコンパイルに必要
  • epel-release: Node.jsをyumでインストールするために必要

その他、依存関係にあるライブラリを入れていきます。

$ sudo yum install libyaml-devel libffi-devel libicu-devel
$ sudo yum install libxml2 libxslt libxml2-devel libxslt-devel
$ sudo yum install zlib zlib-devel readline readline-devel
$ sudo yum install ruby-devel

Node.jsとyarn、nのインストールとNode.jsの最新版へのアップデート

$ sudo yum install nodejs npm --enablerepo=epel 
$ sudo npm install -g yarn
$ sudo npm install -g n
$ sudo n latest

rbenvのインストール

$ 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

ruby-buildのインストール

$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ rbenv rehash 

インストールできるrubyのバージョン一覧を確認

$ rbenv install -l

rubyをインストール

$ rbenv install -v 2.5.0
$ rbenv global 2.5.0
$ source .bash_profile
$ ruby -v

bundlerとrakeのインストール

$ sudo gem update --system
$ sudo gem install bundler
$ sudo gem install rake

railsのインストール

$ gem install rails -N
$ rbenv rehash
$ rails -v

Railsアプリの新規作成

アプリは/var/www/に作成します。wwwディレクトリを作る過程で、varディレクトリとwwwディレクトリの所有者を自分のユーザーに設定します。
DBなしのRailsアプリを作るため、-O オプションをつけてrails newします。
最後に、rakeでアセットをプリコンパイルしておきます。

[ユーザー名@ip~~~]$ cd /
[ユーザー名@ip~~~ /]$ sudo chown ユーザー名 var
[ユーザー名@ip~~~ /]$ cd var
[ユーザー名@ip~~~ var]$ sudo mkdir www
[ユーザー名@ip~~~ var]$ sudo chown ユーザー名 www
[ユーザー名@ip~~~ var ]$ cd www
[ユーザー名@ip~~~ www]$ rails new myapp -O
[ユーザー名@ip~~~ www]$ cd myapp
[ユーザー名@ip~~~ myapp]$ rake assets:precompile RAILS_ENV=production

$ lsコマンドを打った時に自分のアプリ名(myapp)というフォルダができていれば成功です。

UNICORNのインストールと設定

Gemfileに下記を追加

group :production, :staging do
    gem 'unicorn'
end

そしてbundle installを実行

アプリのディレクトリのconfigディレクトリの中にunicorn.rbというファイルを作成します。

[ユーザー名@ip~~~ myapp]$ cd config
[ユーザー名@ip~~~ config]$ vi unicorn.rb

下記をコピペします。コピペしたらShift + ZZで閉じます。

config/unicorn.rb
  # set lets
  $worker  = 2
  $timeout = 30
  $app_dir = "/var/www/myappp" #自分のアプリケーション名
  $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

(viコマンドの操作についてはこちら

ngnixの設定

nginxの設定ファイルを編集します。nginxの設定ファイルは/etc/nginxの中にあるnginx.confです。

[ユーザー名@ip~~~ config]$ cd ~
[ユーザー名@ip~~~ ~]$ sudo vi /etc/nginx/nginx.conf

このファイルの中にinclude conf/mime.types;という記述があるので、その下にinclude /etc/nginx/conf.d/myapp.conf;を追記(セミコロンを忘れない!)

そしてmyapp.confは下記をコピペします。myappのところは自分のアプリ名に編集して下さい。

/etc/nginx/conf.d/myapp.conf
# log directory
error_log  /var/www/myapp/log/nginx.error.log;
access_log /var/www/myapp/log/nginx.access.log;
# max body size
client_max_body_size 2G;
upstream app_server {
  # for UNIX domain socket setups
  server unix:/var/www/myapp/tmp/sockets/.unicorn.sock fail_timeout=0;
}
server {
  listen 80;
  server_name あなたのEC2インスタンスのElastic IP;
  # nginx so increasing this is generally safe...
  keepalive_timeout 5;
  # path for static files
  root /var/www/myapp/public;
  # page cache loading
  try_files $uri/index.html $uri.html $uri @app;
  location @app {
    # HTTP headers
    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;
  }
  # Rails error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /var/www/myapp/public;
  }
}

ここまで完了したら、一度nginxを再起動してみましょう。

$ sudo service nginx stop
$ sudo service nginx start

スクリーンショット 2017-12-29 17.43.38.png

パブリックDNS or EC2インスタンスのElastic IPにアクセスしてこの画面になれば、設定がちゃんとできています。
(nginxが起動していて、unicornが起動できていない時の画面)

シークレットキーを設定してunicornを起動

アプリがあるディレクトリで下記のコマンドを打ってシークレットキーを設定&unicornを起動させます。

[ユーザー名@ip~~~ myapp]$ export SECRET_KEY_BASE=`rake secret`
[ユーザー名@ip~~~ myapp]$ unicorn_rails -E production -c config/unicorn.rb -D

スクリーンショット 2017-12-29 19.31.59.png

パブリックDNS or EC2インスタンスのElastic IPにアクセスして↑の画面になれば、unicornは起動できています。

なお、unicornが起動しているかどうかは ps -ef | grep unicorn | grep -v grepコマンドを打って確認します。3行ほど何か表示されれば起動していて、何も表示されなければ起動していません。

unicornの停止はアプリのあるディレクトリで下記のコマンドを打ちます。

[ユーザー名@ip~~~ myapp]$ sudo kill -QUIT `cat tmp/pids/unicorn.pid`

unicornを再び起動する時には、再びシークレットキーの設定が必要です。

トップページを作る

今のままではページが1ページも作られていないので、”The page you were looking for doesn’t exit.”と表示されています。railsコマンドで適当にトップページを作り、ルーティングを設定してみます。ここではhomeというコントローラのtopアクションを作ります。

[ユーザー名@ip~~~ myapp]$ rails generate controller home top

次に、routes.rbを編集してルーティングを設定します。ルート”/”へのgetリクエストに対して、’home#top’を呼び出すようにします。

[ユーザー名@ip~~~ myapp]$ cd config
[ユーザー名@ip~~~ myapp]$ vi routes.rb

そして下記のように書き換えます。

myapp/config/routes.rb
Rails.application.routes.draw do
  get '/' => 'home#top'

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

ここまで編集したら、一度unicornを再起動します。アプリのあるディレクトリで下記のコマンドを打ちます。

[ユーザー名@ip~~~ myapp]$ sudo kill -QUIT `cat tmp/pids/unicorn.pid`
[ユーザー名@ip~~~ myapp]$ export SECRET_KEY_BASE=`rake secret`
[ユーザー名@ip~~~ myapp]$ unicorn_rails -E production -c config/unicorn.rb -D

そしてパブリックDNS or EC2インスタンスのElastic IPにアクセスして、下記の画面になれば成功です。

スクリーンショット 2017-12-29 19.40.49.png

参考

ec2(amazon linux)にnginxを導入(デフォルトページの表示まで)
(デプロイ編②)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
Rails4 & Unicorn & Nginx & EC2でサーバー構築
AWSのEC2上でRails+Unicorn+Nginxを実現する
Amazon LinuxにRuby on Rails環境構築(rbenv + ruby-build + Ruby 2.2.1 + Rails 4.2.1インストール)

続きを読む

AWS Cloud9 で Ruby on Rails を試してみた

2017/11/30にAWSにて、クラウド型統合IDE Cloud9がローンチされましたので。
さっそく、Railsアプリケーションで試してみました。
AWS Cloud9 – クラウド開発環境

今回使用した環境

クライアントPC:mac book pro
ブラウザ:chrome
AWS使用サービス:
 CodeStar、EC2(t2.micro)、Cloud9

前提

以下の手順は、IAMユーザで行っています。
AWSは、ルートアカウントとは別に管理アカウントを複数作成できます。
これらのアカウントをAWSでは、IAMユーザと呼んでいる様ですが、
こうして作成した、IAMユーザは、クレジット情報などへの
アクセスをさせずに、管理業務だけを委任したりできるため、大変便利です。
AWS アカウント内での IAM ユーザーの作成

CodeStarによる環境セットアップ

まず、EC2にnginx+railsの環境を作成するため、CodeStarを使用します。
EC2のインスタンスを起動して一から必要なものをインストールしても良いのですが、
CodeStar使用すると、その辺の事をよしなにやってくれます。

まず、キーペアがひとつ必要です。
無い場合は、下記の手順で作成しておきます。
Amazon EC2 のキーペア

作成し終えたら、CodeStarのコンソールにアクセスします。
AWSにログインした状態で、以下のアドレスです。
CodeStarコンソール

スクリーンショット 2017-12-19 22.34.37.png

「Start a project」をクリックして、テンプレート選択画面に遷移しましょう。

スクリーンショット 2017-12-19 22.37.31.png

作成可能なテンプレートがたくさん並んでいます。
Railsに関しては、AWS Elastic Beanstalk版とEC2版がありますが、
今回は、簡易的な動作確認ですので、EC2版を選択します。
おそらく、Sqlite3を使った1インスタンスの最小構成で作成されるはずです。
mysqlなどのRDBを使ったり、ロードバランサを置いたりしたい場合は、
AWS Elastic Beanstalk版を選択すると良いと思います。

次はプロジェクト名とリポジトリ名を入力します。

スクリーンショット 2017-12-19 22.44.17.png

両方ともに「RailsSample」にしました。
リポジトリ管理には、AWS CodeCommit か GitHub のどちらかを選択できます。
どちらを選んでも、Gitでのバージョン管理になります。
CodeCommitは、GitHubの簡易版の様な位置づけでしたが、
2017年11月には、pullリクエストの作成もサポートされたらしく
徐々に使える様になってきている感じでしょうか。

今回は、CodeCommitを選択しました。

Create Project を選択すると、キー選択画面がポップアップされますので、
はじめに作成したキーペアを選択します。

スクリーンショット 2017-12-19 22.55.12.png

使用するIDEを選択する画面になりました。
ここで、本題のAWS Cloud9が出てきます。

スクリーンショット 2017-12-19 22.57.18.png

ここは当然、Cloud9を選択してみました。

スクリーンショット 2017-12-19 23.00.43.png

Cloud9を動作させるためのインスタンスの種類を選択します。
無料枠で試すには、t2.micro を選択します。

スクリーンショット 2017-12-19 23.03.24.png

環境の準備中です。
至るところクルクルしてますので、
しばし、待ちます。(5分くらいかな…)

スクリーンショット 2017-12-19 23.10.37.png

デプロイステータスが上記の様になり、
ヘッダ部が以下の様に変わったら、準備OKだと思います。

スクリーンショット 2017-12-19 23.12.29.png

View your app でRailsのサンプル・アプリケーションにアクセスできます。

スクリーンショット 2017-12-19 23.14.42.png

しゃれおつ。

Start coding の方を選択すると、Cloud9の画面に遷移します。

AWS Cloud9

スクリーンショット 2017-12-19 23.23.59.png

IDEっぽいです。
ブラウザだけでこれだけできるなんて、時代が進んだのを感じます。

ディレクトリツリーを見ると、Railsっぽい環境になっているのがわかります。
下部のペインは、EC2のコンソールになっていて、
シェルコマンドはここから実行できます。

RailsUser01:~/environment/railssample (master) $ ruby -v
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
RailsUser01:~/environment/railssample (master) $ gem list

*** LOCAL GEMS ***

actioncable (5.1.4)
actionmailer (5.1.4)
actionpack (5.1.4)
actionview (5.1.4)
activejob (5.1.4)
activemodel (5.1.4)
activerecord (5.1.4)
activesupport (5.1.4)
arel (8.0.0)
bigdecimal (default: 1.3.0)
builder (3.2.3)
bundler (1.15.4)
bundler-unload (1.0.2)
concurrent-ruby (1.0.5)
crass (1.0.2)
did_you_mean (1.1.0)
erubi (1.7.0)
executable-hooks (1.3.2)
gem-wrappers (1.3.2)
globalid (0.4.1)
i18n (0.9.0)
io-console (default: 0.4.6)
json (default: 2.0.2)
loofah (2.1.1)
mail (2.6.6)
method_source (0.9.0)
mime-types (3.1)
mime-types-data (3.2016.0521)
mini_portile2 (2.3.0)
minitest (5.10.1)
net-telnet (0.1.1)
nio4r (2.1.0)
nokogiri (1.8.1)
openssl (default: 2.0.3)
power_assert (0.4.1)
psych (default: 2.2.2)
rack (2.0.3)
rack-test (0.7.0)
rails (5.1.4)
rails-dom-testing (2.0.3)
rails-html-sanitizer (1.0.3)
railties (5.1.4)
rake (12.0.0)
rdoc (default: 5.0.0)
rubygems-bundler (1.4.4)
rvm (1.11.3.9)
sprockets (3.7.1)
sprockets-rails (3.2.1)
test-unit (3.2.3)
thor (0.20.0)
thread_safe (0.3.6)
tzinfo (1.2.3)
websocket-driver (0.6.5)
websocket-extensions (0.1.2)
xmlrpc (0.2.1)

現環境では、rubyは2.4.1、railsは、5.1.4の様です。
何か機能を足してみましょう。

RailsUser01:~/environment $ cd ./railssample
RailsUser01:~/environment/railssample (master) $ rails g scaffold blog title:string body:text
Usage:
  rails new APP_PATH [options]

Options:
  -r, [--ruby=PATH]                                      # Path to the Ruby binary of your choice
                                                         # Default: /usr/local/rvm/rubies/ruby-2.4.1/bin/ruby
  -m, [--template=TEMPLATE]                              # Path to some application template (can be a filesystem path or URL)
  -d, [--database=DATABASE]                              # Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/frontbase/ibm_db/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)

...以下略

おや?
エラーです。。。Usageが出ますね。。。

お気付きでしょうか?
ディレクトリツリーを見てわかる様にbinフォルダが存在しませんね。。。
なぜかは、わかりませんが、
rakeで作成できるはずなので、やってみます。

RailsUser01:~/environment/railssample (master) $ rake app:update:bin
Could not find gem 'passenger' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.

ん?
gem ‘passenger’ がいない?
確かに前述の gem list とGemfileの内容が一致していない様に思います。

bundle isntall します。

RailsUser01:~/environment/railssample (master) $ bundle install
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/.........
Fetching version metadata from https://rubygems.org/..
Fetching dependency metadata from https://rubygems.org/.
Resolving dependencies...
Fetching rake 11.2.2
Installing rake 11.2.2
Fetching concurrent-ruby 1.0.2
Installing concurrent-ruby 1.0.2
Fetching i18n 0.7.0
Installing i18n 0.7.0
Fetching minitest 5.9.0
Installing minitest 5.9.0
Fetching thread_safe 0.3.5
Installing thread_safe 0.3.5
Fetching builder 3.2.2
Installing builder 3.2.2
Fetching erubis 2.7.0
Installing erubis 2.7.0
Fetching mini_portile2 2.1.0
Installing mini_portile2 2.1.0
Fetching pkg-config 1.1.7
Installing pkg-config 1.1.7
Fetching rack 2.0.1
Installing rack 2.0.1
Fetching nio4r 1.2.1
Installing nio4r 1.2.1 with native extensions
Using websocket-extensions 0.1.2
Using mime-types-data 3.2016.0521
Fetching arel 7.1.1
Installing arel 7.1.1
Using bundler 1.15.4
Fetching byebug 9.0.5
Installing byebug 9.0.5 with native extensions
Fetching coffee-script-source 1.10.0
Installing coffee-script-source 1.10.0
Fetching execjs 2.7.0
Installing execjs 2.7.0
Fetching method_source 0.8.2
Installing method_source 0.8.2
Fetching thor 0.19.1
Installing thor 0.19.1
Fetching debug_inspector 0.0.2
Installing debug_inspector 0.0.2 with native extensions
Fetching ffi 1.9.14
Installing ffi 1.9.14 with native extensions
Fetching multi_json 1.12.1
Installing multi_json 1.12.1
Fetching libv8 3.16.14.19 (x86_64-linux)
Installing libv8 3.16.14.19 (x86_64-linux)
Fetching rb-fsevent 0.9.7
Installing rb-fsevent 0.9.7
Fetching puma 3.0.0
Installing puma 3.0.0 with native extensions
Fetching ref 2.0.0
Installing ref 2.0.0
Fetching sass 3.4.22
Installing sass 3.4.22
Fetching tilt 2.0.5
Installing tilt 2.0.5
Fetching spring 1.7.2
Installing spring 1.7.2
Fetching sqlite3 1.3.11
Installing sqlite3 1.3.11 with native extensions
Fetching turbolinks-source 5.0.0
Installing turbolinks-source 5.0.0
Fetching tzinfo 1.2.2
Installing tzinfo 1.2.2
Fetching nokogiri 1.6.8
Installing nokogiri 1.6.8 with native extensions
Fetching rack-test 0.6.3
Installing rack-test 0.6.3
Fetching passenger 5.1.12
Installing passenger 5.1.12 with native extensions
Fetching sprockets 3.7.0
Installing sprockets 3.7.0
Fetching websocket-driver 0.6.4
Installing websocket-driver 0.6.4 with native extensions
Using mime-types 3.1
Fetching coffee-script 2.4.1
Installing coffee-script 2.4.1
Fetching uglifier 3.0.1
Installing uglifier 3.0.1
Fetching rb-inotify 0.9.7
Installing rb-inotify 0.9.7
Fetching therubyracer 0.12.3
Installing therubyracer 0.12.3 with native extensions
Fetching turbolinks 5.0.0
Installing turbolinks 5.0.0
Fetching activesupport 5.0.0
Installing activesupport 5.0.0
Fetching loofah 2.0.3
Installing loofah 2.0.3
Fetching mail 2.6.4
Installing mail 2.6.4
Fetching listen 3.0.5
Installing listen 3.0.5
Fetching rails-dom-testing 2.0.1
Installing rails-dom-testing 2.0.1
Fetching globalid 0.3.7
Installing globalid 0.3.7
Fetching activemodel 5.0.0
Installing activemodel 5.0.0
Fetching jbuilder 2.5.0
Installing jbuilder 2.5.0
Using rails-html-sanitizer 1.0.3
Fetching spring-watcher-listen 2.0.0
Installing spring-watcher-listen 2.0.0
Fetching activejob 5.0.0
Installing activejob 5.0.0
Fetching activerecord 5.0.0
Installing activerecord 5.0.0
Fetching actionview 5.0.0
Installing actionview 5.0.0
Fetching actionpack 5.0.0
Installing actionpack 5.0.0
Fetching actioncable 5.0.0
Installing actioncable 5.0.0
Fetching actionmailer 5.0.0
Installing actionmailer 5.0.0
Fetching railties 5.0.0
Installing railties 5.0.0
Fetching sprockets-rails 3.1.1
Installing sprockets-rails 3.1.1
Fetching coffee-rails 4.2.1
Installing coffee-rails 4.2.1
Fetching jquery-rails 4.1.1
Installing jquery-rails 4.1.1
Fetching web-console 3.3.1
Installing web-console 3.3.1
Fetching rails 5.0.0
Installing rails 5.0.0
Fetching sass-rails 5.0.6
Installing sass-rails 5.0.6
Bundle complete! 17 Gemfile dependencies, 67 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

入ったっぽい。
再度、rakeにトライ。
今度は。bundle execつき

RailsUser01:~/environment/railssample (master) $ bundle exec rake app:update:bin                                                                               
/usr/local/rvm/gems/ruby-2.4.1/gems/rake-11.2.2/lib/rake/ext/fixnum.rb:4: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:206: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/activesupport-5.0.0/lib/active_support/xml_mini.rb:51: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/activesupport-5.0.0/lib/active_support/xml_mini.rb:52: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/digest_utils.rb:47: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/digest_utils.rb:51: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/processor_utils.rb:110: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/processor_utils.rb:111: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
      create  bin
      create  bin/bundle
      create  bin/rails
      create  bin/rake
      create  bin/setup
      create  bin/update
RailsUser01:~/environment/railssample (master) $ 

できた。
再度、scaffold。

RailsUser01:~/environment/railssample (master) $ rails g scaffold blog title:string body:text
/usr/local/rvm/gems/ruby-2.4.1/gems/rake-11.2.2/lib/rake/ext/fixnum.rb:4: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:206: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/activesupport-5.0.0/lib/active_support/xml_mini.rb:51: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/activesupport-5.0.0/lib/active_support/xml_mini.rb:52: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/digest_utils.rb:47: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/digest_utils.rb:51: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/processor_utils.rb:110: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/processor_utils.rb:111: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/activesupport-5.0.0/lib/active_support/core_ext/numeric/conversions.rb:138: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
      invoke  active_record
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
      create    db/migrate/20171219144809_create_blogs.rb
      create    app/models/blog.rb
      invoke    test_unit
      create      test/models/blog_test.rb
      create      test/fixtures/blogs.yml
      invoke  resource_route
       route    resources :blogs
      invoke  scaffold_controller
      create    app/controllers/blogs_controller.rb
      invoke    erb
      create      app/views/blogs
      create      app/views/blogs/index.html.erb
      create      app/views/blogs/edit.html.erb
      create      app/views/blogs/show.html.erb
      create      app/views/blogs/new.html.erb
      create      app/views/blogs/_form.html.erb
      invoke    test_unit
      create      test/controllers/blogs_controller_test.rb
      invoke    helper
      create      app/helpers/blogs_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/blogs/index.json.jbuilder
      create      app/views/blogs/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/blogs.coffee
      invoke    scss
      create      app/assets/stylesheets/blogs.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss
RailsUser01:~/environment/railssample (master) $ 

migrateも成功。

RailsUser01:~/environment/railssample (master) $ bundle exec rails db:migrate
/usr/local/rvm/gems/ruby-2.4.1/gems/rake-11.2.2/lib/rake/ext/fixnum.rb:4: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:206: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/activesupport-5.0.0/lib/active_support/xml_mini.rb:51: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/activesupport-5.0.0/lib/active_support/xml_mini.rb:52: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/digest_utils.rb:47: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/digest_utils.rb:51: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/processor_utils.rb:110: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/sprockets-3.7.0/lib/sprockets/processor_utils.rb:111: warning: constant ::Bignum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/activesupport-5.0.0/lib/active_support/core_ext/numeric/conversions.rb:138: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
== 20171219144809 CreateBlogs: migrating ======================================
-- create_table(:blogs)
   -> 0.0009s
== 20171219144809 CreateBlogs: migrated (0.0017s) =============================

/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated
/usr/local/rvm/gems/ruby-2.4.1/gems/concurrent-ruby-1.0.2/lib/concurrent/map.rb:230: warning: constant ::Fixnum is deprecated

このまま、コミットして、masterにpushします。

RailsUser01:~/environment/railssample (master) $ git add .
RailsUser01:~/environment/railssample (master) $ git commit -m 'blogs追加'
[master c39da40] blogs追加
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 28 files changed, 454 insertions(+), 1 deletion(-)
 create mode 100644 app/assets/javascripts/blogs.coffee
 create mode 100644 app/assets/stylesheets/blogs.scss
 create mode 100644 app/assets/stylesheets/scaffolds.scss
 create mode 100644 app/controllers/blogs_controller.rb
 create mode 100644 app/helpers/blogs_helper.rb
 create mode 100644 app/models/blog.rb
 create mode 100644 app/views/blogs/_form.html.erb
 create mode 100644 app/views/blogs/edit.html.erb
 create mode 100644 app/views/blogs/index.html.erb
 create mode 100644 app/views/blogs/index.json.jbuilder
 create mode 100644 app/views/blogs/new.html.erb
 create mode 100644 app/views/blogs/show.html.erb
 create mode 100644 app/views/blogs/show.json.jbuilder
 create mode 100755 bin/bundle
 create mode 100755 bin/rails
 create mode 100755 bin/rake
 create mode 100755 bin/setup
 create mode 100755 bin/update
 create mode 100644 db/migrate/20171219144809_create_blogs.rb
 create mode 100644 db/schema.rb
 create mode 100644 test/controllers/blogs_controller_test.rb
 create mode 100644 test/fixtures/blogs.yml
 create mode 100644 test/models/blog_test.rb
 create mode 100644 tmp/restart.txt
RailsUser01:~/environment/railssample (master) $ git config --global user.name "RailsUser01"
RailsUser01:~/environment/railssample (master) $ git config --global user.email test@test.com
RailsUser01:~/environment/railssample (master) $ git push
Counting objects: 47, done.
Compressing objects: 100% (44/44), done.
Writing objects: 100% (47/47), 8.65 KiB | 632.00 KiB/s, done.
Total 47 (delta 7), reused 0 (delta 0)
To https://xxxxx/v1/repos/RailsSample
   01dc390..c39da40  master -> master

すると、CodeStarの方で、pushを検知して、再びデプロイが始まります。
デプロイが終わったら、/blogsでアクセス。

スクリーンショット 2017-12-20 0.01.55.png

できたっぽい。
layoutが、しゃれおつのままなので、逆に見た目がアレですが、
一応、これで、コーディングして行けるっぽいです。

この先のこと

この環境では、EC2(Cloud9開発環境) -> EC2(動作確認環境)にいちいちデプロイして
確認することになるので、ちょっと面倒。
実用的に使うには、EC2(Cloud9開発環境) だけで、動作確認できる様にして、
ステージングやプロダクション環境には、必要に応じてデプロイ出来る様にしたいですね。

EC2(Cloud9開発環境)側にenginxを入れるか、
何かしらの制限付きでpumaのポートを開放するかになるのかな?
まだまだ、いろいろ試せそうな感じですが、
Cloud9ともども、おいおい試していきたいです。

試すだけなら無料枠で出来るので、皆様もいつかの機会にどうでしょうか?
今回はここまでです。

続きを読む

本番環境をGCP/AWSで何個か作り、インフラについて少しわかったこと【GCP環境構築編】

Hakusan Mafiaアドベントカレンダー5日目を余語 [Qiita|facebook|github] が担当します!

本番環境をGCP/AWSで何個か作り、インフラについて少しわかったこと【SSL証明書編】
本番環境をGCP/AWSで何個か作り、インフラについて少しわかったこと【GCP環境構築編】 ←今これ
本番環境をGCP/AWSで何個か作り、インフラについて少しわかったこと【パフォーマンス改善編】

はじめに

以前はAWSでインフラ環境を整えるのがベストプラクティスかと思っていました。というのも、EC2は直感的に触って起動できるし、S3・RDS・ DynamoDMなどの記事も相当Webに溢れていたので簡単でした。ただ、プレスリリースを売ったりメディアに出したりする案件があった際にわざわざAmazonへ申請を出さなければならないといけないらしいということを聞いて少し疑問に感じた時もありました。

そんな時に、AWSと同等のものを用意してくれている。且つ、自動スケーリングが凄い(詳しくいうと、ロードバランサがGoogle検索と同じらしい)という記事を見た時に、少々衝撃を覚えました。

今回の記事では、Google Cloud Platform(GCP)を利用して本番環境を構築する方法を記述します。
基本的には、公式ドキュメント通りにやると全てうまくいくのですが、自分のターミナルから色々いじりたい人用に書いてます。

10分でGCP環境構築

1. ログイン、プロジェクト作成

https://cloud.google.com/?hl=ja の右上でログインし、その後「コンソール」へ入る
プロジェクト作成から、「プロジェクト名」を入力して、準備完了

2. GCEを選択し、VMインスタンス作成

https://gyazo.com/0581708139112c11db672d5cdcfb7ea6

名前は適当で、
- ゾーンを「asia-northeast1-a」
- ブートディスクに今回は、「CentOS」
- ファイアウォールの設定は二つともチェックを入れましょう。

https://gyazo.com/5cc259ec583d4635073f1876cbbd28e6

3. Terminalにてgcloudログイン

今回は、ミドルウェア、とりわけWebサーバーをNginx、ApサーバーをUnicornで実装します。
OSは先ほどCentOSを利用すると選択したので、webにあるDebianでの記事と比較しながらやると勉強になると思います。
(RoRアプリケーションを想定しています。)

ミドルウェアの設定は次の通りです。

ミドルウェア 項目
nginx conn./worker 1024
unicorn worker processes/cpu 2 or 3

インスタンス作成後に、そのVMインスタンスの「接続」から「glcloud コマンドを表示」という箇所でコマンドをコピーして、ローカルで接続して見てください。

local
$ gcloud compute --project "xxxxx-yyy-1111111" ssh --zone "asia-northeast1-a" "xxx"
Last login: Sun Dec  3 08:13:59 2017 from softbankxxxx.bbtec.net

server
[xxxx@yyyy ~]$ #こんな感じでログインできる

先ほどGoogle Compute Engineで作成したVMインスタンスにログインできる。
(ここで弾かれたら、permission関連なのでgithubのSSH and GPG keysという箇所に公開鍵を貼り、ログインしてください。)

gcloudがないと言われたら、下記でインストール&ログイン

local
$ curl https://sdk.cloud.google.com | bash
$ gcloud init

4. 権限管理・ミドルウェアのインストール

4.1 新規ユーザー作成

server

[user_name| ~ ]$ sudo adduser [新規ユーザー名]
[user_name| ~ ]$ sudo passwd [新規ユーザー名]
[user_name| ~ ]$ sudo visudo
----------------------------
root ALL=(ALL) ALL
[新規ユーザー名] ALL=(ALL) ALL # この行を追加
# ↑後々 wheelか何かで管理できるとなお良い
----------------------------
[user_name| ~ ]$ sudo su - [新規ユーザー名]

4.2 VMインスタンス内の環境構築

yum -> node.js -> rbenv/ruby-build -> rubyの順

4.2.1 yum (mysql関連含む)

server
[user_name| ~ ]$ sudo yum install 
                 git make gcc-c++ patch 
                 libyaml-devel libffi-devel libicu-devel 
                 zlib-devel readline-devel mysql-server mysql-devel  -y

4.2.2 node.js

server
[user_name| ~ ]$ sudo curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
[user_name| ~ ]$ sudo yum install -y nodejs

4.2.3 rbenv/ruby-build

server
[user_name| ~ ]$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
[user_name| ~ ]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
[user_name| ~ ]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
[user_name| ~ ]$ source ~/.bash_profile
[user_name| ~ ]$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
[user_name| ~ ]$ rbenv rehash

4.2.4 ruby

server
# centOSを選択した場合
[user_name| ~ ]$ sudo yum -y install bzip2

[user_name| ~ ]$ rbenv install -v 2.4.1
[user_name| ~ ]$ rbenv global 2.4.1
[user_name| ~ ]$ rbenv rehash
[user_name| ~ ]$ ruby -v
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]

4.3 Gitとインスタンスの紐ずけ

ssh接続 → git clone

server
[user_name@vm_name .ssh]$ ssh-keygen -t rsa
[user_name@vm_name .ssh]$ cat config 
Host github
  Hostname github.com
  User git
  IdentityFile ~/.ssh/id_rsa #<- 追加
[user_name@vm_name .ssh]$ ssh -T github
# root権限だとgit cloneできないため
[user_name| ~ ]$ sudo chown user_name www/
[user_name@vm_name www]$ pwd
/var/www
[user_name@vm_name www]$ git clone git@github.com:~~~~

4.4 Nginxを積む

server
[ユーザー名|~]$ sudo yum install nginx
[ユーザー名|~]$ cd /etc/nginx/conf.d/
[ユーザー名|~]$ sudo vi <your_app_name>.conf (小文字でもok)
# default.conf/ssl.confなどと分けるとなお良い。(細分化)

Nginxの設定は最小限です。

/etc/nginx/conf.d/your_app_name.conf
upstream unicorn {
    server  unix:/var/www/<your_app_name>/tmp/sockets/unicorn.sock;
}

server {
    listen       80;
    server_name  <ip address and/or domain name>;

    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;

    root /var/www/<your_app_name>/public;

    client_max_body_size 100m;
    error_page  404              /404.html;
    error_page  500 502 503 504  /500.html;
    try_files   $uri/index.html $uri @unicorn;

    location @unicorn {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://unicorn;
    }
}
server
[user_name|~]$ cd /var/lib
[user_name|lib]$ sudo chmod -R 775 nginx #パーミッション調整

4.5 Unicornの導入/設定

server
[user_name@vm_name app_name]$  vi Gemfile
---------------------
group :production do
    gem 'unicorn'
end
---------------------
# gem: command not found
[user_name@vm_name app_name]$ gem install bundler
[user_name@vm_name app_name]$ bundle install
[user_name@vm_name app_name]$ vim config/unicorn.conf.rb
/var/www/app_name/config/unicorn.conf.rb
$worker = 2
$timeout = 30
$app_dir = '/var/www/<App_name>'
$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
worker_processes  $worker
working_directory $app_dir
stderr_path $std_log
stdout_path $std_log
timeout $timeout
listen  $listen
pid $pid
preload_app true

before_fork do |server, _worker|
  defined?(ActiveRecord::Base) && 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_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end

4.6 CSS/JSをコンパイル

server
[user_name@vm_name app_name]$ bundle exec rake assets:precompile RAILS_ENV=production

4.7 Unicorn起動

server
[user_name@vm_name app_name]$ bundle exec unicorn_rails -c /var/www/<your_app_name>/config/unicorn.conf.rb -D -E production

4.7 Nginx再起動

server
[user_name@vm_name app_name]$ sudo service nginx reload

これで本番環境が構築できたかと思います。
エラーが出た際は、下記を参考にデバッグをすれば問題ないので、各自調べてください。

nginx   なら /var/log/nginx/error.log
unicornなら  /log/unicorn.log

AWSやVPSで普段環境構築してる人からしたら、ほとんど難しいところはないかと思います。
今後

GKE・k8sによるオートスケールの設定
Dockerによる環境開発改善・デプロイ改善
Cloud Storageによる外部ファイルサーバ利用

などをする際に、便利さを身にしみて感じるのではと思います。
では最後の投稿を楽しみにしていてください。

本番環境をGCP/AWSで何個か作り、インフラについて少しわかったこと【パフォーマンス改善編】

続きを読む

AWS FargateでとりあえずMastodonを動かしてみる

先日こんな記事を見かけて、

Web, Worker, Websocketと要素が揃っているMastodonのスタックをXXで動かしてみる、というのは感触をつかむのによいなと思いました。

で、じゃあAWS Fargateではどうかなと、このようにしてみました。

Amazon ECS .png

事前準備

Dockerコンテナ以外で、マネージドサービスで揃えられるものは優先的にそちらを使用します。

  • AWSで用意

    • VPS (既存でも新規でも)
    • RDS (Postgresで起動)
    • ACMで証明書 (ALBに適用する)
    • ALB
      • TargetGroup-web (HTTP/3000)
      • TargetGroup-stream (HTTP/4000)
    • S3バケット (PAPERCLIP Wikiのポリシー適用が楽)
  • Redis => Redis Labs / 30MBまでならFreeプランでOK
    • ElastiCacheが使いたければそちらでも
  • MailGunアカウント
    • 専用の認証情報をつくるとよいです

ALBは以下のルーティングを最後に割り当てます。

  • / (default)=> TargetGroup-web
  • /api/v1/streaming* TargetGroup-stream

こんな感じです。

EC2 Management Console 2017-12-03 14-04-04.png

Fargateを考慮したTask definitions

事前準備の内容が揃っていれば、Dockerのコンテナとして動かすのは次の3要素。

  • Web(Rails/puma)
  • Sidekiq(Ruby)
  • Streaming(Node.js)

これらをTask definitionsに起こすとして、全部のコンテナ定義を一つにまとめるとスケール変更が大げさになるので、それぞれを別のECSサービスとして登録できるようにバラします。
compose感はなくなりますが、Fargateならその方が良いように思います。

各タスクはmastodonリポジトリのdocker-compose.ymlをベースに、kubedonを参考にしつつアレンジ。

.env.production

大筋として本家のdocker-composeを使いまわすので、もともと用意されている.env.productionから環境変数という仕組みをほぼ踏襲します。
今回このようにしました。

.env.production
RAILS_ENV=production
NODE_ENV=production
REDIS_URL=redis://:<RedisLabsのパスワード>@<RedisLabsのエンドポイント>

DB_HOST=<RDSのエンドポイント>
DB_USER=<RDSのユーザ>
DB_NAME=<RDSのDB名>
DB_PASS=<RDSのパスワード>
DB_PORT=5432

LOCAL_DOMAIN=<ALBに向けるドメイン>
LOCAL_HTTPS=true

PAPERCLIP_SECRET=<rake secretで作成>
SECRET_KEY_BASE=<rake secretで作成>
OTP_SECRET=<rake secretで作成>

VAPID_PRIVATE_KEY=<rake mastodon:webpush:generate_vapid_key で作成>
VAPID_PUBLIC_KEY=<rake mastodon:webpush:generate_vapid_key で作成>

DEFAULT_LOCALE=ja

SMTP_SERVER=smtp.mailgun.org
SMTP_PORT=465
SMTP_LOGIN=< MAILGUNの認証ユーザ >
SMTP_PASSWORD=< MAILGUNのパスワード >
SMTP_FROM_ADDRESS=noreply@< MAILGUNのドメイン >
SMTP_TLS=true

S3_ENABLED=true
S3_BUCKET=< S3のバケット >
AWS_ACCESS_KEY_ID=< S3用のIAMユーザのキー >
AWS_SECRET_ACCESS_KEY=< S3用のIAMユーザのシークレットキー >
S3_REGION=< S3のリージョン >
S3_PROTOCOL=https
S3_HOSTNAME=< S3のリージョン別エンドポイント >

STREAMING_CLUSTER_NUM=1

web

web用にdocker-compose.web.yml, ecs-param.web.ymlを用意します。ecs-cliの取り回しを考えると、ディレクトリ分けて標準のファイル名を使う方が楽だったかも。
また、汎用性を考えたらloggingは分けて、–fileで追加指定してもよいはずです。

docker-compose.web.yml
version: '2'
services:
  web:
    image: gargron/mastodon:v2.0.0
    env_file: .env.production
    command: ["/bin/ash", "-c", "rails db:migrate && rails assets:precompile && rails s -p 3000 -b 0.0.0.0"]
    ports:
      - "3000:3000"
    mem_limit: 2GB
    logging:
      driver: awslogs
      options:
        awslogs-group: mstdn-fargate-demo
        awslogs-region: us-east-1
        awslogs-stream-prefix: web

assign_public_ipはイメージの取得にDockerhubを使う場合ENABLEDでないとPullできません。(※他にルートを用意できればおそらく可)
SGはALBとさえ通信できればOKなので、特にきにせずENABLEDで良いでしょう。

ecs-param.web.yml
version: 1
task_definition:
  ecs_network_mode: awsvpc
  task_execution_role: ecsTaskExecutionRole
  task_size:
    cpu_limit: 512
    mem_limit: 2GB
  services:
    web:
      essential: true
run_params:
  network_configuration:
    awsvpc_configuration:
      subnets:
        - <YOUR_SUBNETa>
        - <YOUR_SUBNETb>
      security_groups:
        - <YOUR_SG>
      assign_public_ip: ENABLED

webは他に比べてスペック高、ほぼasset:precompileのため(メモリが足りないと落ちる)です。

作成したファイルたちを指定してecs-cli composeを使ってサービス登録するにはこんな感じ。
CLUSTER_NAME=既存ECSクラスタの名前、TARGET_GROUP_WEB=参加させるALBのターゲットグループに置き換えで。

$ ecs-cli compose 
  --file docker-compose.web.yml 
  --ecs-params ecs-param.web.yml 
  --project-name mstdn-fargate-web 
  --cluster ${CLUSTER_NAME} 
  service up --launch-type FARGATE 
  --container-name web 
  --container-port 3000 
  --target-group-arn ${TARGET_GROUP_WEB}
  # --timeout 0

--target-group-arnは後から変更できないので、変更が必要な場合はサービスを一旦消すか別名で作成です。

なお実行の際、CPUをケチる(<1024)と--timeout 0を付与しておかないとデフォルト待ちの5分ではassets生成が終わりません。
このあたり考慮すると、実際に運用する場合は起動時間のことも考えて、よそでprecompileしてpublicを別に用意するのが得策でしょう。

streaming

streaming用にdocker-compose.streaming.yml, ecs-param.streaming.ymlを用意します。ecs-cliの取り回し(以下略

docker-compose.streaming.yml
version: '2'
services:
  streaming:
    image: gargron/mastodon:v2.0.0
    env_file: .env.production
    command: ["npm", "run", "start"]
    ports:
      - "4000:4000"
    logging:
      driver: awslogs
      options:
        awslogs-group: mstdn-fargate-demo
        awslogs-region: us-east-1
        awslogs-stream-prefix: streaming

streamingのパラメータ、サイズは最小。FargateはCPUとメモリの組み合わせに制限があるようです。

ecs-param.streaming.yml
version: 1
task_definition:
  ecs_network_mode: awsvpc
  task_execution_role: ecsTaskExecutionRole
  task_size:
    cpu_limit: 256
    mem_limit: 512
  services:
    streaming:
      essential: true
run_params:
  network_configuration:
    awsvpc_configuration:
      subnets:
        - <YOUR_SUBNETa>
        - <YOUR_SUBNETb>
      security_groups:
        - <YOUR_SG>
      assign_public_ip: ENABLED

作成したファイルたちを指定してecs-cli composeを使ってサービス登録するにはこんな感じ。webとほぼおなじですね。
CLUSTER_NAME=既存ECSクラスタの名前、TARGET_GROUP_STREAMING=参加させるALBのターゲットグループに置き換えで。

$ ecs-cli compose 
  --file docker-compose.streaming.yml 
  --ecs-params ecs-param.streaming.yml 
  --project-name mstdn-fargate-streaming 
  --cluster ${CLUSTER_NAME} 
  service up --launch-type FARGATE 
  --container-name streaming 
  --container-port 4000 
  --target-group-arn ${TARGET_GROUP_STREAMING}

sidekiq

sidekiq用にdocker-compose.sidekiq.yml, ecs-param.sidekiq.ymlを用意します。ecs-cliの取り回し(以下略

docker-compose.sidekiq.yml
version: '2'
services:
  sidekiq:
    image: gargron/mastodon:v2.0.0
    env_file: .env.production
    command: ["sidekiq", "-q", "default", "-q", "mailers", "-q", "pull", "-q", "push"]
    logging:
      driver: awslogs
      options:
        awslogs-group: mstdn-fargate-demo
        awslogs-region: us-east-1
        awslogs-stream-prefix: sidekiq

こちらも最小でOK。

ecs-param.sidekiq.yml
version: 1
task_definition:
  ecs_network_mode: awsvpc
  task_execution_role: ecsTaskExecutionRole
  task_size:
    cpu_limit: 256
    mem_limit: 512
  services:
    sidekiq:
      essential: true
run_params:
  network_configuration:
    awsvpc_configuration:
      subnets:
        - <YOUR_SUBNETa>
        - <YOUR_SUBNETb>
      security_groups:
        - <YOUR_SG>
      assign_public_ip: ENABLED

CLUSTER_NAME=既存ECSクラスタの名前に置き換えで。

$ ecs-cli compose 
  --file docker-compose.sidekiq.yml 
  --ecs-params ecs-param.sidekiq.yml 
  --project-name mstdn-fargate-sidekiq 
  --cluster ${CLUSTER_NAME} 
  service up --launch-type FARGATE

ECS状況

$ ecs-cli ps --cluster ${CLUSTER_NAME}
Name                                            State                                                                               Ports                          TaskDefinition
775a399c-19e1-4e2a-bd3d-98f8b4d7304e/streaming  RUNNING                                                                             34.204.191.189:4000->4000/tcp  mstdn-fargate-streaming:1
921f2d1a-0e4f-49a6-a5b5-434e2b91cf11/sidekiq    RUNNING                                                                                                            mstdn-fargate-sidekiq:2
edb1ba2e-533d-4afd-aaee-39db59ee616a/web        RUNNING                                                                             34.204.174.122:3000->3000/tcp  mstdn-fargate-web:15

$ aws ecs list-services --cluster ${CLUSTER_NAME} 
{
    "serviceArns": [
        "arn:aws:ecs:us-east-1:xxxxxxxxxxxx:service/mstdn-fargate-web", 
        "arn:aws:ecs:us-east-1:xxxxxxxxxxxx:service/mstdn-fargate-sidekiq", 
        "arn:aws:ecs:us-east-1:xxxxxxxxxxxx:service/mstdn-fargate-streaming"
    ]
}

それぞれ別のECSサービスとして動かせたので、個別にコンテナ数を変更できて良い感じのはず。

Mastodon 2017-12-03 14-02-01.png

Mastdon admin登録

さて、Mastodonの管理者になるにはmastodon:make_adminタスクを実行すればよいのですが、Fargate上のDockerコンテナで何か実行(docker exec相当)できるのだろうか。

さっとアタッチはできないぽいので、これもtask definitionからやりますか。

yamlをかいてー

docker-compose.web_make_admin.yml
version: '2'
services:
  web:
    image: gargron/mastodon:v2.0.0
    env_file: .env.production
    command: ["/bin/ash", "-c", "rails mastodon:make_admin USERNAME=sawanoboly"]
    mem_limit: 512MB
    logging:
      driver: awslogs
      options:
        awslogs-group: mstdn-fargate-demo
        awslogs-region: us-east-1
        awslogs-stream-prefix: railstask

ecs-cli compose upと。

$ ecs-cli compose 
  --file docker-compose.web_make_admin.yml 
  --ecs-params ecs-param.web.yml 
  --project-name mstdn-fargate-makeadmin 
  --cluster ${CLUSTER_NAME} 
  up --launch-type FARGATE

で、管理メニューアクセスオープン。

レポート - Mastodon 2017-12-03 14-34-44.png

少々手間だが、できるのでよいです。

おわりに

これまではスケール変更を柔軟にしようと思ったら結局ECSクラスタなりk8s、docker swarmなどのノードを確保しておく必要があったことを考えると、リソース配分が目に見える分だけになるのでシンプルです。

Fargateで起動するコンテナと通常のEC2インスタンスを比較すると、数字上で同等のCPU/メモリのインスタンスを維持するよりFargateのほうがちょっと割高になるはずです。
しかし、EC2ではサービス用のプロセス以外にも色々動かしたりケアする場所も多いため、コンテナより余分に性能やらディスクやらが必要になります。Fargateは下限ギリギリを攻めてもよい分、トータルでどっちがよいかは動かしたいものによるでしょう。

スケールアウトの対応速度は比較にならないほどFargateの方がはやいです。※この記事の例での構成ではコンテナイメージの最適化をしてないので少々もたもたしますが。

Fargate専用のSpotFleetでないかなあ。

続きを読む

サーバ、インフラ経験ゼロの初心者がAWSで「【非公式】Unity JP Mastodon」を作ってみた

Mastodon Advent Calendar 2017 3日目の記事になります。

【非公式】Unity JP Mastodonの管理人、荻野です。
logo.svg

今回はサーバー、インフラの実装経験ゼロの超初心者が、ネットに掲載されている情報のみで生まれて初めて触ったAWSを利用して、Mastodonインスタンスを組み立てたことを書いていきます。

サーバー、インフラ初心者故に引っかかった苦労点や、AWSに全く詳しくなかったために頭から地雷にダイブするなど、バカバカしいお話でも書いていきたいと思います。

ソースだけ読みたい方はこちらから見れます。

Mastodonインスタンスを立てる上で参考にさせていただいたサイト

一番お世話になったのが以下のサイトです。インスタンス作成時は、これをそのまま使わせていただきました。

マストドンAWS構築チュートリアル完全版|初心者から大規模運用まで

簡単な自動メンテナンス処理も記載されているのが本当にありがたかったです。
5月のゴールデンウィークに当時v1.3.2だったMastodonインスタンスを立てたのですが、ほぼこのサイトに書いてある手順をほぼそのままなぞったらMastodonインスタンスがAWSで動きました。

※現状のv2.0以上だと、一部ソフトウェアのバージョンをアップしないとビルドが通らないことがあります

他に参考にさせていただいたサイトをいくつか掲載します
AWSの無料SSLを使ってmastodonインスタンスを立てる手順
AWSでMastodonサーバー立てました chitose.moe
AWSのEC2で最小限の努力でmastodonを構築する
マストドンのインスタンスを構築するドン
Mastodon インスタンスを運用しているサーバを HTTP/2 対応させた話 (CentOS7 + nginx + OpenSSL)

AWS設定

Mastodonインスタンスを立てるにあたり、使用したAWSサービスは以下の通りです。

・EC2インスタンス
OS:ubuntu16.04
タイプ:t2.micro

インスタンス作成時のタイプ:t2.medium
※t2.microだとアセットの初回ビルドでメモリの上限を超えて落ちるため

・RDS
エンジン:PostgreSQL
クラス:db.t2.micro
ストレージ:20GB

・ElastiChache
タイプ:cache.t2.micro

・VPC
・S3
・CloudWatch
・CloudFront
・Route 53
・Certificate Manager

※ほぼ全て無料枠に抑えています。

無料枠でおさめられれば、費用はだいたい100円以下となっています。
画像をのぞいて、Unityリンク集やお知らせ表示の簡単なカスタマイズを入れています。

スクリーンショット 2017-12-02 21.25.28.png

現バージョン(v2.0以上)でMastodonインスタンスをAWSで動かしたい場合

Mastodonは日々高速で改良が加えられているため、2017年4月前に記載されたマストドンAWS構築チュートリアル完全版を見て新規にMastodonインスタンスを組み立てる場合、いくつか引っかかる点と当時未実装だった機能があります。

dockerのバージョンが1.13以上であることが必須

v1.4.1からdockerが1.13以上でないと、ビルドが通らないように変更されています。

現在、非公式のUnity Mastodonのバージョンアップ中
どうやら1.4.1はdockerが1.13以上でないとビルドできないようになっているっぽいな

— 荻野雄季@デジゲー博X-03ab (@YuukiOgino) 2017年6月14日

バージョンが1.13より低い場合、公式ドキュメントを見て、docker ceをインストールしましょう。

プッシュ通知(VAPIDキー)

プッシュ通知はv1.5.0から新規に追加されました。
そのため、プッシュ通知に対応する場合は以下の作業が追加されます。

1.以下のコマンドを叩いて秘密鍵/変数を生成します
RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key
(ドッカーの場合、docker-compose run –rm web rake mastodon:webpush:generate_vapid_key)

2.生成した秘密鍵/変数を設定ファイルにセット
大抵の人が.env.productionと名付けるファイルで、以下の定数に生成した秘密鍵と変数をセットします。

VAPID_PRIVATE_KEY =
VAPID_PUBLIC_KEY =

生成さえすれば、どちらがどのKEYに対応しているかはわかると思います。

AWS(インフラ)初心者ゆえやらかした失敗

AWSは2017年5月のGWで初めて触ったため、いくつかバカバカしい失敗をしました。
自分への戒めとして、晒していきます。

RDSとElastiCacheを本番稼動用のデフォルト設定のまま本番公開した

はい、Mastodonインスタンス作成時に初めてAWSに触ったため、ろくに調べずに無知故にやらかした失敗です。

これ、何が失敗かというと、最大でも一日あたりのアクティブユーザーが50人以下のコンテンツなのに、明らかに超オーバースペックな上に壮大に無駄な費用が発生するモンスタースペックな構成に知らず知らずにしてしまったことです。

1.ElastiCache
ElastiCacheのデフォルトだとシミュレーションができなかったので、大雑把な計算をしてみました。

ノードのタイプ:cache.r4.large(メモリ12.3GB) 時間で$0.288の費用発生
レプリケーション数:2

大雑把に料金を計算すると$0.288×2×24×31=$428.544(約48,083円)
明らかに不必要な投資です。

2.RDS
こちらは実際のデフォルト設定からある程度シミュレーションで計算ができました。
スクリーンショット 2017-12-02 19.07.27.png

なんと驚愕の月額$1386.07(約155,521円)!
明らかに過剰投資です。

これは現在の料金設定からの計算であり、当時は1日1万ずつ自動課金されるぐらいの消費をしていました。
構築時は設定した時間が3〜4時間程度な上、請求の欄を見ていなかったために異常な料金の上がり方に気づいていませんでした。

リリースしてから1日後、請求額を見たら明らかに想定と違う料金の上がり方をしていることに気づき、料金を調査して発覚しました。これをどうにかしないと毎月20万消える恐ろしいモノになるため、早期に構成を変更せざるを得ませんでした。

この時に初めてAWSの仕様として、容量は簡単に上げることは可能だが、容量を減らすことはできないことを知り、改めてインスタンスを作り直さないといけないことになりました。

ElastiCacheの再設定

Mastodonはサーバーキャッシュは全て捨てても、直近で影響が出るのがホームのページの表示ぐらいというのが検証してわかったため、完全に付け替える方針にしました。
超小規模であればレプリケーション数は1、メモリ0.5GBでも十分と判断し、ElastiCacheは無料枠に収めるインスタンスを改めて作成し、付け替えました。

無事に接続を確認後、金食い虫のインスタンスは即刻削除して料金を発生しないようにしました。

RDSの再設定

一番困ったのがDB、RDSの再構築です。一度世間に解放してしまった以上、当時90人弱のユーザー登録があったので破棄してしまうと再度登録させるという非常に面倒な手間を強いることになるため、DBをそのまま移植しないといけません。

仕事では基本的にSQLでの流し込みぐらいしかしてなかったため、時間が過ぎるごとに課金額があがる恐怖と戦いながらネット上でRDSのバックアップと復旧方法を検索しました。

最終的に以下の方法でDBの移植を行いました。

1.dumpファイル作成

まずdumpファイルを作成します。叩いたコマンドは以下の通りです。

psql -f [作成するdumpファイル名] --host=[RDSエンドポイント]  --port=[ポート] --username=[ユーザー名] --password --dbname=[DB名]

2.dumpから復旧

無料枠で収まるRDSインスタンスを作成後、以下のコマンドを実行しました。

sudo pg_restore -c -h [RDSエンドポイント] -U [ユーザ名] -d [DB名] [dumpファイル] 

詳しくはPostgreSQL 9.2.4文書をご覧ください。

あとは新規に作成したRDSに接続するように設定を変更し、無事トゥート一覧やユーザーリストが表示されていることを確認後、古いインスタンスを即時削除しました。

これでなんとかDBの復旧ができました。
頭ではDBはバックアップとって復旧する、ということをやらなければいけないとはわかってましたが、dumpファイルからの復旧は初めての作業だったため、非常にテンパった覚えがあります。

久しぶりに頭をフル回転させましたw

S3をダイレクトに接続していた結果、通信プロトコルがHTTP1.1形式でページの表示が遅かった

これもやらかしの一つです。ドキュメントを読めば明らかなのですが、S3の通信プロトコルはHTTP/1.1のため、せっかくHTTPSで接続しているのにHTTP/2.0にしていないために非常に無駄な通信コストが発生していました。

CloudFrontを経由すればS3でもHTTP/2.0対応ができることを知ったため、早速試してみました。

1.ドメイン&証明書発行

S3用のドメインと証明書を発行する必要があるため、AWSの証明書で作成します。
mastodonインスタンス作成時と同様、証明書のリクエストを行います。このドメインさえ確保できれば、あとはCloudFrontでインスタンスを作成するのみです。
スクリーンショット 2017-12-02 20.41.29.png

2.CloudFrontインスタンス作成

まずインスタンスを作成します。上のWebから作成します。
スクリーンショット 2017-12-02 20.34.50.png

Create Distribution画面が出てくるので、Origin Domain NameにS3のバケットをセットします。

スクリーンショット 2017-12-02 20.35.23.png

続いて、SSL CertificateでCustom SSL Certificateを選択し、先ほど発行したドメインをセットします。

スクリーンショット 2017-12-02 20.36.40.png

最後、HTTP VersionsがHTTP/2をサポートする設定になってるか確認し、インスタンスを作成します。
スクリーンショット 2017-12-02 20.35.59.png

最後、このドメインをS3_BUCKETに設定すれば、HTTP/2.0対応完了となります。
HTTP/2.0に変更後、画像等のアセットダウンロードが体感速度的に2倍ぐらい早くなった気がします。

参考に、画像がたくさん上がってくるPawooのインスタンスユーザーを表示した上での速度です。

スクリーンショット 2017-12-02 20.58.30.png

※すみません、データ取る前に切り替えてしまったので、変更前の具体的な数値が出せないです

33の画像を読み込んだ上での速度です

一見わかりにくくて申し訳ないですが、これはAWSで全て無料枠で収めてこの速度が出るということなので、EC2やElastiCacheの性能をあげればもっと早くなると思います。

Mastodonインスタンスを組み立てる上で役だったスキル

私は一応、会社で某ソーシャルゲームのWebフロントエンジニアのため、会社で(嫌でも)以下の経験をしたのがMastodonを立てる時に役立ちました。

・簡単なLinuxコマンドとコマンドライン

大体本番で使われているWebサーバーはLinuxのCUIベースだったので、フロントのソースをアップするために何回かviを編集していたこと、シンクコマンドを叩いていたのが役に立ちました。(GUIばっかり触ってると、CUIだとわかりにくい部分があるため)
Linuxでサーバーを立てる場合、ある程度Linuxコマンドを叩いて慣れておいたほうがいいと思います。

MastodonとAWSを触ったり、地雷を踏んだりして得られたスキル

最後のまとめです。
インスタンス作成時はAWSを触って4日、色々と失敗をやらかして得られた経験は以下の通りです。

・RDS(PostgreSQL)でのバックアップ復旧作業
・AWSにおけるサーバー環境構築
・Mastodonインスタンス構築の知見
・サーバーコストへの意識
・ユーザーがいる状況での本番環境のバージョンを更新するという恐怖と覚悟

とくによかったと思えるのはサーバーコストへの意識です。
実際に立てたからわかることですが、サーバーコストを適切にしないと無駄な費用が発生して回らなくなるというのをよく理解しました。
実質、フロント部分しか触ってないと、会社環境によってはこの辺りの意識がないところもあるので、改めてサーバーコストの意識が高まったのはやってよかったと思います。

本番環境の更新は毎回冷や汗を書きます。なぜなら会社では万が一が起きても頼れる人がいますが、このインスタンスで頼れるのは自分一人です。万が一が発生した場合、ネット上で情報がなければお手上げです。
謎のエラーでバージョンが更新できずに起動できない(だいたいコンフリクト放置が原因)ときは本当にあせります。

かなり必死で頭を回してるからこそ、動いた時に得られる経験値というのは相当なものだと感じています。
もし、Web系の会社に行きたいと考えている人は、mastodonインスタンスを立てて運営してみると、色々と実践的な経験を短期間で詰めるかもしれません。

明日はxserverさんによる「インスタンス運用アンチパターン」です。楽しみです!!

続きを読む

AWS Elastic BeanstalkでRails5アプリをデプロイする際の注意点(後編)

この記事

こちらの前編の続きです。

再デプロイエラー

上記の記事で初回デプロイまでは難なくできましたが、再デプロイが全然上手くいきませんでした。
出ていたエラーが下記のようなものです。(文字化けはご容赦ください。)

Webpacker is installed 脂 魂
  Using /var/app/ondeck/config/webpacker.yml file for setting up webpack paths
  Compiling窶ヲ
  Compilation failed:
  yarn run v1.2.1
  $ /var/app/ondeck/node_modules/.bin/webpack --config /var/app/ondeck/config/webpack/production.js
  info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

 warning From Yarn 1.0 onwards, scripts don’t require “--” for options to be forwarded. In a future version, any explicit “--” will be forwarded as-is to the scripts.
  fs.js:1331
      writeAll(fd, isUserFd, buffer, 0, buffer.length, position, callback);
                                              ^

 TypeError: Method get TypedArray.prototype.length called on incompatible receiver [object Object]
      at Buffer.get length [as length] (native)
      at writeFd (fs.js:1331:45)
      at fs.js:1322:7
      at FSReqWrap.oncomplete (fs.js:123:15)
  error Command failed with exit code 1.
   (Executor::NonZeroExitStatus)

状況としては書き込み時にメモリなどの問題で失敗しているようでした。
私の環境ではVue.jsを使ってほぼSPAに近い状態だったので.vueファイルなどをコンパイルしたファイルが数MBとかなり大きくなっていたことが原因のようでした。

暫定策

プレコンパイルをローカルで実施することにしました。

インスタンスサイズにもよるのでしょうが、この方が格段にデプロイが早かったです。
結果的には下記のようなファイルで落ち着きました。

01_yarn.config
commands:

  01_node_get:
    cwd: /tmp
    command: 'sudo curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash -'

  02_node_install:
    cwd: /tmp
    command: 'sudo yum -y install nodejs'

  03_yarn_get:
    cwd: /tmp
    # don't run the command if yarn is already installed (file /usr/bin/yarn exists)
    test: '[ ! -f /usr/bin/yarn ] && echo "yarn not installed"'
    command: 'sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo'

  04_yarn_install:
    cwd: /tmp
    test: '[ ! -f /usr/bin/yarn ] && echo "yarn not installed"'
    command: 'sudo yum -y install yarn'

  05_mkdir_webapp_dir:
    command: mkdir /home/webapp
    ignoreErrors: true

  06_chown_webapp_dir:
    command: chown webapp:webapp /home/webapp
    ignoreErrors: true

  07_chmod_webapp_dir:
    command: chmod 700 /home/webapp
    ignoreErrors: true
03_conteiner_comand.config
container_commands:
  01-bundle_install:
    command: bundle install --path vendor/bundle
  02-db_migrate:
    command: bundle exec rake db:migrate
  03-db_seed:
    command: bundle exec rake db:seed

その上で、環境変数は下記のようにしています。(実行時は1行)
()の中は適宜自分の環境に読み変えてください。

eb setenv
RDS_PORT=3306
SECRET_KEY_BASE=<secret_key>
RAILS_SKIP_ASSET_COMPILATION=true
RDS_PASSWORD=<pass>
RDS_DB_NAME=ebdb
RACK_ENV=production
RDS_USERNAME=<user_name>
BUNDLE_WITHOUT=test:development
RAILS_SKIP_MIGRATIONS=true 
RDS_HOSTNAME=<hogehoge.rds.amazonaws.com>
-e <environment_name>

デプロイ手順は下記。

bundle exec rake assets:precompile assets:clean RAILS_ENV=production SECRET_KEY_BASE=<secret_key>
git add .
eb deploy <environment_name> --staged

最後に

AWS Elastic BeanstalkでRailsアプリをデプロイする際の参考になれば幸いです。
Railsはまだ初心者のため、色々ご指摘ありましたら優しく教えてください。

続きを読む

マストドンを2.0.0へバージョンアップを行う

概要

既に動いているインスタンスを2.0.0へ上げる
動かし方としてはEC2上から docker-compose up -d でそのまま使っている。
バージョンを上げるついでに画像データはS3へ、DBはRDSへ同時に移行させる。

環境

$ cat /proc/version
Linux version 4.4.0-1039-aws (buildd@lcy01-02) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) ) #48-Ubuntu SMP Wed Oct 11 15:15:01 UTC 2017
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"
$ docker -v
Docker version 17.05.0-ce-rc3, build 90d35ab
$ docker-compose -v
docker-compose version 1.12.0, build b31ff33
$ git describe --tags #マストドン
v1.4rc3-24-gbbc3db8

やったこと

RDSの作成

  • 時間がかかるので一番最初に作成してしまう。
  • 何らかの方法で適宜RDS(PostgreSQL)を作成。
    • 特に設定はしていない。文字コードぐらい?

S3の作成

  • コンソールからS3を作成
  • バケットポリシーを変更
バケットポリシー
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"PublicS3Objects",
      "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::<YOUR BUCKET NAME>/*"]
    }
  ]
}
  • S3へ既存の画像データをアップロード

    • $ aws s3 sync ./public/system/ s3://<YOUR BUCKET NAME>/

既存DBのダンプを取得

  • docker内からダンプを取得するため、 docker-compose.yml を書き換える

    • dockerとバージョンの合ったpsqlコマンドを取得するのが面倒なため中から実行する。
  db:
    restart: always
    image: postgres:9.6-alpine
### Uncomment to enable DB persistance
    volumes:
      - ./postgres:/var/lib/postgresql/data
      - ./dump:/dump
  • ダンプを取得する

    • $ docker-compose run --rm db pg_dump -h localhost -p 5432 -U <USER NAME> <DB NAME> > /dump/dump.sql
  • 取得したダンプをRDSへ流し込む
    • $ psql -h <RDS ENDPOINT> -U <USER NAME> <DB NAME> < ./dump/dump.sql

リポジトリをクローンし直す

  • 現在動いているマストドンを停止させる

    • $ docker-compose stop
  • 適当なディレクトリに移動し、マストドンをcloneする

    $ cd /opt
    $ git clone https://github.com/tootsuite/mastodon
    $ cd mastodon
    

.env.productionの編集

  • 運用していたマストドンディレクトリから .env.production を取得

    • $ cp /path/to/mastodon/.env.production ./
  • .env.production を編集

    • 編集するのは DB パラメータと、 S3 パラメータ。
    • S3はENDPOINTは以下の通り編集する必要あり
      • ex) S3_ENDPOINT=https://s3-ap-northeast-1.amazonaws.com
  • VAPIDを埋める
    • $ docker-compose run --rm web rake mastodon:webpush:generate_vapid_key を実行して出力されたパラメータをコピペ

DBのマイグレーションとアセットのコンパイル

  • DBのマイグレーションの実行とアセットのコンパイル

    • $ docker-compose run --rm web rake db:migrate; docker-compose run --rm web rake assets:precompile

マストドンの起動

  • $ docker-compose up -d

参考

続きを読む