nginx + uWSGI + Flaskを試してみる

nginxという軽量Webサーバの話を最近よく耳にするので、とりあえず試してみますヨ

とりあえずnginx上でFlaskアプリを動かすのを最終目標にゴニョゴニョしてみますデス

まずnginxをインストール

まずはnginx本体のインストールをしてみますよ→nginx

ここを参考に作業したらあっさり動きました。

とりあえず手順を羅列していきます

# 最新版の0.8.54をダウンロード
$ wget http://sysoev.ru/nginx/nginx-0.8.54.tar.gz

# nginx実行ユーザを作成
sudo useradd -s /sbin/nologin -d /usr/local/nginx -M nginx

コンパイルオプションが豊富なのでスクリプト形式で保存しておきます
# 参考サイトのものを参考に作成しました

#!/bin/sh
 
NGINX=nginx-0.8.54
 
# インストール先は /usr/local/nginx
cd $NGINX \
# 初回コンパイル時にはエラーになるのでコメントアウト
# 一度makeしたあとだとOK
#&& make clean \
#&& ./configure \
./configure \
  --conf-path=/etc/nginx/nginx.conf \
  --error-log-path=/var/log/nginx/error.log \
  --pid-path=/var/run/nginx/nginx.pid  \
  --lock-path=/var/lock/nginx.lock \
  --user=nginx \
  --group=nginx \
  --with-http_stub_status_module \
  --with-http_ssl_module \
  --with-http_gzip_static_module \
  --with-http_realip_module \
  --http-log-path=/var/log/nginx/access.log \
  --http-client-body-temp-path=/var/tmp/nginx/client/ \
  --http-proxy-temp-path=/var/tmp/nginx/proxy/ \
  --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
&& make

上記スクリプトでmakeまでしたらインストールしますよ

# インストール
sudo make install

# nginxが使用する各種ディレクトリを用意
sudo mkdir /var/tmp/nginx/{proxy,client,fcgi}

とりあえずお試し実行してみます

# サーバ起動コマンド
sudo /usr/local/nginx/sbin/nginx
 
# サーバ終了コマンド
sudo /usr/local/nginx/sbin/nginx -s quit

"Welcome to nginx!"という文字がブラウザに表示されればOKです(`・ω・´)

Flask動かす茨の道

とりあえずnginxがあっさり動くようになったので、これ幸いとFlaskを動かす設定をしてみます…が、なかなか上手く動かず四苦八苦するはめに…

とりあえず羅列するとこんな感じ
  • nginx用mod_wsgiがある(゚∀゚)
    • 0.8系ではmod_wsgiを組み込んだnginxコンパイルが通らない
    • 0.7系でもmod_wsgiを組み込んだnginxコンパイルが通らない
      • そもそもmod_wsgi内で呼び出されている関数が違うとか…云々
  • FastCGI...はとりあえず置いとこう…いや、なんとなく
  • 最近出てきたuWSGIとやらを試してみる
    • 0.8系ではコンパイルエラーに…
    • 0.7系では…なんとか動いた!_|\○_ヒャッ ε=\_○ノ ホーウ!!
uWSGIを採用シマス

...というわけでnginx + uWSGI + Flaskという構成で動かしてみることに

# 今になってnginx用mod_wsgiにパッチがあることを発見…あとで試しマス

uWSGIの導入

そんなわけでuWSGIを導入しますデス

uWSGIはWSGIアプリケーションのアプリケーションコンテナとして動作するらしく、そのフロントエンドとしてnginxが動作するイメージですネ

適当に図式化するとこんな感じですかね

[各種HTTPクライアント]
  ↓ HTTPでの問い合わせ
[nginx]:HTTPの通信を(80番とかで)受け付けて、uWSGIに処理をぶん投げ
  ↓ 実際のアプリケーション要求を中継
[uWSGI]:適当なポート番号で待ち受けて、要求された処理を実行
    
Apacheモジュールなんかとは違ってnginxにuWSGIを組み込むのではなく、各々が独立して動作しつつも連携するイメージが近いみたいです

# このイメージが最初出来なくて、イマイチ設定方法に戸惑ってました
# まあ、このイメージで合ってるのかというのも疑問が残りますが:(;゙゚'ω゚'):

とりあえず、まあインストール

インストール自体はこちらを参考におこないました。なお、nginxは0.7.68にダウングレードしております。

# ソースをゲットします
$wget http://projects.unbit.it/downloads/uwsgi-0.9.6.8.tar.gz

# 解凍してmakeしてバイナリを作成します
$ tar zxvf uwsgi-0.9.6.8.tar.gz
$ cd uwsgi-0.9.6.8
$ make

必要なディレクトリを用意します

mkdir tmp/ sock/ pid/ log/

とりあえず動かしてみますよ

# TCP:10000番で待ち受けるように起動
$  ./uwsgi -s 0.0.0.0:10000

うん、とりあえず動くみたいです

nginxにモジュールを組み込み

nginxのコンパイルオプションで--add-moduleでuWSGIを組み込みます

  --add-module=<解凍したuwsgiソースが置いてあるディレクトリ>/uwsgi-0.9.6.8/nginx/

上記オプションを追加して再びコンパイルしマス

コンパイルが完了したらnginx設定ファイルのnginx.confを編集シマス。とりあえず動けば良いや!って勢いで修正したので、間違ってたらゴメンナサイ(´・ω・`)

worker_processes  1;
pid               pid/nginx.pid;
error_log         log/nginx-error.log;
   
events {
  worker_connections  1024;
}
    
http {
  # Some sensible defaults.
  #include               mime.types;
  default_type          application/octet-stream;
  keepalive_timeout     10;
  client_max_body_size  20m;
  sendfile              on;
  gzip                  on;
      
  # Directories
  client_body_temp_path tmp/client_body/  2 2;
  fastcgi_temp_path     tmp/fastcgi/;
  proxy_temp_path       tmp/proxy/;
  uwsgi_temp_path       tmp/uwsgi/;
      
  # Logging
  access_log            log/nginx-access.log  combined;
      
  # uWSGI serving flask.
  upstream flask {
    server 127.0.0.1:10000;
  }
      
  server {
    listen      80;
    server_name example.com;
    charset     utf-8;
        
    location / {
      uwsgi_pass  flask;
      include     uwsgi_params;
    }
  }
}

とりあえずこんな設定でnginxを動かしてみますよ。また、nginxのuwsgiモジュール用の設定としてuwsgi_paramsファイルを次のように用意します

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;
Flaskアプリを用意します

環境を汚したくなかったのでvirtualenvで作成したPython環境でFlaskのテストアプリを用意します

$ virtualenv test
$ source test/bin/activate
$(test) pip intall flask

Flaskアプリはこんな感じのHelloWorld仕様です

# test.pyとして保存します
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()
uWSGIを起動します

virtualenv環境を指定しつつ、flaskアプリを起動してやります

# -Hで実行環境、-wでモジュール:アプリケーションを指定します
./uwsgi-0.9.6.8/uwsgi -s 0.0.0.0:10000 -H test/ -w test:app

うん、Helloworldが表示されました

とりあえず動くようになったかな?

今回は、何をおいてもFlaskアプリを動かしてみる、を目標に駆け足でnginxを触ってみました。

とりあえずnginxもなんとか動かせる、怖くない…と思えるようになったものの、実際の設定なんかについては置き去りにした箇所がかなりあるので、今後細かい項目をいじっていろいろと試してみたいと思いますデス。

…あと、この設定チゲーよ!ってのがあれば教えてください(´・ω・`)

と、今になって気づく事実

こちらをみてみるとnginx0.84以上にはuWSGIが既に組み込まれているとのこと…だからコンパイル通らなかったのね orz

あとで試してみます(´・ω・`)