본문 바로가기
Python/Django

[Django] uwsgi + nginx in ubuntu

by 혀나Lee 2016. 10. 18.

이 페이지는 https://www.digitalocean.com/community/tutorials/how-to-serve-django-applications-with-uwsgi-and-nginx-on-ubuntu-14-04 사이트에 설명된 가이드 해석 및 테스트를 하며 발생된 이슈를 정리합니다.


~~ 작성중 (이 부분의 내용은 프로젝트 생성 관련 내용으로 위의 링크에서도 이해하기 쉽습니다.) ~~

uWSGI 애플리케이션 서버 설정하기

이제 두개의 Django 프로젝트 설정을 마쳤고, uWSGI 설정을 할 준비가 되었다. uWSGI 는 Django 애플리케이션과 WSGI 라는 표준 인터페이스로 통신하는 애플리케이션 서버이다. ubuntu에서 Nginx와 uWSGI 를 설정하는 더 자세한 사항은 여기에서 확인할 수 있다.

uWSGI 설치하기

위에서 제공한 링크와는 다르게, 본 가이드에서는 uWSGI 를 전체시스템에 설치할 것이다. 이렇게 함으로써 multi Django 프로젝트를 처리할 때 충돌을 줄일 수 있다. uWSGI 를 설치하기 전에 uWSGI에 의존성이 있는 Python development 파일을 설치해야 한다. 설치는 아래의 방법으로 ubuntu 저장소로 부터 바로 설치할 수 있다.

$ sudo apt-get install python-dev

이제 development 파일이 이용가능 하며, pip 를 이용하여 uWSGI를 전체시스템에 설치한다. (단, python3을 사용할 경우 pip3을 이용하여 설치한다.)

$ sudo pip install uwsgi
# sudo pip3 install uwsgi

설치 후, uWSGI 를 간단하게 테스트 해볼 수 있다. user 에는 계정 이름, firstsite 는 프로젝트 이름을 써주면 된다. (계정 이름 확인 명령어: whoami)

$ uwsgi --http :8080 --home /home/user/Env/firstsite --chdir /home/user/firstsite -w firstsite.wsgi

프로젝트 폴더 firstsite를 변경하고 wsgi.py 을 사용하기 위해 ~/Env 안에 만든 가상환경을 사용하여 uWSGI 에 알려주었다. 위 예시에서는 8080 포트의 HTTP 서버를 사용했고 정상적으로 실행이 되고 있는지 확인하기 위해서는 브라우저에서 :8080 포트 앞에 도메인 이름 또는 IP 주소를 작성(예, 127.0.0.1:8080)하여 들어가면 runserver 와 동일하게 실행되는 것을 확인할 수 있다. (그렇지만 /admin 의 static 엘리먼트들은 아직 동작하지 않는다.) CTRL-C 로 테스트를 종료할 수 있다.

설정파일 생성하기

커맨드라인에서 uWSGI 를 동작시키는 것은 테스트할 때 유용하다. 하지만 실제 배포환경에는 도움이 되지 않는다. 대신 uWSGI 를 독립된 애플리케이션들을 자동으로 관리해 주는 "Emperor mode" 에서 uWSGI 를 실행할 것이다. 

우선, 설정파일을 저장할 폴더를 생성하자. 전체 시스템에서 실행시켜야 하기 때문에 /etc/uwsgi/sites/ 경로에 설정파일을 저장하기 위한폴더를 생성한다. 

$ sudo mkdir -p /etc/uwsgi/sites
$ cd /etc/uwsgi/sites


위 폴더에 서비스할 프로젝트의 설정파일을 각각 생성해야 한다. uWSGI 는 다양한 포맷의 설정파일을 가져올 수 있지만, 본 가이드에서는 간단하게 .ini 파일을 사용할 것이다.


vi 또는 nano 등을 이용하여  .ini 파일을 만든다.


$ sudo vi firstsite.ini


.ini 파일의 시작줄에는 [uwsgi] 라는 section header 로 시작되어야 하고 모든 설정은 이 섹션 아래에 있어야 한다. project 이름과 home 폴더는 재사용하기 위해서 변수 projectbase 로 만들어준다.


[uwsgi]

project = firstsite

base = /home/user


project 명 또는 home 폴더가 변경되면 자동으로 바뀔 수 있도록 %(변수명) 을 이용하여 project, base 의 폴더 경로를 chdir 옵션을 설정해 준다. 비슷한 방식으로 환경 변수들을 설정해 준다. module 에 설정한 값은 project 안의 wsgi.py 파일의 "application" 을 import 한다는 뜻이다.


[uwsgi]

project = firstsite

base = /home/user


chdir = %(base)/%(project)

home = %(base)/Env/%(project)

module = %(project).wsgi:application


5 개의 워커를 가진 마스터 프로세스를 설정해 준다.


[uwsgi]

project = firstsite

base = /home/user


chdir = %(base)/%(project)

home = %(base)/Env/%(project)

module = %(project).wsgi:application


master = true

processes = 5


다음으로 uWSGI 가 어떻게 네트워크를 연결해야 할지를 설정한다. 위의 uWSGI 테스트에서는 HTTP 와 네트워크 port 를 사용했다. 하지만 역프로시(reverse proxy)로써 Nginx 를 사용할 것이다. 


모든 컴포넌트들이 한 서버에서 실행하기 때문에 네트워크 port 를 사용하는 대신 Unix socket 을 사용할 수 있다. Unix socket 은 안전하고 좋은 성능을 제공한다. 이 socket 은 HTTP 를 사용하지 않지만, 다른 서버와 통신하기 위해 디자인된 바이너리 프로토콜인 uWSGI의 uwsgi 프로토콜을 사용한다. Nginx 는 기본적으로 uwsgi 프로토콜을 사용할 수 있기 때문에 unix socket 이 가장 좋은 선택이다.


웹 서버가 쓰기 권한을 가질 수 있도록 socket 의 권한을 수정한다. socket 파일이 서비스가 종료되면 자동적으로 지워질 수 있도록 vacuum 옵션을 설정할 것이다.


[uwsgi]

project = firstsite

base = /home/user


chdir = %(base)/%(project)

home = %(base)/Env/%(project)

module = %(project).wsgi:application


master = true

processes = 5


socket = %(base)/%(project)/%(project).sock

chmod-socket = 664

vacuum = true


이렇게 첫번째 프로젝트의 uWSGI 설정이 끝났다. 


파일에서 변수를 사용하면 재사용성이 좋아진다. 첫번째 프로젝트의 설정파일을 두번째 프로젝트를 위해서 복사한다.


$ sudo cp /etc/uwsgi/sites/firstsite.ini /etc/uwsgi/sites/secondsite.ini


vi 또는 nano 등을 이용하여  .ini 파일을 연다.


$ sudo vi /etc/uwsgi/sites/secondsite.ini


첫번재 프로젝트의 환경설정에서 변수를 사용했기 때문에 두번째 프로젝트를 위해서 project 변수의 값만 바꾸면 된다. 


[uwsgi]

project = secondsite

base = /home/user


chdir = %(base)/%(project)

home = %(base)/Env/%(project)

module = %(project).wsgi:application


master = true

processes = 5


socket = %(base)/%(project)/%(project).sock

chmod-socket = 664

vacuum = true


이렇게 두번째 프로젝트 설정파일도 준비되었다.

uWSGI 를 위한 Upstart 스크립트 생성하기

Django 프로젝트를 서비스하기 위한 설정파일이 준비되었다. 하지만, 아직 자동화된 프로세스는 아니기 때문에 부팅시에 uWSGI 를 자동으로 시작시켜주기위한 Upstart 스크립트를 생성할 것이다.

Upstart 스크립트 파일은 /etc/init 폴더에 생성한다.


$ sudo vi /etc/init/uwsgi.conf


uWSGI 서비스를 위한 설명을 작성해 주고 자동적으로 동작될 때의 런레벨을 알려준다. 여기서는 평범한 멀티 유저 런레벨인 2, 3, 4, 5 를 사용했다. 


description "uWSGI application server in Emperor mode"


start on runlevel [2345]

stop on runlevel [!2345]


다음으로 프로젝트가 어떤 유저와 그룹으로 실행될 지를 설정한다. 유저는 지금까지 파일을 생성한 권한이 있는 사용자로 설정을 하도록 하고 그룹은 www-data 로 설정한다. uWSGI 설정파일에서의 소켓설정은 웹서버가 소켓에 쓰기권한을 가지고 있어야 한다.


description "uWSGI application server in Emperor mode"


start on runlevel [2345]

stop on runlevel [!2345]


setuid user

setgid www-data


마지막으로 실제 실행 명령어를 입력한다. 설정파일이 있는 폴더를 입력하고 uWSGI 를 Emperor 모드로 시작한다. uWSGI 가 해당 파일들을 읽고 각 프로젝트를 서비스하게 된다.


description "uWSGI application server in Emperor mode"


start on runlevel [2345]

stop on runlevel [!2345]


setuid user

setgid www-data


exec /usr/local/bin/uwsgi --emperor /etc/uwsgi/sites


Nginx 를 설치하기 전까지는 www-data 그룹이 없기 때문에 아직 uWSGI 를 시작하지 않는다.

Nginx 설치하기 및 역프록시 설정하기

uWSGI 설정 준비가 되었다. 역프로시로써 Nginx 를 설치하고 설정하자. Nginx 는 ubuntu 의 기본 저장소로부터 다운로드 받을 수 있다.

$ sudo apt-get install nginx

Nginx 가 설치되면 각 프로젝트를 위한 서버블록 설정파일을 만들 수 있다. 첫번째 프로젝트에 대한 서버블록 설정파일부터 만들어보자.

$ sudo vi /etc/nginx/sites-available/firstsite


서버블록 설정파일 안에 첫번째 프로젝트에 접근할 수 있도록 port number 와 도메인 명(또는 IP 주소)을 설정할 수 있다. 


server {

    listen 80;

    server_name firstsite.com www.firstsite.com;

}


다음으로 파비콘을 찾을 수 없어도 실행할 수 있도록 정적 파일 폴더의 경로를 지정해 준다.


server {

    listen 80;

    server_name firstsite.com www.firstsite.com;


    location = /favicon.ico { access_log off; log_not_found off; }

    location /static/ {

        root /home/user/firstsite;

    }

}


그 후, uwsgi_pass 를 이용해서 트래픽을 프로젝트 폴더에 있는 firstproject.sock 소켓 파일로 전달하도록 지정한다. 또한, include 를 이용하여 네트워크 연결 핸들링에 필요한 uwsgi 파라미터를 포함시킨다.


server {

    listen 80;

    server_name firstsite.com www.firstsite.com;


    location = /favicon.ico { access_log off; log_not_found off; }

    location /static/ {

        root /home/user/firstsite;

    }

 

    location / {

        include            uwsgi_params;

        uwsgi_pass      unix: /home/user/firstsite/firstsite.sock;

    }

}


이제 실행하기 위한 설정이 끝났다. 두번째 프로젝트의 Nginx 설정 파일 을 위해 복사한다.


$ sudo cp /etc/nginx/sites-available/firstsite /etc/nginx/sites-available/secondsite


vi 명령어를 통해 파일을 열고 두번째 프로젝트를 위해 firstsite 로 설정된 값들을 secondsite 로 바꿔주고 server_name 의 도메인 명을 바꿔준다.


$ sudo vi /etc/nginx/sites-available/secondsite


server {

    listen 80;

    server_name secondsite.com www.secondsite.com;


    location = /favicon.ico { access_log off; log_not_found off; }

    location /static/ {

        root /home/user/secondsite;

    }

 

    location / {

        include            uwsgi_params;

        uwsgi_pass      unix: /home/user/secondsite/secondsite.sock;

    }

}


저장하고 종료한다.


다음으로 설정 파일들을 사용하기 위해 Nginx 의 sites-enabled 폴더에 두 설정 파일들의 링크를 생성한다. (기본적으로 설정파일들을 만들 때는 sites-available 폴더에 만들어 놓고, 서비스를 운영할 때는 설정파일들은 sites-enabled 폴더로 링크복사해서 사용한다.)


$ sudo ln -s /etc/nginx/sites-available/firstsite /etc/nginx/sites-enabled

$ sudo ln -s /etc/nginx/sites-available/secondsite /etc/nginx/sites-enabled


Nginx 의 설정파일이 정상적으로 만들어졌는지 체크해보자.


$ sudo service nginx configtest


설정파일이 문제가 없다면 Nginx 를 재시작해서 설정파일을 다시 로딩한다.


$ sudo service nginx restart


아직 uWSGI 를 시작한 적이 없기 때문에 uWSGI 역시 동작시킨다.


$ sudo service uwsgi start


이제 전에 만들었던 두 프로젝트에 접근할 수 있게 된다. 기대한대로 프로젝트의 일반 사이트와 어드민 사이트가 제대로 동작될 것이다.


'Python > Django' 카테고리의 다른 글

[Django] values() values_list() flat  (0) 2016.10.26
[Django] File upload (FileField, ImageField)  (0) 2016.10.19
[Django] Test  (0) 2016.10.12
[Django] Extra  (0) 2016.10.06
[Django] Filter vs Exclude  (0) 2016.10.04

댓글