Experiments never fail s2

실험에 실패란 없다 블로그 시즌 2

Mac OS X에서 Django, uWSGI, Nginx 서비스 설정

Pythonist - 2014년 3월 25일 5:08:22 오후

맥프로에 장고(Django) 웹 어플리케이션을 올려야 하는 고객이 있다. 무지막지한 맥프로의 성능에 잠시 놀란 후, 제대로된 서비스 환경을 구축하고 싶은 맘에 성능이 제일 좋다는 Django, uWSGI, Nginx 조합을 써보기로 했다.

Mac OS X에는 이미 아파치(Apache)가 깔려 있는데, 저 서버에 mod_wsgi를 연동하는 것도 방법이겠지만, 맥에서 기본 제공되는 웹서버를 건드는 것이 뭔가 아닌 것 같아, 새로 엔진엑스(Nginx)를 설치해 쓰기로 하다. 그리고, 재부팅시에도 자동 실행되는 설정까지 해야 함. 구글에서 자료들을 찾아봤지만 딱히 맘에 드는 자료를 못찾고는, 직접 이것저것 해보고 정리해보다.

Nginx

아파치보다 훨씬 가볍고 높은 성능을 낸다는 Nginx. Mac OS X에서는 homebrew를 이용하여 다음처럼 설치한다.

yong27@saturn:~ » brew install nginx

Nginx 가 어떻게 설치됐는지, 설정을 어떻게 바꿔야 하는지 알고 싶으면 brew info nginx

yong27@saturn:~ » brew info nginx
nginx: stable 1.4.7 (bottled), devel 1.5.12, HEAD
http://nginx.org/
/usr/local/Cellar/nginx/1.4.6 (7 files, 876K)
  Poured from bottle
/usr/local/Cellar/nginx/1.4.7 (7 files, 888K) *
  Poured from bottle
From: https://github.com/Homebrew/homebrew/commits/master/Library/Formula/nginx.rb
==> Dependencies
Required: pcre ✔, openssl ✔
Optional: passenger ✘
==> Options
--with-debug
Compile with support for debug log
--with-gunzip
Compile with support for gunzip module
--with-passenger
Compile with support for Phusion Passenger module
--with-spdy
Compile with support for SPDY module
--with-webdav
Compile with support for WebDAV module
--devel
install development version 1.5.12
--HEAD
install HEAD version
==> Caveats
Docroot is: /usr/local/var/www

The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that nginx can run without sudo.

To have launchd start nginx at login:
    ln -sfv /usr/local/opt/nginx/*.plist ~/Library/LaunchAgents
Then to load nginx now:
    launchctl load ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist
Or, if you don't want/need launchctl, you can just run:
    nginx
yong27@saturn:~ »

어찌어찌 설치됐고, 데몬 서비스 등록을 하려면 어떻게 해야하는지가 표시된다. 설정파일은 /usr/local/etc/nginx/nginx.conf 를 사용해야 함. 여기 설정은 일단 다음처럼,

worker_processes  4;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location /static {
            alias /Users/yong27/work/django-project/django-app/static/;
            autoindex off;
        }
        location /media {
            alias /Users/yong27/work/django-project/media/;
            autoindex off;
        }
        location / {
            include uwsgi_params;
            uwsgi_pass unix:///tmp/uwsgi_django.sock;
        }
    }
}

/static 과 /media 를 위한 alias 설정을 했고, uWSGI는 /tmp/uwsgi_django.sock 으로 연결된다.

이를 데몬 서비스로 등록하려면 brew info nginx 에 나온 것 처럼 plist 파일을 ~/Library/LaunchAgents 에 링크해야 하나, 80포트로 서비스해야 하므로, /Library/LaunchDemons에 링크한다.

yong27@saturn:~ » sudo ln -svf /usr/local/opt/nginx/homebrew.mxcl.nginx.plist /Library/LaunchDaemons
Password:
/Library/LaunchAgents/homebrew.mxcl.nginx.plist -> /usr/local/opt/nginx/homebrew.mxcl.nginx.plist
yong27@saturn:~ » sudo chown root /Library/LaunchDaemons/homebrew.mxcl.nginx.plist
yong27@saturn:~ » sudo launchctl load -w /Library/LaunchDaemons/homebrew.mxcl.nginx.plist
yong27@saturn:~ »

80포트 서비스를 위해서는 plist 파일의 소유권도 root 이어야 한다.

uWSGI

uWSGI 는 pip3으로 설치한다. homebrew 로 설치할 수 도 있는데, 그 경우, 디폴트 파이썬인 python2.7과 연결된다. 내 프로젝트가 python3.4에서 돌아야 한다면 uWSGI는 pip3으로 설치해야 한다.

yong27@saturn:~ » pip3 install uwsgi

uwsgi를 구동하기 위한 ini 파일은 다음처럼 설정한다. my_uwsgi.ini 파일을 Django 프로젝트 디렉토리에 만든다.

[uwsgi]
chdir=/Users/yong27/django-project
module=django-project.wsgi:application
master=true
pidfile=/tmp/uwsgi_django.pid
socket=/tmp/uwsgi_django.sock
vacuum=true
max-request=500
demonize=/var/log/uwsgi/django.log

위 설정에서 chdir 은 나의 Django 프로젝트가 있는 경로를 의미하고, module은 실제 Django 프로젝트 경로안의 wsgi.py 파일의 application 이름(함수)를 가르킨다.

uWSGI의 실행은 다음처럼 가능하다.

yong27@saturn:~ » uwsgi --ini my_uwsgi.ini --chmod-socket=666

socket 파일권한 666 설정은 좀 맘에 안드는데, 저걸 안해주면 /tmp 디렉토리임에 있음에도 불구하고 nginx 에서 권한이 없다고 나온다. 왜 그런지 알 수 없는 부분. (일단은 이렇게)

위 실행을 데몬으로 만들어야 하는데 그러기 위해서는 다음과 같은 it.unbit.uwsgi.plist 파일을 직접 만들어야 한다. (uwsgi github 페이지 예제 참고)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/
PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>it.unbit.uwsgi</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/uwsgi</string>
        <string>--ini</string>
        <string>/Users/yong27/django-project/django-project/my_uwsgi.ini</string>
        <string>--chmod-socket=666</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

위 plist 파일을 Mac OS X의 데몬으로 만들기 위해 다음처럼 진행.

yong27@saturn:~ » ln -sfv it.unbit.uwsgi.plist ~/Library/LaunchAgents
yong27@saturn:~ » launchctl load ~/Library/LaunchAgents/it.unbit.uwsgi.plist
yong27@saturn:~ » launchctl start it.unbit.uwsgi.plist

코드저장소에는 it.unbit.uwsgi.plist.sample 파일, my_uwsgi.ini.sample 파일을 Django 프로젝트 사이트 경로에 복사에 두면 다른 사람들도 복사해 쓰기 좋다.

이렇게 하고 나면 재부팅하고 나서도 깔끔하게 Django 어플리케이션 동작.


Posted by Hyungyong Kim (yong27)

태그(들): django, homebrew, mac, nginx, osx, python3, uwsgi


comments powered by Disqus

« 파이썬 멀티프로세싱 함수는 Celery로 처리할 수 없다?

올해부터 있었던 Moves-Momento 동기화 문제가 수정됨 »