레일스 어플리케이션 배포와 서버 설정

레일스 어플리케이션 배포에 대한 것은 Deploying Rails Application is Easy을 참조하면 됩니다.

정말 배포하기가 쉬운지는 각자가 느끼기에 달려 있는 것 같습니다. ㅎㅎㅎ

레일스 어플리케이션을 배포할 때 서버 설정하는 부분에서 두가지 옵션을 생각해 볼 수 있습니다.

하나는 메인 도메인명에 슬래시한 후에 어플리케이션명을 붙여서 사용하는 sub-URI 방식을 들 수 있고, 다른 하나는 포트를 추가하여 서비스하는 방법입니다.

Capistrano를 이용하여 레일스 어플리케이션을 배포하면서 공짜는 없다는 생각을 했습니다.

위에서 언급한 바와 같이 sub-URI 이용하여 서비스하기로 하고 다음과 같이 아파치 서버설정 파일을 수정하였습니다.

/var/www 디렉토리에 서버상의 레일스 어플리케이션의 public  디렉토리의 링크를 생성합니다.

$ sudo ln -s /home/[user account]/Sites/[rails proj-name]/public /var/www/[rails proj-name]

다음에는 아파치 설정 파일을 열어서

$ sudo vi /etc/apache2/sites-available/default

아래와 같이 수정합니다. (16~20번사이)


        ServerAdmin webmaster@localhost

        DocumentRoot /var/www

                Options FollowSymLinks
                AllowOverride None

                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all

        # 추가해 줄 부분...>>>>>>>>>>>>>>>>>>>>>>>>>>
        RailsBaseURI /[rails proj-name]
        <Directory /var/www/[rails proj-name]/>
           allow from all
        </Directory>

        # 하나 이상을 추가해 줄 수 있으며 이미 설명한 바와 같이 추가해 줄 어플리케이션의 링크를 만들어 준 후에 바로 위의 부분을 추가해 주면 된다.

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all

        ErrorLog ${APACHE_LOG_DIR}/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/access.log combined

    Alias /doc/ "/usr/share/doc/"
    <Directory "/usr/share/doc/">
        Options Indexes MultiViews FollowSymLinks
        AllowOverride None
        Order deny,allow
        Deny from all
        Allow from 127.0.0.0/255.0.0.0 ::1/128

Capistrano의 레시피(config/deploy.rb)를 작성한 후 배포절차를 시작합니다.

우선 로컬에서 어플리케이션 루트 디렉토리로 이동합니다.

$ :~/> cd [app]

capify 명령을 실행해서 Capistrano의 레시피 파일을 생성합니다.

$ :app> capify .

그러면, 어플리케이션 루트 디렉토리에 Capfile이, config 디렉토리에 deploy.rb 파일이 생성됩니다.

Capfile은 텍스트파일로써 매우 간단한 코드가 들어 있습니다. 거의 손댈 일이 없지만, asset pipeline을 사용할 경우에는 아래와 같이 해당 부분의 코멘트 표시를 제거합니다.

require "bundler/capistrano"

set :application, "app-name"

set :scm, :git
set :repository,  "git@200.50.84.100:#{application}.git"
set :branch, "master"

default_run_options[:pty] = true
ssh_options[:forward_agent] = true

set :user, "username"
set :use_sudo, false

set :deploy_to, "/home/#{user}/sites/#{application}"
set :deploy_via, :remote_cache


role :web, "domain.name"                          # Your HTTP server, Apache/etc
role :app, "domain.name"                          # This may be the same as your `Web` server
role :db,  "domain.name", :primary => true # This is where Rails migrations will run

require "rvm/capistrano"
set :rvm_ruby_string, '1.9.3-p125@rails.3.2.2'
set :rvm_type, :system

# if you're still using the script/reaper helper you will need
# these http://github.com/rails/irs_process_scripts

# If you are using Passenger mod_rails uncomment this:
namespace :deploy do
   task :start do ; end
   task :stop do ; end
   task :restart, :roles => :app, :except => { :no_release => true } do
     run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
   end
end

namespace :apache do
  [:stop, :start, :restart, :reload].each do |action|
    desc "#{action.to_s.capitalize} Apache"
    task action, :roles => :web do
      invoke_command "#{sudo} /etc/init.d/apache2 #{action.to_s}", :via => run_method
    end
  end
end

namespace :logs do
  task :watch do
    stream("cat /home/username/sites/app-name/current/log/production.log")
  end
end

다음에는 실제로 서버로 배포작업을 시작합니다.

# 배포 준비작업으로 원격서버에 기본 디렉토리 구조를 생성합니다.
$ app_root> cap deploy:setup

# 실제 배포작업시 문제가 없는지를 테스트해 봅니다
$ app_root> cap deploy:check

# 소스코드를 서버로 배포한 후, 서버에서 bundle install작업을 수행하고, assets:precompile하고 데이터베이스 스키마를 로드하여 마이그레이션 작업을 일괄적으로 수행합니다.
$ app_root> cap deploy:cold

이후부터는 소스변경후 재배포할 때는,

$ app_root> cap deploy

와 같이 한줄로 모든 배포작업이 끝나게 됩니다. 너무 간단한 절차입니다.

성공적으로 배포작업이 완료되기에 실제 운영서버로 접속하여 브라우저에서 해당 URL로 연결을 해 보았습니다.

에구, 이런~ 문제가 발생했습니다. CSS상에 링크된 모든 이미지가 웹페이지에서 보이지 않았습니다.

배포 작업시 에러가 전혀 없었는데….

3일 정도 구글을 하면서 검색을 해보다가, 결국, stackoverflow.com 에서 구체적인 문제의 원인을 찾게 되었고 또한 해결책도 얻게 되었습니다.

바로 sub-URI를 이용하여 레일스 어플리케이션을 배포할 때 서버단에서의 assets:precompile시에 sub-URI가 제대로 반영되지 않는데서 문제가 발생했던 것입니다.

http://stackoverflow.com/a/8398122 를 방문하면 잘 설명이 되어 있습니다.

우선 config/initializer 디렉토리에 임의의 루비파일을 생성한 후에,

module Sprockets
  module Helpers
    module RailsHelper

      def asset_path(source, options = {})
        source = source.logical_path if source.respond_to?(:logical_path)
        path = asset_paths.compute_public_path(source, asset_prefix, options.merge(:body => true))
        path = options[:body] ? "#{path}?body=1" : path
        if !asset_paths.send(:has_request?)
          path = ENV['RAILS_RELATIVE_URL_ROOT'] + path if ENV['RAILS_RELATIVE_URL_ROOT']
        end
        path
      end

    end
  end
end

위의 소스코드를 붙여넣기 하고 저장했습니다. 그리고 config/deploy.rb 파일의 제일 하단에 아래의 코드를 추가했습니다.

desc "precompile the assets"
namespace :assets do
  task :precompile_assets do
    run "cd #{release_path} &amp;&amp; rm -rf public/assets/* &amp;&amp; RAILS_ENV=production bundle exec rake assets:precompile RAILS_RELATIVE_URL_ROOT='/rorlab'"
  end
end
before "deploy:symlink", "assets:precompile_assets"

자, 이제 다시 배포작업을 해보았습니다.

$ app-root> cap deploy

Voila~, 문제가 해결되어 이미지가 보이게 되었습니다.

혹시 저와 똑같은 상황에 직면했을 때 도움이 될까봐 저의 경험을 정리해 보았습니다.

글쓴이: 최효성

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

2 thoughts on “레일스 어플리케이션 배포와 서버 설정”

  1. 안녕하세요. 윈도우에서 배포는 어떻게 하는지 알 수 있을까요?
    윈도우에서 passenger-install-apache-module2 를 하면 noexec option 이라고 나오면서 설치가 되지 않습니다.
    도움 부탁드립니다.

  2. 윈도우 서버에 배포한다는 말씀이죠? 죄송합니다. 유감스럽게도 윈도우 서버에 배포해 본 적이 없어서 도움말을 드리지 못할 것 같습니다.

답글 남기기

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

WordPress.com 로고

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

Twitter 사진

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

Facebook 사진

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

Google+ photo

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

%s에 연결하는 중