Ubuntu14.04でGitフックを使用してRailsアプリをデプロイする方法
序章
このチュートリアルでは、Gitフックを使用して、Railsアプリケーションの本番環境のリモートUbuntu14.04サーバーへのデプロイを自動化する方法を示します。 Gitフックを使用すると、データベースの移行を手動でプルして実行する必要がなく、変更を本番サーバーにプッシュするだけでアプリケーションをデプロイできます。 アプリケーションで作業を続けると、Gitフックなどの何らかの形式の自動デプロイを設定することで、長期的には時間を節約できます。
この特定のセットアップでは、アプリケーションサーバーとしてのPuma、PumaへのリバースプロキシとしてのNginx、およびデータベースとしてのPostgreSQLに加えて、単純な「受信後」のGitフックを使用します。
Gitフックを初めて使用し、先に進む前に詳細を知りたい場合は、次のチュートリアルをお読みください:Gitフックを使用して開発およびデプロイタスクを自動化する方法。
前提条件
Ubuntuサーバーでスーパーユーザー権限を持つroot以外のユーザーにアクセスする必要があります。 セットアップ例では、deploy
というユーザーを使用します。 このチュートリアルでは、その設定方法を説明します: Ubuntu14.04を使用したサーバーの初期設定。 パスワードを入力せずにデプロイする場合は、必ずSSHキーを設定してください。
サーバーにRubyをインストールする必要があります。 まだインストールしていない場合は、rbenvまたはRVMを使用してRailsと一緒にインストールできます。
また、ローカル開発マシンのgitリポジトリで管理されるRailsアプリケーションが必要になります。 持っておらず、フォローしたい場合は、簡単なサンプルアプリを提供します。
始めましょう!
PostgreSQLをインストールする
ほとんどの本番Rails環境はデータベースとしてPostgreSQLを使用しているので、今すぐサーバーにインストールしましょう。
本番サーバーで、apt-getを更新します。
sudo apt-get update
次に、次のコマンドを使用してPostgreSQLをインストールします。
sudo apt-get install postgresql postgresql-contrib libpq-dev
注:PostgreSQLアダプターであるpg
gemをローカルにインストールできるように、開発マシンにもPostgreSQLをインストールする必要があります。 これは、アプリケーションのGemfileにgemを追加するときに、bundle install
を実行するために必要になります。 インストール手順はOSによって異なるため、これは読者に任された演習です。
本番データベースユーザーの作成
簡単にするために、本番データベースのユーザーにアプリケーション名と同じ名前を付けましょう。 たとえば、アプリケーションの名前が「appname」の場合、次のようなPostgreSQLユーザーを作成する必要があります。
sudo -u postgres createuser -s appname
データベースユーザーのパスワードを設定したいので、次のようにPostgreSQLコンソールに入ります。
sudo -u postgres psql
次に、データベースユーザーのパスワード(例では「appname」)を次のように設定します。
\password appname
希望のパスワードを入力して確認します。
次のコマンドでPostgreSQLコンソールを終了します。
\q
これで、適切なデータベース接続情報を使用してアプリケーションを構成する準備が整いました。
Railsアプリケーションを準備する
開発マシン、おそらくローカルコンピューターで、アプリケーションを展開する準備をします。
オプション:Railsアプリケーションを作成する
理想的には、デプロイしたいRailsアプリケーションがすでにあるはずです。 この場合は、このサブセクションをスキップして、フォローしながら適切な置換を行うことができます。 そうでない場合、最初のステップは新しいRailsアプリケーションを作成することです。
これらのコマンドは、ホームディレクトリに「appname」という名前の新しいRailsアプリケーションを作成します。 強調表示された「appname」を他のものに自由に置き換えてください。
cd ~ rails new appname
次に、アプリケーションディレクトリに移動します。
cd appname
サンプルアプリでは、スキャフォールドコントローラーを生成して、アプリケーションに次の情報を表示します。
rails generate scaffold Task title:string note:text
次に、アプリケーションがgitリポジトリにあることを確認しましょう。
Gitリポジトリを初期化する
何らかの理由でアプリケーションがまだGitリポジトリにない場合は、アプリケーションを初期化して初期コミットを実行します。
開発マシンで、アプリケーションのディレクトリに移動します。 この例では、アプリは「appname」と呼ばれ、ホームディレクトリにあります。
cd ~/appname
git init git add -A git commit -m 'initial commit'
次に、アプリケーションを微調整して、本番のPostgreSQLデータベースに接続できるように準備します。
データベース構成の更新
開発マシンで、まだそこにいない場合は、アプリケーションのディレクトリに移動します。 この例では、アプリは「appname」と呼ばれ、ホームディレクトリにあります。
cd ~/appname
次に、お気に入りのエディターでデータベース構成ファイルを開きます。 vi
を使用します:
vi config/database.yml
アプリケーションのデータベース構成のproductionセクションを見つけて、本番データベースの接続情報に置き換えます。 設定された例に正確に従った場合、次のようになります(必要に応じて任意の値に置き換えてください)。
config/database.ymlの抜粋
production: <<: *default host: localhost adapter: postgresql encoding: utf8 database: appname_production pool: 5 username: <%= ENV['APPNAME_DATABASE_USER'] %> password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>
保存して終了。 これは、アプリケーションの本番環境で、ローカルホスト(本番サーバー)で「appname_production」と呼ばれるPostgreSQLデータベースを使用する必要があることを指定します。 データベースのユーザー名とパスワードは環境変数に設定されていることに注意してください。 それらは後でサーバー上で指定します。
Gemfileを更新する
GemfileにPostgreSQLアダプターgem、pg
、およびPuma gemが指定されていない場合は、ここで追加する必要があります。
アプリケーションのGemfileをお気に入りのエディターで開きます。 ここではvi
を使用します。
vi Gemfile
次の行をGemfileに追加します。
Gemfileの抜粋
group :production do gem 'pg' gem 'puma' end
保存して終了。 これは、production
環境でpg
およびpuma
ジェムを使用する必要があることを指定します。
Pumaを構成する
Pumaを構成する前に、サーバーに搭載されているCPUコアの数を調べる必要があります。 次のコマンドを使用して、サーバー上で簡単にそれを行うことができます。
grep -c processor /proc/cpuinfo
次に、開発マシンで、Puma構成をconfig/puma.rb
に追加します。 テキストエディタでファイルを開きます。
vi config/puma.rb
この構成をコピーしてファイルに貼り付けます。
config / puma.rb
# Change to match your CPU core count workers 2 # Min and Max threads per worker threads 1, 6 app_dir = File.expand_path("../..", __FILE__) shared_dir = "#{app_dir}/shared" # Default to production rails_env = ENV['RAILS_ENV'] || "production" environment rails_env # Set up socket location bind "unix://#{shared_dir}/sockets/puma.sock" # Logging stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true # Set master PID and state locations pidfile "#{shared_dir}/pids/puma.pid" state_path "#{shared_dir}/pids/puma.state" activate_control_app on_worker_boot do require "active_record" ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env]) end
workers
の数をサーバーのCPUコアの数に変更します。 この例では、2つのコアがあると想定しています。
保存して終了。 これにより、アプリケーションの場所、およびそのソケット、ログ、およびPIDの場所を使用してPumaが構成されます。 ファイルを自由に変更するか、必要な他のオプションを追加してください。
最近の変更をコミットします。
git add -A git commit -m 'added pg and puma'
次に進む前に、アプリの実稼働環境で使用される秘密鍵を生成します。
rake secret
rake secret sample output:29cc5419f6b0ee6b03b717392c28f5869eff0d136d8ae388c68424c6e5dbe52c1afea8fbec305b057f4b071db1646473c1f9a62f803ab8386456ad3b29b14b89
次の手順では、出力をコピーして使用し、アプリケーションのSECRET_KEY_BASE
を設定します。
PumaUpstartスクリプトを作成する
Pumaを簡単に起動および停止し、起動時に確実に起動できるように、Upstartinitスクリプトを作成しましょう。
本番サーバーで、JungleUpstartツールをPumaGitHubリポジトリからホームディレクトリにダウンロードします。
cd ~ wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma-manager.conf wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma.conf
次に、提供されたpuma.conf
ファイルを開いて、Pumaデプロイメントユーザーを構成できるようにします。
vi puma.conf
setuid
とsetgid
を指定する2行を探し、「apps」をデプロイメントユーザーとグループの名前に置き換えます。 たとえば、デプロイメントユーザーが「デプロイ」と呼ばれる場合、行は次のようになります。
puma.confの抜粋1/2
setuid deploy setgid deploy
次に、exec /bin/bash <<'EOT'
という行を探します。 その下に次の行を追加します。必ずPostgreSQLのユーザー名とパスワード、および前に作成したrakeシークレットに置き換えてください。
puma.confの抜粋2/2
export APPNAME_DATABASE_USER='appname' export APPNAME_DATABASE_PASSWORD='appname_password' export SECRET_KEY_BASE='rake_secret_generated_above'
保存して終了。
次に、スクリプトをUpstartサービスディレクトリにコピーします。
sudo cp puma.conf puma-manager.conf /etc/init
puma-manager.conf
スクリプトは、管理する必要のあるアプリケーションの/etc/puma.conf
を参照します。 今すぐそのインベントリファイルを作成して編集しましょう:
sudo vi /etc/puma.conf
このファイルの各行は、puma-manager
で管理するアプリケーションへのパスである必要があります。 ユーザーのホームディレクトリにある「appname」という名前のディレクトリにアプリケーションを展開します。 この例では、次のようになります(アプリが存在する場所へのパスを必ず更新してください:
/etc/puma.conf
/home/deploy/appname
保存して終了。
これで、アプリケーションは起動時にUpstartを介して起動するように構成されました。 これは、サーバーが再起動された後でもアプリケーションが起動することを意味します。 アプリケーションをデプロイしていないため、まだ開始したくないことに注意してください。
Nginxをインストールして構成する
アプリケーションをインターネットにアクセスできるようにするには、NginxをWebサーバーとして使用する必要があります。
apt-getを使用してNginxをインストールします。
sudo apt-get install nginx
次に、テキストエディタでデフォルトのサーバーブロックを開きます。
sudo vi /etc/nginx/sites-available/default
ファイルの内容を次のコードブロックに置き換えます。 強調表示された部分を適切なユーザー名とアプリケーション名(2つの場所)に置き換えてください。
/ etc / nginx / sites-available / default
upstream app { # Path to Puma SOCK file, as defined previously server unix:/home/deploy/appname/shared/sockets/puma.sock fail_timeout=0; } server { listen 80; server_name localhost; root /home/deploy/appname/public; try_files $uri/index.html $uri @app; location @app { proxy_pass http://app; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; } error_page 500 502 503 504 /500.html; client_max_body_size 4G; keepalive_timeout 10; }
保存して終了。 これにより、Nginxがリバースプロキシとして構成されるため、HTTPリクエストはUnixソケットを介してPumaアプリケーションサーバーに転送されます。 必要に応じて、自由に変更してください。
アプリケーションはまだサーバー上に存在しないため、今のところNginxの再起動は控えます。 次にアプリケーションを準備します。
ProductionGitRemoteを準備する
本番サーバーで、apt-getを使用してgitをインストールします。
sudo apt-get install git
次に、リモートリポジトリ用のディレクトリを作成します。 「appname_production」という名前のホームディレクトリに裸のgitリポジトリを作成します。 リモートリポジトリには、自由に名前を付けてください(ただし、~/appname
には、アプリケーションをデプロイする場所であるため、配置しないでください)。
mkdir ~/appname_production cd ~/appname_production git init --bare
これはベアリポジトリであるため、作業ディレクトリはなく、従来の設定で.gitにあるすべてのファイルはメインディレクトリ自体にあります。
受信後のgitフックを作成する必要があります。これは、本番サーバーがgitプッシュを受信したときに実行されるスクリプトです。 エディタでhooks/post-receive
ファイルを開きます。
vi hooks/post-receive
次のスクリプトをコピーしてpost-receive
ファイルに貼り付けます。
フック/受信後
#!/bin/bash GIT_DIR=/home/deploy/appname_production WORK_TREE=/home/deploy/appname export APPNAME_DATABASE_USER='appname' export APPNAME_DATABASE_PASSWORD='appname_password' export RAILS_ENV=production . ~/.bash_profile while read oldrev newrev ref do if [[ $ref =~ .*/master$ ]]; then echo "Master ref received. Deploying master branch to production..." mkdir -p $WORK_TREE git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f mkdir -p $WORK_TREE/shared/pids $WORK_TREE/shared/sockets $WORK_TREE/shared/log # start deploy tasks cd $WORK_TREE bundle install rake db:create rake db:migrate rake assets:precompile sudo restart puma-manager sudo service nginx restart # end deploy tasks echo "Git hooks deploy complete" else echo "Ref $ref successfully received. Doing nothing: only the master branch may be deployed on this server." fi done
次の強調表示された値を必ず更新してください。
GIT_DIR
:以前に作成したベアgitリポジトリのディレクトリWORK_TREE
:アプリケーションをデプロイするディレクトリ(これは、Puma構成で指定した場所と一致する必要があります)APPNAME_DATABASE_USER
:PostgreSQLユーザー名(レーキタスクに必要)APPNAME_DATABASE_PASSWORD
:PostgreSQLパスワード(レーキタスクに必要)
次に、# start deploy tasks
コメントと# end deploy tasks
コメントの間のコマンドを確認する必要があります。 これらは、マスターブランチが本番gitリモート(appname_production
)にプッシュされるたびに実行されるコマンドです。 それらをそのままにしておくと、サーバーはアプリケーションの実稼働環境に対して次のことを実行しようとします。
- バンドラーを実行する
- データベースを作成する
- データベースを移行する
- アセットをプリコンパイルします
- Pumaを再起動します
- Nginxを再起動します
変更を加えたり、エラーチェックを追加したりする場合は、ここで自由に行ってください。
受信後のスクリプトの確認が完了したら、保存して終了します。
次に、スクリプトを実行可能にします。
chmod +x hooks/post-receive
パスワードなしのSudo
post-receiveフックはsudoコマンドを実行する必要があるため、デプロイユーザーがパスワードなしのsudo
を使用できるようにします(異なる場合は、ここでデプロイユーザー名に置き換えてください)。
sudo sh -c 'echo "deploy ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-deploy'
これにより、deploy
ユーザーはパスワードを入力せずにsudo
コマンドを実行できるようになります。 デプロイユーザーがスーパーユーザー権限で実行できるコマンドを制限したい場合があることに注意してください。 少なくとも、SSHキー認証を使用し、パスワード認証を無効にする必要があります。
ProductionGitRemoteを追加する
本番サーバーですべてがセットアップされたので、本番gitリモートをアプリケーションのリポジトリに追加しましょう。
開発マシンで、アプリケーションのディレクトリにいることを確認してください。
cd ~/appname
次に、本番サーバーで作成したベアgitリポジトリappname_production
を指す「production」という名前の新しいgitリモートを追加します。 ユーザー名(deploy)、サーバーIPアドレス、およびリモートリポジトリ名(appname_production)を置き換えます。
git remote add production deploy@production_server_public_IP:appname_production
これで、アプリケーションをgitpushでデプロイする準備が整いました。
本番環境にデプロイする
これまでに行ったすべての準備が完了したら、次のgitコマンドを実行して、アプリケーションを本番サーバーにデプロイできます。
git push production master
これは、ローカルマスターブランチを以前に作成した本番リモートにプッシュするだけです。 本番リモートはプッシュを受信すると、前に設定したpost-receive
フックスクリプトを実行します。 すべてを正しく設定すると、アプリケーションは本番サーバーのパブリックIPアドレスで使用できるようになります。
サンプルアプリケーションを使用した場合は、Webブラウザでhttp://production_server_IP/tasks
にアクセスして、次のように表示できるはずです。
結論
アプリケーションに変更を加えるときはいつでも、同じgitpushコマンドを実行して本番サーバーにデプロイできます。 これだけで、プロジェクトの全期間にわたって多くの時間を節約できます。
このチュートリアルでは「受信後」フックについてのみ説明しましたが、展開プロセスの自動化を改善するのに役立つフックには他にもいくつかの種類があります。 Gitフックの詳細については、このチュートリアルをお読みください: Gitフックを使用して開発およびデプロイタスクを自動化する方法!