#前提(絶対にやってはいけないこと)
「.env」ファイルをgithubにあげない。
過去、一度でも上げている場合の対処手順
1, 「.gitignore」ファイルに「.env」を追記
2, ファイルを残したまま、管理対象から除外。
# ファイルを残したまま、管理対象から除外。
git rm --cached .env
3, コミットして、gitにpush
#EC2のインスタンス生成
-
リージョンを東京に変更
-
railsアプリをデプロイする上で、事前サポートが充実している「Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type」を選択
※AMIとは、OSやアプリケーションなど、インスタンスの作成に必要なソフトウェアのパッケージのようなもの。バージョンは作成時に変わると思う。 -
「インスタンスの詳細の設定」:特に何もなければいじらない
-
「ストレージの追加」:通常サイズは8、ボリュームタイプは汎用になっているため、特に何もなければ、このまま何もいじらない
-
「タグの追加」:必須ではないが、設定しておくと後が楽。
Ex),「キー」に「name」、「値」に「(アプリ名)-production」 -
セキュリティグループ作成:
ブラウザなどからアクセスするためのhttpと、コンソールからEC2にログインするためのsshへの通信を許可する必要がある。
#キーペアの生成と固定IPの割り振り
EC2インスタンスに対しては、公開鍵認証方式によるSSH接続を前提としている(githubとローカル環境で行っている接続方式と、考え方はほぼ一緒)
- まずは、EC2へログインするための手段として仮のキーであるキーペアをAWSで作成し、ダウンロード(秘密鍵)し、インスタンスの作成をクリック。
※ローカルからEC2に接続できていないと何もできないので、仮のキーを使う。「キーペア名」はなんでも良い。Ex),[アプリ名]-key
- ダウンロードしたキーペアへの読み取り権限付与
$ chmod 400 [アプリ名]-key.pem
$ ssh -i キー名 ユーザ名@パブリック(ElasticIP)IP
# Ex), ssh -i "sample-key.pem" ec2-user@51.168.225.224
「The authenticity of host '51.168.225.224 (51.168.225.224)' can't be established.」と表示されるが、コマンド要求時に「yes」と打てば、大丈夫。
#EC2インスタンス初期設定
$ sudo su -
$ yum update -y
Amazon LinuxはRedHat系のOSなのでyumでパッケージ管理をする。
$ ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
$ vi /etc/sysconfig/clock
ZONE="Asia/Tokyo"
UTC=false
vi /etc/sysconfig/i18n
LANG=ja_JP.UTF-8
vi /etc/cloud/cloud.cfg
repo_upgrade: none
locale: ja_JP.UTF-8
$ dd if=/dev/zero of=/swapfile bs=1M count=1024
$ mkswap /swapfile
$ swapon /swapfile
$ vi /etc/fstab
/swapfile swap swap defaults 0 0
swap:サーバ動作中で、物理メモリ(RAM)の容量が満杯になった時点で必要になるのがswap領域
- 新規ユーザーの作成
デフォルトユーザであるec2-userで開発していくのはセキュリティ的に危険。
新しくユーザを作成し、今後はそのユーザで開発していく必要がある。
$ useradd app -G wheel
$ visudo
%wheel ALL=(ALL) NOPASSWD: ALL
#EC2へのSSH接続
- 公開鍵をローカルからEC2のインスタンスへコピー
$ exit
cat ~/.ssh/id_rsa.pub
- 公開鍵をEC2上に設置
- EC2上のsshディレクトリ配下にauthorized_keysファイルを作成
- そのファイルの中に、公開鍵を保存。
$ ssh -i キー名 ユーザ名@パブリック(ElasticIP)IP
# Ex), ssh -i "sample-key.pem" ec2-user@51.168.225.224
$ sudo su app
# ホームディレクトリー配下でないと権限が持てない
$ cd ~
#sshディレクトリを作成(既に存在している場合は省略)
$ mkdir .ssh
#自分のみに実行権を付与
$ chmod 700 .ssh
$ cd .ssh
$ touch authorized_keys
#自分のみに編集権限を付与
$ chmod 600 authorized_keys
#authorized_keysファイルを開いて、公開鍵をセットし、保存の後、ローカルに戻るためにexitする
$ vi authorized_keys
$ cd ~/.ssh
$ pwd #ディレクトリーを確認
$ ssh -i "pwdで確認したpath/id_rsa" [ユーザー名]@パブリック(ElasticIP)IP
接続が成功しているか確かめる意味でも、「date」コマンドで時刻を確認。
- crondの時刻のズレ修正のためにcrondを再起動
$ sudo service crond restart
$ sudo reboot
$ sudo su -
$ userdel ec2-user
#EC2にgit/rbenv/ruby-build/ruby/bundlerをインストール
$ sudo su -
$ yum -y install git
$ git --version
$ git clone https://github.com/rbenv/rbenv.git /usr/local/rbenv
vi /etc/profile.d/rbenv.sh
export RBENV_ROOT=/usr/local/rbenv
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"
パス(PATH)を通すとは?
→環境変数PATHにコマンド検索パスを追加する作業
つまりは、/usr/local配下にあるrbenvにPATHを通し、システム上からPATH指定がなくてもコマンドが実行できるように設定している。
$ source /etc/profile.d/rbenv.sh
# バージョンが出力されるか、念のため確認
$ rbenv --version
git clone https://github.com/rbenv/ruby-build.git /usr/local/rbenv/plugins/ruby-build
ruby-buildとは?
rbenv installコマンドを実行するためのrbenvのプラグイン
$ rbenv install -list
$ yum -y groupinstall "Development Tools"
$ yum -y install gcc-c++ glibc-headers openssl-devel readline libyaml-devel zlib zlib-devel libffi-devel libxml2 libxslt libxml2-devel libxslt-devel mysql-devel readline-devel
$ yum -y install ImageMagick ImageMagick-devel
$ yum install gcc44
$ alternatives --set gcc /usr/bin/gcc44
AWSの環境内にはあるgcc(コンパイラツール)が、デフォルトのAWSでのバージョンがrbenvに非対応のため、ダウングレードする。
$ rbenv install 2.6.2
$ rbenv versions #念のため、バージョンの確認
デプロイするアプリのバージョンと合わせる
$ rbenv global 2.6.2
$ rbenv rehash
$ ruby -v #バージョンの確認
rbenv rehashコマンドの意味は?
それぞれのRuby環境にある各種コマンドが、ある決まった場所に登録され、実行可能にするため。
$ cd /usr/local/rbenv/
$ sudo chown app version
$ sudo chown app shims
$ rbenv global 2.6.2
$ rbenv rehash
$ ruby -v #バージョンの確認
$ sudo su - #rootユーザーに切り替え
$ rbenv exec gem install bundler
$ rbenv rehash
$ which bundler
# /usr/local/rbenv/shims/bundlerが出力されれば成功
データベース(PostgreSQL)の設定
$ yum -y install postgresql94 postgresql94-server postgresql94-devel postgresql94-contrib postgresql94-docs
$ /etc/init.d/postgresql94 initdb
$ /etc/init.d/postgresql94 start
$ vi /var/lib/pgsql94/data/postgresql.conf
PostgreSQLの初期状態では、接続時に認証を必要としない設定になっているため、認証設定を編集する。
$ vi /var/lib/pgsql94/data/pg_hba.conf
$ /etc/init.d/postgresql94 restart
- ユーザとデータベースを作成
$ psql -U postgres
postgres=# CREATE ROLE "sample" WITH SUPERUSER LOGIN;
ROLEとは?
PostgreSQLではロールという概念を使ってデータベース上の権限管理をしている。
postgres=# CREATE DATABASE "sample_production";
ユーザー名、データベース名はconfig/database.ymlのファイルの記載内容と合わせる
$ /etc/init.d/postgresql94 restart
#Nginxの設定
$ yum -y install nginx
$ chkconfig nginx on
$ /etc/init.d/nginx start
デプロイツール(Capistrano)のインストール
Capistranoを使ったデプロイまでの流れ
1、Capistranoのコマンドを使ってEC2に対しデプロイ命令。
2、EC2からGithubに対し必要なコードを要求。
3、GithubからEC2へgit cloneが実行。
4、デプロイが実行。
まずは、EC2上に秘密鍵を、Github上に公開鍵を設置
(基本、命令元に秘密鍵。命令先に公開鍵を設置する)
$ sudo su app # ユーザーの切り替え
$ cd # ホームディレクトリに移動
$ ssh-keygen -t rsa # 公開鍵秘密鍵のペアを作成
$ cat ~/.ssh/id_rsa.pub
$ cd /var
$ sudo mkdir www
$ sudo chown -R app:app www #作成したwwwディレクトリの所有ユーザをユーザー自身に変更
$ cd /var/www
gem 'dotenv-rails' # 開発環境で環境変数を操作するのに必要
gem 'unicorn'
gem 'mini_racer', platforms: :ruby # デプロイ時に必要
group :development, :test do
gem 'capistrano', '3.6.0' # capistranoのツール一式
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano-rbenv'
gem 'capistrano3-unicorn'
# 以下省略
end
gemを追加しbundle installする。
※必要に応じてbundle updateする
- ローカルでCapfileを作成、編集する
$ bundle exec cap install
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'
デプロイ先のサーバ情報、アクセスキー情報を設定
server 'EC2のIPアドレス', user: 'app', roles: %w{app db web}
set :ssh_options, keys: 'ローカルの秘密鍵へのpath'
ローカルの秘密鍵のディレクトリーpathは、だいたい
/Users/ユーザー名/.ssh/id_rsa にある。
# config valid only for current version of Capistrano
lock '3.6.0'
# デプロイするアプリケーション名
set :application, 'sample'
# cloneするgitのレポジトリ(xxxxxxxx:ユーザ名、yyyyyyyy:アプリケーション名)
set :repo_url, 'https://github.com/xxxxxxxxx/yyyyyyyyy'
# deployするブランチ。デフォルトはmasterなのでなくても可。
set :branch, ENV['BRANCH'] || 'master'
# deploy先のディレクトリ。
set :deploy_to, '/var/www/sample'
# シンボリックリンクをはるフォルダ・ファイル
set :linked_files, %w{.env config/secrets.yml}
set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets public/uploads}
# 保持するバージョンの個数(※後述)
set :keep_releases, 5
# Rubyのバージョン
set :rbenv_ruby, '2.5.1'
set :rbenv_type, :system
#出力するログのレベル。エラーログを詳細に見たい場合は :debug に設定する。
#本番環境用のものであれば、 :info程度が普通。ただし挙動をしっかり確認したいのであれば :debug に設定する。
set :log_level, :info
namespace :deploy do
desc 'Restart application'
task :restart do
invoke 'unicorn:restart'
end
desc 'Create database'
task :db_create do
on roles(:db) do |host|
with rails_env: fetch(:rails_env) do
within current_path do
execute :bundle, :exec, :rake, 'db:create'
end
end
end
end
desc 'Run seed'
task :seed do
on roles(:app) do
with rails_env: fetch(:rails_env) do
within current_path do
execute :bundle, :exec, :rake, 'db:seed'
end
end
end
end
after :publishing, :restart
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
end
end
end
config直下にunicornディレクトリ作成し、直下にproduction.rbを作成
$worker = 2
$timeout = 30
#自分のアプリケーション名(currentがつくことに注意)
$app_dir = "/var/www/アプリケーション名/current"
$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) 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_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
もし、background-imageを設定していたらのurlをimage-urlに書き換える
- Nginxの設定ファイルを新規作成
$ sudo vi /etc/nginx/conf.d/アプリケーション名.conf
upstream unicorn {
server unix:/var/www/アプリケーション名/shared/tmp/sockets/unicorn.sock;
}
server {
listen 80;
server_name EC2のIPアドレス;
root /var/www/アプリケーション名/shared/public;
access_log /var/log/nginx/アプリケーション名_access.log;
error_log /var/log/nginx/アプリケーション名_error.log;
location ~ ^/assets/ {
}
location / {
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;
}
}
$ sudo nginx -s reload
$ bundle exec cap production deploy:check
多分、gem追加してね、ってエラーがでる。
gem 'bcrypt', '~> 3.1.7'
gem 'ed25519'
gem 'bcrypt_pbkdf'
※.envファイルに関するエラーは後で、実装するのでここでは無視。
- 環境変数を登録
API情報など、公開すべきではない情報をコードと分離させるために、EC2上にsecrets.ymlというファイルを設定
$ bundle exec rake secret
$ cd /var/www/アプリケーション名/shared/config
$ vi secrets.yml
production:
secret_key_base: 生成した乱数をコピペ
$ cd /var/www/アプリケーション名/shared # /shared/config/ ではないので注意
$ vi .env
.envファイルに環境変数を記載する
$ bundle exec cap production deploy
ここで多分、エラーがでる。
#追加で実装したこと
$ sudo yum install sqlite-devel
nodeをインストール
https://qiita.com/paranishian/items/bddaed7c3aacedb11967
画像が表示されない問題(解決法3 public/images 以下に画像を置くを使う)
https://qiita.com/wadako111/items/03bc00d914e62243a511
background: image-url("space.jpg") repeat;
ドメインをNginxに設定変更する
https://qiita.com/ryuchan00/items/3e172fbfd1044e093c52
SSL証明書の設定方法
https://labs.mobingi.com/aws-certificate-manager-and-freenom/
https://recipe.kc-cloud.jp/archives/11084
https://qiita.com/iwaseasahi/items/1687426add4124899fe3
解除方法
https://dev.classmethod.jp/cloud/aws/mesoko-r53-cdn/
S3
https://cre8cre8.com/aws/https-s3-and-cloudfront.htm#hl2
Nginxで画像アップロードサイズを調整
client_max_body_size 20M;
bundle exec rails db:seed RAILS_ENV=production