Node.js de Server 〜仮想環境を添えて〜

![advent2018_blk.png](https://qiita-image-store.s3.amazonaws.com/0/217369/ada067cc-32d8-08d8-52ff-4c442ae3209c.png)

[aratana Advent Calendar 2018](https://qiita.com/advent-calendar/2018/aratana) 3日目の記事です。

宮崎在住エンジニアのジョウ(@JotarO_Oyanagi) です。
つい先日の 12/1 でまた一つ大人の階段を登りましたが、心は永遠のハイティーン・ブギです。

今年の夏頃までは「フロントエンド一筋！一生バックエンドは触らない！」と誓っていたんですが、運命とは皮肉なもので、ここ最近はバックエンド気味のあれこれを行う毎日です。

バックエンドをやるにしても、どうせなら **Node.js** を使おう！ということで、ローカルでの開発環境用に **Vagrant** を使った環境構築の手順を記します。

# TL;DR
- 環境は centos 7.5、Node.js 8.11.4
- **anyenv** と **ndenv** を使用して Node.js をインストール
- Node アプリの常駐化に **PM2** を使用し、ホットリロード、自動起動までを設定

# [準備] 仮想環境用ファイルをインストール

まずは仮想環境用アプリケーション一式を取得します。

## 準備1. VirtualBox をインストール

公式より取得し、インストールしてください。
https://www.virtualbox.org/wiki/Downloads

## 準備2. Vagrant をインストール

公式より取得し、インストールしてください。
https://www.vagrantup.com/downloads.html

# 1. 作業用フォルダに仮想環境を作成

##  1-1. 作業用フォルダを作成

作業用フォルダを作成して移動します。

```bash

$ mkdir 作業用フォルダ && cd 作業用フォルダ
```

## 1-2. VagrantFile を作成

```bash

$ vagrant init bento/centos-7.5
```

## 1-3. VagrantFile にローカル用の設定を記述

**Vagrantfile** を編集します。

```bash

$ vi Vagrantfile
```

### 1-3-1. ローカル環境用 IP を設定

**private_network** にローカル環境用 IP を設定します。

ここでは  **10.10.10.11**  をローカル環境用 IP とします。

（コメントアウトを外すのを忘れずに）

```vim

- # config.vm.network "private_network", ip: "192.168.33.10"
+ config.vm.network "private_network", ip: "10.10.10.11"
```

### 1-3-2. Vagrant と同期させるローカルフォルダを設定

ここでは作業用フォルダを同期させるローカルフォルダとします。

（コメントアウトを外すのを忘れずに）

```vim

- # config.vm.synced_folder "../data", "/vagrant_data"
+ config.vm.synced_folder "./", "/vagrant", create: true, owner: "vagrant", group: "vagrant", mount_options: ["dmode=777", "fmode=777"]
```

Vagrantfile を保存して閉じます。

## 1-4. 仮想環境を起動

```bash

$ vagrant up
```

そこそこ時間かかるので ☕️でも飲んで待ちましょう。

# 2. Node.js を準備する

Node.js de Server なので、Node.js をインストールします。

## 2-1. Git を準備する

yum でインストールされる Git がバージョン 1.8 と古かったりするので、最新版をインストールする方法を記します。

### 2-1-1. パッケージの Git を削除

これをしておかないと、この先に記したことを実行しても 1.8 がインストールされることに。

```bash

$ sudo yum -y remove git
```

### 2-1-2. ライブラリをインストール

```bash

$ sudo yum -y install curl-devel expat-devel gettext-devel openssl-devel perl-devel zlib-devel autoconf asciidoc xmlto docbook2X make gcc
$ sudo ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi
```

###  2-1-3. Git をダウンロード＆インストール

最新版のバージョン 2.19.2（2018.12.3 現在）をインストールします。

```bash

$ cd ~
$ wget https://github.com/git/git/archive/v2.19.2.tar.gz
$ tar -zxf v2.19.2.tar.gz
$ cd git-2.19.2
$ make configure
$ ./configure --prefix=/usr
$ sudo make install
```

そこそこ時間かかるので ☕️でも飲んで待ちましょう。

### 2-1-4. バージョン確認し、OKならインストール用のファイルを削除

```bash

$ git --version
git version 2.19.2
$ cd ~
$ sudo rm -rf git-2.19.2 && rm -f v2.19.2.tar.gz
```

## 2-2. Node.js をインストール

Node.js のバージョン管理ツールよりインストールします。

その前に、各言語のバージョン管理ツールの総合管理ツールとして **anyenv** をインストールします。

```bash

$ cd ~
$ git clone https://github.com/riywo/anyenv ~/.anyenv
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
```

続いて Node.js のバージョン管理ツール **ndenv** をインストールします。

```bash

$ anyenv install ndenv
$ source ~/.bash_profile
$ git clone https://github.com/riywo/node-build.git $(ndenv root)/plugins/node-build
```

いよいよ Node.js をインストールします。

```bash

$ ndenv install v8.11.4
$ ndenv rehash
$ ndenv global v8.11.4
```

バージョンが問題ないか確認します。

```bash

$ node -v
v8.11.4
```

## 2-3. yarn をインストール

Node モジュールのパッケージマネージャとして、 **yarn** を使用したいのでインストールします。

```bash

$ npm install -g yarn
```

ただインストールしただけだと `yarn global add` で追加したモジュールが使えないので、パスを通します。

```bash

$ echo 'export PATH="$PATH:`yarn global bin`"' >> ~/.bash_profile
$ source ~/.bash_profile
```

## 2-4. PM2 をインストール

Node アプリを常駐化させる **PM2** をインストールします。

```bash

$ yarn global add pm2
```

## 2-5. Node アプリ起動用ファイルを作成・設定する

普通に PM2 で Node アプリを起動（常駐させる）には `pm2 start アプリファイル名` でいいんですが、起動オプションや環境変数を設定できるファイルを作成し、そこから起動するようにします。

### 2-5-1. 起動用ファイルを作成

```bash

$ pm2 ecosystem
```

これで **ecosystem.config.js** というファイルが作成されます。

このファイルを修正します。

```javascript:ecosystem.config.js

module.exports = {
  apps : [{
    name: 'アプリ名', // 任意で
    script: 'app.js', // アプリファイル名
    watch: true, // ホットリロードにする設定
    watch_options: {
      usePolling: true // 後述
    },
    env: { // env オプション無しで起動した場合の設定
      NODE_ENV: 'development' // 環境変数
      // 他にポートやタイムゾーンなど、Node のオプションを設定できる
    },
    env_production: { // --env production で起動した場合の設定
      NODE_ENV: 'production'
    }
  }]
};
```

上記で設定した **watch_options** の **usePolling: true** ですが、Vagrant で共有フォルダ配下のファイルを監視（ホットリロード対象に）するための記述です。

あとは、このファイルを PM2 起動時に指定します。

```bash

$ pm2 start ecosystem.config.js
```

production 用の設定をしていて、その設定で起動する場合は以下になります。

```bash

$ pm2 start ecosystem.config.js --env production
```

## 2-6. サーバー起動時に PM2 も起動させる

サーバー（Vagrant）を起動時に PM2 も起動させる設定をしておきます。

### 2-5-1. PM2 をサービス化

```bash

$ pm2 startup
```

出力された `sudo env PATH=********` をコピペして実行します。

**/etc/systemd/system/** にサービスファイルが作成されましたので、確認します。

```bash

$ cd /etc/systemd/system/
```

**pm2-ユーザー名.service** ができていればリネームします。

```bash

$ sudo mv pm2-vagrant.service pm2.service
```

### 2-5-2. 自動起動にする

以下を実行すれば、次回からサーバー起動時に PM2 も起動します。

```bash

$ sudo systemctl enable pm2
```

# 終わりに

これで、同期させたフォルダで Node.js によるアプリ開発をガシガシ行う準備が完了しました。

あとは、Webアプリのフレームワークとして **Express.js** を使うもよし、お好みで各種ミドルウェアを入れるもよし。
気軽に Node.js de Apps 制作をお楽しみください😃