Node.jsをpm2でデプロイするためのAnsible Playbook

Node.jsアプリの継続動作には今までforever使ってたんですが、pm2は色々親切で高機能なので乗り換えることにしました。pm2を使うようにデプロイしてみましょう。

Ansible

デプロイするためには普通sshで入ってgit pullしてとかやらなきゃいけないですが、1個1個手でやるのは忘れやすいし間違いやすいのでAnsibleを使います。
Ansibleはあれやってこれやってを列挙しておけるもので、それを実行すると順番に全部やってくれます。
詳しくはhttp://yteraoka.github.io/ansible-tutorial/とか見てください。

では、node.jsもgitも何も入っていないubuntuに手元のnode.jsを入れるとします。
ただし、sshでは入ることが出来るように公開鍵はセットされてて、sudoはパスワード無しで出来るユーザーだとします。ここまではよろしくね。

apt-get

まず。

  1. Node.js
  2. npm
  3. pm2
  4. Git

を入れます。


---
# Install Node.js(include npm) pm2
- name: Prepare Install Node.js
  apt: name=python-software-properties

- name: Prepare Install latest Node.js by adding repo
  apt_repository: repo='ppa:chris-lea/node.js'

- name: Update apt-get packages using apt-get update
  apt: update_cache=yes

- name: Install Node.js
  apt: name=nodejs state=present

- name: Install pm2
  npm: name=pm2 global=yes state=latest
 
# Install Git
- name: Install Git
  apt: name=git state=present

ここまででapt-get系は終了です。
apt-getするので、sudo=yesがplaybookに必要です。
ちなみにnode.jsとnpmは一緒に入ってきますのでご心配なく。そしてそれが入るとAnsibleのnpmモジュールでnpmの操作ができるようになります。
こうやって何かが入っていないと実行できない場合は -checkをつかったテスト実行だと失敗しますが、ちゃんとした実行だとnpmも入るわけですからうまく動きます。
また、今回は最新のnode.jsを入れたかったのでchris-leaのリポジトリを利用しています。

git pull

node.jsアプリをgit 経由でデプロイしましょう。
git pullする時に気にするのは鍵です。公開リポジトリならいいですが、そうでない場合対象となるサーバーがリポジトリにアクセスできるかが問題になります。方法として

  1. deploy用の秘密鍵をそもそも自分で秘密鍵を入れておく
  2. deploy用の秘密鍵をAnsibleで入れて使うようにする
  3. 手元の秘密鍵をforwardする

などの手があります。2とかがキレイですが、どうせ手元からしかやらないのであれば3はオススメです。そのための設定がいるが必要でansible.cfgをplaybookと同じディレクトリに置きます。内容は


[ssh_connection]
ssh_args = -o ForwardAgent=yes

とします。
また、ansible-playbookする時に


--private-key=~/.ssh/id_rsa

といった感じでリポジトリにアクセスできる秘密鍵を指定するようにします。これで手元の秘密鍵がgit pull の時に使われるので問題なくpullできます。

実際のtaskは


---
# Deployment
- name: Create Target Directory.
  file: state=directory path={{app_dir}}/{{app_name}} mode=0755
 
- name: Change Owner
  file: owner={{deploy_user}} state=directory path={{app_dir}}/{{app_name}} recurse=yes

- name: Pull code from Repository
  sudo: no
  git: repo={{repo_url}} dest={{app_dir}}/{{app_name}} version=master accept_hostkey=yes

- name: npm install
  npm: path={{app_dir}}/{{app_name}}

- name: List of Node.js apps running.
  sudo: no
  shell: pm2 list
  register: node_app_list
  changed_when: false
  tags: restart

- name: Stop old process if exist
  sudo: no
  command: pm2 stop {{app_process_name}}
  when: node_app_list.stdout.find('{{app_process_name}}') != -1
  tags: restart
 
- name: Start process with pm2
  sudo: no
  command: pm2 start {{app_dir}}/{{app_name}}/bin/www --name {{app_process_name}}
  tags: restart

こんな感じです。
同じくsudo=yesが必要です。
ここまでやるとhttp://入れた場所:3000/ とかで動きます。
ちなみにpm2で手動的にプロセスを再起動していますが、pm2にはファイルの変更監視をして変更されてたら再起動するようなwatch機能があるのでそれを使って更新することも可能です。

後はnginxの設定などで特定のサブドメインだったらこのnodeのアプリとかやるといいですね。