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