Capistrano 3로 배포하기 – 2015 업데이트

Capistrano 3를 이용하여 레일스 프로젝트를 배포하는 방법을 소개한다.

카피스트라노(Capistrano)란 루비 기반의 원격서버 자동화 툴이다. 레일스에서는 대개 이 카피스트라노를 이용하여 웹애플리케이션을 배포하게 된다. 이 글에서는 카피스트라노(Capistrano 3)를 이용하여 레일스 프로젝트를 원격서버로 배포하는 방법에 대해서 설명한다. (이 글을 읽기 전에 초보자를 위한 레일스가이드북을 공부하면 많은 도움이 될 것이다.)


배포환경의 준비

  • 서버 Ubuntu 12.04.5 LTS (GNU/Linux 3.2.0-70-generic x86_64)
  • 웹서버 Nginx (nginx/1.1.19)
  • 애플리케이션서버 Unicorn (unicorn-4.9.0)
  • ruby 2.2.2
  • rails 4.2.1

레일스로 개발한 웹애플리케이션을 배포하기 위해서 먼저 원격 웹서버를 준비해 놓아야 한다. 이 글에서는 Nginx 웹서버에서 Unicorn 애플리케이션 서버를 이용하여  레일스 애플리케이션을 서비스 하는 것에 대해서 설명하기로 한다. 원격 서버에는 이미 Nginx 웹서버(Apache 웹서버로 가능함)가 설치되어 있는 것으로 가정한다. 그리고 시스템에 배포용 사용자 deployer를 생성하고 적절한 권한을 부여한다. 또한 레일스 프로젝트에서 사용하는 데이터베이스가 생성되어 있고 deployer 사용자에게 사용권한을 지정해 놓을 상태로 가정한다.

카피스트라노3를 이용하여 레일스 애플리케이션을 배포하기 위해서는 몇가지 젬들의 사전 설치가 필요한데, 개발PC의 프로젝트 루트 디렉토리에 있는 Gemfile에 아래와 같이 추가한다.

Gemfile의 추가

# Use Unicorn as the app server
gem 'unicorn'

# Use Capistrano for deployment
gem 'capistrano-rails', group: :development
gem 'capistrano-rbenv' # required
gem 'capistrano-rbenv-install'
gem 'capistrano-unicorn-nginx'
gem 'capistrano-upload-config'
gem 'capistrano-safe-deploy-to'
gem 'capistrano-ssh-doctor'
gem 'capistrano-rails-console'
gem 'capistrano-rails-collection'
gem 'capistrano-rails-tail-log'
gem 'capistrano-faster-assets'

이제 커맨드라인에서 bundle install 명령을 실행하여 추가된 젬들을 설치한다.

주의 : capistrano-unicorn-nginx 젬 3.3.3 버전에서는 unicorn 서비스 실행시 에러가 발생한다. 이것은 CentOS 환경에서도 마찬가지다. 두 OS간에 unicorn 서비스 실행 권한 상의 문제인 것으로 구글 검색상 알 수 있었다. 이에 대해서 하단에 별도로 추가 설명할 것이다.

배포단계

(1) 배포용 작업파일 생성하기

실제 배포 작업은 아래의 명령으로 시작한다.

$ cap install
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified

(2) Capfile 수정

# Load DSL and set up stages
require 'capistrano/setup'

# Include default deployment tasks
require 'capistrano/deploy'
# require 'capistrano/rails' or
require 'capistrano/bundler' # Rails needs Bundler, right?
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'

require 'capistrano/rbenv'
require 'capistrano/rbenv_install'
require 'capistrano/unicorn_nginx'
require 'capistrano/faster_assets'
require 'capistrano/upload-config'
require 'capistrano/safe_deploy_to'
require 'capistrano/ssh_doctor'
require 'capistrano/rails/console'
require 'capistrano/rails/collection'
require 'capistrano/rails_tail_log'

# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

 (3) deploy.rb 수정

# config valid only for current version of Capistrano
lock '3.4.0'

set :application, '[application-name]'
set :repo_url, "git@github.com:[user-name]/#{fetch(:application)}.git"
set :deploy_to, "/home/[deployer-account]/apps/#{fetch(:application)}"

set :rbenv_type, :user # or :system, depends on your rbenv setup
set :rbenv_ruby, '2.2.2'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w{rake gem bundle ruby rails}
set :rbenv_roles, :all # default values

# Default value for :linked_files is []
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')
set :config_files, fetch(:linked_files)
set :pty, true
set :keep_releases, 5

before 'deploy:check:linked_files', 'config:push'

namespace :deploy do
  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
      # Here we can do anything such as:
      # within release_path do
      #   execute :rake, 'cache:clear'
      # end
    end
  end
end

4) config/deploy/production.rb 파일 수정

server '[server-ip]', user: '[deploy-username]', roles: %w{web app db}

set :nginx_server_name, '[domain-name]'
set :unicorn_workers, 4

5) database.yml과 secrets.yml 파일의 별도 관리

이 두 파일의 내용은 보안상 노출되지 않도록 하는 것이 좋다. 따라서 git 저장소에 추가하지 않도록 한다. 대신에 이미 Gemfile 에 추가하여 설치한 capistrano-upload-config 젬에서 제공하는 rake 작업을 이용하여 배포시 로컬 머신의 이 두 파일을 서버로 직접 복사하도록 한다. 위의 26번 코드라인은 배포시에 이 두 파일을 서버로 직접 업로드하도록 해 준다.

아래와 같이 config/database.ymlconfig/secrets.yml 이 두 파일을 .gitignore 파일에 등록하여 git 소스관리에 포함하지 않도록 한다.

.
.
.
config/secrets.yml
config/database.yml

이제 cap production config:init 명령을 실행하여 config/database.production.ymlconfig/secrets.production.yml 파일을 생성하고 database.ymlsecrets.yml 파일로부터 내용을 복사한 후 적절하게 수정하여 사용한다. 이 때 주의할 것은 이 두 개의 파일은 git 소스관리에 포함할 것이 때문에 민감한 정보가 외부로 노출될 수 있다는 것이다. 따라서 데이터베이스 접속을 위한 database.ymlusernamepassword, 그리고 secrets.ymlproduction key 값은 시스템 환경변수에서 가져오도록 해야 한다. 이를 위해서 원격 서버로 접속한 후 sudo vi /etc/environment 명령을 실행하여 3개의 환경변수를 지정한다.

DEPLOY_USERNAME=[deploy-username]
DEPLOY_PASSWORD=[deploy_password]
SECRET_KEY_BASE=[secret_key_base]

참고: SECRET_KEY_BASE 키에 할당한 값은 로컬 터미널에서 rake secret 명령을 실행하여 얻을 수 있다.

위에서 생성한 두 개의 파일에 추가할 내용은 아래와 같다.

secrets.production.yml

production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

database.production.yml

production:
   adapter: mysql2
   encoding: utf8
   reconnect: false
   database: [database-name]
   pool: 5
   username: <%= ENV['DEPLOY_USERNAME'] %>
   password: <%= ENV['DEPLOY_PASSWORD'] %>
   host: localhost

로컬 머신에서 환경변수 사용하기

로컬 머신에서도 환경변수를 편리하게 사용할 수 있다. 아래와 같이 Gemfile에 젬을 추가하고 bundle install 한다.

gem 'dotenv-rails', :groups => [:development, :test]

그리고 레일스 프로젝트 루트 디렉토리에 .env 파일을 생성하고 .gitignore 파일에 추가해서 git 에서 tracking하지 못하도록 한다. 방금 생성한 .env 파일을 열고 아래와 같이 작성한다. 잊어서는 안 될 사항은 .env 파일 역시 git 소스관리에 포함되지 않도록 해야 한다. 따라서 .gitignore 파일에 추가해 주도록 한다.

export DEPLOY_USERNAME='[user-name]'
export DEPLOY_PASSWORD='[user-passwrod]'
export SECRET_KEY_BASE='[secret_key_base']

배포 실행

$ cap production setup
$ cap production deploy

실제 배포과정은 두 번의 명령을 실행하여 완성된다. 단한번 만에 배포가 성공한다면 정말 복이 많은 사람일 것이다. ^^

Unicorn 서비스 관련 오류 수정

레일스 애플리케이션을 배포시 nginx와 unicorn 설정 파일을 작성해 주는 ‘capistrano-plugins/capistrano-unicorn-nginx’ 젬(버전 3.3.3)을 사용할 경우 아래의 두 가지 문제점이 발생한다.

  1. 원격 웹서버의 OS를 감지하지 못하는 문제로, CentOS가 설치되어 있는 서버로 배포할 경우 ‘update-rc.d’ 오류가 발생하게 된다.(CentOS에서 서비스를 등록할 때는 chkconfig 명령을 사용함)
  2. Ubuntu OS 로 배포시에는 unicorn 서비스 실행 오류가, CentOS로 배포시에는 unicorn 서비스를 실행하지 못하여, ‘service stdout: /usr/bin/env: service: 그런 파일이나 디렉터리가 없습니다’라는 오류가 발생한다. 구글 검색을 통해서 이러한 문제는 각 OS에서 sudo 권한으로 unicorn 서비스를 실행해야 한다는 내용을 접할 수 있었다.

그러나 두 OS별로 sudo 권한으로 실행하는데는 문법상의 차이점을 발견할 수 있었다. 따라서 OS를 검출한 후 각 OS별로 sudo 문법을 다르게 작성해 줌으로 해결할 수 있었다. 포크후에 이 두 가지 문제를 해결하여 업데이트 하였다. 따라서 위의 Gemfile에서 gem ‘capistrno-unicorn-nginx’ 에 github: ‘hschoidr/capistrano-unicorn-nginx’ 옵션을 추가하여 젬을 설치하면 이러한 문제점을 깔끔하게 해결할 수 있다.

Gemfile

gem 'capistrano-unicorn-nginx', github: 'hschoidr/capistrano-unicorn-nginx'

카피스트라노 3 배포를 위한 유용한 플러그인 모음

https://github.com/capistrano-plugins 를 방문하면 카피스트라노를 이용하여 레일스 프로젝트를 원격서버로 배포할 때 도움이 되는 여러가지 플러그인을 볼 수 있다.

(1) Capistrano::UnicornNginx https://github.com/capistrano-plugins/capistrano-unicorn-nginx : 카피스트라노를 이용하여 레일스 프로젝트를 원격서버로 배포할 때 unicorn과 nginx 설정을 자동화해 주는 젬이다.

(2) Capistrano::FasterAssets https://github.com/capistrano-plugins/capistrano-faster-assets : 최종 배포 이후에 assets의 변경내용이 없으면 assets precompile을 하지 않도록 해 배포 속도를 빠르게 해 주는 젬이다.

(3) Capistrano::DelayedJob https://github.com/capistrano-plugins/capistrano-delayed-job : DelayedJob 설정을 자동화해 주는 카피스트라노 task를 제공해 주는 젬이다.

(4) Capistrano::Rbenv::Install https://github.com/capistrano-plugins/capistrano-rbenv-install : 원격서버에서 rbenv을 이용하여 루비 버전을 관리해 주는 카피스트라노 플러그인이다.

(5) Capistrano::SafeDeployTo https://github.com/capistrano-plugins/capistrano-safe-deploy-to : 원격서버로 배포시 배포 디렉토리가 존재하는지와 배포 디렉토리의 권한이 올바르게 설정되었는지를 확인해 주는 카피스트라노 플러그인이다.

(6) Capistrano-Upload-Config https://github.com/rjocoleman/capistrano-upload-config : database.yml 파일을  git 으로부터 untracking한 후 별도로 배포하는 플러그인

(7) Capistrano SSH Doctor https://github.com/capistrano-plugins/capistrano-ssh-doctor : 원격서버로 배포시 ssh 관련 사항들을 점검해 주는 카피스트라노 플러그인이다.


 문제해결

이것은 이 글을 작성하면서 문제 해결을 참고했던 내용들이다.

1. Nokogiri 설치 에러시 해결법

http://stackoverflow.com/questions/29020478/error-installing-nokogiri-on-bundle-install-but-already-installed

2. Error on asset_manifest_backup

https://github.com/capistrano/rails/issues/33

3. Alternative to update-rc.d with Centos

http://blog.slucas.fr/en/tips/centos-configure-service
http://www.cyberciti.biz/faq/rhel5-update-rcd-command/

글쓴이: 최효성

외과전문의,웹프로그래밍,컴퓨터 일러스트레이션 / Surgeon, Medical Illustration, Web Programmer

2 thoughts on “Capistrano 3로 배포하기 – 2015 업데이트”

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중