AWS EC2, Flask, WSGIを使って、ウェブサイトを作ってみる。

<h2>注意</h2>
<p>練習のためにウェブサイトを構築する場合、使い終わったら、EC2インスタンスは停止しておきましょう。</p>
<h2>環境</h2>
<ul>
<li>Windows 10 Home</li>
<li>AWS EC2</li>
<li>ubuntu 22.04</li>
<li>Flask 3.0.0</li>
</ul>
<h2>背景</h2>
<p>今までVPSでウェブアプリをホストしてきたけど、時代はクラウドなので、AWSに挑戦する。</p>
<h2>結論</h2>
<p>AWS EC2を使ってFlaskの動的ウェブサイトをホストしたが、クラウド特有の機能を使わなかったので、もちろん手順はVPSと全く同じだった。つまり、EC2にssh接続をして、GitHubからプロジェクトをcloneして、apache2サーバでルーティングする。</p>
<p>クラウド特有の機能の例としては、拡張性の高いDBを、EC2とは別の場所に設置するRDSというサービスが挙げられる。今回は、クラウド特有の機能を使わずに、EC2で完結する動的ウェブサイトをホストした。</p>

<h2>AWS EC2を使って動的ウェブサイトをホストする</h2>
<h3>動的ウェブサイトとは</h3>
<p>動的ウェブサイトは、APIを介してDBにアクセスするなどして、毎回の表示が一致しないウェブサイトのことである。今回のウェブサイトは、動的ウェブサイトではないが、WSGI, Flaskを使っているため、動的ウェブサイトへの入り口となるだろう。</p>

<h3>EC2にssh接続するまでの手順</h3>
<p>EC2にssh接続するまでの手順として、下記のリンクの動画が分かりやすかったです。</p>
<p>下記のリンクは、app.pyを手動で実行しているので、実行している時のみしか、ウェブサイトにアクセスすることができません。本記事のように、WSGIを使うことで、常にウェブサイトをホストすることができます。</p>

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

<h3>apache2をインストール</h3>
<p>EC2にssh接続してからこれ以降の手順に進みます。</p>
<p>apache2は複数のウェブサイトをホストするサーバです。</p>
<p>下記のコマンドで、apache2をインストールする。</p>
<p>active (running)になっているので、無事にインストールされている。</p>

```WSL2(ubuntu)
$ sudo apt update
...
$ sudo apt install apache2
...
$ sudo systemctl enable apache2
...
$ systemctl status apache2
...
Active: active (running)
...
```

<p>下記のコマンドで、apache2フォルダが作成されていることを確認する。</p>

```WSL2(ubuntu)
$ cd /etc
/etc$ ls -l
...
drwxr-xr-x 8 root root       4096 Oct 20 14:45 apache2
...
```

<h3>apache2の設定ファイルを追加</h3>
<p>新しく作成するウェブサイトのために、apache2に関する設定ファイルを追加します。</p>
<p>下記の設定により、「awsec2test.yourdomainname.com」にアクセスが来た場合、「/var/www/AWSTest/app.wsgi」にルーティングされるようになります。</p>
<p>今回、ドメイン名は「yourdomainname.com」で、サブドメイン名は「awsec2test」となっています。また、プロジェクトフォルダは、「/var/www/AWSTest/」となっています。</p>

```WSL2(ubuntu)
/etc$ cd apache2
/etc/apache2$ ls -l
...
drwxr-xr-x 2 root root  4096 Oct 20 14:45 sites-available
drwxr-xr-x 2 root root  4096 Oct 20 14:45 sites-enabled
...
/etc/apache2$ cd  sites-available
/etc/apache2/sites-available$ ls -l
total 12
-rw-r--r-- 1 root root 1332 May  3 20:02 000-default.conf
-rw-r--r-- 1 root root 6338 May  3 20:02 default-ssl.conf
/etc/apache2/sites-available$ sudo touch awsec2test.yourdomainname.com.conf
/etc/apache2/sites-available$ ls -l
total 12
-rw-r--r-- 1 root root 1332 May  3 20:02 000-default.conf
-rw-r--r-- 1 root root    0 Oct 20 14:55 awsec2test.yourdomainname.com.conf
-rw-r--r-- 1 root root 6338 May  3 20:02 default-ssl.conf
/etc/apache2/sites-available$ sudo nano awsec2test.yourdomainname.com.conf
/etc/apache2/sites-available$ cat awsec2test.yourdomainname.com.conf
<VirtualHost *:80>
    ServerName awsec2test.yourdomainname.com

    WSGIDaemonProcess awstest threads=5
    WSGIScriptAlias / /var/www/AWSTest/app.wsgi

    <Directory /var/www/AWSTest/>
        WSGIProcessGroup awstest
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/awstest_error.log
    CustomLog ${APACHE_LOG_DIR}/awstest_access.log combined
</VirtualHost>
```


<h3>apache2の設定ファイルを有効化</h3>
<p>さきほど作ったapache2の設定ファイルを有効化します。</p>

```ubuntu
/etc/apache2/sites-available$ cd ../
/etc/apache2$ ls -l
...
drwxr-xr-x 2 root root  4096 Oct 20 14:56 sites-available
drwxr-xr-x 2 root root  4096 Oct 20 14:45 sites-enabled
...
/etc/apache2$ cd  sites-enabled
/etc/apache2/sites-enabled$ ls -l
total 0
lrwxrwxrwx 1 root root 35 Oct 20 14:45 000-default.conf -> ../sites-available/000-default.conf
$ sudo a2ensite awsec2test.yourdomainname.com.conf
/etc/apache2/sites-enabled$ ls -l
lrwxrwxrwx 1 root root 35 Oct 20 14:45 000-default.conf -> ../sites-available/000-default.conf
lrwxrwxrwx 1 root root 51 Oct 20 14:57 awsec2test.yourdomainname.com.conf -> ../sites-available/awsec2test.yourdomainname.com.conf
$ sudo systemctl restart apache2
```

<h3>ウェブサイトのプロジェクトフォルダ</h3>
<p>すでに、プロジェクトフォルダがGitHub上に作成されているものとします。</p>
<p>今回は、下記の構成のようになっているウェブサイトが、GitHub上にすでにpushされています。</p>

```AWSTestフォルダの中身
templates
    -index.html
app.py
app.wsgi
```
```app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

if __name__ == "__main__":
    app.run()
```
```app.wsgi
import sys
sys.path.insert(0, '/var/www/AWSTest')

from app import app as application
```

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello AWS</title>
</head>
<body>
    <h1>Hello AWS. Hello Flask with WSGI.</h1>
</body>
</html>
```

<h3>GitHubからEC2にコピーする</h3>
<p>下記のyournameの部分には、あなたのGitHubの名前を入れてください。</p>
<p>下記のAWSTestは、GitHubレポジトリの名前です。名前が異なる場合は、変更してください。</p>

```clone
/var/www$ sudo git clone https://github.com/yourname/AWSTest
...
/var/www$ ls -l
total 8
drwxr-xr-x 4 root root 4096 Oct 20 15:15 AWSTest
drwxr-xr-x 2 root root 4096 Oct 20 14:45 html
```

<h3>WSGIが機能するようにモジュールをインストールする</h3>
<p>libapache2-mod-wsgi-py3をインストールします。</p>

```clone
$ sudo apt-get install libapache2-mod-wsgi-py3
$ sudo systemctl restart apache2
```

<h3>今回使用するPythonモジュール（Flask）をインストールする</h3>
<p>Flaskをインストールします。</p>

```clone
$ sudo apt install python3-pip
...
$ pip3 install flask
...
```


<h3>DNSのAレコードを設定する</h3>
<p>私はXserver VPSからドメインを取得しているので、そこから、新しいAレコードを追加しました。</p>
<p>「XXX.XXX.XXX.XXX」の部分は、AWSのEC2インスタンスのIPアドレスです。</p>
<p>DNSレコードの追加が反映されるのには、少し時間がかかります（5~20分くらいな気がする）。</p>

```clone
awsec2test.yourdomainname.com    A    XXX.XXX.XXX.XXX
```

<h3>成功しているかどうかの確認</h3>
<p>「awsec2test.yourdomainname.com」にアクセスして、ウェブサイトが表示されるかどうかを確認します。</p>
<p>index.htmlに記載した文字列（今回は、「Hello AWS. Hello Flask with WSGI.」という文字列）が表示されていれば成功です。</p>

<h2>今後の展望</h2>
<p>Amazon GameLiftとか使ってみる。AutoScailingとか使ってみる。無限請求には気を付ける。</p>

<h2>参考</h2>
<ul>
<li>https://www.youtube.com/watch?v=AGmkG0wJ8LA</li>
</ul>