3行で
- 自分で作った機械学習モデルを簡単にweb上にAPIとして公開したい。
- flaskを使うとpythonのアプリケーションがwebに公開できる。
- apacheを使う場合、.confにmod_wsgiの設定を書く必要がある。設定例を公開する。
目標
ターミナルから
curl https://example.com/yourapp
の結果として、Contentに
Hello World!!!!
と表示させる
環境
項目 | 使用環境 |
---|---|
クラウドサービス | AWS EC2 |
OS | ubuntu 18.04 LTS |
サーバーソフト | Apache/2.4.29 (Ubuntu) |
認証局 | let's encrypt |
必要な作業
- apacheのインストール
- (オプション)https対応
- mod_wsgiのインストール
- apacheの設定変更
- ディレクトリリスティングの無効化
- ドキュメントルートの設定
- mod_wsgiを読み込む設定
- flaskのインストール
- flaskでアプリ作成
- wsgiファイルの書き換え
全体通しての注意
apacheが思い通りの挙動をしない場合、ログを見ながらトラブルシューティングすることが大事です。
ubuntuの場合デフォルトではログは/var/log/apache2
配下にあります。例えば
tail /var/log/apache2/error.log
でログを確認してください。
apacheが起動しなくなった場合、確認するのはsystemd
のログです。これを確認するには、以下のコマンドが使えます。
journalctl | grep apache2
apacheのインストール、https対応
前に書いた自分の記事を参考にできます。
ubuntu18.04+apacheでhttps対応
mod_wsgiのインストール
注意
flask公式を見ると、apt-get install libapache2-mod-wsgi
でインストールしろという記述がありますが、これをやるとpython2系のmod-wsgiが入ってしまいます。python3系を使いたい場合は避けましょう。
https://flask.palletsprojects.com/en/1.1.x/deploying/mod_wsgi/
apacheでpythonのwebアプリを作るにはmod_wsgiが必要です。
mod_wsgi パッケージは、Python WSGI 仕様をサポートする任意の Python ウェブアプリケーションをホストすることができる、使いやすい Apache モジュールを実装しています。
https://modwsgi.readthedocs.io/en/develop/
(deepl訳)
そこでmod_wsgiをインストールするわけですが、我らpythonの民はソースからビルドすると寿命が減ってしまうので、pipでインストールします。
https://pypi.org/project/mod-wsgi/
ちょっと前置きが長いですが、System Requirementsの項に
If you are running Debian or Ubuntu Linux with Apache 2.4 system packages, regardless of which Apache MPM is being used, you would need both:
apache2
apache2-dev
https://pypi.org/project/mod-wsgi/
とあるので、apache2-devをインストールしてからmod-wsgiをpipでインストールします。
sudo apt install apache2-dev
pip3 install mod-wsgi
動作確認の前にapacheの設定を変更します。
apacheの設定変更
ディレクトリリスティングの無効化
まずはこういうやつが表示されないように設定を変えます。
/etc/apache2/apache2.conf
を見ると
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
のようになっていると思いますが、Options
の項からIndexes
を消します
<Directory /var/www/>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
これでOKです。
参考
Indexes
もし、URL がディレクトリにマップするリクエストであって、 且つ DirectoryIndex で指定したファイル (例えば、index.html) が ディレクトリ内に無ければ、mod_autoindex が ディレクトリ内の一覧を整形して返します。
https://httpd.apache.org/docs/2.4/ja/mod/core.html#options
ドキュメントルートの設定
自分のドメインにアクセスされた際、どのディレクトリをルートディレクトリ(ドキュメントルート)として扱うか設定できます。
デフォルトでは/var/www/html/
になっています。
Apache2 Ubuntu Default Pageとして表示されているものの正体は/var/www/html/index.html
だったわけですね。
この設定は/etc/apache2/apache2.conf
(と、let's encryptのcertbotを使った場合/etc/apache2/sites-available/000-default-le-ssl.conf
)内でできます。例えば/home/ubuntu/apache_docroot
をドキュメントルートにしたい場合は
<Directory /home/ubuntu/apache_docroot>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
を書き加えVirtualHost
ディレクティブ内(certbotを使った場合/etc/apache2/sites-available/000-default-le-ssl.conf
にあります)に下記を加えます
DocumentRoot /home/ubuntu/apache_docroot
デフォルトでDocumentRoot /var/www/html
の記述があるので、どこに書けばいいかはわかると思います。
mod_wsgiを読み込む設定
まず、pipでインストールしたmod_wsgiのインストール先をapacheに教える必要があります。
これは
python -c "import sys; print(sys.path)"
を実行して、表示されるディレクトリのどれかの配下にある.so
ファイルです。
私の環境では以下の場所にありました。
/home/ubuntu/.local/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
これもVirtualHost
ディレクティブ内に書き込みます
LoadModule wsgi_module /home/ubuntu/.local/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
次に、mod_wsgi
の挙動を決める.wsgi
ファイルを作成します。
例として/home/ubuntu/apache_docroot
配下にyourapp
などというディレクトリを作りhello.wsgi
という名前で以下の内容を書いたファイルを保存してください。
def application(environ, start_response):
status = '200 OK'
output = b'Hello World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
VirtualHost
ディレクティブ内にこのhello.wsgi
を読みにかせるようWSGIScriptAlias
という項に記述します。
https://example.com/yourapp というURLを踏んだ際にhello.wsgi
を読みに行かせたい場合、以下のように書きます
WSGIScriptAlias /yourapp /home/ubuntu/apache_docroot/yourapp/hello.wsgi
1つ目の引数は設定したいURLのドキュメントルートからの相対パス、2つ目の引数は.wsgi
ファイルの絶対パスです。
ここまで書き換えて最終的に、VirtualHost
ディレクティブは以下のようになります。
<VirtualHost *:443>
ServerAdmin webmaster@localhost
#DocumentRoot /var/www/html
DocumentRoot /home/ubuntu/apache_docroot
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
#for flask
LoadModule wsgi_module /home/ubuntu/.local/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
WSGIDaemonProcess hello user=ubuntu
WSGIScriptAlias /tegaki_api /home/ubuntu/apache_docroot/tegaki_api/hello.wsgi
ServerName example.com
SSLCertificateFile hogehoge.pem
SSLCertificateKeyFile fugafuga.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
WSGIDaemonProcess hello user=ubuntu
はflaskのhelloという(これから作る)アプリがubuntuという名前のユーザー権限で動作するように書き加えています。
ここまで出来たら、設定を反映させてapacheを再起動すると、.wsgi
ファイルの挙動を確認できます。
コマンドは
cd /etc/apache2/sites-enabled
sudo a2dissite 000-default-le-ssl.conf
cd ../sites-available/
sudo a2ensite 000-default-le-ssl.conf
sudo /etc/init.d/apache2 restart
です。
flaskのインストール
いよいよflaskをインストールします。
これは実に簡単。(仮想環境使わないなら)以下のコマンドだけでできます。
easy_install flask
easy!
flaskでアプリ作成
flask部分を作ります。/home/ubuntu/apache_docroot/yourapp
配下にhello.py
として下記のコードを書いておきます。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return "Hello World!!!!"
if __name__ == '__main__':
app.run()
wsgiファイルの書き換え
URLを踏まれたときの挙動を定義している実体はflaskになったので、.wsgi
ファイルも書き換えます。
import sys
sys.path.insert(0, '/home/ubuntu/apache_docroot/yourapp')
from hello import app as application
前項で作ったhello.py
がインポートできるようにパスを通し、application
という名前でインポートできればOKです。
これでapacheを再起動すれば
curl https://example.com/yourapp
の結果として、Contentに
Hello World!!!!
が表示されます。
参考
Apache2.4セキュリティ「ディレクトリ一覧表示対策」
[Python] mod_wsgiを使ってPython3.6をApacheで動かす(CentOS6系)