【AWS】Amazon EC2 を利用した Web サーバーを構築してみた

# はじめに
これは「imtakalab Advent Calendar 2023」の 23 日目の記事です。

https://adventar.org/calendars/9285

こんにちは :tada: そこらへんにいる私立理系大学の学部 4 年生です :bomb: 

# 背景
自分が所属している研究室では Web アンケート作成ツールの [Qualtrics](https://www.qualtrics.com/jp/lp/qualtrics-watch-demo/?utm_source=google&utm_medium=ppc&utm_campaign=JP-Brand-EXACT-RLSA&campaignid=1697490378&utm_content=brandpure--general&adgroupid=65745153066&utm_term=%E3%82%AF%E3%82%A2%E3%83%AB%E3%83%88%E3%83%AA%E3%82%AF%E3%82%B9%20%E4%BD%BF%E3%81%84%E6%96%B9|e&utm_keyword=%E3%82%AF%E3%82%A2%E3%83%AB%E3%83%88%E3%83%AA%E3%82%AF%E3%82%B9%20%E4%BD%BF%E3%81%84%E6%96%B9|e&device=c&placement=&network=g&creative=629756478920&gad_source=1&gclid=Cj0KCQiAm4WsBhCiARIsAEJIEzVyMkkGYUB6Y08KCFkBYLnkIyp8CqS_Q77MX759VozMUAKWrGRp18AaAulUEALw_wcB0) が研究によく使われています。
とても便利ですよね〜使ったことはないですが。（アンチとかではない :bomb: ） 

しかし、Qualtrics はとても使いやすく柔軟に表現可能ですが、自分が納得のいくようないい感じに実験ページを組めないことがあると思います。
その際には自分で実験ページの Web サイトを作成してしまえばいいのです。

たまたま研究開発でお手伝いする機会があったので備忘録がてら、記事にしたいと思います〜

# この記事でやること
AWS (Amazon Web Services) で EC2 (Elastic Compute Cloud) を利用して仮想環境にサーバーを立てて、簡単な Web ページをデプロイするところまでやっていきたいと思います。

AWS では 12 ヶ月間無料で利用することができるので今回はその枠をありがたく使用したいと思います〜

https://aws.amazon.com/jp/free/?gclid=Cj0KCQiAm4WsBhCiARIsAEJIEzUssGiI1T2imv8g9EpFYYzsvK34POASxCspDuFIT1d5rCtaP5qR8qQaAoSbEALw_wcB&trk=94c18984-27d1-4395-8dae-cdbf523f1ae5&sc_channel=ps&ef_id=Cj0KCQiAm4WsBhCiARIsAEJIEzUssGiI1T2imv8g9EpFYYzsvK34POASxCspDuFIT1d5rCtaP5qR8qQaAoSbEALw_wcB:G:s&s_kwcid=AL!4422!3!568105078079!e!!g!!aws&all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all

:::note warn
サーバーを停止を忘れたり、IP アドレスを固定したのにサーバーをずっと停止していたりすると課金対象になります！
:::

## そもそも AWS とは？
AWS (Amazon Web Services) とは Amazon が提供しているクラウドサービスのことです :cloud:
どんなことができるのかについては下の記事を書いた方がまとめているので気になる方は見てみてください！
(料金については変動している可能性があります。)

https://qiita.com/kohashi/items/1bb952313fb695f12577


## EC2 の構築イメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/e4b4e588-7a30-7acf-a65c-c8e32c2d0665.png)

# 流れ
この動画がとてもわかりやすかったので、参考にさせていただきます。

https://www.youtube.com/watch?v=AGmkG0wJ8LA

以下の流れで進めていきます
1. AWS アカウントの作成
1. キーペアの作成 ( PC ↔️ AWSサーバー)
1. インスタンス (EC2 から立てられるサーバー) の作成・起動
1. 作成した仮想サーバーに SSH でアクセスする
1. インスタンスの停止・終了

### 番外編
- IP アドレスの固定化
- サーバーのデーモン化

## 1. AWS アカウントの作成
AWSを使用するにはやはりアカウントが必要なので、AWS アカウントを持っていない方は作成してください。

https://aws.amazon.com/jp/free/?gclid=Cj0KCQiAm4WsBhCiARIsAEJIEzUssGiI1T2imv8g9EpFYYzsvK34POASxCspDuFIT1d5rCtaP5qR8qQaAoSbEALw_wcB&trk=94c18984-27d1-4395-8dae-cdbf523f1ae5&sc_channel=ps&ef_id=Cj0KCQiAm4WsBhCiARIsAEJIEzUssGiI1T2imv8g9EpFYYzsvK34POASxCspDuFIT1d5rCtaP5qR8qQaAoSbEALw_wcB:G:s&s_kwcid=AL!4422!3!568105078079!e!!g!!aws&all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all
## 2. キーペアの作成 ( PC ↔️ AWSサーバー)
次に、AWS上に立てるコンピュータにアクセスするために必要な公開鍵と秘密鍵を作成します。
- 左上の「サービス」＞「コンピューティング」＞ 「EC2」 ＞「キーペア」 へ進み、
右上の「キーペアを作成」を選択します。
- 作成するコンピュータの名前やキーペアのタイプなどの選択が終わったら「キーペアを作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/bcf14a4b-362d-dc59-a269-79944a175680.png)

`aws_test_key` がダウンロードされるのでお使いのPCの以下の場所に `aws_test_key` を移動してください。

```
# Mac
$ /Users/<ユーザー名>/.ssh
# Windows
$ C:¥Users¥<ユーザー名>¥.ssh
```

## 3. インスタンス (EC2 から立てられるサーバー) の作成・起動
次に、サーバーを立てていきたいと思います。

> インスタンス：AWS クラウド上で実行される仮想マシン

左上の「EC2 ダッシュボード」＞「インスタンスを起動」を選択します。
ここで、作成するインスタンスの名前や OS イメージ等を設定します。



Key pair (login) のところで先ほど作成したキーペアを選択します。
そして、その下のネットワーク設定のところの以下の二つを選択
- インターネットからの HTTPS トラフィックを許可
- インターネットからの HTTP トラフィックを許可]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/a96aa779-8ec4-8b25-445b-529514288d98.png)


今回はストレージ数などはデフォルトのままで行います。

そして最後に右下の「インスタンスを起動」を選択します。

右下の「全てのインスタンスを表示」を選択すると自分が作成したインスタンスの一覧を見ることができます。

:::note warn
いま作成したインスタンスは実行中となり課金し続けるため、使っていないのに放置しているということがないように注意してください
:::

## 4. 作成した仮想サーバーに SSH でアクセスする
:::note alert
AWSの無料枠では、規模が大きいと仮想サーバーを VS Code で起動すると負荷がかかりすぎて、SSH 接続タイムアウトになりやすくなって、`インスタンスを停止` -> `インスタンスを開始` を行う手間が増えますので、その場合は terminal 等で操作することを強くお勧めします
:::

インスタンス ID を選択すると詳細情報を見ることができます。
「接続」＞「SSH クライアント」へ進み、SSH で作成した仮想サーバーにアクセスしていきたいと思います。

```terminal
$ ssh -i <秘密鍵のファイルパス> ユーザ名@ホスト名
```

ホスト名が反映されたものが例として下に用意されているので、これをコピペして、秘密鍵のパスを変更するだけで OK です。
これを実行すると AWS 上の自分が作成した仮想サーバーにアクセスすることができます。

初期状態では Python3 は入っていますが、Python は入っていません。
なので、以下を実行することで Python でも動くようになります。

```terminal
$ sudo apt install python-is-python3
```

### VS Code を使ってアクセスする
ターミナル等で ssh 接続すると作業効率がとても悪いです。
そこで VS Code の拡張機能の「Remote-SSH」をインストールして、VS Code 上でも作業できるようにしていきます。

左下の「＞＜」のようなアイコンまたは左のバーにあるスクリーンのアイコンから ssh 接続することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/de72c550-892a-b0d8-3601-57af96f88ccb.png)


> 左下の「＞＜」からの場合

アイコンを選択＞「ホストに接続する」＞「新規 SSH ホストを追加する」を選択して SSH 接続コマンドを入力

> 左のバーにあるスクリーンのアイコンからの場合

SSH フォルダの「＋」を選択し、SSH 接続コマンドを入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/61d1495d-f44d-5129-b1e6-935ed404ff50.png)

そして、SSH 接続コマンドを入力したら以下を選択します。
```
自分のユーザ名/.ssh/config
```
そして、先ほど作ったインスタンスのホスト名が表示されているのでそのウィンドウを選択すると VS Code 上で SSH 接続することができます。

### 簡易的な Web ページをデプロイする
作成した仮想サーバー上で簡易的な Flask で Webページを作成していきます。

まず pip が入っていないのでインストールします。
```terminal
$ sudo apt update
$ sudo apt install python3-pip
```

次に flask をインストールします。

```terminal
$ pip install flask
```
https://www.youtube.com/watch?v=AGmkG0wJ8LA

この動画と同じようにお試し用のWebページを作成します。
ソースコードは [こちら](https://github.com/iitz-i13/flaskr) 

そして、flaskr と同じ階層にいる状態で以下のコードを実行

```terminal
$ sudo flask --app flaskr run --port 80 --host 0.0.0.0
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/3cbe2629-d381-5abc-5693-d025ddde6caa.png)

:::note alert
上の画像のまるで囲ったところにアクセスしても Web ページは表示されません 
:::

:::note 
AWS のインスタンス詳細画面に行き、`パブリック IPv4 アドレス` にアクセスする必要があります
`http://<パブリック IPv4 アドレス>`
:::

この URL にアクセスすることでちゃんと表示されます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/3ba02ef6-0d6a-4cca-0f16-66e461d858db.png)



## 5. インスタンスの停止・終了
最後にインスタンスの停止・終了についてです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/ae315f58-69bf-cead-e207-7b3094724669.png)

インスタンスの画面にある、操作したいインスタンスを選択し、
> 「インスタンスの状態」＞「インスタンスの停止」

を選択することで、選択したインスタンスを停止させることができます。
もうこのインスタンスは使用しないなーっていうようなインスタンスは
> 「インスタンスの状態」＞「インスタンスの終了」

を選択することで終了することができます。
（再び起動したい場合は「インスタンスを開始」を選択）

:::note warn
ホスト名や IP アドレスは起動するたびに変更されます
(ElasticIP で固定することも可能)
:::


## 番外編
### IP アドレスの固定化
インスタンスを停止して再度開始すると IP アドレスやホスト名が新たに割り振られるため、アクセスするのに毎回設定し直すことは面倒くさいです。そこで、ElasticIP を作成することで割り振られる IP アドレスを固定化することができます。

1. ElasticIP の作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/739abf2e-9b42-f2d2-99d1-2fd333edc023.png)

1. ElasticIP と EC2 インスタンスを関連付ける


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3657116/3c3421ae-b76d-d6fb-b203-44fd7ae104da.png)

これで、インスタンスを停止して再度開始しても IP アドレスが不変になります！

:::note
ElasticIP を作成して関連付けているインスタンスを起動しているときはお金は請求されない
:::
:::note warn
ElasticIP を作成して関連付けているインスタンスを起動していないときは微小に課金対象になるので注意
また、無料枠の ElasticIP は 12 ヶ月間で 1 時間のみ
:::
たしか、0.005ドル / 1h とか？間違えていたらすみません。

https://repost.aws/ja/knowledge-center/elastic-ip-charges

### サーバーのデーモン化
自分は Django, gunicorn, Nginx の構成で行いました。
ファイルを設定する必要があるので以下の記事を参考にやってみてください。
その際に、仮想サーバーと Git アカウントを接続しておくと作業がさらにしやすくなります。

https://qiita.com/youyonghua/items/5d7fb4c2a460eae4f2c0

https://qiita.com/RNakao/items/4cf55572d70714c86ff9#5-nginx%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B

https://qiita.com/ekzemplaro/items/356d1673d0eee7970479

https://qiita.com/CK_BLUE/items/b7d4cf1810de66fcbf49

https://zenn.dev/century/articles/6b7d6ad29605f8

#### デーモン化で起動
```terminal
$ gunicorn project_name.wsgi:application --daemon --bind=0.0.0.0:8000
```
また、gunicornとnginxに関する設定ファイルの変更をした場合
```terminal
$ sudo systemctl restart gunicorn
$ sudo systemctl restart nginx
```

# おわりに
いかがでしたでしょうか？


思ったより記事を書くのが楽しくなってしまい、気分が高揚してしまいました。
アウトプットするいい機会となったので、タイミングがあれば記事を投稿したいと思います〜
最後まで見ていただき、ありがとうございました！ :bomb::collision:


# 参考
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/concepts.html

https://www.youtube.com/watch?v=AGmkG0wJ8LA