Nginx + Gunicorn + Django + PostgreSQL

여태 Django의 빌트-인 웹 서버를 이용하다가, Nginx와 Gunicorn을 연동해보기로 했다. 아래의 링크에서 가장 많은 도움을 받았고, 설치하며 겪었던 시행착오를 정리하기 위해서 글로 정리한다.

환경

  • OS : Ubuntu 16.04
  • Python : 3.4
  • Django : 1.8.5 (LTS)

패키지 설치

$ sudo apt-get update

$ sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx

PostgreSQL

PostgreSQL은 오픈소스 RDBMS다. MySQL에 비해 SQL 표준을 잘 지키고 있고, Genetic query optimizer라고 불리는 알고리즘 덕분에 쿼리가 복잡해질 수록 성능이 더 잘나오는 편이라고 한다.

$ sudo -u postgres psql

  • psql : 쿼리문을 입력할 수 있는 데이터베이스 콘솔 실행.
  • postgres : PostgreSQL의 디폴트 사용자.

postgres=# CREATE DATABASE myproject;

postgres=# CREATE USER myprojectuser WITH PASSWORD 'password';

postgres=# ALTER ROLE myprojectuser SET client_encoding TO 'utf8';

postgres=# ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';

postgers=# ALTER ROLE myprojectuser SET timezone TO 'UTC';

postgres=# GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

virtualenv, virtualenv-wrapper

virtualenv는 프로젝트 개발에 필요한 파이썬 패키지를 독립된 가상환경에서 설치하고 관리할 수 있게 돕는 툴인데, virtualenv-wrapper는 기존의 virtualenv를 좀 더 편하게 쓸 수 있도록 몇 가지 기능을 추가한 툴이다.

$ pip3 install virtualenvwrapper

아래의 환경 변수와 쉘 스크립트를 .bash_rc에 추가한다.

.bash_rc

WORKON_HOME=/home/ubuntu/Envs
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/bin/virtualenvwrapper.sh
  • WORKON_HOME이 가르키는 디렉토리에 가상 환경들이 모인다.

$ source ~/.bash_rc : 변경된 .barh_rc 스크립트 실행

$ mkvirtualenv myenv : 가상환경 생성, 활성화

$ deactivate : 가상환경 비활성화

$ workon myenv : 가상환경 활성화

Django

$ workon myenv

$ pip3 install django

$ django-admin.py startproject myproject

$ cd myproject && ./manage.py migrate

settings.py

ALLOWED_HOSTS = ['server_domain_or_ip', ]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': '',
        'HOST': 'localhost',
        'PORT': '',
    }
}

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files/')
MEDIA_URL = '/uploads/'
MEDIA_ROOT = 'upload_files'

$ ./manage.py collectstatic : 프로젝트 내의 static file(css, javascript, image ..)을 STATIC_ROOT가 가르키는 디렉토리 밑으로 복사

Gunicorn

$ pip3 install gunicorn

/etc/systemd/system/gunicorn.service

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
Environment="variable=value"
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/myproject
ExecStart=/home/ubuntu/Envs/myenv/bin/gunicorn --workers 3 --bind unix:/home/ubuntu/myproject/myproject.sock myproject.wsgi:application

[Install]
WantedBy=multi-user.target

Environment : .bash_rc에 있는 환경 변수를 읽어오지 못하기 때문에 필요한 시스템 환경 변수는 여기에 작성.

User : gunicorn을 실행할 시스템 사용자의 이름

WorkingDirectory : Django 프로젝트의 경로

ExecStart : django 서버를 실행하는 명령어. ' myproject.sock ' 파일로 Nginx와 통신하게 된다.

$ sudo systemctl start gunicorn

$ sudo systemctl enable gunicorn

$ sudo systemctl daemon-reload : gunicorn.service 파일이 변경됐을 때 적용.

$ sudo systemctl status gunicorn : gunicorn의 실행 상태, 에러 여부도 알 수 있다.

NginX

/etc/nginx/site-available/default

server {
    listen 80;
    server_name my_domain.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        alias /home/ubuntu/myproject/static_files/;
    }

    location /uploads/ {
        alias /home/ubuntu/myproject/upload_files/;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/ubuntu/myproject/myproject.sock;
    }
}

$ sudo ln -s /etc/nginx/site-available/default /etc/nginx/site-enabled/default

 - 'site-enabled' 폴더의 심볼릭 링크('site-available' 폴더의 default 파일)를 기준으로 Nginx 서버가 실행된다.

$ sudo nginx -t : Nginx 설정 파일의 문법 에러 검출.

$ sudo systemctl start nginx : Nginx 서버 재시작.

  • /var/log/nginx/error.log : 에러 로그 파일.

성능비교 ( Pingdom )


Django를 "빌트인 서버"로 실행할 때와 "Nginx+Gunicorn"로 서버를 실행했을 때, 웹 사이트 성능 비교


빌트인 서버

 


Nginx, Gunicorn

 






+ Recent posts