Edited at

EC2にNginx + Gunicorn + SupervisorでDjangoアプリケーションをデプロイする

More than 1 year has passed since last update.

Nginx + Gunicorn + Supervisorの組み合わせでDjangoアプリケーションを立ち上げたので手順のメモ

今回はOSに何も入っていない状態から始めていきます


環境

OS: Amazon Linux AMI

Python: 3.6.1

Django: 1.11.4

Nginx: 1.10.3

Gunicorn: 19.7.1

Supervisor: 3.3.3


Nginxのインストール

nginxのインストール

$ sudo yum install nginx

nginx起動する

$ sudo nginx

nginx自動起動設定

$ sudo chkconfig --add nginx

$ sudo chkconfig nginx on

自動起動設定確認

以下のようになっていればok

$ chkconfig | grep nginx

nginx 0:off 1:off 2:on 3:on 4:on 5:on 6:off

http://ipアドレスにアクセスしちゃんと起動しているか確認する

以下の通りになっていればOK

スクリーンショット 2017-08-03 13.40.56.png


Python環境の構築

今回はAnacondaで構築した

こちらからPython 3.6 versionをダウンロードする

ダウンロードしたパッケージをCyberduckなどのFTPツールで/home/ec2-userにアップロードする

アップロード完了したら下記コマンドでAnacondaインストールする

$ bash Anaconda3-4.4.0-Linux-x86_64.sh

インストール完了後、Anacondaのコマンドが使えるようにPATHを通す

$ export PATH="$PATH:/home/ec2-user/anaconda3/bin"

condaのコマンドを打って確認

$ conda info -e

# conda environments:
#
root * /home/ec2-user/anaconda3

良さげです

なお、annacondaインストール時にbashrcに環境変数の設定を追加していると

Do you wish the installer to prepend the Anaconda3 install location

to PATH in your /root/.bashrc ? [yes|no]
[no] >>> yes

ルート環境のpythonも3.6になっている

$ python --version

Python 3.6.1 :: Anaconda 4.4.0 (64-bit)


Djangoプロジェクトの作成

今回は直接EC2上でプロジェクトを作成します

本来はローカルで開発したDjangoアプリケーションをgit cloneすべき

また、DBもデフォルトのSQliteを使用しますが、実際のサービスを公開するにはPostgresqlやMariaDBを使う

まずはDjangoのインストール

root環境で動かすかどうかは少し議論の分かれるところで、別に環境を作ってDjangoを動かした方がいいんじゃないか、と思ったりもしますが、とりあえず今回はroot環境でインストールしてしまいます

$ pip install django

問題なければプロジェクトを作成

$ django-admin startproject test_project

プロジェクトが作られていることを確認

$ ls -ltr

total 511032
-rw-rw-r-- 1 ec2-user ec2-user 523283080 Aug 3 04:50 Anaconda3-4.4.0-Linux-x86_64.sh
drwxrwxr-x 20 ec2-user ec2-user 4096 Aug 3 04:53 anaconda3
drwxrwxr-x 3 ec2-user ec2-user 4096 Aug 3 05:05 test_project

/test_project/test_project/settings.pyのALLOW HOSTを下記の通り編集しておく


settings.py

# SECURITY WARNING: don't run with debug turned on in production!

DEBUG = True

ALLOWED_HOSTS = ["サーバのIPアドレス"]


下記のコマンドでDjangoを起動

デフォルトだと127.0.0.1:8000がbindアドレスとして使用されているため、オプションで0.0.0.0:8000を追加する必要があります

また、事前にAWSのセキュリティグループで8000番ポートを解放しておく必要があります

$ cd test_project

$ python manage.py runserver 0.0.0.0:8000

そして、http://IPアドレス:8000にアクセスすると以下の通りDjangoアプリケーションにアクセスできる

スクリーンショット 2017-08-03 15.23.25.png


Gunicornのインストール

GunicornはPython製のWSGIサーバ

WSGIサーバというのはWebサーバとWebアプリケーションをつなぐサーバのこと

なので、Nginx <-> Gunicorn <-> Djangoというような構成をイメージしていただければと

まずはGunicornのインストールをやっていく

$ pip install gunicorn

インストールされたらGunicornでDjangoを起動させる

$ gunicorn test_project.wsgi --bind=0.0.0.0:8000

先程と同様、http://IPアドレス:8000にアクセスするとDjangoアプリケーションに接続できる

なお、settings.pyを本番用とか開発用で分けている場合は以下のような感じで

$ gunicorn test_project.wsgi.wsgi --env DJANGO_SETTINGS_MODULE=test_project.settings_dev --bind=0.0.0.0:8000


Nginxの設定の変更

/etc/nginx.confを以下の通り編集する


/etc/nginx.conf


〜中略〜

http {
〜中略〜

upstream app_server {
server 127.0.0.1:8000 fail_timeout=0;
}

server {
#以下4行はコメントアウト
#listen 80 default_server;
#listen [::]:80 default_server;
#server_name localhost;
#root /usr/share/nginx/html;

# 以下3行を追加
listen 80;
server_name IPアドレス or ドメイン;
client_max_body_size 4G;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

location / {
# 以下4行を追加
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}

〜以下略〜


編集したら下記コマンドでnginxを再起動する

$ sudo service nginx restart

Stopping nginx: [ OK ]
Starting nginx: [ OK ]

これでNginxでのリバースプロキシの設定は完了

今回はnginx.confを直接編集したけれど、設定ファイルをどこか別のところに書いてそれを読み込ませる、という方法でもOK

その後、DjangoをGunicornで立ち上げる

$ gunicorn test_project.wsgi --bind=0.0.0.0:8000

次はhttp://IPアドレスにアクセスするとDjangoの画面が表示されるはず


Supervisorでプロセスをデーモン化する

今の状態だとGunicornのコマンドを中止したり、サーバからログアウトするとアプリケーションが停止してしまう

これを解消するためにSupervisorでGunicornのプロセスをデーモン化する

早速、Supervisorをインストール、としたいところだけれど、SupervisorはPython2系でしか動作しない

そのためAnacondaでPython2系の仮想環境を構築し、その環境にSupervisorをインストールしていく

まずは下記コマンドでSupervisor用のPython2系の仮想環境を作る

$ conda create -n supervisor python=2.7

python2系の環境に切り替えてpipでsupervisorをインストール

$ source activate supervisor

$ pip install supervisor

問題なくインストールできたら、supervisorの設定ファイルを作成し、それを/etc配下に配置する

$ echo_supervisord_conf > supervisord.conf

$ sudo mv supervisord.conf /etc

次にsupervisorの設定を行うため、supervisord.confを下記の通り編集


supervisord.conf

〜中略〜

[supervisord]
logfile=/var/log/supervisord.log ; ログの場所を変更
;logfile=/tmp/supervisord.log ; main log file; default $CWD/supervisord.log #コメントアウト
logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 50MB
logfile_backups=10 ; # of main logfile backups; 0 means none, default 10
loglevel=info ; log level; default info; others: debug,warn,trace
pidfile=/var/run/supervisord.pid ; 追記
;pidfile=/tmp/supervisord.pid ; supervisord pidfile; default supervisord.pid #コメントアウト

〜中略〜
# includeはコメントアウトされているのでコメント外す
[include]
files = supervisord.d/*.conf ; 起動するプロセスのconfファイルの配置場所
;files = relative/directory/*.ini


ログファイルは作っておき、パーミッションも設定しておく

$ sudo touch /var/log/supervisord.log

$ sudo chown ec2-user /var/log/supervisord.log
$ sudo chgrp ec2-user /var/log/supervisord.log
$ sudo chmod 774 /var/log/supervisord.log

あと、ログローテションも設定しておく

$ sudo sh -c "echo '/var/log/supervisord.log {

missingok
weekly
notifempty
nocompress
}' > /etc/logrotate.d/supervisor"

次にデーモン化するプロセスのコマンドを記載したファイルを作っていく

まずはそれらのファイルを配置するディレクトリを作成

$ sudo mkdir /etc/supervisord.d

/etc/supervisord.d配下にdjango_app.confを作成

ここに、Gunicornのプロセスをデーモン化するための設定を以下のように書く


django_app.conf

[program:django_app]

directory=/home/ec2-user/test_project
command=gunicorn test_project.wsgi --bind=0.0.0.0:8000
numprocs=1
autostart=true
autorestart=true
user=ec2-user
redirect_stderr=true

directoryに実行するディレクトリを指定、commandのところにプロセスを起動するためのコマンドを指定する

ここまでできたら下記のコマンドでsupervisorを立ち上げる

$ supervisord

次に、confファイルを読み込ませる

こちらは仮にconfを修正などする場合は必ず実行する

$ supervisorctl reread

なお、下記のコマンドでデーモンを再起動し、そのタイミングでもconfが読み込まれたりする

$ supervisorctl reload

下記のコマンドでGunicornのプロセスをデーモン化する

$ supervisorctl start django_app

仮にdjango_app: ERROR (already started)というメッセージが出た場合は、以下のコマンドでプロセスの再起動をしたり、停止をしてからstartしたりする

$ supervisorctl stop django_app # 停止

$ supervisorctl restart django_app # 再起動

さて、この状態でサーバからログアウトしてみる

そして、http://IPアドレスにアクセスすると、Djangoの画面が表示される

GunicornのプロセスがSupervisorによりデーモン化されていることになる

よかったですね