Railsプロジェクトで環境構築をするときに何が必要だったか忘れちゃうので、メモをまとめてみました。
途中、まとめるのに力尽きたところや抜けてたところは、思い立ったら追記していこうかなと思いますが、まずはざっくり^^;
□ itamae レシピ用意
▼itamaeレシピのファイル構造例
├── Gemfile # `gem "itamae"`
├── Gemfile.lock
├── README.md
├── Vagrantfile
├── cookbooks # ここにレシピを置く 命名、分け方自由
│ ├── dir_set # Rails pjt を置くディレクトリを用意 / 権限設定 など
│ ├── etc_packages # 基本的なpackage群をinstall
│ ├── iptables
│ ├── mysql
│ ├── nginx
│ ├── ntp
│ ├── redis
│ ├── security
│ ├── time_set # 日本時間にする設定
│ ├── unicorn
│ ├── yum
│ └── zabbix
├── node
│ └── rails # ここで設定したものをレシピの中で`node[:hoge]`と呼び出して使う
│ ├── batch_pro.yaml
│ ├── batch_stg.yaml
│ ├── development.yaml
│ ├── production.yaml
│ └── staging.yaml
├── project
│ └── rails_pjt # 決まりはないが、ローカルで扱いやすいようにここにRailsのコードを置くようにしている
├── rails.rb # レシピ実行 をここにまとめて書く ex.`include_recipe "cookbooks/mysql/default.rb"`
├── tmp
└── vendor
└── bundler
▼レシピの実行 (Vagrantの仮想サーバーやAWSのインスタンスに向けて)
$ bundle exec itamae ssh --user <ユーザー名> --host <IP> -y node/rails/<反映したい環境>.yaml rails.rb
※itamaeレシピの書き方参考:
- Chef脱落者が、Itamaeで快適インフラ生活する話 - Qiita
- zaru/itamae-rails
- Itamaeが構成管理を仕込みます! ~新進気鋭の国産・構成管理ツール~:連載|gihyo.jp
□ 環境変数設定ファイル用意
- 便利なgem をセット
# Gemfile
gem 'config' # 定数管理
gem 'dotenv-rails' # 環境変数管理
gem 'dotenv-deployment' # Production, Stating環境での環境変数設定
-
.env
にexport RAILS_ENV="development"
など定数を設定 -
settings ファイル作成
$ bundle exec rails g config:install
config/settings/development.yml
とかができるので、環境ごとの設定を書く
例えば、ymlにsite_url: https://hoge.com
と書くと
→ Settings.site_url #=> "https://hoge.com"
と呼び出せる
□ capistrano 設定
# Gemfile
gem 'aws-sdk-v1' # AWS SDK for Ruby v1 ※前のpjtコードを参考にしたのでv2に寄せきれてなくていったん両方いれましたm(_ _)m
gem 'aws-sdk-core' # AWS SDK for Ruby v2
group :development, :test do
gem 'capistrano-sidekiq', github: 'seuros/capistrano-sidekiq'
end
group :development do
gem 'capistrano'
gem 'capistrano-rails'
gem 'capistrano-rbenv'
gem 'capistrano-bundler'
gem 'capistrano3-unicorn'
end
group :production, :staging do
gem 'unicorn'
end
$ bundle exec cap install
# => Capfile、config/deploy.rb 等が作成される
# Capfile
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
require 'capistrano/rbenv'
set :rbenv_type, :user
set :rbenv_ruby, '2.2.0'
require 'capistrano/bundler'
require 'capistrano/rails'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/sidekiq'
require 'capistrano3/unicorn'
require 'whenever/capistrano'
require 'dotenv'
Dotenv.load
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
# config/deploy.rb
# config valid only for current version of Capistrano
lock '3.4.0'
set :application, 'app_name'
set :repo_url, 'git@github.com:hoge/app_name.git'
set :deploy_to, "/var/www/project/#{fetch :application}"
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }
set :whenever_roles, ->{ :batch }
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
# dotenvファイルはgit管理できないので、S3に置いてdeploy時に取得してそれを使うように
# FileUpdate & ln -s :.env --------
desc '.env file from s3'
task :update_dotenv do
on roles( %w(web batch)) do
within release_path do
with rails_env: fetch(:rails_env) do
execute :bundle, :exec, :rake, "dotenv:update"
end
end
end
end
desc 'link dotenv'
task :link_dotenv do
on roles( %w(web batch) ) do
execute "ln -s /home/ec2-user/.env #{release_path}/.env"
execute "source /home/ec2-user/.env"
end
end
# Restart Unicorn
desc 'Restart application'
task :restart do
# lib/capustrano/tasks/unicorn.rake 内処理を実行
invoke 'unicorn:restart'
end
# FileUpdate & ln -s :.env
after :updated, 'deploy:update_dotenv'
after :update_dotenv, 'deploy:link_dotenv'
end
▼環境別のdeploy設定
# config/deploy/staging.rb
require 'aws-sdk-v1'
set :branch, "develop"
set :rails_env, "staging"
set :unicorn_config_path, "#{current_path}/config/unicorn.conf.rb"
set :default_env, {
RAILS_ENV: "staging",
FOG_DIRECTORY: "app_name-stg",
FOG_REGION: ENV["FOG_REGION"],
}
set :pty, false
set :sidekiq_role, :batch
AWS.config(access_key_id: ENV["AWS_ACCESS_KEY_ID"],
secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
region: ENV["FOG_REGION"],
ec2_endpoint: "※ ec2_endpoint を記載",
elb_endpoint: "※ elb_endpoint を記載")
elb = AWS::ELB.new
lb = elb.load_balancers["app_name-stg-elb"]
web_roles = %w{web app}
lb.instances.map(&:public_ip_address).each_with_index do |ip, i|
web_roles << "db" if 0 == i
server ip, user: 'ec2-user', roles: web_roles
end
ec2 = AWS::EC2.new.instances.with_tag "Name", "app_name-stg-batch"
server ec2.first.public_ip_address, user: 'ec2-user', roles: %w{batch cron}
set :ssh_options, {
keys: [File.expand_path('~/.ssh/keyname.pem')],
forward_agent: false,
auth_methods: %w(publickey)
}
▼dotenvファイルはgit管理できないので、S3に置いてdeploy時に取得してそれを使うように
#lib/tasks/dotenv.rake
namespace :dotenv do
desc "update dotenv file"
task :update => :environment do
S3_DOTENV_PATH = "dotenv"
LOCAL_DOTENV_PATH = "#{ENV['HOME']}/.env"
s3 = AWS::S3.new
bucket = s3.buckets[ENV['FOG_DIRECTORY']]
File.write LOCAL_DOTENV_PATH, bucket.objects[S3_DOTENV_PATH].read
FileUtils.chmod 0600, LOCAL_DOTENV_PATH
end
end
参考:AWS RailsアプリケーションのCapistranoによるデプロイ - Qiita
□ unicorn 設定
# config/unicorn.conf.rb
rails_env = ENV["RAILS_ENV"] || "production"
workers_procs = {production: 3, staging: 2}
workers_procs.default = 2
worker_processes workers_procs[rails_env.to_sym]
app_directory = "/var/www/project/app_name/current"
working_directory app_directory # available in 0.94.0+
listen "#{app_directory}/tmp/sockets/unicorn.sock", backlog: 128
timeout 30
pid "#{app_directory}/tmp/pids/unicorn.pid"
stderr_path "#{app_directory}/log/unicorn_#{rails_env}_error.log"
stdout_path "#{app_directory}/log/unicorn_#{rails_env}.log"
preload_app true
GC.respond_to?(:copy_on_write_friendly=) and
GC.copy_on_write_friendly = true
before_exec do |server|
ENV["BUNDLE_GEMFILE"] = "#{app_directory}/Gemfile"
end
before_fork do |server, worker|
old_pid = "#{server.config[:pid]}.oldbin"
if old_pid != server.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
end
end
sleep 1
end
□ AWS S3 用意
Amazon S3 (スケーラブルなクラウドストレージサービス ) | AWS
今回利用するbucketを環境ごとに作成
□ CDN サービス設定 (アカマイなど)
CDN サービス|クラウドコンピューティングサービス| Akamai
□ asset sync 設定
# Gemfile
gem 'asset_sync'
# config/initializers/asset_sync.rb
AssetSync.configure do |config|
config.fog_provider = 'AWS'
config.fog_directory = ENV['FOG_DIRECTORY']
config.fog_region = ENV['FOG_REGION']
config.aws_iam_roles = true
config.manifest = true
end
# config/environments/production.rb
config.action_controller.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/assets.example.com' # CDN サービスを使ってりる場合そこで設定したhost
参考:Railsアプリケーションを公開するならAssets on Cloudパターンを使おう - 働かないプログラマのメモ帳
□ AWS EC2 インスタンス 用意 (上記 itamae で作成)
Amazon EC2 (クラウドサーバー・ホスティング) | AWS
- □ web 用
- □ batch 用
参考:AWS VPCによるネットワーク構築とEC2によるサーバー構築 - Qiita
□ AWS ELB 作成 / インスタンス紐付け
Elastic Load Balancing(クラウドネットワークのロードバランサー) | AWS
□ AWS RDS 用意
Amazon RDS(クラウドでのリレーショナルデータベースサービス) | AWS
□ サーバーに入ってitamaeで設定したものの反映を確認
- □ chkconfig でonになっているか
- □ BASIC認証の設定ができているか確認 (
$ htpasswd /etc/nginx/conf.d/.htpasswd
) - □ DB 接続確認 / database設定 (mysql 接続確認)
etc.
□ ドメイン/DNS設定 (AWS Route53)
Amazon Route 53(ドメインネームサーバー、DNS サービス) | AWS
ELBのaliasと紐付ける
□ AWS SES 設定
Amazon Simple Email Service(クラウドベースのメールサービス) | AWS
# Gemfile
gem 'aws-ses', require: 'aws/ses'
# config/initializers/aws_ses.rb
AppName::Application.configure do
config.action_mailer.smtp_settings = {
:address => Settings.smtp.address,
:port => 587,
:user_name => ENV["SMTP_USERNAME"] || Settings.smtp.user_name,
:password => ENV["SMTP_PASSWORD"] || Settings.smtp.password,
:authentication => :login
}
end
□ AWS Elasticcache 用意
Amazon ElastiCache (キャッシュ管理・操作サービス) | AWS
▼用意したら設定ファイルで読み込めるように
# dotenv ※.env
export REDIS_HOST="AWS Elasticcacheで設定したhost"
# config/initializers/session_store.rb
Rails.application.config.session_store :redis_store, servers: "redis://#{Settings.redis.host}:6379/0/session", key: '_r_cw_session', expire_after: 1.month
□ Git管理サービス(GitHubなど)に デプロイキー 設定
ssh-keygen -t rsa
で作成したpublic key を設定
□ デプロイ実行
$ git push upstream deploy_brach
$ bundle exec cap staging deploy
□ secret_key_base の 設定
$ bundle exec rake secret
で作成したkeyをdotenvに設定してconfig/secret.yml
で呼べるように
□ サーバー監視設定
Zabbixなど
□ エラー通知設定
- エラー通知サービスsentry設定
Sentry:Track exceptions with modern error logging for JavaScript, Python, Ruby, Java, and Node.jp
# Gemfile
gem 'sentry-raven'
# config/initializers/sentry.rb
Raven.configure do |config|
config.dsn = '※ sentry で設定したもの'
config.environments = ['production']
end
-
Chatに通知
- slackやChatworkなどに重要なものは通知できるように
- sidekiqなど利用
□ CI 対応
CircleCI など