WebサーバにはuWSGI + nginxをセットアップします。uWSGIは、Upstartを使ってデーモンを起動するようにします。
OSは、EC2の Ubuntu Server 14.04 LTS (HVM), SSD Volume Type - ami-a21529cc です。
個人的に、PythonでWebサービスを書いたことがなかったので、どういうふうになっているのか興味があって調べてみた。というのが今回の動機です。
以下、セットアップ方法です。ステップバイステップで説明していきます。
Python 3.5をインストール
システムにインストールします。
複数バージョンのPythonを扱うpythonzというプロダクトもありますが、ここでは使わないでおきます。
fkrull's repository (https://launchpad.net/~fkrull/+archive/ubuntu/deadsnakes)を使います。
$ sudo add-apt-repository ppa:fkrull/deadsnakes $ sudo aptitude update $ sudo apt-get install python3.5 python3.5-dev python3-pip python-pip/usr/bin/pythonへシンボリックリンクを貼る。
$ sudo rm /usr/bin/python $ sudo ln -s /usr/bin/python3.5 /usr/bin/pythonバージョン確認。
$ python --version Python 3.5.1 $ pip --version pip 1.5.4 from /usr/lib/python3/dist-packages (python 3.5)
Djangoのサンプルアプリを準備
テスト用ディレクトリを作って、DjangoとuWSGIをインストール。
$ mkdir test-app $ cd test-app/ $ emacs requirements.txt Django==1.9.4 uWSGI==2.0.12 $ sudo pip install -r requirements.txtテスト用プロジェクトを作成。
$ django-admin startproject mywebサンプルアプリを作成。
$ cd myweb $ python manage.py startapp hello $ emacs myweb/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'hello', ] $ emacs hello/views.py from django.http import HttpResponse def main(request): return HttpResponse("Hello!") $ emacs myweb/urls.py urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^hello/', 'hello.views.main'), ]マイグレーションを実行。
$ python manage.py migrate簡易Webサーバを立てて、HTTPでアクセスしてみます。
$ python manage.py runserver 0.0.0.0:8000 $ curl http://127.0.0.1:8000/hello/ Hello!サンプルアプリの準備ができました。
nginxのインストール
nginxをインストールします。
UNIXドメインソケットを通じてWSGIへ繋ぐように設定します。
uwsgi_passは都合よく変更してください。
$ sudo aptitude install nginx-full $ sudo emacs /etc/nginx/sites-available/default server { listen 80; location / { include uwsgi_params; uwsgi_param Host $host; uwsgi_param X-Real-IP $remote_addr; uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for; uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto; uwsgi_pass unix:/home/yako/test-app/myweb/uwsgi.sock; } } $ sudo service nginx restart
uWSGI設定ファイルを編集
uWSGIは、スレッドをサポートしていますが、スレッドを有効にすると graceful restart がうなく動かなかったので、ここでは有効にしませんでした。
$ cd /home/yako/test-app/myweb $ emacs uwsgi_staging.ini [uwsgi] base = /home/yako/test-app/myweb chdir = %(base) socket = %(base)/uwsgi.sock pidfile = %(base)/exchange-server.pid touch-reload = %(base)/uwsgi_touch_reload.trigger touch-logreopen = %(base)/uwsgi_touch_logreopenr.trigger daemonize = %(base)/manage.log module = myweb.wsgi master = True vacuum = True processes = 4 max-requests = 1000 harakiri = 10 chmod-socket = 666 die-on-term = true
Upstart設定ファイルを編集
uWSGIスタート前に、touch-logreopenファイルを削除します。このファイルが存在する状態で、uWSGIをスタートすると、touch-logreopen機能が動きませんでした。
(さらに、uWSGIをreloadするとtouch-logreopen機能が動かなくなりました。良い回避方法があったら教えてください。)
Djangoでファイル名に日本語が入っているファイルのアップロードできるように、export LC_ALL=en_US.UTF-8を入れておきます。
$ sudo emacs /etc/init/uwsgi.conf description "myweb" start on runlevel [2345] stop on runlevel [!2345] setuid yako setgid yako expect daemon respawn pre-start script # remove touch files base=/home/yako/test-app/myweb/ touch_reload_file=$base/uwsgi_touch_logreopenr.trigger touch_logreopen_file=$base/uwsgi_touch_logreopenr.trigger if [ -e $touch_reload_file ]; then rm $touch_reload_file fi if [ -e $touch_logreopen_file ]; then rm $touch_logreopen_file fi end script script export LC_ALL=en_US.UTF-8 chdir /home/yako/test-app/myweb exec uwsgi --ini uwsgi_staging.ini end script
サンプルアプリをスタート
$ sudo service uwsgi startプロセスチェック。
$ ps auxf | grep uwsgi yako 16870 0.0 0.0 10460 936 pts/0 S+ 06:02 0:00 | \_ grep --color=auto uwsgi yako 16850 2.8 0.6 97708 26948 ? S 06:02 0:00 uwsgi --ini uwsgi_staging.ini yako 16853 0.0 0.6 318904 23324 ? Sl 06:02 0:00 \_ uwsgi --ini uwsgi_staging.ini yako 16854 0.0 0.6 318904 23136 ? Sl 06:02 0:00 \_ uwsgi --ini uwsgi_staging.ini yako 16855 0.0 0.6 318904 23336 ? Sl 06:02 0:00 \_ uwsgi --ini uwsgi_staging.ini yako 16859 0.0 0.6 318904 23324 ? Sl 06:02 0:00 \_ uwsgi --ini uwsgi_staging.iniログを確認。
$ tail -f /home/yako/test-app/myweb/manage.logHTTPでアクセスしてみます。
curl -> nginx -> uWSGI -> Django と、繋がる形になります。
$ curl 127.0.0.1/hello/ Hello!うまくいきました。
uWSGIの運用
ログファイルをローテートするときは、touch-logreopenで設定したファイルを更新します。
$ touch /home/yako/test-app/myweb/uwsgi_touch_logreopenr.trigger
See also)
Django Under The Hood Photo by Bartek Pawlik
https://www.flickr.com/photos/137962885@N08/22793957097/in/photolist-AJdZji-rJ1Av8-9RzYXi-cabjcj-Dgv6rN-rKK85W-s3kxtP-r6x6Gx-5KNeRh-s3kxre-rKK8dG-s13tgs-5kYmmW-5jMxyf-6cBmZt-djfBr4-6eVGGw-ekyaUg-dUbX9V-4ptVd-B9As9d-81dkcd-4JvxJL-B9AB59-5Sz4Gp-s3cT3G-r6x6Mn-r6kjvU-rKK8p3-rKTa8D-s3kxt8-r6kjou-rJ1Anc-r6x6Ra-5jDb1t-ASV1Fw-dKUbwX-BhKcMS-s3kxvc-s3cSwb-rKLg1L-rJ1ABa-s3gZ3P-rJ1A7c-s3ky8e-s13tq5-rKK8aA-FEgA9-cYohhb-AnvLtC
The Web framework for perfectionists with deadlines | Django
https://www.djangoproject.com/
The uWSGI project — uWSGI 2.0 documentation
http://uwsgi-docs.readthedocs.org/en/latest/index.html
Running uWSGI via Upstart — uWSGI 2.0 documentation What is –die-on-term?
http://uwsgi-docs.readthedocs.org/en/latest/Upstart.html#what-is-die-on-term
Managing the uWSGI server — uWSGI 2.0 documentation
http://uwsgi-docs.readthedocs.org/en/latest/Management.html#signals-for-controlling-uwsgi
NGINX as an Application Gateway with uWSGI and Django
https://www.nginx.com/resources/admin-guide/gateway-uwsgi-django/
EC2上で Django + Nginx + uWSGI を試す - Qiita
http://qiita.com/melos/items/91dc3b45a589ea5a369b