AWS LightsailでFlaskアプリをデプロイする

## はじめに
AWS Lightsailというサービスに触れる機会があったため、ハンズオン形式でデプロイ手順を記事にまとめました。
比較的簡単な手順ですが、備忘録として記録し、これから同様の環境構築を行う方の参考になれば幸いです。

## 最終目標
Lightsailを使ってFlaskアプリをデプロイすること。

## この記事でやること
- AWS Lightsailの設定
- Flaskアプリのデプロイ


## LET'S START
### 前提条件
- AWSアカウントが作成済みで、コンソールにログインできる状態
- Flaskアプリが作成済み（筆者はGitHubでリポジトリを管理しています）
- ドメインを取得済み（任意、なくても問題ありません）


### 1. Lightsailインスタンスの作成
1. AWS Management Consoleにログインし、[Lightsailサービス](https://Lightsail.AWS.amazon.com/ls/webapp/home/instances)に移動
2. 「インスタンスの作成」をクリック
3. 設計図（blueprint）の選択→「OSのみ」を選択
4. OS→「Amazon Linux 2023」を選択
![img1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/188b3c26-abed-4242-06f8-1e1976a62568.png)
5. ネットワークタイプを選択→「デュアルスタック」を選択
6. サイズを選択→「$5」を選択（適宜変更可能）
![img1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/3304d6e5-2e63-964a-54c7-5efc9dae4078.png)
7. Lightsailのインスタンス名を入力
8. インスタンスの作成をクリック
![img1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/67547213-5475-a772-0b51-b84ba69f3daa.png)


### 2. 静的IPの作成（任意）
:::note info
Lightsailインスタンスは、デフォルトでは再起動時にIPアドレスが変わる仕様です。ドメインを使用する場合や安定した接続が必要な場合には、静的IPの作成をお勧めします。
また、DNSの反映時間を考慮すると、インスタンスを作成して真っ先に静的IPを作成しインスタンスにアタッチする方が効率が良いです。
:::

1. 左側のナビゲーションペインで、「ネットワーキング」を選択
2. 「静的IPの作成」をクリック
3. 静的IPを作成するリージョンを選択
4. 作成したインスタンスに静的IPをアタッチ
5. 静的IPの名前を入力
6. 「Create(作成)」をクリック
![img2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/fe75adc7-8191-af05-026f-0269f93bdacb.png)

#### 以降はドメインを取得している場合のみ必要な手順です。
7. ドメインのDNS設定を開く
8. 管理しているドメインの一覧から該当のドメインを選択
9. 「DNSレコード設定」画面でAレコードを設定
   - ホスト名: 空欄または@（ルートドメインの場合）
   - 値: Lightsailで作成した静的IP（例: 123.45.67.89）
   - TTL: 標準設定（通常3600秒）を使用
10. サブドメインの設定（必要に応じて）
    サブドメイン（例: `www.example.com`）もLightsailに関連付ける場合、サブドメイン用に別のAレコードを追加する。


### 3. インスタンスへのSSH接続
LightsailのブラウザベースSSHクライアントを使用します。
1. Lightsailダッシュボードで作成したインスタンスをクリック
![img3-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/83245e18-c1f9-8b89-79b0-09b86c5992b3.png)
2. 「接続」タブを選択し、ブラウザベースのSSHクライアントを起動
![img3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/cec4a6e1-3864-5b7f-bd2f-1ed437ccbbdb.png)


### 4. Flaskなどのパッケージのインストール
1. システムパッケージの更新
    ```bash
    sudo yum update -y
    ```
2. Pythonとpipのインストール\
   Amazon Linux 2023にはデフォルトでPython3がインストールされていますが、バージョンを確認し、pipをインストールします。
    ```bash
    sudo yum install -y python3
    sudo yum install -y python3-pip
    ```
3. Gitのインストール
    ```bash
    sudo yum install -y git
    ```

### 5. GitHubへのSSH接続
1. SSHキーを作成
    ```bash
    mkdir ~/.ssh
    cd ~/.ssh
    ssh-keygen -t rsa
    ```
    → Enterキーを3回押してパスフレーズをスキップ。
2. 公開鍵を確認
    ```bash
    cat id_rsa.pub
    ```
3. GitHubでSSHキーを登録
   1. GitHubにログインし、左上のアカウントのアイコンから「Settings」をクリック
   ![img5-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/39b6dbb9-06b2-1eaa-aa35-92136a4ed2a6.png)
   2. 画面右端のサイドメニューから「SSH and GPG keys」をクリック
   3. 「New SSH key」をクリック
   ![img5-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/e1b91047-1891-a129-293c-71132c8d263e.png)
   4. 表示されたAdd new SSH Keyのタブから「Title」と「Key」を入力し「Add SSH key」をクリック
   ![img5-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721815/a970f51f-b31c-5e34-fe42-bc3f2f4530ec.png)
4. GitHub疎通確認
   ```bash
   ssh -T git@github.com
   ```


### 6. Flaskアプリの配置・パッケージのインストール
1. アプリを配置する場所に移動
   ```bash
   cd ~
   ```
2. リポジトリをクローン
   ```bash
   git clone git@github.com:Ymmy833y/flask-sample.git # 適宜修正してください
   cd flask-sample # 適宜修正してください
   ```

#### 以降は各環境によって異なります。
筆者は仮想環境を使って依存関係を管理していたので、venv作成→依存関係のインストールを行います。

3. 仮想環境の作成・起動
    ```bash
    python3 -m venv venv
    source venv/bin/activate
    ```
4. 依存関係のインストール
   ```bash
   pip install -r requirements.txt
   ```

:::note warn
注意事項
この後、Flaskアプリをプロダクション環境で稼働させるにあたり、Gunicornを使用します。
Gunicornが依存関係に含まれていない場合、下記コマンドを用いてGunicornをインストールしてください。
```bash
pip3 install gunicorn
```
:::


### 7. GunicornとSystemdの設定
1. GNU nanoを使用してサービスファイルを作成
   ```bash
   sudo nano /etc/systemd/system/flask-sample.service # ファイル名は適宜修正してください
   ```
2. 下記内容を記述（`Description`、`WorkingDirectory`、`ExecStart` については適宜修正してください）
    ```ini
    [Unit]
    Description=Gunicorn instance to serve Flask app (flask-sample)
    After=network.target

    [Service]
    User=ec2-user
    Group=ec2-user
    WorkingDirectory=/home/ec2-user/flask-sample
    ExecStart=/bin/bash -c 'source /home/ec2-user/flask-sample/venv/bin/activate && exec gunicorn -w 3 -b 0.0.0.0:5000 run:app'

    [Install]
    WantedBy=multi-user.target
    ```
3. サービスを有効化して起動
   ```bash
   sudo systemctl daemon-reload
   sudo systemctl enable flask-sample
   sudo systemctl start flask-sample
   ```
4. サービスのステータス確認
   ```bash
   sudo systemctl status Flask-sample
   ```
   `Active (running)`と表示されていれば成功です


### 8. Nginxの設定
Nginxを使用してFlaskアプリをリバースプロキシとして設定します。
1. GNU nanoを使用してNginxの設定ファイルを作成
    ```bash
    sudo nano /etc/nginx/conf.d/flask-sample.conf
    ```
2. 下記内容を記述（`server_name`、`root` については適宜修正してください）
    ```nginx
    server {
        listen 80;
        server_name your-domain.jp www.your-domain.jp;

        # Flaskアプリケーションの静的ファイルのルートディレクトリ
        root /home/ec2-user/flask-sample;

        location / {
            proxy_pass http://127.0.0.1:5000;  # Flaskアプリケーションが動作するポート
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_buffer_size 128k;
            proxy_buffers 4 256k;
            proxy_busy_buffers_size 256k;
        }
    }
    ```
3. 設定の適用
   設定ファイルを保存後、Nginxの設定をテストして適用します
    ```bash
    sudo nginx -t
    sudo systemctl reload nginx
    ```

### 9. 動作確認
- 静的IPまたはドメインでアプリにアクセス
- DNS設定が反映されているか確認するには、[WhatsMyDNS](https://www.whatsmydns.net/) を使用

## さいごに
SSL証明書の設定についても触れたかったのですが、ボリューミーになるため今回は割愛します。なお、設定する際は [Let's Encrypt](https://letsencrypt.org/) を使用する方法をおすすめします。

この記事がAWS LightsailでのFlaskアプリのデプロイに役立てば幸いです。