突然気温が暑くなって眠れないニッシー☆です。
先日、とあるイベントにてAzure App Serviceを使ったアプリケーションのデプロイについてハンズオン形式で受けました。
驚いたことにたったの10分ほどでデプロイは愚かCI/CDパイプラインまで組まれてしまったので感動しました。すごい。。
ハッカソンは時間との勝負。開発という本質的な取り組みに時間を割くためにもCI/CDパイプラインを組み、デプロイの自動化をしておきたいところですね。
ここでふと思ったのは敢えてめんどくさい方のデプロイ方法ではどのくらいの時間が掛かるのだろう、、と。。
めんどくさい方のデプロイ方法とは
以下のことを愚直にやることです!
- 実際のLinuxPCを用意する(VPSを使ったのでインターネット上に公開する作業は省略)
- ssh接続する
- OSのアプデをする
- ファイアウォールを設定する
- アプリに必要なライブラリやランタイムをインストールする
- アプリをgit cloneする
- デーモンとしてアプリを起動させる
- Nginxをリバースプロキシとして設定する
- ドメインを紐付ける
- SSL化する
- etc…
それでは行ってみよう!!
本編スタート
今回はNode.jsアプリケーションをUbuntu20.04に最速でデプロイする手順をメモしていきます。もちろんエンタープライズな場では参考にしないでください。
Linux機を1台用意する
公開する物理的なサーバーが無いと始まらないので用意します。今回はレンタルサーバーサービスであるConoHa VPSのUbuntu20.04イメージを契約することで準備とします。
VPSにSSH接続できるようにする
ConoHa VPSでは管理画面での設定を弄ることで公開鍵認証方式の公開鍵をVPSのホストにセットできます。対になる秘密鍵を手元のパソコンにセットしてSSH接続できるようにします。例えば以下のような情報を ~/.ssh/config
に設定します。
Host ubuntu
HostName <your-server-ip>
User root
Port 22
IdentityFile ~/.ssh/ubuntu.pem
この設定により以下のコマンドでVPSにSSH接続できるようになります。
ssh ubuntu
以後rootユーザーでの操作を前提とします。
OSのアップデートをする
後に入れるNginxがパッケージ一覧にデフォルトでなかったりするので必須です。以下のコマンドでできます。
apt update -y && apt upgrade -y
Ubuntuのアップデートについて↓
https://ubuntu.com/server/docs/upgrade-introduction
少し休憩。
休憩もつかの間。
ところで、、
アプデが終わったら確実に反映させるためにOSの再起動をしましょう。
Nginxを入れる
Webサーバーの一種であるNginxを入れます。複数のアプリを同一インスタンス上で動かす予定があったのでリバースプロキシとして動いてもらうことが目的です。以下の記事を参考にインストール&設定しました。
https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04-ja
ファイアウォールを有効にする
必須ではないですが宗教上の理由で有効化させます。ポイントはWebサーバー用で利用する80番ポートと443番ポートの他にSSH接続で使う22番ポートを許可する設定にすることです。こうしないと次回のSSH接続で繋がらなくなくなります。こうなると直接サーバーにアクセスしないといけなくなります。(まあこのあたりはConoHa VPSではWeb上の管理画面から端末を開くことでアクセスできるのですが、、初学者だったころのぼくはテンパりました。。)
参考にしたサイトはこちら↓
正しく設定できればブラウザからグローバルIPアドレスにアクセスすることでNginxのWelcomeページが見られます。
hostname -I
# もしくは
curl -4 icanhazip.com
アプリケーションを配置する
ここまで書くまで意識していませんでしたがここから先の工程がいわゆるデプロイの本質的な部分です。
デプロイユーザーを作成する
デプロイに必要な権限だけを持ったユーザーでアプリケーションのコードを管理します。以下のコマンドで作成します。
adduser deployuser
アプリ配置先のディレクトリを作成する
アプリを配置するディレクトリを作成します。その際にディレクトリの所有者をdeployuser
にします。
mkdir /var/www/nodejsapp/
chown deployuser: /var/www/nodejsapp/
git cloneする
GitHubなどのリモートリポジトリからコードをクローンします。
cd /var/www/nodejsapp/
sudo -u deployuser -H git clone <your awesome nodejs app repository url> code
deployuser
としてコマンドを実行するために sudo -u deployuser -H ...
といった形にコマンドがなっています。それからgit cloneの第2引数にcode
という文字列を渡しているのでクローンしたリポジトリのディレクトリ名はcode
になります。
Node.jsをインストールする
コードをクローンするだけではNode.jsアプリは動きません。Node.jsランタイムを入れていきます。今回は宗教上の理由でanyenvからのnodenvからのnode16系を入れます。RTAなのでapt install nodejsで適当なNodeを入れればよいのは確かです。
ローカル開発環境にはanyenvとanyenv-updateとnodenv-yarn-installを脳死でいつも入れてます。
Node.jsのインストール完了後、ローカルでやるのと同じ通りにプロジェクトのルートへ行き、npm i && npm start
を実行します。(環境によってコマンドは変わると思います)
一旦、実行したままにしておきます。
リバースプロキシの設定をする(その1)
現状でNginxの設定を弄り、リバースプロキシの設定をします。新しく端末を開き、VPSに接続します。
以下の内容で/etc/nginx/conf.d/nodejsapp.conf
を作成します。
server {
client_max_body_size 50M;
server_name <サーバーのグローバルIPアドレス>;
location / {
proxy_pass http://localhost:8000; # nodeアプリが待機しているアドレス
}
}
Nginxの設定を再読み込みします。
systemctl reload nginx
グローバルIPアドレスにアクセスしてnodeアプリが応答することを確認します。
http://<your-server-ip>/
アプリをデーモン化する
動かし続けるために端末を一個犠牲にするなんてことはしたくないので裏側で起動させるための設定をしていきます。systemdの仕組みを利用します。
https://qiita.com/bluesDD/items/eaf14408d635ffd55a18
一旦、nodeアプリが動いている端末に戻り、ctrl+Cで停止させてください。
以下のような内容を /etc/systemd/system/nodejsapp.service
に記述します。
[Unit]
Description=cicd handson js sample app
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/home/deployuser/.anyenv/envs/nodenv/shims/node /var/www/azure-web-app-js/code/bin/www
Working/Directory=/var/www/nodejsapp/code
KillMode=process
Restart=always
User=deployuser
Group=deployuser
[Install]
WantedBy=multi-user.target
以下のコマンドでnodeアプリを起動できるようになります。
systemctl start nodejsapp
改めてグローバルIPで挙動を確認します。
systemd化のために参考にしたサイト↓
https://qiita.com/you21979@github/items/588bddb59378ce7303a2
ドメインを紐付ける
IPアドレスで直接アクセスするのはダサいのでドメインを紐付けます(個人の意見です)
ドメインを管理しているサービスで例えば以下のようなレコードを追加します。
レコード名 | レコードタイプ | 値 |
js.yukinissie.com (your domain) | A | 118.27.22.88 (your-server-ip) |
リバースプロキシの設定をする(その2)
ドメインを紐付けたのでNginxの設定を変更し、ドメインからのアクセスをNodeアプリに中継するようにします。/etc/nginx/conf.d/nodejsapp.conf
を以下のコードに修正します。
server {
client_max_body_size 50M;
server_name js.yukinissie.com; # 変更点。ここは人によって異なる
location / {
proxy_pass http://localhost:8000; # nodeアプリが待機しているアドレス
}
}
ドメインでアクセスできるようになりました。
SSL化する
http
じゃなくてhttps
にして通信内容を暗号化し情報を守る仕組みですね。
今どきSSL化されてないとかダサいとしか言いようがないのでします。(個人の偏見です)
無料で且つ自動的に発行を行うためにcertbotを使います。証明書の発行自体はLet’s Encryptが使われます。以下のコマンドでcertbotを入れます。(snapが入っている前提です)
snap install core && snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
そして以下のコマンドを打ってcertbotを実行します。
certbot --nginx
いくつかの質問を対話的に答えることでSSLの設定が完了します。

これでSSL化ができます。(うまく行かないときはNginxをreloadすると動くかもしれません)
ちなみにcertbotがNginxの設定を自動的に書き換えてくれるのでSSL化させたドメインでアクセスできるようになる仕組みです。/etc/nginx/conf.d/nodejsapp.conf
を改めて見るとその痕跡がみれて勉強になります。
SSL化のためにみたドキュメント↓
https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal
ようやくデプロイができました!!!!🚀
RTAに掛かった時間は、、
1時間50分でした!うん、長い!!
感想
やっぱりクラウドサービスって偉大なんだなって思いました。。