LoginSignup
24
15

More than 3 years have passed since last update.

flask+apacheでAPI公開

Last updated at Posted at 2020-05-21

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

必要な作業

  1. apacheのインストール
  2. (オプション)https対応
  3. mod_wsgiのインストール
  4. apacheの設定変更
    1. ディレクトリリスティングの無効化
    2. ドキュメントルートの設定
    3. mod_wsgiを読み込む設定
  5. flaskのインストール
  6. flaskでアプリ作成
  7. 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を見ると

apache2.conf
<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

のようになっていると思いますが、Optionsの項からIndexesを消します

apache2.conf
<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をドキュメントルートにしたい場合は

apache2.conf
<Directory /home/ubuntu/apache_docroot>
        Options FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

を書き加えVirtualHostディレクティブ内(certbotを使った場合/etc/apache2/sites-available/000-default-le-ssl.confにあります)に下記を加えます

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ディレクティブ内に書き込みます

000-default-le-ssl.conf
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という名前で以下の内容を書いたファイルを保存してください。

/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ディレクティブは以下のようになります。

000-default-le-ssl.conf
<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として下記のコードを書いておきます。

/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ファイルも書き換えます。

hello.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系)

24
15
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
24
15