Macでnginx→uwsgi→djangoの構成で連携させる

macとかでお試しでdjangoのアプリケーション開発してるとapacheやnginxを介さず直接djangoアプリケーションにアクセスしがちですが、
それだといざ公開しよう！ってなったときにうまく行かない（連携の仕方がわからない）ことが多いので、はじめから連携させるていでやっていきたいと思います。

※必要に応じてvirtualenvとかで環境をわけてください。

## 環境

・Mac
・Python 3.6.1


### djangoインストール

まずはdjango本体をインストールして、プロジェクトを作成します。
ここではratesiteというプロジェクト名にしました。

```
pip install Django
django-admin.py startproject ratesite
cd ratesite
```

### uwsgiインストール

深くは理解していませんが、nginxとdjangoを繋いでくれるものと理解しています。

```
pip install uwsgi
```

### test.pyを作成

`test.py` を作成し、

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

```

を貼り付けます。

### 起動し確認。

```
uwsgi --http :8000 --wsgi-file test.py
```

でuwsgiからtest.pyを起動し、

localhost:8000

にアクセスし、Hello World
が表示されるのを確認します。

今この状態は、

【ブラウザ】→【uWSGI】→【Python（test.py）】

です。

（多分）本来uwsgiはnginxからPythonへの橋渡しをする役割なので、
これからnginxを前に立たせる設定をしていきます。


### nginxのインストール、設定

もともとMacにnginxをインストールしていれば問題ないですが、
もしまだインストールされていない場合は、
`brew install nginx`
とかでいれてください。

参考：
https://qiita.com/amemolee/items/56332100f182088687cf


これからnginxの設定進めていきますが、デフォルトから結構かえるため、
念の為バックアップを取りながらいきます。

```
cp -p /usr/local/etc/nginx/nginx.conf /usr/local/etc/nginx/nginx.conf.bk
vi /usr/local/etc/nginx/nginx.conf
```

以下の内容を貼り付けます。


```
worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;

    default_type  application/octet-stream;

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

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    include /usr/local/etc/nginx/conf.d/*.conf;

    include servers/*;
}

```

これだけだとなんの意味もありません。

`    include /usr/local/etc/nginx/conf.d/*.conf;`
ここで、バーチャルホストごとの設定ファイルを読み込む形になります。

インストールした直後だと、
`/usr/local/etc/nginx/conf.d`
というディレクトリはないと思うので、

```
cd /usr/local/etc/nginx
mkdir conf.d
```
で作成しましょう。

※本当は `servers` というディレクトリ適当なのかもしれませんが、それに気づく前に `conf.d` を作ってしまったのでこのままいかせてください。

`conf.d` を作成したらその配下に

新たに、 `django_ratesite.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/ratesite/media;  # your Django project's media files - amend as required
    }

    location /static {
        alias /path/to/your/ratesite/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/ratesite/uwsgi_params; # the uwsgi_params file you installed
    }
}
```

を貼りけます。
#### 注意

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

location /static {
    alias /path/to/your/ratesite/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/ratesite/uwsgi_params; # the uwsgi_params file you installed
}

```
のパスの部分はご自身の環境に合わせて変更してください。

ここまででいったんnginxの設定は終わります。

### django側で必要なディレクトリ、ファイルの作成

その後、
先程作成したプロジェクト配下に移動し、(manage.pyが置いてあるディレクトリ)

```
mkdir media
mkdir static
```

```
vi 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  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;
```

を作成、貼り付けます。

`ratesite/settings.py`

に

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

を追記。

```
python manage.py collectstatic
```

### nginxを再起動、ブラウザから確認

```
sudo nginx -s stop
sudo nginx
```

そして、
http://localhost:8000/media/aaa.png

にアクセスしてaaa.pngが表示されればOKです。
※aaa.pngはご自分で置いてください。

ただこれは、ブラウザからnginxにアクセスして、単純にmedia配下のディレクトリにアクセスしただけです。

### uwsgi経由でpythonが動くことを確認

```
uwsgi --socket :8001 --wsgi-file test.py
```

を実行し、ブラウザから、
http://localhost:8000
にアクセスしてみてください。

Hello World
がでるはずです。

このままでもいいのですが、uwsgiへの待ち受け方を変えます。

先程作成した、

`vi /usr/local/etc/nginx/conf.d/django_ratesite.conf`

を開き。

```
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)
}
```

の部分を、

```
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)
}
```


に変えます。

そして、

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

を実行します。
※「なんかうまく行かないぞ・・・？って方は上記のコマンドをうって、mysite.sockが出来上がるのを確認し、
　そこへのパスが、 `/usr/local/etc/nginx/conf.d/django_ratesite.conf` に書いたパスと合うか確認してみましょう。

これでうまくいったら、

```
uwsgi --socket mysite.sock --wsgi-file ratesite/wsgi.py --chmod-socket=666
```
をうって、
http://localhost:8000
にアクセスしdjangoのページが表示されれば完了です。


## 以上です

だいぶ雑かもしれませんが一応これで、

`the web client <-> the web server <-> the socket <-> uWSGI <-> Python(django)`

という構成が作れたと思います。

ここまでできればあとは、
djangoプロジェクトの改修や修正をしていくだけで良いかと思われます（多分）

実際開発のときはわざわざnginxかます必要はないんですけどね。
いざ、ローカルで動作確認してさあ公開だ！ってなったときにつまづくと結構混乱するので・・・。

ご指摘等あればコメントにて教えていただけると幸いです。