2022年8月10日水曜日

WebARENA Indigo (Ubuntu) で Flask + uWSGI + Nginx を使って Web アプリを作る。【後編】

前編では WebARENA Indigo の設定を行いました。続きです。

Flask + uWSGI + Nginx を使って Web アプリを作っていきます。


▼ Web アプリ作成の下準備


必要なパッケージをインストール。
$ sudo apt update
$ sudo apt install python-is-python3
$ sudo apt install python-pip python3-pip
$ sudo pip install flask
$ sudo pip install uwsgi
$ sudo apt install nginx

ホームディレクトリに app ディレクトリを作成。
$ mkdir app


▼ 常時 SSL 化(HTTPS 化)の下準備


私がドメインを取得している Xserver Domain と Xserver SSL での設定例になります。

Xserver Domain の DNSレコード設定で Web アプリに使うドメインに A レコードを追加(インスタンスの IP アドレス)。

SSL 証明書を Xserver SSL で申し込み。利用環境は他社サーバー。「取得申請」から「DNS認証」(TXT レコードを DNSレコード設定に追加)。

「SSL証明書」と「秘密鍵」をダウンロード。

「SSL証明書」と「秘密鍵」を app ディレクトリに設置。
> scp -P 2222 -i ~/.ssh/private_key.txt ~/Downloads/letsencrypt12345678.crt ユーザー名@IPアドレス:/home/ユーザー名/app/ (SSL証明書)
> scp -P 2222 -i ~/.ssh/private_key.txt ~/Downloads/letsencrypt12345678.key ユーザー名@IPアドレス:/home/ユーザー名/app/ (秘密鍵)


▼ Web アプリの作成


アプリの本体 main.py を app ディレクトリに作成。
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return '<h1>WebARENA Indigo (Ubuntu) で Flask + uWSGI + Nginx を使って Web アプリを作る。</h1>'

if __name__ == "__main__":
    import ssl
    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    ssl_context.load_cert_chain(
        '/home/ユーザー名/app/letsencrypt12345678.crt', '/home/ユーザー名/app/letsencrypt12345678.key'
    )
    app.run(host='0.0.0.0', port=443, ssl_context=ssl_context)
※ ローカルでアプリのテストを行う場合は、10~15行目を「app.run()」に置き換えてください。インスタンス上での確認には curl や wget を使います。


▼ uWSGI の設定


アプリを呼び出す WSGI のエントリポイント wsgi.py を app ディレクトリに作成。
from main import app

if __name__ == '__main__':
    app.run()

uWSGI の設定ファイル app.ini を app ディレクトリに作成。
[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = /tmp/myapp.sock
chmod-socket = 666
vacuum = true

die-on-term = true

wsgi-file = /home/ユーザー名/app/wsgi.py
logto = /home/ユーザー名/app/uwsgi.log
※ sock や log ファイルは自動で作成されます。


▼ Nginx の設定


サーバーブロック構成ファイル myapp.conf を /etc/nginx/sites-available ディレクトリに作成。
server {
    listen 80;
    server_name サーバー名(Web アプリのドメイン);
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    ssl on;
    server_name サーバー名(Web アプリのドメイン);
    ssl_certificate /home/ユーザー名/app/letsencrypt12345678.crt;
    ssl_certificate_key /home/ユーザー名/app/letsencrypt12345678.key;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/myapp.sock;
    }
}
※ HTTP (80番ポート) へのアクセスは HTTPS (443番ポート) にリダイレクトされます。

myapp.conf を /etc/nginx/sites-enabled ディレクトリにリンク。デフォルトの構成ファイルのリンクを削除。
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled
sudo unlink /etc/nginx/sites-enabled/default
※ nginx.conf から読み込まれるのは sites-enabled ディレクトリ内のファイルになります。

セキュリティ上好ましくないので Nginx のバージョンを表示させなくする。
$ sudo nano /etc/nginx/nginx.conf

http {
    ~
    server_tokens off; (コメントアウトを外す)
    ~
}

Nginx を起動。
$ sudo systemctl start nginx


▼ サービス化(デーモン化)

myapp.service を /etc/systemd/system ディレクトリに作成。
[Unit]
Description=uWSGI instance for myapp
After=syslog.target

[Service]
ExecStart=/usr/local/bin/uwsgi --ini /home/ユーザー名/app/app.ini
WorkingDirectory=/home/ユーザー名/app/

User=ユーザー名
Group=www-data
RuntimeDirectory=uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target

myapp を起動。自動起動を有効化。
$ sudo systemctl start myapp
$ sudo systemctl enable myapp




ということで完成です。

uWSGI、Nginx あたりの理解がまだいまいちなのですが、とりあえず動かしながら学習していければと思います。




・関連投稿


Twitter (@nkkmd) 日々更新中です。