- 現状・条件
- Python 仮想環境を設定
- Django Project を作成
- uWSGI のインストールと設定|仮想環境
- Nginx を設定
- Nginx 基本テスト
- TCP Port Socket を使用して Python コードを実行する
- Unix Socket を使用して Python コードを実行する
- Nginx と uWSGI で Django アプリを実行する
- .ini ファイルで uWSGI を実行する
- .ini ファイルを使用して uWSGI を実行する
- System-wide 環境に uWSGI をインストールする
- python3 をデフォルトの Python に修正する
- Emperor モード
- uWSGI サービス自動起動を設定する
現状・条件
- CentOS Linux release 7.6.1810 (Core)
- Python : 仮想環境 ( 3.7.3 ) / System-wide 環境( 2.7.5 → 3.6.8)
- Nginx : 1.14.0
- uWSGI : 2.0.18
- Django : 2.2.5
- 構築するには、Python 仮想環境 ( Pyenv + Anaconda )と Django REST framework 環境 もしくは Django アプリケーション環境を事前に設定し、正常に動作することを確認してください。
- uWSGI を Systemd で自動化するため、Python の System-wide 環境バージョンを3.6.8 に変更します。
- uWSGI は emperor モード に設定します。
- uWSGI + Django + Nginx を使用して API サーバ を構築します。
それでは、Python の仮想環境を構築します。
Python 仮想環境を設定
仮想環境の設定がまだの方は ▼ の記事をご参照ください。
Django Project を作成
Django Project を作成する方法は ▼ の記事をご参照ください。
ここで使用するサーバ IP アドレスは 192.168.10.10 にします。
ユーザ名は admin を使用します。
※ 構築する際には、ご自身の環境に合わせて適宜変更してください。
また、使用するポートは Django 開発サーバのデフォルトポートである 8000/TCP を使用します。
それでは、Python 仮想環境 で uWSGI を設定します。
uWSGI のインストールと設定|仮想環境
Django Project ディレクトリまで移動して仮想環境 ( ここでは py37 ) に入ります。
[admin@centos7 ~]$ cd /reactjs/snowball/backend [admin@centos7 backend]$ source activate py37
仮想環境で uWSGI をインストール
(py37) [admin@centos7 backend]$ pip install uwsgi # 問題ないか uwsgi コマンドを実行してみます。 (py37) [admin@centos7 backend]$ uwsgi *** Starting uWSGI 2.0.18 (64bit) on [Tue Oct 15 11:22:48 2019] *** compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-36) on 05 September 2019 03:51:37 os: Linux-3.10.0-957.27.2.el7.x86_64 #1 SMP Mon Jul 29 17:46:05 UTC 2019 nodename: centos7 machine: x86_64 clock source: unix pcre jit disabled detected number of CPU cores: 4 ... ↑エラーがないことを確認してください。
uWSGI の基本動作テスト:Python ファイル
テスト用のファイルを作成して uWSGI を起動します。
(py37) [admin@centos7 backend]$ vi uwsgi_nginx_test.py def application(env, start_response): start_response('200 OK', [('Content-Type','text/html')]) return [b"Hello World"] # python3 (py37) [admin@centos7 backend]$ uwsgi --http :8000 --wsgi-file uwsgi_nginx_test.py
http://192.168.10.10:8000 にアクセスします。
画面に Hello World が表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
uWSGI の基本動作テスト:Django Project
まず、Django Project 自体が正常に動作するか次のように確認しておきます。
(py37) [admin@centos7 backend]$ python manage.py runserver 0:8000
http://192.168.10.10:8000 にアクセスします。
画面にあなたの Django アプリ関連ページが表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
次は、uWSGI を使用して起動します。
(py37) [admin@centos7 backend]$ uwsgi --http :8000 --module snowball.wsgi
同じく、http://192.168.10.10:8000 にアクセスします。
画面にDjango アプリページが表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
ここまで、uWSGI を使用して Python コード や Django project を実行してみました。
次は Nginx を設定して本来の WEB サーバで、Django project を実行します。
Nginx を設定
conda deactivate コマンドで仮想環境から出てください。
Nginx をインストール・基本動作テスト
[admin@centos7 ~]$ sudo yum install nginx [admin@centos7 ~]$ sudo systemctl start nginx
http://192.168.10.10 へアクセスします。
Welcome to nginx! が表示されれば OK です。
もし、80 ポートが使用中であれば、8000 ポートなどに変更しましょう。
Nginx の設定ファイルを作成
uWSGI と連動するため、Conf ファイルを作成します。
※下記の Conf ファイルは ;の後ろのコメント部分を消して使用してください。
# default.conf ファイルを使わないようにします ( 任意 ) [admin@centos7 conf.d]$ sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf_ # snowball_nginx.conf ファイルを作成します ( ファイル名は任意 ) [admin@centos7 conf.d]$ sudo vi /etc/nginx/conf.d/snowball_nginx.conf # サーバグループを指定 upstream django { # django は任意 #server unix:/run/uwsgi/snowball.sock; # 位置やファイル名は任意 server 127.0.0.1:8001; # ポート番号は任意 } server { listen 8000; charset utf-8; # max upload size client_max_body_size 75M; server_name 192.168.10.10; location / { root /reactjs/snowball/backend; # django project ホームを nginx のドキュメントルートに指定 include /etc/nginx/uwsgi_params; uwsgi_pass django; # 作成した upstream 名を指定 } # Django media location /media { alias /reactjs/snowball/backend/media; } location /static { alias /reactjs/snowball/backend/static; } } [admin@centos7 conf.d]$ # conf ファイルを保存し、設定の誤りがあるかチェックします。( 任意 ) [admin@centos7 conf.d]$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [admin@centos7 conf.d]$
静的ファイルを構成
上記の conf ファイルの media/static 設定は Django 側でも一致させる必要があります。
まず、サイトの静的ファイルを保持するディレクトリ ( static ) を構成するため、Django Project ホームに移動して下記のように実際の静的ファイルを集めておきます。
[admin@centos7 ~]$ cd /reactjs/snowball/backend [admin@centos7 backend]$ source activate py37 (py37) [admin@centos7 backend]$ vi snowball/settings.py # 任意のところに下記の一行をコピペしておきます。 STATIC_ROOT = os.path.join(BASE_DIR, "static/") # ファイルを保存&閉じて、collectstatic コマンドを実行すると自動的に Static ファイルを集めます。 (py37) [admin@centos7 backend]$ ./manage.py collectstatic 157 static files copied to '/reactjs/snowball/backend/static'. (py37) [admin@centos7 backend]$
Nginx を再起動します。
(py37) [admin@centos7 backend]$ sudo systemctl restart nginx
Nginx 基本テスト
media ディレクトリがなければ作成します。
[admin@centos7 backend]$ mkdir /reactjs/snowball/backend/media
任意の media ファイルをアップロードします。
# Mac で scp を使い、city.jpg ファイルをアップする 例: try🐶everything backend$ scp ~/Downloads/city.jpg admin@centos7:/reactjs/snowball/backend/media
http://192.168.10.10:8000/media/city.jpg にアクセスします。
イメージが表示されれば Nginx の動作は問題ないことです!
TCP Port Socket を使用して Python コードを実行する
次は、Nginx で設定した TCP Port Socket ( server 127.0.0.1:8001 ) をテストします。uWSGI を8001 ポートで起動して、冒頭で作成した uwsgi_nginx_test.py を Nginx から表示させます。
Nginx を起動した状態で行います。upstream 設定が http になっていることを確かめてください。Conf ファイルを修正したらまた、Nginx を再起動してください。
(py37) [admin@centos7 backend]$ sudo vi /etc/nginx/conf.d/snowball_nginx.conf upstream django { #server unix:/run/uwsgi/snowball.sock; server 127.0.0.1:8001; # << ここ! } ... (py37) [admin@centos7 backend]$ sudo systemctl restart nginx
uWSGI を起動します。
(py37) [admin@centos7 backend]$ uwsgi --socket :8001 --wsgi-file uwsgi_nginx_test.py
http://192.168.10.10:8000 にアクセスします。
画面に Hello World が表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
これから、
この記事のゴールである Unix Socket を使用した設定を行いますが、Permissionエラー が多すぎてかなり苦労する部分なので Permission エラーが発生する理由や対処方法 をここで紹介します。
Unix Socket を使用して Python コードを実行する
今回は、Unix socket を使い、uWSGI を再度起動します。
Nginx の conf ファイルを下記のように Unix Socket を使えるように変更してください。
(py37) [admin@centos7 backend]$ sudo vi /etc/nginx/conf.d/snowball_nginx.conf upstream django { server unix:/run/uwsgi/snowball.sock; # << ここ! #server 127.0.0.1:8001; } ... # 変更したら nginx を再起動します。 (py37) [admin@centos7 backend]$ sudo systemctl restart nginx
uwsgi コマンドの –socket オプションは nginx の設定に合わせましょう。
# /run/uwsgiディレクトリを作成して権限を admin:nginx に設定します。 (py37) [admin@centos7 backend]$ sudo mkdir /run/uwsgi (py37) [admin@centos7 backend]$ sudo chown admin.nginx /run/uwsgi # uWSGI を起動します。 (py37) [admin@centos7 backend]$ uwsgi --socket /run/uwsgi/snowball.sock --wsgi-file uwsgi_nginx_test.py
ここで、下記のような Permission エラー 発生します。
先ほどの 正しい所有権限 を再度チェックしてみましょう!
先ほどの uwsgi コマンドを実行したのは admin ユーザで、WEBサーバの役割は nginx が担当しています。したがって、
Socket ディレクトリ の所有者は admin、Socket ファイル の所有者は nginx が正しいです。
先ほど /run/uwsgi ディレクトリを作成する際に設定済みですが、uwsgi コマンドを実行する前に、sudo chown admin.nginx /run/uwsgi コマンドで Socket ディレクトリの所有者を admin に変更もしくはご確認ください。変更しないと ▼ のようなエラーになります。
Socket ファイルは uWSGI が起動した状態で修正します。
一旦、uWSGI を起動します。
(py37) [admin@centos7 backend]$ uwsgi –socket /run/uwsgi/snowball.sock –wsgi-file uwsgi_nginx_test.py
ブラウザでアクセスすると 502 Bad Gateway が表示され、snowball.sock ファイルは uWSGI を実行した admin が所有者になっているはずです。
合計 0
srwxrwxr-x 1 admin admin 0 9月 10 16:36 snowball.sock
[admin@centos7 uwsgi]$
uwsgi プロセスを起動したまま、別のウィンドウを開いて Socket ファイルの所有者をnginx に変更します。
[admin@centos7 uwsgi]$ ll
合計 0
srwxrwxr-x 1 nginx admin 0 9月 10 16:36 snowball.sock
[admin@centos7 uwsgi]$
権限を修正したら、http://192.168.10.10:8000 にアクセスもしくはブラウザをリロードします。
画面に Hello World が表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
次は、Pythonコードの代わりに、Django アプリを実行します。
Nginx と uWSGI で Django アプリを実行する
Socket ディレクトリの所有者は既に admin に変更済みであるため、今回はそのまま uwsgi コマンドを実行します。
(py37) [admin@centos7 backend]$ uwsgi --socket /run/uwsgi/snowball.sock --module snowball.wsgi
uwsgi プロセスを起動したまま、別のウィンドウを開いて Socket ファイルの所有者を nginx に変更します。
http://192.168.10.10:8000 にアクセスします。
画面に Hello World ではなく、Django アプリ関連ページが表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
.ini ファイルで uWSGI を実行する
※ ここからは sudo tail -f /var/log/nginx/error.log でエラーログを確認しながらデバッグするとよりスムーズです。
ini ファイル を作成します。ファイルの場所や名前は適宜修正してください。
(py37) [admin@centos7 backend]$ mkdir -p /reactjs/snowball/backend/uwsgi/ (py37) [admin@centos7 backend]$ vi /reactjs/snowball/backend/uwsgi/snowball_uwsgi.ini [uwsgi] chdir = /reactjs/snowball/backend module = snowball.wsgi master = true processes = 5 socket = /run/uwsgi/snowball.sock daemonize = /var/log/uwsgi/uwsgi-emperor.log (py37) [admin@centos7 backend]$
※ home オプションは Python 仮想環境が正常動作すればスキップしても自動認識されます。
.ini ファイルを使用して uWSGI を実行する
下記のように設定されているか確認します。
sudo chown admin /run/uwsgi
sudo chown nginx /run/uwsgi/snowball.sock
sudo chown admin /var/log/uwsgi/uwsgi-emperor.log
確認できたら起動します。
(py37) [admin@centos7 backend]$ uwsgi --ini ./uwsgi/snowball_uwsgi.ini
# --ini オプションで起動すると uwsgi プロセスはバックグラウンドで実行されます。 (py37) [admin@centos7 backend]$ uwsgi --ini ./uwsgi/snowball_uwsgi.ini [uWSGI] getting INI configuration from ./uwsgi/snowball_uwsgi.ini (py37) [admin@centos7 backend]$ # ini ファイルで設定した processes 数の worker プロセスが起動するので、しばらくしてからプロセスを確認できます。 (py37) [admin@centos7 backend]$ ps -ef | grep wusgi (py37) [admin@centos7 backend]$ ps -ef|grep uwsgi admin 382 1 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 384 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 385 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 386 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 387 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 393 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 1187 19347 0 18:00 pts/2 00:00:00 grep --color=auto uwsgi # エラーになったらプロセスを Kill してから再度 uwsgi コマンドを打ちましょう。 (py37) [admin@centos7 backend]$ ps -ef|grep uwsgi (py37) [admin@centos7 backend]$ kill -9 382
http://192.168.10.10:8000 にアクセスします。
画面にあなたの Django アプリ関連ページが表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
これで、Python 仮想環境での設定は完了です。
次は Systemd に登録して自動化するための構成を行います。
System-wide 環境に uWSGI をインストールする
※ 以下は、System-wide 環境に Python 仮想環境を構築していないことが条件です。
conda deactivate コマンドで Python 仮想環境から出てください。
(py37) [admin@centos7 backend]$ conda deactivate [admin@centos7 backend]$
System-wide で動作するためは、Python 仮想環境のバージョンと合わせる必要があります。
Python 3.7.3
[admin@centos7 backend]$ sudo python -V
Python 2.7.5
CentOS 7 ではデフォルトの python コマンドが python2 にリンクされています。python3 を追加で設置した後、python3 をデフォルトの python バージョンに変更してから uWSGI をインストールします。
( root ユーザで実行 ) [root@centos7 backend]# yum install epel-release [root@centos7 backend]# yum search python3 # 設置可能な python パッケージを確認します。 # インストールします。 [root@centos7 backend]# yum -y install python36-devel [root@centos7 backend]# yum -y install python36-setuptools [root@centos7 backend]# easy_install-3.6 pip [root@centos7 ~]# which pip /usr/local/bin/pip
python3 をデフォルトの Python に修正する
必要なのは Symbolic link を python3.6 に変更するだけです!
( root ユーザで実行 ) # python コマンドの位置を確認します。 [root@centos7 ~]# which python /bin/python # python2.7 にリンクされていることを確認します。 [root@centos7 ~]# ll /bin/python* lrwxrwxrwx 1 root root 9 Sep 5 12:07 /bin/python -> python2.7 ... # リンクを削除して、python3.6 を python にリンクします。 [root@centos7 ~]# rm -f /bin/python [root@centos7 ~]# cd bin [root@centos7 bin]# ln -s python3.6 python # pythonコマンドが3.6バージョンに変更されたことを確認します。 [root@centos7 bin]# ll python* lrwxrwxrwx 1 root root 9 Sep 5 12:07 /bin/python -> python3.6 ...
Python バージョンを確認します。
Python 3.6.8
[root@centos7 bin]#
System-wide に uWSGI をインストールします。
( root ユーザで実行 ) [root@centos7 ~]# yum install python-devel gcc [root@centos7 ~]# pip install uwsgi # or, /usr/local/bin/pip install uwsgi # /usr/local/lib/python3.6/site-packages 以下に設置されたことを確認してください。 ( 3.6の数字は環境によって異なります )
uwsgi コマンドを実行してエラーが出ないか確認します。
( root ユーザで実行 ) [root@centos7 ~]# which uwsgi /usr/local/bin/uwsgi # uwsgi コマンドを実行 [root@centos7 ~]# uwsgi < エラーがないことを確認!! >
snowball_uwsgi.ini ファイルを修正して、Socket ファイルの所有者を nginx に変更して保存します。
chown-socket = nginx:nginx
[admin@centos7 backend]$ vi uwsgi/snowball_uwsgi.ini [uwsgi] chdir = /reactjs/snowball/backend module = snowball.wsgi master = true processes = 5 socket = /run/uwsgi/snowball.sock chmod-socket = 664 chown-socket = nginx:nginx vacuum = true daemonize = /var/log/uwsgi/uwsgi-emperor.log [admin@centos7 backend]$
System-wide 環境で、ini ファイルを使って uWSGI を再度起動します
表示されるメッセージにエラーがないことを確認します。
特に、Python version:で始まる行に 3.x と表示されていることを確認してください。
# uwsgi プロセスが起動中であれば閉じます。 [admin@centos7 backend]$ ps -ef|grep uwsgi admin 382 1 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 384 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 385 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 386 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 387 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini admin 393 382 0 17:51 ? 00:00:00 uwsgi --ini ./uwsgi/snowball_uwsgi.ini [admin@centos7 backend]$ sudo kill -9 382 # uWSGI を起動します。 [admin@centos7 backend]$ sudo uwsgi --ini ./uwsgi/snowball_uwsgi.ini [uWSGI] getting INI configuration from ./uwsgi/snowball_uwsgi.ini
http://192.168.10.10:8000 にアクセスします。
画面にあなたの Django アプリ関連ページが表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
Emperor モード
uWSGI は emperor モードで実行できます。 このモードでは、uWSGI 構成ファイルのディレクトリを監視し、見つかった各インスタンス ( vassals ) を生成します。
Emperor モードを設定する
[admin@centos7 backend]$ sudo mkdir /etc/uwsgi [admin@centos7 backend]$ sudo mkdir /etc/uwsgi/vassals [admin@centos7 backend]$ sudo chown -R admin.nginx /etc/uwsgi # symlink from the default config directory to your config file [admin@centos7 backend]$ sudo ln -s /reactjs/snowball/backend/uwsgi/snowball_uwsgi.ini /etc/uwsgi/vassals/
emperor モードで実行する
実行する前に、下記をご確認ください。
sudo chown admin.nginx /run/uwsgi
↓ iniファイルに chown-socket、chmod-socket 設定を追加したため、不要になります。
[admin@centos7 backend]$ sudo uwsgi --emperor /etc/uwsgi/vassals
http://192.168.10.10:8000 にアクセスします。
画面にあなたの Django アプリ関連ページが表示されれば OK です。
問題なければ、control + c コマンドでプロセスを終了しておきます。
uWSGI サービス自動起動を設定する
uWSGI の Systemd Unit File を作成する
[admin@centos7 backend]$ cat /etc/systemd/system/uwsgi.service [Unit] Description=uWSGI Emperor service After=syslog.target [Service] ExecStartPre=/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown nginx:nginx /run/uwsgi' ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid nginx --gid nginx Restart=always KillSignal=SIGQUIT Type=notify NotifyAccess=all [Install] WantedBy=multi-user.target [admin@centos7 backend]$
uWSGI デーモン を起動する前に、uwsgi-emperor.log ファイルを生成し、所有者を下記のように設定してください。
[admin@centos7 backend]$ sudo touch /var/log/uwsgi/uwsgi-emperor.log [admin@centos7 backend]$ sudo chown nginx.nginx /var/log/uwsgi/uwsgi-emperor.log
uWSGI デーモンを起動します。
[admin@centos7 backend]$ sudo systemctl start uwsgi.service
http://192.168.10.10:8000 にアクセスします。
画面に Django アプリ関連ページが表示されれば OK です。
問題なく動作するなら、付加オプションをつけましょう!( 任意 )
pidfile ファイルを生成
[admin@centos7 backend]$ vi uwsgi/snowball_uwsgi.ini ... # create a pidfile safe-pidfile = /run/uwsgi/snowball.pid [admin@centos7 backend]$
Python Threads と Thunder Lock 機能を有効にする
[admin@centos7 backend]$ vi uwsgi/snowball_uwsgi.ini ... enable-threads = true thunder-lock = true [admin@centos7 backend]$
よければ他の追加オプションも試してみてください。
env = DJANGO_SETTINGS_MODULE=mysite.settings # set an environment variable harakiri = 20 # respawn processes taking more than 20 seconds limit-as = 128 # limit the project to 128 MB max-requests = 5000 # respawn processes after serving 5000 requests
emperor モード用 snowball_nginx.ini の完成版
[uwsgi] # Django-related settings # the base directory (full path) chdir = /reactjs/snowball/backend # Django's wsgi file module = snowball.wsgi # the virtualenv (full path) #home = /home/admin/.pyenv/versions/anaconda3-2019.03 # process-related settings # master master = true # maximum number of worker processes processes = 5 # the socket (use the full path to be safe socket = /run/uwsgi/snowball.sock # socket permissions - when run nginx chmod-socket = 664 chown-socket = nginx:nginx # clear environment on exit vacuum = true # python threads support enable-threads = true # uwsgi thunder lock thunder-lock = true # create a pidfile safe-pidfile = /run/uwsgi/snowball.pid # background the process & log daemonize = /var/log/uwsgi/uwsgi-emperor.log
uWSGI デーモン を再起動して、サイトが正常に動作するか再度確認します。
[admin@centos7 backend]$ sudo systemctl restart uwsgi.service
問題なければ API サーバ の構築はこれで完了です。
お疲れ様でした!
※ 2019/12/18 追記:
この後は、Nginx と連動してメール方式や Twitter アカウントでのユーザ認証機能を実装しました。興味のある方はご参考にどうぞ!▼
Django REST framework API サーバと Nginx WEB サーバを連動する|CentOS 7
参考文献
How to deploy with WSGI
How to use Django with uWSGI
Setting up Django and your web server with uWSGI and nginx
WiMAX +5GをはじめるならBIGLOBE
公式特典!初期工事費実質0円!最大41,250円割引!おトクにauひかりをスタートできる!
コメント