Re:ゼロから始めるWebアプリケーション公開

この記事は数年前に note にて書いたものを微修正した記事となっております。
技術系？の記事を Qiita にまとめておいておきたいと思い移植しました。

Webアプリケーションを作ったことがあるけど公開したことない or これから Webアプリケーションを作って公開してみたいと思っている人向けの記事です！以下本文です。

## 0. まえがき

バックエンドとかフロントエンドのコード書いてる時にふと思ったんですよね、Webアプリケーションを本当にゼロから作って公開してみたいなって…（というのは建前で、本当はインフラ・バックエンド系の技術課題解けなくて萎えたので勉強しなきゃと思って復習半分で書いてます）
ということでゼロから公開するためのステップを順に見ていきましょう！
各節ごとに参考記事を末尾に載せているので、ぜひ参考にしてください！
現役のエンジニアの方や自前サーバをいじってるつよつよな人にとっては退屈な記事になってしまうこと、知識が浅い人間が書いているため間違いがある可能性があることご了承ください。また、この記事を参考にしたサーバ構築については自己責任にてよろしくお願いします。
さて、予防線はこの程度にしてやっていきましょうか…

## 1. インスタンス（サーバー）を立てる

ブラウザなどからWebアプリケーションにアクセスできるようにするには、アプリケーションを配信するサーバが必要です。ですからサーバを買って自宅に用意しましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629296/de9bff94-46c9-37af-6e1b-52aa17acd179.png "むむむ…")

むむむ…ということで金ないんでレンタルサーバを使いましょうか。（この時点でゼロからじゃないやん…って思っても言わないで）レンタルサーバの会社はいくつかありますのでお好きなレンタルサーバーを利用すれば良いと思います。

今回は AWS(Amazon Web Service) のレンタルサーバである [EC2(Elastic Compute Cloud)](https://aws.amazon.com/jp/ec2/?nc2=h_ql_prod_fs_ec2) を利用しようと思います。
EC2 は厳密にはクラウドサーバと呼ばれるもので、クラウド上に仮想のサーバを構築することができるサービスです。
自前のサーバを利用する際に必要な面倒なあれこれを楽に解決することができるので、自前サーバにこだわりがない人はクラウドサーバを利用するのがベストプラクティスである場合がほとんどでしょう。
クラウドサーバではサーバの1単位を「インスタンス」と呼びます。

2段階認証の設定とか色々めんどいかもしれませんがAWSのアカウントを作ってEC2 のページに飛んでもらって、「インスタンスの起動」ボタンを押してOSイメージ・インスタンスタイプ・SSHログインのためのRSAキーペア・ネットワーク（ファイアウォール）・ストレージの設定を行い、インスタンスを起動します。

:::note info
下の画像の四角のところをいじろうそれ以外はデフォで大丈夫
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629296/c77f4c6a-56a2-49be-d393-30b189e8cfd5.png)

不正アクセスされないようにしっかりRSAキーペアを生成・設定した上で、自分のIPからのSSHトラフィックのみを許可する設定にすることだけ注意すれば、それ以外はデフォルトのままで大丈夫だと思います。（秘密鍵がDLされるのでちゃんと保管）今回は Amazon Linux のサーバを立てることにします。

サーバを立てることができたら、自分のコマンドラインからSSH接続できることを確認します。

```
ssh -i <RSAの秘密鍵の場所> <インスタンスのURL>
```

実行してこんなのが出てきたら成功です！インスタンスを停止・再起動するとインスタンスのURLが変わることがあるので注意してください。（単に exit しただけではインスタンスが停止することはありません）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629296/14fc6e11-5d51-4bc8-5cce-27654670b9d9.png)

左のやつが立体のEC2って文字だと気づくまでに時間かかった...
切断するには `exit` と打ちましょう。

### この節の参考
[キーペアを作成する](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/create-key-pairs.html)
[Amazon EC2 インスタンスの IP アドレス指定](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-instance-addressing.html)

## 2. 作業環境を用意する

リモートサーバ内で作業する際はVScodeの`remotessh`を使うと便利です。拡張機能から Remote-SSH をインストールします。
Microsoftは偉大ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629296/86b2bbaa-7de5-c101-7ed4-6fdcea027fdc.png)

インストールしたら次の画像の+ の横の歯車を押して…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629296/57e71509-c0c4-723d-0b8a-4bd29191fe38.png)

`.ssh/config` の編集のボタンを押して、`.ssh/config` に次の通り追記します。

```
Host remotessh
    Hostname <インスタンスのURL>
    User ec2-user
    Port 22
    IdentityFile <キーペアを生成した時に保存した秘密鍵のパス>
```

そうしたらremotesshのモニターマークの横の+ウィンドウボタンを押して、新規ウィンドウでリモートに接続しましょう！

また、EC2のデフォルトではHTTPの80番ポートアクセスが許可されていないので、インスタンスの `セキュリティグループ->インバウンドルール->インバウンドルール` を編集で自分のIPのみから80番ポートにアクセスできるようにしておきましょう。任意のブラウザから閲覧できるようにしたくなったときは 80 番ポートのアクセスのソースに `0.0.0.0/0` を指定すれば良いです。

:::note info
以下のような2つのインバウンドルールにしましょう（ソースの指定に注意）
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629296/92751216-da96-8270-0897-597461e04da3.png)

### この節の参考
[AWSのポート解放](https://www.fenet.jp/aws/column/aws-beginner/782/)
[VSCodeのRemote SSH でAWSのEC2に接続する方法](https://confrage.jp/vscode%E3%81%AEremote-ssh%E3%81%A7aws%E3%81%AEec2%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)

## 3. Webアプリケーションを作成し、ポート設定する

本とか買ってお好きなフレームワークでアプリケーションを作りましょう！
急に雑だなと思った方もいらっしゃると思いますが、世界にはたくさんのフレームワークがあって合う合わないとかあると思うんで委ねてます。
アプリケーションを作るという点についてはたくさん本が出ていますしそれを参考にした方が僕のゴミコード読むよりよっぽど参考になると思うので、本とかサイトとかで勉強してください…
Amazon-linux-extra に入っているフレームワークであれば楽にインストールや起動設定などが行えます。
AWSすげ〜定期。興味あったら調べてみてください。

アプリを作るまではいいんですが、__初めて公開するとなると[ここからがマグマなんです。](https://www.youtube.com/watch?v=hezLdsjvCKk) （難しいという意味です）__

走らせたアプリが `localhost:3000` とかにあるパターンが多いと思うのですが、`localhost:3000` を立てるだけではインスタンスのURLにアクセスした際に何も表示されません。
なぜなら `http` のURLにアクセスした際は基本 80 番ポートにアクセスするという世界の掟があるからですね。（役割ごとに決まっているポートを [well-known port](https://e-words.jp/w/%E3%82%A6%E3%82%A7%E3%83%AB%E3%83%8E%E3%82%A6%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88.html) といいます）
インスタンスのURLにアクセスした際にアプリケーションを表示するようにするには Apacheやnginxなどの Webサーバや Docker を使って 80 番ポートへのアクセスと `localhost:3000` を対応付けする必要があります。（[ポートフォワーディング](https://wa3.i-3-i.info/word12664.html)といいます）
ポートフォワーディングのやり方は使うミドルウェアによってやり方が違うので調べてください。今回は nginx を利用してやってみます。

### やってみた

自分は JavaScript教にいつしか入信してしまっていたので今回は Node + nginx で立てることにします！
初めに Node.js のパッケージ管理システムである npm を利用するので、[これ]()を参考にインスタンスに node をインストールしましょう。（自分が手元で実行した時は v18 のインストールはうまくいかず、調べたところ簡単に解消できなさそうだったので v16 をインストールしました。）

:::note info
`ec2-user` として実行する際は権限がないことがあるので、必要に応じて `sudo` をつけたり、ルートユーザーとして実行したりしてなんとかしてください。
:::

すぐトップページが表示できたほうがいいと思うので、Express Generator を利用することにします。次のコマンドを叩いて express-generator をインストールし、プロジェクトを立てて実行しましょう。

```
npm install -g express-generator
express --view=ejs <プロジェクト名>
cd <プロジェクト名>
npm install
npm start
```

これを実行すると サーバの `localhost:3000` にアプリケーションが立ちます。

:::note info
この localhost はサーバ自体を指すので、お手元の pc で `localhost:3000` にアクセスしてもアクセスできないことに注意してください。
:::

続けて nginx をインストールし、localhost を関連づけてから起動することを目指します。
nginx は amazon-linux-extras に含まれているので、利用していきます。
`npm start` をしたターミナルとは別のターミナルを開いて、次のコマンドを実行します。

```
amazon-linux-extras enable nginx1
yum install -y nginx
```

nginx ではポートフォワーディングなどのサーバ周りを .conf ファイルで管理しています。
`/etc/nginx/nginx.conf` がメインとなる conf ファイルなので、このファイルの `server->http` の中に次の通り追記しましょう。

```
server {
    ...
    http {
      ...
      location / {
              proxy_pass http://localhost:3000;
      }
    }
  } 
```

追記したら、nginx を起動しましょう。

```
sudo systemctl start nginx
sudo systemctl status nginx
---- ステータスが表示されます -----
```

これで準備は完了です。インスタンスのパブリックIPアドレスにアクセスすると…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629296/67d77ea2-9802-2a84-3eaa-3013e1a831db.png)

おー

表示されました〜やった〜表示されない場合は・npmとnginx がしっかり起動しているか・パブリックIPアドレスの前の部分が http になっているか・インスタンスのアクセス制限は適切に設定されているかなどを確認してみてください。アプリ作ってないのは勘弁してください…

もし、node アプリケーションを永続化したい場合は node の pm2 というパッケージを利用すれば良いです。また、nginx の永続化には次のコマンドを打ちましょう。

```
sudo systemctl enable nginx
systemctl is-enabled nginx
-----enable と表示されればok-----
```

### この節の参考
[Nginxでリバースプロキシ](https://tex2e.github.io/blog/linux/nginx-reverse-proxy)
[Amazon Linux 2 EC2 インスタンスに Extras Library からソフトウェアをインストールする](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-install-extras-library-software/)

↓はこの記事の完全上位互換です

[AWS EC2 で Node.js(Express) + Nginx アプリケーションのホスティング環境を VPC上に構築する](https://sagara.ink/article/app/302/)

## 4. まとめ

いかがでしたか？（これが言いたかっただけ）たくさんの人が本とかで勉強して Webアプリケーションを作っているかもしれないのに http://localhost:3000 で終わらせるのは勿体無い！と思い、それを公開するまでに注目した記事を書いてみました。参考になったなら幸いです。