Djangoのデプロイ:Nginx、uWSGI

DjangoプロジェクトをUbuntuにデプロイする方法をご紹介します。

nginxとuWSGIを用いて動作するように設定します。

条件

  • Ubuntu 16.04 LTS。(Ubuntu 18.04 LTSでも確認済み)
  • Nginxがインストール済み。
  • Djangoプロジェクトが存在する。
    (Djangoプロジェクト作成済み、またはgitからクローン済み)

uWSGIのインストール

uWSGIとは?

WebサーバーとDjangoアプリケーションは直接対話することができません。
そこでWSGI(Web Server Gateway Interface)がWebサーバーとDjangoアプリケーションの橋渡しを行います。
WSGIは、WebサーバーとPythonアプリケーション間のインターフェースを規定している仕様です。
この仕様にのっとって実装されたものがuWSGIです。

インストール実行

python 2.xの場合

$ sudo pip install uwsgi

python 3.xの場合

$ sudo pip3 install uwsgi

インストール確認

$ uwsgi --version
2.0.17.1

python 2.xの場合

$ pip list
・・
uWSGI (2.0.17.1)
・・

python 3.xの場合

$ pip3 list
・・
uWSGI (2.0.17.1)
・・

簡単な動作確認

「Hello World」と表示させる簡単なプログラムを用いて簡単な動作確認を行います。

テストプログラム作成

test.pyを作成します。

$ cd ~/djangoTest/mysite
$ vi test.py

ファイルの内容は以下の通りです。

# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"] # python3

動作確認実行

以下のコマンドを実行します。

$ cd ~/djangoTest/mysite
$ uwsgi --http :8000 --wsgi-file test.py

このコマンドは以下の意味となります。

  • HTTPプロトコルでポート8000を使用して通信する。
  • その際の処理はtest.pyに記述された内容を使用する。

ブラウザで以下のURLを確認します。(サーバー内部からアクセスする場合)
http://127.0.0.1:8000/

以下のように表示されればOKです。

サーバー外部からアクセスを行う場合、ブラウザで以下のURLを確認します。(IPが123.45.67.89の場合)
http://123.45.76.89:8000/

現在の構成は以下の通りです。

the web client <-> uWSGI <-> Python

Djangoプロジェクトでの動作確認

今度はtest.pyではなく、Djangoプロジェクトでの動作確認を行います。

$ cd ~/djangoTest/mysite
$ uwsgi --http :8000 --module mysite.wsgi

ブラウザにアクセスして想定通りに表示されればOKです。

サーバー外部からアクセスを行う場合、settings.pyに以下の設定が必要です。(IPが123.45.67.89の場合)

ALLOWED_HOSTS = ['123.45.67.89']

サーバー外部からアクセスを行う場合、ブラウザで「http://123.45.67.89/polls/」を指定します。
(アクセスURLはプロジェクト毎に読み替えてください。)

現在の構成は以下の通りです。

the web client <-> uWSGI <-> Django

nginxの設定

nginxのインストールについてはこちらをご確認ください。

nginxの動作確認

ブラウザで以下のURLにアクセスして「Welcome to nginx!」と表示されればOKです。
http://127.0.0.1:80

uwsgi_paramsのコピー

/etc/nginx/uwsgi_params を Djangoプロジェクトmysiteディレクトリにコピーします。

コピー元

/etc/nginx$ ls -ltr
合計 48
-rw-r--r-- 1 root root 3610  4月 18 00:22 win-utf
-rw-r--r-- 1 root root  664  4月 18 00:22 uwsgi_params
-rw-r--r-- 1 root root  636  4月 18 00:22 scgi_params
-rw-r--r-- 1 root root 5170  4月 18 00:22 mime.types
-rw-r--r-- 1 root root 2223  4月 18 00:22 koi-win
-rw-r--r-- 1 root root 2837  4月 18 00:22 koi-utf
-rw-r--r-- 1 root root 1007  4月 18 00:22 fastcgi_params
-rw-r--r-- 1 root root  643  4月 18 00:59 nginx.conf.bak
lrwxrwxrwx 1 root root   22  4月 18 01:00 modules -> /usr/lib/nginx/modules
drwxr-xr-x 2 root root 4096  9月 24 12:35 conf.d
-rw-r--r-- 1 root root 4600  9月 24 12:54 nginx.conf

コピー後の状態(uwsgi_paramsをコピーした状態)

/djangoTest/mysite$ ls
MyDatabase  manage.py  mysite  polls  templates  test.py  uwsgi_params  venv

nginx参照設定

Djangoプロジェクトにコピーしたuwsgi_paramsをnginxが参照するよう以下を実施します。

Djangoプロジェクトにmysite_nginx.confを作成

$ sudo vi ~/djangoTest/mysite/mysite_nginx.conf

以下の設定ファイルのパス等は、自分の環境に合った値に編集します。(mysite_nginx.conf)

# the upstream component nginx needs to connect to
upstream django {
    # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # the port your site will be served on
    listen      8000;
    # the domain name it will serve for
    server_name example.com; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media  {
        alias /path/to/your/mysite/media;  # your Django project's media files - amend as required
    }

    location /static {
        alias /path/to/your/mysite/static; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed
    }
}

シンボリックリンク

シンボリックリンクを/usr/local/etc/nginx/sites-enabled/に貼ります。
⇒nginxがmysite_nginx.confを参照出来るようになります。

$ sudo mkdir /etc/nginx/sites-enabled
$ sudo ln -s ~/djangoTest/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/

設定ファイルの参照確認

nginxの起動時にどの設定ファイルが読み込まれているのか確認します。

/etc/nginx/nginx.conf を確認します。
(/etc/nginx/sites-enabled/*が読み込まれる設定になっているかを確認します。)

・・・
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    include /etc/nginx/sites-enabled/*; # ←この記述が存在することを確認する。
・・・

staticファイルのデプロイ

~/djangoTest/mysite/mysite/settings.py に以下の記述を追加します。

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

~/djangoTest/mysite で以下のコマンドを実行します。

$ python3 manage.py collectstatic

すると~/djangoTest/mysiteの下にstaticディレクトリが作成されます。

~/djangoTest/mysite$ ls
MyDatabase  manage.py  mysite  mysite_nginx.conf  polls  static  templates  test.py  uwsgi_params  venv

設定の反映

nginxを再起動します。

$ sudo service nginx restart

nginxとtest.pyの対話確認

以下のコマンドを実行してtest.pyとnginxが対話できることの確認を行います。

$ cd ~/djangoTest/mysite
$ uwsgi --socket :8001 --wsgi-file test.py

以下のURLを確認します。
http://127.0.0.1:8000/

以下のように表示されればOKです。

サーバー外部からアクセスを行う場合、ブラウザで以下のURLを確認します。(IPが123.45.67.89の場合)
http://123.45.76.89:8000/

現在の構成は以下の通りです。

the web client <-> the web server <-> the socket <-> uWSGI <-> Python

nginxとDjangoアプリケーションの対話確認

今度はtest.pyと同様、Djangoアプリケーションとnginxが対話できることの確認を行います。

$ cd ~/djangoTest/mysite
$ uwsgi --socket :8001 --module mysite.wsgi

以下のように表示されればOKです。

サーバー外部からアクセスを行う場合、settings.pyに以下の設定が必要です。(IPが123.45.67.89の場合)

ALLOWED_HOSTS = ['123.45.67.89']

サーバー外部からアクセスを行う場合、ブラウザで「http://123.45.67.89/polls/」を指定します。
(アクセスURLはプロジェクト毎に読み替えてください。)

現在の構成は以下の通りです。

the web client <-> the web server <-> the socket <-> uWSGI <-> Django

TCPポートソケットの代わりにUnixソケットを使用

Unixソケットの方がオーバーヘッドが少なくて済むため、Unixソケットを使用するよう設定します。

mysite_nginx.conf を以下のように編集します。
(パスを訂正しコメントアウトを付け直します)

$ cd ~/djangoTest/mysite
$ sudo vi mysite_nginx.conf

以下のように設定します。

# the upstream component nginx needs to connect to
upstream django {
    server unix:///home/username/djangoTest/mysite/mysite.sock; # for a file socket
    # server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
・・・

nginxを再起動して設定を反映します。

$ sudo service nginx restart

uWSGIを起動してtest.pyで確認

以下のコマンドを実行します。

$ cd ~/djangoTest/mysite
$ uwsgi --socket mysite.sock --wsgi-file test.py

以下のように「mysite.sock」が生成されます。

~/djangoTest/mysite$ ls
MyDatabase  mysite       mysite_nginx.conf  static     test.py       venv
manage.py   mysite.sock  polls              templates  uwsgi_params

以下のURLを確認します。
http://127.0.0.1:8000/

エラーになりました。

エラーログ(/var/log/nginx/error.log)を確認したところ、/djangoTest/mysite/mysite.sock failed (13: Permission denied) というログが出力されていました。
権限に問題がありそうです。

そこで、パーミッションを指定してuWSGIを起動します。

$ uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666

以下のURLを確認します。
http://127.0.0.1:8000/

以下のように表示されればOKです。

uWSGIを起動してDjangoアプリケーションで確認

以下のコマンドを実行します。

$ cd ~/djangoTest/mysite
$ uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=666

以下のように表示されればOKです。

iniファイルによる設定

iniファイルにuWSGIの各種設定を記述することで起動コマンドを簡略化します。

mysite_uwsgi.ini ファイルを作成します。

$ sudo vi ~/djangoTest/mysite/mysite_uwsgi.ini

内容は以下の通りです。
自分の環境に合わせて編集します。

[uwsgi]

# Django-related settings
# the base directory (full path)
chdir           = /path/to/your/project
# Django's wsgi file
module          = project.wsgi
# the virtualenv (full path)
home            = /path/to/virtualenv

# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 10
# the socket (use the full path to be safe
socket          = /path/to/your/project/mysite.sock
# ... with appropriate permissions - may be needed
# chmod-socket    = 664
# clear environment on exit
vacuum          = true

今回は以下のように設定しました。

[uwsgi]

# Django-related settings
# the base directory (full path)
chdir           = /home/username/djangoTest/mysite
# Django's wsgi file
module          = mysite.wsgi
# the virtualenv (full path)
# home            = /path/to/virtualenv

# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 10
# the socket (use the full path to be safe
socket          = /home/username/djangoTest/mysite/mysite.sock
# ... with appropriate permissions - may be needed
chmod-socket    = 666
# clear environment on exit
vacuum          = true

以下のコマンドを実行します。
(作成したiniファイルを指定してuWSGIを起動します)

$ cd ~/djangoTest/mysite
$ uwsgi --ini mysite_uwsgi.ini

以下のように表示されればOKです。

起動、停止、確認コマンド

バックグラウンド起動

$ cd ~/djangoTest/mysite
$ uwsgi --ini mysite_uwsgi.ini &

☆「&」を付けてコマンドを実行します。

プロセス確認

$ ps -aux | grep uwsgi

例)

server@XXX-XX-XX-XX:~/djangoTest/mysite$ ps -aux | grep uwsgi
server   1636 10.0  4.2 131196 42724 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1638  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1639  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1640  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1641  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1642  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1643  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1644  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1645  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1646  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1647  0.0  3.1 131196 31852 pts/0    S+   11:31   0:00 uwsgi --ini mysite_uwsgi.ini
server   1649  0.0  0.0  13136  1000 pts/1    S+   11:31   0:00 grep --color=auto uwsgi
server@XXX-XX-XX-XX:~/djangoTest/mysite$

プロセス停止

$ kill -QUIT マスタプロセスのPID

☆プロセスの削除は「マスタプロセス」(一番上)のみkillすればすべて消えます。

例)

server@XXX-XX-XX-XX:~/djangoTest/mysite$ ps -aux | grep uwsgi
server   1755  4.5  4.1 130052 41820 pts/0    S+   11:54   0:00 uwsgi --ini mysite_uwsgi.ini
server   1757  0.0  3.1 130052 32004 pts/0    S+   11:54   0:00 uwsgi --ini mysite_uwsgi.ini
server   1759  0.0  0.1  13136  1048 pts/1    S+   11:54   0:00 grep --color=auto uwsgi
server@XXX-XX-XX-XX:~/djangoTest/mysite$

server@XXX-XX-XX-XX:~/djangoTest/mysite$ kill -QUIT 1755

server@XXX-XX-XX-XX:~/djangoTest/mysite$ ps -aux | grep uwsgi
server   1762  0.0  0.0  13136  1004 pts/1    S+   11:55   0:00 grep --color=auto uwsgi
server@XXX-XX-XX-XX:~/djangoTest/mysite$

uWSGIのログ出力設定

ログ出力先ディレクトリ作成

以下のコマンドで、ログ出力先ディレクトリ作成&アクセス権設定を行います。

sudo mkdir /var/log/uwsgi
sudo chmod o+w /var/log/uwsgi

ログ出力先の指定

mysite_uwsgi.iniに以下を追記してログ出力先を指定します。

$ cd ~/djangoTest/mysite
$ sudo vi mysite_uwsgi.ini
# logging
logto = /var/log/uwsgi/mysite.log

uWSGIを起動すると、指定したパスへログが出力されるようになります。

ログローテーション設定

ログローテーション設定ファイル作成

ログローテーション設定のディレクトリに移動し、uwsgi用の設定ファイルを作成します。
(内容は適宜変更してください。)

$ cd /etc/logrotate.d
$ sudo vi uwsgi

以下は1日ごとにログローテーションを行い、古いログには末尾に年月日を付ける設定です。

/var/log/uwsgi/mysite.log {
        daily
        rotate 5
        missingok
        notifempty
        copytruncate
        dateext
        dateformat %Y-%m-%d
}

設定反映

以下のコマンドを実行して設定を反映します。

sudo /usr/sbin/logrotate /etc/logrotate.conf

参考

以下のサイトを参考にさせて頂きました。

https://qiita.com/Ningensei848/items/e91fbeef5f03685a7a0b

https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html

uWSGI公式:ロギング設定

https://uwsgi-docs.readthedocs.io/en/latest/Logging.html

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です