github x wercker x capistranoの設定の記録

f:id:ihatov08:20160926122207j:plain

github x wercker x capistranoの設定の記録です。

  • werckerでユーザー登録
    githubアカウントでサクッと作成できる。

  • 新しいapplicationを登録する。

  • repositoryの追加

githubを選択

  • githubから対象にするrepositoryの選択

  • owner userの選択

  • アクセス方法を選択

今回は公開鍵をgithubに登録する方法を選択(1番上)

Make my app publicにチェックを入れると、後ほど出てくるbadgeをクリックしたさいに、deploy情報を公開できるようになります。 (今回チェックをつける)

  • pipelineの作成

production-deployというpipelineを作成。
masterブランチにpushされたらproductionサーバーにdeployしてくれるようにする。

ここにenviroment variablesとして
WERCKER_DEPLOYTARGET_NAMEをproduction
WERCKER_CAP_PRIVATE_KEY(この値は後で入れる)
を作成。
SSH Key variablesも作成
名前はWERCKER_SSH_KEY

  • 環境変数の登録
    環境変数を登録しているようなら、wercker上でrspecを走らせる時にエラーが起きる可能性があるので、enviromentタブから環境変数を登録する。

  • wercker.yml

今回は下記のように作成。該当ブランチにpushするとrspecを自動で走らせて、capistranoも走ってくれる。

box: ruby
build:
steps:
- script:
name: set timezone
code: |
export TZ="Asia/Tokyo"
- script:
name: echo timezone
code: |
date
- script:
name: Display version
code: |
cat /etc/issue
- script:
name: Update packeages
code: |
sudo apt-get update && sudo apt-get upgrade -y
- script:
name: Install Node.js
code: |
sudo apt-get install -y nodejs
- script:
name: Install MySQL
code: |
sudo debconf-set-selections <<< 'mysql-server mysql-server/root_password password wercker_test_password'
sudo debconf-set-selections <<< 'mysql-server mysql-server/root_password_again password wercker_test_password'
sudo apt-get -y install mysql-server
sudo /etc/init.d/mysql start
mysql -uroot -pwercker_test_password -e "CREATE DATABASE app_name_test CHARACTER SET utf8 COLLATE utf8_general_ci;"
mysql -uroot -pwercker_test_password -e "CREATE USER appname@localhost IDENTIFIED BY 'password';"
mysql -uroot -pwercker_test_password -e "GRANT ALL PRIVILEGES ON app_name_test.* TO appname@localhost IDENTIFIED BY 'appname';"
mysql -uroot -pwercker_test_password -e "FLUSH PRIVILEGES;"
- bundle-install:
jobs: 4
- script:
name: echo ruby information
code: |
echo "ruby version $(ruby --version) running"
echo "from location $(which ruby)"
echo -p "gem list: $(gem list)"
- script:
name: Set up db
code: |
bundle exec rake db:create RAILS_ENV=test
bundle exec rake db:schema:load RAILS_ENV=test
bundle exec rake db:seed_fu RAILS_ENV=test
- script:
name: RSpec
code: bundle exec rspec --color -f d
staging-deploy:
steps:
- bundle-install:
jobs: 4
- script:
name: make .ssh directory
code: mkdir -p "$HOME/.ssh"
- create-file:
name: write ssh key
filename: $HOME/.ssh/id_rsa
overwrite: true
hide-from-log: true
content: $WERCKER_SSH_KEY_PRIVATE
- script:
name: set permissions for ssh key
code: chmod 0600 $HOME/.ssh/id_rsa
- cap:
stage: $WERCKER_DEPLOYTARGET_NAME
tasks: deploy
production-deploy:
steps:
- bundle-install:
jobs: 4
- script:
name: make .ssh directory
code: mkdir -p "$HOME/.ssh"
- create-file:
name: write ssh key
filename: $HOME/.ssh/id_rsa
overwrite: true
hide-from-log: true
content: $WERCKER_SSH_KEY_PRIVATE
- script:
name: set permissions for ssh key
code: chmod 0600 $HOME/.ssh/id_rsa
- cap:
stage: $WERCKER_DEPLOYTARGET_NAME
tasks: deploy
  • とりあえずpush
    wercker.ymlを作成したので、githubにpushする。

  • ユーザーの作成とpasswordの設定

rootユーザーでログインして、

passwd ユーザー名

でpasswordの再設定をする。
このpasswordを後で利用する。

$ ssh-keygen

いろいろ出るが、enter連打。
これで.ssh/id_rsaと.ssh/id_rsa.pubができる。
id_rsaの秘密鍵をwercker側のenviroment valiableに設定する。
これはpipelineのenviroment valiableでも、enviromentのどちらでもいいみたい。
名前はWERCKER_CAP_PRIVATE_KEYでprotectedにチェックをつけること。

  • デプロイ先サーバーの公開鍵設定
    本番環境サーバーにて行う。
    .ssh/authorized_keysディレクトリの作成。
    .ssh/authorized_keysにid_rsa.pubを入れる。
    また、werckerの公開鍵もここに入れておく。

  • githubに公開鍵を登録

デプロイ先サーバーdepoyユーザーの公開鍵をgithubに登録。名前はproduction_server_keyにでもしておく。
id_rsa.pubの中身をコピペ。

  • known_hosts
    このディレクトリが存在する。自動で作られるのか?
    過去コマンドを検索しても出てこない。

  • liked_filesは自動的に作成されない

linked_filesは自動的に作成されないので、手動で追加する。

config/deploy.rb
namespace :deploy do
desc 'Restart application'
task :restart do
invoke 'unicorn:start'
end
desc 'Upload database.yml'
task :upload do
on roles(:app) do |host|
if test "[ ! -d #{shared_path}/config ]"
execute "mkdir -p #{shared_path}/config"
end
upload!('config/database.yml', "#{shared_path}/config/database.yml")
end
end
before :starting, 'deploy:upload'
after :finishing, 'deploy:cleanup'
end

こんな感じでデプロイ時にアップロードするように設定もできる。

  • deviseのsecret_keyを作成

Devise.secret_key was not set. Please add the following to your Devise initializer:
こんなエラーメッセージが。
deviseのsecret_keyを作成すればOK

  • nginxの設定確認

/etc/nginx以下の設定ファイルの確認。
unicornと対応するように!

upstream unicorn_server {
# This is the socket we configured in unicorn.rb
server unix:/home/team_name/current/tmp/sockets/unicorn.sock
fail_timeout=0;
}
server {
listen       80 default_server;
client_max_body_size 4G;
keepalive_timeout 5;
root /home/team_name/current/public;
location / {
#auth_basic "Restricted";
#auth_basic_user_file /etc/nginx/.htpasswd;
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;
}
}
#    location ~ ^/assets/ {
#       expires 1y;
#       add_header Cache-Control public;
#       add_header ETag "";
#       break;
#    }
#   location ~ ^/(assets)/  {
#       root /home/team_name/current/public;
#       gzip_static on;
#       expires max;
#       add_header Cache-Control public;
#   }
location @unicorn_server {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn_server;
}
error_page   500 502 503 504  /500.html;
location = /500.html {
root /home/team_name/current/public;
}
}
  • 権限の変更
$ chmod 755 /home/team_name/
  • secret_key_base
    これを設定しないと画面真っ白!
    capstranoでデプロイするとき毎回更新する羽目になるので、dotenv gemに登録することにした。
$ bundle exec rake secret RAILS_ENV=production
  • pidの向きの変更

今回unicorn.pidの名前を少しいじっていたので、向き合っていなかった模様。

http://blog.hypermkt.jp/failed-to-restart-unicorn-by-capistrano3-unicorn/

config/deploy/production.rb

set :unicorn_pid, "#{sahred_path}/tmp/pids/unicorn_team_name.pid"
  • ユーザーに注意
    rootユーザーでunicornを立ち上げているとダメなので、stopしておく。

  • unicorn.rake

namespace :unicorn do
##
# Tasks
##
desc "Start unicorn for development env."
task(:start) {
env = ENV['RAILS_ENV']
if env.blank?
env = 'development'
end
config = Rails.root.join('config', 'unicorn', "#{env}.rb")
sh "bundle exec unicorn_rails -c #{config} -E #{env} -D"
}
desc "Stop unicorn"
task(:stop) { unicorn_signal :QUIT }
desc "Restart unicorn with USR2"
task(:restart) { unicorn_signal :USR2 }
desc "Increment number of worker processes"
task(:increment) { unicorn_signal :TTIN }
desc "Decrement number of worker processes"
task(:decrement) { unicorn_signal :TTOU }
desc "Unicorn pstree (depends on pstree command)"
task(:pstree) do
sh "pstree '#{unicorn_pid}'"
end
def unicorn_signal signal
Process.kill signal, unicorn_pid
end
def unicorn_pid
begin
env = ENV['RAILS_ENV']
if env.blank? || env == 'development'
File.read("/tmp/unicorn.pid").to_i
elsif env == 'staging'
File.read("/home/team_name/current/tmp/pids/unicorn.pid").to_i
elsif env == 'production'
File.read("/home/team_name/current/tmp/pids/unicorn.pid").to_i
end
rescue Errno::ENOENT
raise "Unicorn doesn't seem to be running"
end
end
end
  • config/deploy.rb
# config valid only for current version of Capistrano
lock '3.4.1'
set :application, 'app_name'
set :repo_url, 'git@github.com:team_name/app_name.git'
set :keep_releases, 5
set :rvm_type, :auto
set :rvm_ruby_version, '2.3.0'
set :pty, true
set :ssh_options, {
forward_agent: true,
keys: %w(/home/team_name/.ssh/id_rsa),
auth_methods: %w(publickey password),
password: 'password'
}
set :log_level, :debug
set :linked_files, %w{config/database.yml .env}
set :linked_dirs, %w{bin bundle log tmp/pids tmp/cache tmp/sockets public/system public/uploads}
set :default_env, {
###
}
set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }
set :unicorn_rack_env, 'development'
SSHKit.config.command_map[:rake] = 'bundle exec rake'
namespace :deploy do
desc 'Create Database'
task :db_create do
on roles(:db) do |host|
with rails_env: fetch(:rails_env) do
within current_path do
execute :rake, 'db:reset'
execute :rake, 'db:setup'
execute :rake, 'db:migrate'
execute :rake, 'db:seed_fu'
end
end
end
end
task :restart do
invoke 'unicorn:restart'
end
after :publishing, :restart
after :finishing, :cleanup
end
  • config/unicorn/production.rb
@app_path = '/home/app_name'
working_directory @app_path + "/current"
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
preload_app true
timeout 30
listen "#{@app_path}/current/tmp/sockets/unicorn.sock", :backlog => 64
pid "#{@app_path}/current/tmp/pids/unicorn.pid"
stderr_path "#{@app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{@app_path}/shared/log/unicorn.stdout.log"
before_fork do |server, worker|
ENV['BUNDLE_GEMFILE'] = "#{@app_path}/current/Gemfile"
end
before_exec do |server|
Dotenv.overload
end
before_fork do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.connection.disconnect!
end
old_pid = "#{server.config[:pid]}.oldbin"
if File.exists?(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
end
end
end
after_fork do |server, worker|
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
end
end
  • config/deploy/production.rb
# server-based syntax
# ======================
# Defines a single server with a list of roles and multiple properties.
# You can define all roles on a single server, or split them:
# server 'example.com', user: 'deploy', roles: %w{app db web}, my_property: :my_value
# server 'example.com', user: 'deploy', roles: %w{app web}, other_property: :other_value
# server 'db.example.com', user: 'deploy', roles: %w{db}
set :rails_env, "production"
set :branch, ENV['BRANCH'] || 'master'
set :deploy_to, '/home/team-name/'
set :unicorn_rack_env, 'production'
set :unicorn_pid, "#{shared_path}/tmp/pids/unicorn.pid"
server 'ip-address', user: 'team-name', roles: %w{web app db}
# role-based syntax
# ==================
# Defines a role with one or multiple servers. The primary server in each
# group is considered to be the first unless any  hosts have the primary
# property set. Specify the username and a domain or IP for the server.
# Don't use `:all`, it's a meta role.
# role :app, %w{deploy@example.com}, my_property: :my_value
# role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value
# role :db,  %w{deploy@example.com}
pro_server =  "user_name@ip-address"
role :app, pro_server
role :web, pro_server
role :db,  pro_server
set :ssh_options, {
forward_agent: false,
keys: %w(~/.ssh/id_rsa),
auth_methods: %w(publickey)
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です