はじめに
これは AWS(Amazon Web Service)へFlaskアプリをデプロイするための手順書です。
- Herokuは30分間アプリへのアクセスが無いとスリープ状態になり、再起動に数10秒かかりますが、AWSではそのような問題がありません。
- SocketIOを使ったチャット機能などはHerokuでは動作しません(回避策は未調査)が、AWSでは動作が確認されています。ただし動作確認できているのはuWSGI経由の場合のみ。Nginx経由での動作は調査中。
- アカウント登録後1年間は、月間750時間の 無料利用枠 があるので24時間の連続稼働が可能です。
- アカウント登録にはクレジットカードが必要です。
- 【参考】AWS以外のVPSの利用
AWS以外のVPSの利用も選択肢として可能性があります。例えば Conoha の場合、使用時間だけ課金されるプランがあり、テスト目的で数日使用するだけなら数10~100円で済みます。デプロイ手順はAWS特有の部分を除けば、Ubuntuの設定そのものは同じです。
AWSのアカウント登録
- アカウントを作成する
AWSサイト でアカウントを作成してください。詳細な操作手順は ここ にあります。かなり厳密に個人情報を聞かれます。住所を英語で入力しなければならなかったり、慣れてないと手ごわいので落ち着いて進めてください。
サポートプランは [ベーシックプラン(無料)] を選んでください。(無料)と書いてありますが、無料枠の条件を超えると課金されますので注意が必要です。無料枠での使用でもクレジットカードを登録しなければなりません。
- AWSへログイン
AWSのサイト の [アカウント]→[AWSマネージメントコンソール] から、ルートユーザーとしてサインインすると、[AWSマネージメントコンソール] の画面になります。
画面上部のリージョンが [東京] になっていることを確認してください。なっていなければ [東京] を選択してください。
- 【重要】課金管理
画面上部のアカウント名から、プルダウンメニュー → [マイ請求ダッシュボード] を時々確認することを忘れないでください。無料枠に収まっていれば「$0.00」と表示されるはずです。月間750時間の無料枠は累計なので、EC2インスタンスを複数起動すると超過の恐れがあります。定期的に請求額を確認することを強く推奨します。
サーバー(EC2インスタンス)を起動する
- [AWSマネージメントコンソール] の [サービスを検索する] からEC2を探してEC2ダッシュボードに入ります。
- 画面左側のメニューから [キーペア] を選択します。キーペア名を適当に入力します。キーペアはリージョンに依存するので、混乱を避けるために名前に “Tokyo” を含めると良いでしょう。例えば AWS-Keypair-Tokyo など。ファイル形式は pem を指定して「キーペアを作成」し、パソコン内の分かりやすいフォルダに保存してください。このファイルで認証してサーバーにログインするので厳重に管理するよう心掛けてください。
- [インスタンスを起動] を選ぶ。
- ステップ1:Amazonマシンイメージ(AMI)から [Ubuntu Server 20.04 LTS~] と表示されたもので、[64ビット(x86)] をチェックして選択する。このとき [無料利用枠の対象] と表示されていることを確認すること。
- ステップ2:インスタンスタイプの中から、t2.micro を選ぶ。このとき [無料利用枠の対象] と表示されていることを確認すること。
- [確認と作成] をクリック、続いて [起動] をクリック。
- キーペアを聞かれるので、保存したキーペアを指定する。
- 確認事項をチェックして [インスタンスの作成] をクリック。
- [インスタンスの表示] をクリック。ステータスチェックの欄に [初期化しています] と表示され、しばらくすると表示が変化する。「2/2のチェックに合格しました」のような表示に変化したら準備完了である。
- アクセス許可するポートの設定
インスタンスの一覧(最初は1個だけ)から [インスタンスID] の項目をクリックするとそのインスタンスの概要が表示される。画面下半分のタブから [セキュリティ] を選ぶ。さらに [セキュリティグループ] のリンクをクリックする。ここでファイヤーウォールの設定を行う。[インバウンドルール] のタブで、[インバウンドルールを編集] をクリックする。[ルールを追加] をクリックして、下記の各ルールをひとつずつ追加していく。
・タイプ=SSHはデフォルトで設定されているはずなのでそのままにする。
・タイプ=HTTP、ソース=任意の場所 (HTTPアクセスが予想されるので)
・タイプ=HTTPS、ソース=任意の場所 (HTTPアクセスが予想されるので。SSL認証しない場合は不要)
・タイプ=カスタムTCP、ポート範囲=5000、ソース=任意の場所 (Flaskアプリが5000番を使用するので。Flaskでポート8000番を使う場合は8000を指定)
[ルールを保存」をクリック。
- EC2ダッシュボードで [実行中のインスタンス] が1個だけで、その [インスタンスタイプ] が [t2.micro] であることを確認する。そうでない場合はインスタンスの管理を見直さないと課金される恐れがある。使用しないインスタンスは「停止」しておくと良い。「終了」してしまうとインスタンスが削除されるので注意。
- インスタンスの一覧から、[パブリックIPv4アドレス] の情報を参照して覚えておく。
- AWSの設定は以上なのでサインアウトする。
ターミナルソフト
サーバー(EC2インスタンス)の操作にはターミナルソフトが必要です。SSH接続できるツールなら何でも構いません。Macならターミナルを使います。VSCode のターミナル機能からSSHログインすることも可能です。WSL からも可能です。
ターミナルソフトを起動したら次のコマンドを実行してください。
1 |
$ ssh ユーザー名@ホスト名 |
・ホスト名は、EC2のインスタンスの「パブリック IPv4(DNS)」
・ログインユーザー名は”ubuntu”
パスワードをタイプするとEC2にログインできます。
Ubuntuの一般的な環境設定
WSLの説明 でやったように、Ubuntuの一般的な環境を設定する。WSLをインストールする の後半($ sudo apt update 移行の手順)を参照してください。ユーザー名は「ubuntu」が登録済なのでそのまま使ってください。
ファイルをアップロードして動作確認
- FlaskでHello World! を参考に、ローカル環境でFlaskアプリを作成して動作確認してください。アプリの名前を myproject、Python環境名を myprojectenv として説明を続けます。
- [ファイル]>[SFTPファイルの転送]を起動して、
ローカルでテスト済みのプログラムをEC2に転送します。このとき、環境が保存されたフォルダ myprojectenv はEC2上で作り直しますので転送する必要ありません。Gitの管理フォルダ .git がもしあれば、それも転送する必要ありません。 - アプリの動作を確認する
1 2 3 4 5 6 7 |
$ sudo apt install python3-pip $ sudo apt install virtualenv $ cd ~/myproject (アプリのディレクトリに移動) $ virtualenv myprojectenv $ source myprojectenv/bin/activate (仮想環境を有効化) $ pip3 install -r requirements.txt (必要なライブラリをインストール) $ python3 myproject.py |
この段階ではエラーが発生していないことだけ確認してください。まだWEBアプリとしては動作しません。いったん Ctrl+C をタイプしてアプリを止めます。
- uWSGI経由での動作を確認
AWS上でWEBアプリとして動作させるためにはuWSGIを使います。wsgi.pyを作成します。 (ファイル名に注意。uwsgi.pyではない。)
1 2 3 4 5 |
# -*- coding: utf-8 -*- from myproject import app if __name__ == "__main__": app.run() |
uWSGIをインストールして、uWSGI経由でFlaskアプリを動作させる。
1 2 |
$ pip3 install uwsgi $ uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app |
http://(パブリック IPv4(DNS)):5000 にアクセスして動作を確認。(ポート番号はアプリで5000以外を設定しているならその数字)
1 |
http://ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com:5000/ (アドレスはそれぞれ違います) |
この状態では、Ctrl+C でアプリを止めたり、AWSからログアウトするとFlaskアプリも停止します。
- アプリを止めて、仮想環境から抜ける
1 |
$ deactivate |
ここからはUbuntuのシステム環境で操作します。
HTTPサーバーの設定
以上の手順でAWS上でFlaskアプリが動作したと思いますが、これはあくまでテスト的な環境です。アプリを終了すればブラウザでアクセスしても反応してくれません。常にアプリが反応するようにするにはAWS上でHTTPサーバーを動作させなければなりません。手順については、flask を uWSGI と Nginx でデプロイする、写経「flask を uWSGI と Nginx でデプロイする」 を参考にさせていただきました。
- Nginxをインストールする
1 |
$ sudo apt install nginx |
- ソケットのディレクトリを作成
Nginx と uWSGI の間をソケットで繋いで動作させます。そのためのディレクトリを /var/run に作ります。(多くの事例では /tmp に作っていますが、それでは動作しないので /var/run に実装しました)/var/run/myproject のディレクトリを作成して、権限を777に設定します。
1 2 |
$ sudo mkdir /var/run/myproject $ sudo chmod 777 /var/run/myproject |
- myproject.iniをアプリのフォルダ ~/myproject の中に作成します。
1 2 3 4 5 6 7 8 9 10 11 |
[uwsgi] module = wsgi:app master = true processes = 5 socket = /var/run/myproject/myproject.sock chmod-socket = 666 vacuum = true die-on-term = true |
- /etc/systemd/system/myproject.service のファイルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[Unit] Description=uWSGI instance to serve myproject After=network.target [Service] User=ubuntu ←ユーザー名 Group=users ←グループ名 WorkingDirectory=/home/ubuntu/myproject ←アプリの場所 Environment="PATH=/home/ubuntu/myproject/myprojectenv/bin" ←環境ファイルの中を指定 ExecStart=/home/ubuntu/myproject/myprojectenv/bin/uwsgi --ini myproject.ini ←環境の中のuwsgiを指定 [Install] WantedBy=multi-user.target |
WEBアプリに複数の環境変数を設定したい場合は、Environment の代わりに EnvironmentFile が使って、環境変数は別ファイルに書く方法もあります。
1 |
EnvironmentFile=/etc/systemd/system/myproject.env |
/etc/systemd/system/myproject.env
1 2 |
PATH=/home/ubuntu/myproject/myprojectenv/bin FLASK_ENV="TEST" |
- サービスを起動
1 2 3 |
$ sudo systemctl start myproject $ sudo systemctl enable myproject ←自動起動を有効にする $ sudo systemctl status app で状態を確認する |
※エラーが出ていれば再起動する
1 2 3 4 |
$ sudo systemctl daemon-reload $ sudo systemctl stop myproject $ sudo systemctl start myproject $ sudo systemctl status myproject |
- /etc/nginx/sites-available/myproject のファイルを作成します。
1 2 3 4 5 6 7 8 |
server { listen 80; location / { include uwsgi_params; uwsgi_pass unix:/var/run/myproject/myproject.sock; } } |
- Nginxの設定と確認
1 2 3 |
$ sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled $ sudo rm -f /etc/nginx/sites-enabled/default $ sudo nginx -t |
- Nginxを再起動する。もしエラーが出ていたら設定を修正してNginxを再起動する。
1 2 |
$ sudo systemctl restart nginx (再起動だけ) $ sudo systemctl reload nginx (設定ファイルを読み直して再起動) |
- テスト
http://(IPアドレス)にアクセスして動作を確認する。ポート番号が無くても動作するはずです。
1 |
http://ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com/ (アドレスはそれぞれ違います) |
502 Bad Gateway と出る場合は設定を見直してください。コマンド journalctl -xe でシステムログを確認すると原因がわかるかもしれません。
コメント