[Python]Apache + Gunicorn + hug で簡単APIサーバ
先日、Apacheとmod_wsgiでPythonを動かし、APIサーバを作成してみました。
しかし、hugに備わっているBasic認証を追加することは出来ませんでした。
その後Gunicornを試してみたら、驚くほど簡単に実現できてしまいました。。
最初からこっちにすればよかった。。
前提
Pythonの環境とアプリケーションは前回のものを使います。
import sys,json,os import hug import util from dotenv import load_dotenv dotenv_path = join(dirname(__file__), '.env') load_dotenv(dotenv_path) HUG_USER_NAME = os.environ.get("HUG_USER_NAME") HUG_PASSWORD = os.environ.get("HUG_PASSWORD") authentication = hug.authentication.basic(hug.authentication.verify(HUG_USER_NAME, HUG_PASSWORD)) @hug.get("/hoge",,requires=authentication) def hoge(text): hoge_list = util.getHogeList(text) return json.dumps({"hoge":hoge_list})
前回記述したsys.path.append('/var/www/app')
はなくても今回は正常に動作しました。
また、動作させるアプリケーションは、gunicornを起動する際にパラメータとして渡すので、application = __hug_wsgi__
も不要です。
Gunicornのインストール
pipでインストールします。
$ pip3.6 install gunicorn
これで完了です。
$ cd /var/www/app/ # gunicornの起動 $ gunicorn app:__hug_wsgi__ [2017-09-12 22:54:04 +0000] [3994] [INFO] Starting gunicorn 19.7.1 [2017-09-12 22:54:04 +0000] [3994] [INFO] Listening at: http://127.0.0.1:8000 (3994) [2017-09-12 22:54:04 +0000] [3994] [INFO] Using worker: sync [2017-09-12 22:54:04 +0000] [3997] [INFO] Booting worker with pid: 3997
アプリがポート8000で起動します。
$ curl http://localhost:8000/hoge?text=hoge
結果が帰ってくればOKです。(Basic認証をかけているので認証エラーとなりますが。)
Apacheの設定
次にApacheの設定をします。
/etc/httpd/confd/httpd.conf
に以下の1行を記述し、リクエストをすべてgunicornに流すよう設定します。
ProxyPass / http://localhost:8000/
gunicornを起動した状態で、ブラウザからhttp://192.168.33.10/hoge?text=hoge
にアクセスして認証画面がでて認証できればOK!なのですが、なにやらまた、「Internal Server Error」が。。。
前回とまた同じです。
SELinuxの無効化
Apacheのエラーログを見ると、
[Tue Sep 12 12:03:36.233033 2017] [proxy:error] [pid 5746] (13)Permission denied: AH00957: HTTP: attempt to connect to 127.0.0.1:8000 (localhost) failed [Tue Sep 12 12:03:36.233187 2017] [proxy:error] [pid 5746] AH00959: ap_proxy_connect_backend disabling worker for (localhost) for 60s [Tue Sep 12 12:03:36.233202 2017] [proxy_http:error] [pid 5746] [client 192.168.33.1:62957] AH01114: HTTP: failed to make connection to backend: localhost
proxyがうまくいっていないみたいです。
エラーログを調べてみると色々情報がありました。
SELinuxが原因で、どうやらよくあることらしいです。
こちらを参考にしました。
/var/log/audit/audit.log
を見てみると、たしかに以下のエラーが。
type=AVC msg=audit(1505218092.201:865): avc: denied { name_connect } for pid=5745 comm="httpd" dest=8000 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:soundd_port_t:s0 tclass=tcp_socket
/etc/sysconfig/selinux
を修正して、SELINUX=disabled
とします。
OSを再起動して、再度gunicornを立ち上げると、無事動作しました。
Basic認証も問題なく、きちんと認証できます。
gunicornの自動起動設定
OSを立ち上げたときにApacheは自動起動するよう設定しましたが、gunicornも自動起動するように設定しないとアプリをWebサーバで動作させられません。
ここに記載されているとおりに実行すればOKです。
$ cd /etc/systemd/system/ $ vim app.service
今回gunicornのパスは/bin/gunicorn
で、アプリケーションのディレクトリは/var/www/app
なのでapp.service
の中身は以下のようになりました。
[Unit] Description=gunicorn daemon After=network.target [Service] User=apache Group=apache WorkingDirectory=/var/www/app ExecStart=/bin/gunicorn schedule:__hug_wsgi__ [Install] WantedBy=multi-user.target
自動起動するように設定します。
$ systemctl enable app $ systemctl start app
OSを再起動し、ブラウザからhttp://192.168.33.10/hoge?text=hoge
にアクセスして結果が出ればOKです。
まとめ
前回mod_wsgiでアプリケーションを動作させたよりももっと簡単に実現できました。
また、前回躓いたBasic認証も正常に動作させることが出来ました。
今回はgunicornを運用していこうと思います。