LoginSignup
3
4

More than 1 year has passed since last update.

Apache2.4 (Ubuntu) + Python (Flask) + uWSGI で Python アプリを Web サーバで動かす

Last updated at Posted at 2021-08-03

今回はタイトルの通り、Ubuntu20.04 LTS 上で動く Apache2.4 で uWSGI を用いて Python アプリを Web サーバで動かす手順について説明します。
Apache の記事を見ると、CentOS などの RedHat 系の Linux OS の記事はたくさん出てくるのですが Ubuntu でやっているような記事はあまり見当たらず、さらに WSGI の導入に大変苦労したので、記事を執筆しました。

WSGI とは

WSGI とは、Python アプリと Web サーバをつなぐような役割を持ちます。一応 Flask 単体でも Web サーバ上で動かすことは可能ですが、Development 用と明確に記載されているため WSGI を使用する必要があります。詳しい話は uWSGI入門WSGI を使う場合と使わない場合 などの記事を読むと良いでしょう。
有名どころでは mod_wsgi や uWSGI などがありますが、mod_wsgi の開発自体が2016年頃に終了しているせいなのか、自分の設定が悪いのかよくわかりませんが mod_wsgi の導入が上手くいきませんでした。そこで、uWSGI を導入しました。

環境・バージョン等

$ cat /etc/issue
Ubuntu 20.04.3 LTS \n \l
$ apache2 -v
Server version: Apache/2.4.41 (Ubuntu)
Server built:   2021-09-28T11:00:45
$ python --version
Python 3.8.10

導入方法

導入方法を説明します。

uWSGI と Flask をインストール

今回は Flask と uWSGI を用いて行います。pip でインストールしましょう。

$ sudo pip install uwsgi
$ sudo pip install flask

動かす Python プログラムを作成

今回は run.py というプログラムを作成。

run.py
from flask import Flask, jsonify, request
app = Flask(__name__) 

@app.route('/')
def hello():
    text = "Hello World!"
    return jsonify(message = text)

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

これをターミナルで

$ python3 run.py

を実行しましょう。ブラウザで http://localhost:5000/ にアクセスし、画面上に

{"message":"Hello World!"}

と表示されることを確認してください。もしくは、curl コマンドを用いて実行しても構いません。ターミナルをもう一つ開いて curl コマンド

$ curl http://localhost:5000/

と実行して

{"message":"Hello World!"}

というレスポンスが帰ってくるかを試し、Python ファイルがきちんと動いていることを確認してください。

きちんと動いていれば、Ctrl + C などのコマンドで Python プログラムを終了させてください。動かなかった場合は、スペルミスなどを注意してやり直してください。

uWSGIの実行(コマンドで)

以下のようなコマンドを実行してください。module は Python ファイルの名前(今回は run)、callable は Flask のアプリの名前を指定します(今回は app)。仮想環境(virtualenv など)を使用している場合は、仮想環境のある場所を指定してください( --virtualenv=/home/env/ などを付ける)。

$ uwsgi --http=0.0.0.0:8930 --module=run  --callable=app 

これで、先ほどのようにブラウザまたは curl コマンドを用いて

{"message":"Hello World!"}

と表示されているかどうかを確かめてください。

uWSGIの実行(ini ファイルで)

後述するデーモン化(コマンドを入力しなくても Python プログラムが動いている状態にすること)にも関係してくるところなので、ini ファイルでの起動について説明します。一時的なデバッグなら、先述のコマンドで uWSGI を動かせば良いですが、デーモン化するならこちらでやる方がおすすめです。
以下のような ini ファイルを作成します。

uwsgi.ini
[uwsgi]
socket = 127.0.0.1:8930
module = run
callable = app
master = True 
chdir = /var/www/html/
; virtualenv = /home/api_env/env/
; logto = /var/log/uwsgi/uwsgi.log

今回は virtualenvlogto をコメントアウトにしていますが、必要に応じてこれらの設定を変えてください(後述するデーモン化する際はコンソールに uWSGI のログが出力されないのでコメントアウトを外し、$ mkdir /var/log/uwsgi/ でディレクトリを作成、そこにログを収集していくのがいいかもしれません)。
また、chdir も ini ファイルの存在するディレクトリに変更してください。
先ほどと同様に、uWSGI を起動します。

$ uwsgi --ini uwsgi.ini

Web サーバとの連携

localhost 環境ではこのままでOKなのですが、これを Apache などを通して独自ドメインなどで公開する際は Apache の設定が必要です。
まずは、Apache の設定で、ポートフォワードと uWSGI のモジュールを有効化します。/etc/apache2/apache2.conf で以下の2行のコメントアウトを外します。そもそも記述されていない場合は最終行など、適当な場所に書き足してください。

/etc/apache2/apache2.conf
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_uwsgi_module /usr/lib/apache2/modules/mod_proxy_uwsgi.so

http://example.com で公開したい場合、/etc/apache2/sites-available/example.com.conf を編集してパスを通す必要があります。

/etc/apache2/sites-available/example.com.conf
ProxyPass / uwsgi://127.0.0.1:8930/
ProxyPassReverse / uwsgi://127.0.0.1:8930/

http://example.com/ のディレクトリで実行する場合は上記の設定で良いのですが、http://example.com/api/ などのディレクトリで実行する際は、 ProxyPass や ProxyPassReverse を

/etc/apache2/sites-available/example.com.conf
ProxyPass /api/ uwsgi://127.0.0.1:8930/
ProxyPassReverse /api/ uwsgi://127.0.0.1:8930/

としてください。うまく行かない場合は、/etc/apache2/apache2.conf に

/etc/apache2/sites-available/example.com.conf
ProxyPass / uwsgi://127.0.0.1:8930/
ProxyPassReverse / uwsgi://127.0.0.1:8930/

を記述してください。

これらの設定後、再度 uWSGI を実行しながら http://example.com/ にブラウザでアクセスしたり curl コマンドで

{"message":"Hello World!"}

のレスポンスがあることを確認してください。

500 Internal Error の場合

500 エラーが発生している場合は、/var/log/uwsgi/uwsgi.log のログを見て修正してください。

デーモン化

Ubuntu でのデーモン化について、systemdでプロセス自動再起動Systemd Restart = alwaysは受け入れられません などの記事を参考にして行いました。

手順

/etc/systemd/system/ に uwsgi.service ファイルを作成し、以下の内容で書き込みます。

/etc/systemd/system/uwsgi.service
[Unit]
Description = uWSGI
After = syslog.target

[Service]
WorkingDirectory = /var/www/html/
ExecStart = /usr/local/bin/uwsgi --ini /var/www/html/uwsgi.ini
# ここは各自による(後述)
Restart = on-failure
# Restart = always
RestartSec = 3
KillSignal = SIGQUIT
Type = notify
StandardError = syslog
NotifyAccess = all

[Install]
WantedBy = multi-user.target

ExecStart = /usr/local/bin/uwsgi については(仮想環境を実装している場合は、仮想環境をオンにした状態で)$ which uwsgi のコマンドを実行し、表示されたディレクトリを指定してください(私は /usr/local/bin/uwsgi でした)。

また、先述のようにログの出力の指定をしてもいいかもしれません。

[Service]WorkingDirectory はご自身の Python ファイルが格納されている場所にしてください。
Restart は、always にしてしまうと Python プログラムが途中で切れてしまうために on-failure としました。
また Restart 間隔がデフォルトのまま(実行間のデフォルトの遅延は100ミリ秒 = 0.1秒)であると、Restart する回数が多すぎると私の環境では怒られたので、RestartSec = 3 にすることによって間隔を広げています。

これで、デーモンのリロードおよび Apache のリロードを行います。

$ sudo systemctl daemon-reload
$ sudo systemctl restart apache2

デーモンを起動させる時は

$ sudo systemctl start uwsgi

などを実行し、逆にデーモン化を止める場合は

$ sudo systemctl stop uwsgi

などを実行してください。

おわりに

以上の手順で uWSGI を用いて Python プログラムを Web サーバ上で実行することができます。
できない、間違っている場合などがありましたらご指摘お願いします。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4