アリババクラウドが提供するサービスを利用したNode.jsアプリケーションの展開

このチュートリアルでは、**Alibaba Cloud**が提供するサービスを利用して、本番環境に対応した**Node.js**アプリケーションのセットアップを取り上げます。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/deploying-node-js-apps-for-production-on-alibaba-cloud_594639)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

#序章
Node.jsは、高性能で高速なサーバーサイドアプリケーションを構築するために使用されるJavascriptのランタイム環境です。Node.js サーバーサイドアプリケーションは、間違った方法でデプロイされた場合、本当に遅くなり、トラフィックの増加をサポートできなくなる可能性があります。

このチュートリアルでは、アリババクラウドサービスが提供する素晴らしいサービスを使用して、本番環境に対応したNode.jsアプリケーションを設定する方法を説明します。**Node.js Blog**というアプリケーションをデプロイしますが、そのために以下のAlibaba Cloudサービスを使用します。

- [Elastic Compute Service](https://www.alibabacloud.com/ja/product/ecs):CPU、メモリ、OS、帯域、ディスクなどの基本的なコンピューティングコンポーネントを含む仮想コンピューティング環境。このサービスを使用してLinuxインスタンスを起動し、そこにNode.jsアプリケーションをデプロイします。
- [ApsaraDB for MongoDB](https://www.alibabacloud.com/ja/product/apsaradb-for-mongodb): 安全で信頼性が高く、弾力的にスケーラブルなクラウドデータベースサービスです。このサービスを使ってNode.jsアプリケーション用のMongoDBデータベースを起動します。

#前提条件
このチュートリアルを始める前に、以下のものが必要です。

- デプロイする Node.js アプリケーション。以下の [Github リポジトリ](https://github.com/bahdcasts/node-js-blog?spm=a2c65.11461447.0.0.159a7f66fIIASr)にあります。
- Ubuntu 16.04 64ビットECSインスタンス。[このチュートリアル](https://www.alibabacloud.com/help/ja/doc-detail/25424.htm)を使って作成することができます。
- ApsaraDB for MongoDB のインスタンス。[このチュートリアル](https://www.alibabacloud.com/help/ja/doc-detail/55137.htm)を使って作成することができます。
- ECS インスタンスへ接続します。SSH を使って接続するには、[このチュートリアル](https://www.alibabacloud.com/help/ja/doc-detail/51793.htm)に従ってください。


- 
**注**: ECS インスタンスと ApsaraDB for MongoDB インスタンスがまったく同じゾーンに作成されていることを確認してください。そうすることでアプリケーションのパフォーマンスが向上し、接続の問題や制限を回避することができます。

#ステップ 1 - すべてのサーバーの依存関係をインストールする
このステップでは、node js アプリケーションを実行するために必要なすべての依存関係をインストールします。手順に従うには、ECS インスタンスにログインしていることを確認してください。

####Git のインストール
GitHubからアプリケーションのコードを取得できるようにするには、gitを使ってリポジトリをクローンする必要があります。以下のコマンドでインスタンスにgitをインストールしてみましょう。

```
sudo apt-get install git
```

インストールを確認するには、以下のコマンドを実行してインストールされているgitのバージョンを確認します: `git --version. `私の場合、以下のような出力が出てきました: `git version 2.7.4.`

####Node.jsのインストール
node.jsアプリケーションを実行するためには、このアプリケーションを実行するために必要な特定のnode.jsのバージョンをインストールする必要があります。私たちのnode.jsブログの場合は、Nodeのバージョン8以上が必要です。インストールするには、以下のコマンドを実行します。

```
curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh
```

このコマンドは、`nodeource_setup.sh`というファイルをダウンロードします。これはnode jsをインスタンスにインストールするためのシェルスクリプトです。このシェルスクリプトを以下のコマンドで実行します。

```
sudo bash nodesource_setup.sh
```

そして最後に、インストールを完了させるために、以下を実行します。

```
sudo apt-get install -y nodejs
```

node jsのインストールを確認するには、`node -v`を実行して、インストールされているnodeのバージョンを確認します。私の場合は、最新のバージョン8のサブバージョン`（v8.13.0）`がインストールされています。

####Nginxのインストール
Nginx は世界で最も人気のあるウェブサーバーの一つであり、いくつかの大規模なサイトで使用されています。アプリケーションをデプロイするために、プロキシサーバとしてnginxを使用してアプリケーションを提供します。これについては後ほど詳しく説明します。nginxをインストールするには、以下を実行してください。

```
sudo apt-get install nginx
```

インストールをテストするには、`nginx -v`を実行して、インストールされているバージョンを確認します。私の場合、以下のような出力が出てきました：`nginx version: nginx/1.10.3 (Ubuntu)`

####PM2プロセスマネージャのインストール
Node.jsアプリケーションは非常に脆いため、運用環境では強力なプロセスマネージャを使用してnode.jsアプリケーションを監視し、プロセスが常に実行されていることを確認する必要があります。このケースで使用するプロセスマネージャは `pm2` と呼ばれ、node.js パッケージとして提供されています。PM2はnode jsアプリケーションのクラッシュを監視するだけでなく、node jsアプリケーションを自動的にスケーリングし、インスタンス上のすべてのCPUを最適化します。PM2をインストールするには、次のように実行します。

```
npm i -g pm2
```

インストールを確認するには、`pm2 -v` を実行してください。私の場合、以下のような出力が表示されました。`3.2.2.`

#ステップ 2 - アプリケーションコードの取得
このステップでは、インスタンス上で実行できるようにアプリケーションリポジトリをクローンします。

####アプリケーションコードのクローン
アプリケーションのコードをクローンするには、以下のコマンドを実行します。

```
cd /home
git clone https://github.com/bahdcasts/node-js-blog.git
```

####プロジェクトの依存関係のインストール
プロジェクトの依存関係をインストールするには、以下のコマンドを実行します。

```
cd /home/node-js-blog
npm install
```

####環境変数の設定
ほとんどのnode jsアプリケーションでは、サーバの環境変数を設定する必要があります。このプロジェクトでは`dot-env`というパッケージを使用しており、このパッケージを使用することで、すべての環境変数を`.env`というファイルに配置することができます。このファイルを作成し、環境変数を追加します。以下のコマンドを実行します。

```
cd /home/node-js-blog
nano .env
```

ターミナルコードエディタ`nano`を使って`.env`という新しいファイルを開きます。ファイルの中に以下の内容を入れます。

```
PORT=3000
DB_URI=
CLOUDINARY_API_KEY=xxxx
CLOUDINARY_API_SECRET=xxxx
CLOUDINARY_NAME=xxx
EXPRESS_SESSION_KEY=d29z4944SxETKPNWqKAkCNUjrZ4A
```

これらはこのプロジェクトが動作するために必要な環境変数です。`PORT`はNode.jsアプリケーションが動作する特定のポートです。`EXPRESS_SESSION_KEY`は、ユーザーセッションを暗号化するために使用されるランダムな文字列です。

また、このブログの画像はcloudinaryにアップロードされており、そのためにcloudinaryの環境変数が必要になります。このチュートリアルの焦点ではないので省略しても構いません。これは、独自のNode jsプロジェクトをデプロイする際に、独自のカスタム環境変数を設定する方法を紹介するだけです。

最後の環境変数は `DB_URI` で、これが ApsaraDB for MongoDB インスタンスに接続するための環境変数になります。これは後のステップで追加します。

**注**: `nano editor`を終了するには、`CTRL + X`を押してから`Y`を押してください。

#ステップ3 - MongoDBインスタンスへの接続
このステップでは、先ほど作成した `ApsaraDB for MongoDB` インスタンスにアプリケーションを接続します。

####ApsaraDB for MongoDB のサーバー IP をホワイトリスト化する
デフォルトでは、MongoDB インスタンスはどのアドレスからの接続も許可しません。コンソールを使って、ECS インスタンスの IP アドレスをホワイトリストに登録して、アプリケーションが正常に接続できるようにします。

まず、コンソールにアクセスして MongoDB インスタンスを開き、「データセキュリティ」タブにアクセスします。ここで、`Manually modify` ボタンをクリックして新しい IP アドレスを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/82acee9c-be58-0d0c-0476-25ff27697b23.png)

変更を保存します。このアクションは、アプリケーションがこの MongoDB インスタンスに接続するための許可を与えます。

####DB_URI接続文字列の設定
`Database Connection` タブから、データベースへの接続文字列を取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/4cb25145-4a63-7da7-d7d4-a81abf777554.png)

####環境変数 DB_URI の設定
接続文字列をコピーし、環境変数 `DB_URI` の値を更新します。`nano .env`を使うと、`.env`ファイルは以下のようになります。

```
PORT=3000
DB_URI="mongodb://root:passWORD1234@dds-gs50fb23291731d41.mongodb.singapore.rds.aliyuncs.com:3717,dds-gs50fb23291731d42.mongodb.singapore.rds.aliyuncs.com:3717/admin?replicaSet=mgset-300215248"
CLOUDINARY_API_KEY=132255634713478
CLOUDINARY_API_SECRET=aeBNzdZFcju9ZEAiL7KsEMbBlFI
CLOUDINARY_NAME=bahdcoder
EXPRESS_SESSION_KEY=d29z4944SxETKPNWqKAkCNUjrZ4P
```

**注**: 文字列中の***は、インスタンスの実際のルートパスワードに置き換えることを忘れないでください。

#ステップ4 - Nginxの設定をする
このステップでは、nginx ウェブサーバが node js アプリケーションを利用できるように、nginx の設定を行います。

これを行うために、デフォルトのnginx設定ファイルを編集します。以下のコマンドを実行します。

```
# Empty the current configuration file
echo > /etc/nginx/sites-available/default

# Open the file using nano
nano /etc/nginx/sites-available/default
```

このファイルの内容を以下のように置き換えてください。

```
server {
  listen 80;

  server_name 47.88.230.255;

  location / {
      proxy_pass http://localhost:3000;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_cache_bypass $http_upgrade;
  }
}
```

注意すべき2つの重要な設定は、`server_name`と`proxy_pass`です。`server_name` は理想的にはアプリケーションのドメイン名であるべきで、ユーザーが特定のサイトにアクセスしようとした場合に基礎となる設定を使用するよう nginx に指示します。この場合、このアプリケーションのためにドメイン名を設定しないので、単に ECS のインスタンスの IP アドレスを使用します。

第二に、`proxy_pass` の設定は nginx に、`http://localhost:3000` 上で実行されているプロセスに、`server_name` のために入ってくるすべてのトラフィックをリダイレクトするように指示します。つまり、ユーザーが`47.88.230.255`にアクセスしようとすると、nginxはユーザーのリクエストをポート`3000`で動作しているnode jsアプリケーションにリダイレクトします。ここでは3000番ポートを使用していますが、これはnode jsアプリケーションを起動するポートであるためです。

**注**: `47.88.230.255`をECSインスタンスの実際のIPアドレスに置き換えることを忘れないでください。

最後に、設定変更を保存するためにnginxを再起動する必要があります。

以下のコマンドを実行してください。

```
sudo systemctl restart nginx
```

#ステップ5 - アプリケーションの起動
最後に、プロセスマネージャPM2を使用してnode jsアプリケーションを起動する必要があります。 これを行うには、以下のコマンドを実行します。

```
cd /home/node-js-blog

pm2 start index.js --name "blog"
```

このコマンドは、`index.js`ファイルをルートとして使用してアプリケーションを起動し、このプロセスに`blog`という名前を与えます。このコマンドは以下のような出力が出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/a32fa5e2-a77e-38c3-acda-99b1268546b9.png)

####アプリケーションログのトラッキング
アプリケーションをデバッグして監視するには、以下のコマンドを使用して、アプリケーションからログに記録されたすべてのメッセージをリアルタイムで表示することができます。

```
pm2 logs blog
```

これは`blog`というプロセスのログをプリントアウトします。出力は以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/ed2b8e16-2317-90ad-af7d-3753b3ccf3d9.png)

#結論
このチュートリアルでは、Alibaba Cloud [Elastic Compute Service](https://www.alibabacloud.com/ja/product/ecs) (ECS) と [ApsaraDB for MongoDB](https://www.alibabacloud.com/ja/product/apsaradb-for-mongodb) を使用して本番アプリケーションをデプロイする方法を学びました。また、PM2と呼ばれる高度なプロセスマネージャを使用してNode.jsアプリケーションを管理し、自動的にスケーリングしました。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*