[컴] Django + postgresql + uwsgi + nginx 설치하기, 배포하기




PostgreSQL 설치

여기 django 는 PostgreSQL 을 사용하기에 PostgreSQL 을 미리 설치하자. 설치방법은 아래 링크를 확인하자.


Django + uWSGI + nginx 설치

위의 문서를 기준으로 여기서 따라 해 봤다.





Deploy Django


admin 계정으로 할일

apt package list update

$ sudo apt-get update

package 설치

apt-get install python2.7 python-pip virtualenv libpq-dev python-dev

python-dev, libpq-dev 설치하기
python-dev 와 libpg-dev 는 virtualenv 에 설치할 psycopg2 를 위해 필요하다. 아래 사항을 참고하자.


user 계정으로 할 일

virtualenv env

env 라는 이름의 virtualenv 를 만든다.
django@namh-VirtualBox:~$ virtualenv env
New python executable in env/bin/python
Installing setuptools, pip, wheel...done.

activate, virtualenv 활성화

django@namh-VirtualBox:~/env$ source bin/activate
(env)django@namh-VirtualBox:~/env$ 


pip install -r requirements.txt

이제 django project file 을 가져와서 원하는 path 에 옮겨놓는다. 그리고 설치할 package 들의 목록인 requirements 를 이용해서 필요한 package 를 설치 해 준다.

$ pip install -r ./requirements/production.txt



syncdb

(env)django@myuser-VirtualBox:~/app/myproject$ ./manage.py syncdb --settings=myproject.settings.production
Operations to perform:
  Synchronize unmigrated apps: staticfiles, rest_framework, messages
  Apply all migrations: authtoken, sessions, admin, sites, auth, handsetcare, contenttypes, tinyurl
Synchronizing apps without migrations:
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying authtoken.0001_initial... OK
  Applying tinyurl.0001_initial... OK
  Applying tinyurl.0002_auto_20151007_1901... OK
  ...
  Applying sessions.0001_initial... OK
  Applying sites.0001_initial... OK

You have installed Django's auth system, and don't have any superusers defined.
Would you like to create one now? (yes/no): yes     
Username (leave blank to use 'django'): admin_account
Email address: adminemail@mail.com
Password: 
Password (again): 
Superuser created successfully.
(env)django@myuser-VirtualBox:~/app/myproject$ 


loaddata

db 에 처음에 들어갈 값을 넣어주는 작업이다. 아래를 참고하자.



runserver

서버 실행해서 제대로 서버가 뜨면 아래처럼 된다.

(env)django@myuser-VirtualBox:~/app/myproject$ ./manage.py runserver 0.0.0.0:8080 --settings=myproject.settings.production
Performing system checks...

System check identified no issues (0 silenced).
October 27, 2015 - 07:35:54
Django version 1.8.4, using settings 'myproject.settings.production'
Starting development server at http://0.0.0.0:8080/
Quit the server with CONTROL-C.





uwsgi

uwsgi 설치

주의할 점은 python 의 pip 를 통해서 설치하는 것이다. apt-get 을 통해서 설치할 필요가 없다. 그리고 apt-get 을 통해서 설치를 하고 pip install uwsgi 를 한 경우에 아래같은 error 가 나올 수 있다.
-- unavailable modifier requested: 0 --


(env)django@namh-VirtualBox:~/app/myproject$ sudo apt-get install uwsgi-core

(env)django@namh-VirtualBox:~/app/myproject$ pip install uwsgi
Collecting uwsgi
/home/django/env/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning
  Downloading uwsgi-2.0.11.2.tar.gz (782kB)
    100% |████████████████████████████████| 782kB 94kB/s 
Building wheels for collected packages: uwsgi
  Running setup.py bdist_wheel for uwsgi
  Stored in directory: /home/django/.cache/pip/wheels/a7/33/50/7bb71db37249e30aabe7c1247f283bc19e299b533597c8bafd
Successfully built uwsgi
Installing collected packages: uwsgi
Successfully installed uwsgi-2.0.11.2



uwsgi 실행

# source from : https://uwsgi.readthedocs.org/en/latest/tutorials/Django_and_nginx.html
# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    #return [b"Hello World"] # python3
    return ["Hello World"] # python2


(env)django@namh-VirtualBox:~/app$ uwsgi --http :8000 --wsgi-file test.py
*** Starting uWSGI 2.0.11.2 (64bit) on [Tue Oct 27 21:42:14 2015] ***
compiled with version: 4.8.4 on 27 October 2015 21:38:47
os: Linux-3.19.0-31-generic #36~14.04.1-Ubuntu SMP Thu Oct 8 10:21:08 UTC 2015
nodename: namh-VirtualBox
machine: x86_64
clock source: unix
detected number of CPU cores: 1
current working directory: /home/django/app
detected binary path: /home/django/env/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 7918
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :8000 fd 4
spawned uWSGI http 1 (pid: 15206)
uwsgi socket 0 bound to TCP address 127.0.0.1:55924 (port auto-assigned) fd 3
Python version: 2.7.6 (default, Jun 22 2015, 18:01:27)  [GCC 4.8.2]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0xb25fc0
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72768 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0xb25fc0 pid: 15205 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 15205, cores: 1)


uwsgi 로 django project 실행하기

uwsgi 가 원래 project 이름으로 된 module 안에 있는 wsgi.py 를 사용하는데, 이 녀석을 지정해 주고 실행 하면 된다.
(env)django@namh-VirtualBox:~/app/myproejct$ uwsgi --http :8000 --module myproject.wsgi --env DJANGO_SETTINGS_MODULE=myproject.settings.production

이 부분을 .ini 파일로 만들어서 사용할 수 있다.
[uwsgi]
socket=127.0.0.1:49152
processes=5
chdir=/home/django/app/myproject
module=myproject.wsgi:application
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000


(env)django@namh-VirtualBox:~/app$ uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production
[uWSGI] getting INI configuration from uwsgi.ini
*** Starting uWSGI 2.0.11.2 (64bit) on [Wed Oct 28 10:32:22 2015] ***
compiled with version: 4.8.4 on 27 October 2015 21:38:47
os: Linux-3.19.0-31-generic #36~14.04.1-Ubuntu SMP Thu Oct 8 10:21:08 UTC 2015
nodename: namh-VirtualBox
machine: x86_64
clock source: unix
detected number of CPU cores: 1
current working directory: /home/django/app
writing pidfile to /tmp/project-master.pid
detected binary path: /home/django/env/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
chdir() to /home/django/app/myproject
your processes number limit is 7918
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address 127.0.0.1:49152 fd 3
Python version: 2.7.6 (default, Jun 22 2015, 18:01:27)  [GCC 4.8.2]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x82ae00
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 436608 bytes (426 KB) for 5 cores
*** Operational MODE: preforking ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x82ae00 pid: 16531 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 16531)
spawned uWSGI worker 1 (pid: 16534, cores: 1)
spawned uWSGI worker 2 (pid: 16535, cores: 1)
spawned uWSGI worker 3 (pid: 16536, cores: 1)
spawned uWSGI worker 4 (pid: 16537, cores: 1)
spawned uWSGI worker 5 (pid: 16538, cores: 1)


uWSGI 사용법


그 밖의 기능들









Nginx


nginx 설치


namh@namh-VirtualBox:/home$ sudo apt-get install nginx
[sudo] password for namh: 
패키지 목록을 읽는 중입니다... 완료
의존성 트리를 만드는 중입니다       
상태 정보를 읽는 중입니다... 완료
다음 패키지를 더 설치할 것입니다:
  nginx-common nginx-core
제안하는 패키지:
  fcgiwrap nginx-doc
다음 새 패키지를 설치할 것입니다:
  nginx nginx-common nginx-core
0개 업그레이드, 3개 새로 설치, 0개 제거 및 1개 업그레이드 안 함.
348 k바이트 아카이브를 받아야 합니다.
이 작업 후 1,297 k바이트의 디스크 공간을 더 사용하게 됩니다.
계속 하시겠습니까? [Y/n] 
$ sudo /etc/init.d/nginx start

$ ps aux | grep ng
...
django   16531  0.0  1.5 150272 32536 pts/1    S+   10:32   0:00 uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production
django   16534  0.0  1.2 150272 25388 pts/1    S+   10:32   0:00 uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production
django   16535  0.0  1.2 150272 25388 pts/1    S+   10:32   0:00 uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production
django   16536  0.0  1.2 150272 25388 pts/1    S+   10:32   0:00 uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production
django   16537  0.0  1.2 150272 25388 pts/1    S+   10:32   0:00 uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production
django   16538  0.0  1.2 150272 25388 pts/1    S+   10:32   0:00 uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production
root     17142  0.0  0.1  85888  2880 ?        Ss   11:01   0:00 nginx: master process /usr/sbin/nginx
www-data 17143  0.0  0.1  86228  3604 ?        S    11:01   0:00 nginx: worker process
www-data 17144  0.0  0.1  86228  3604 ?        S    11:01   0:00 nginx: worker process
www-data 17145  0.0  0.1  86228  3604 ?        S    11:01   0:00 nginx: worker process
www-data 17146  0.0  0.1  86228  3604 ?        S    11:01   0:00 nginx: worker process

여기까지 하면 nginx 를 80 port 로 확인할 수 있다.




nginx 에서 static file 서비스하기

nginx.conf 만들기

ngix 의 설정파일을

  • etc/nginx/sites-enabled/

에 넣어줘야 하는데, 이 부분을 project 에 file 을 만드록, symbolic link 를 만들어서 해결할 것이다.
만약 내 nginx conf 를 ~/app/nginx.conf 에 넣었다면, 아래처럼 해주면 된다.
$sudo ln -s ~/app/nginx.conf /etc/nginx/sites-enabled/


# nginx.conf

# the upstream component nginx needs to connect to
upstream django {
    # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

# for ssl
# server {
#     listen  8080;
#     return 301 https://192.168.0.108/;
# }


# configuration of the server
server {
    # the port your site will be served on
    listen      8000;
    # the domain name it will serve for
    server_name .myprojectis.net; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # for ssl
    # listen 443;
    # ssl on;
    # ssl_certificate /etc/nginx/cert/dummy-cert.pem;
    # ssl_certificate_key /etc/nginx/cert/dummy-key.pem;
    # ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    # ssl_ciphers          HIGH:!aNULL:!MD5;


    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media  {
        alias /home/django/app/myproject/mystatic;  # your Django project's media files - amend as required
    }

    location /static {
        alias /home/django/app/myproject/mystatic; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        uwsgi_read_timeout 180s;
        include     /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
    }
}

uwsgi_read_timeout

uwsgi_read_timeout 을 늘려줬다. django 의 실행타임(execution time) 이 오래걸리면 504 Gateway Time-out 이 발생한다. 아래 글을 참고하자.

django 에서 static file 을 모으기

$python manage.py collectstatic
collectstatic 을 하면 static file 이 STATIC 설정을 한 곳으로 모인다. 자세한 사항은 collectstatic 를 참고하자.

참고로, 다른 webserver 가 static file 을 service 하게 되면, local 에서 collectstatic 을 하고, rsync 로 전송하는 방법을 택하라고 한다.[The staticfiles app | Django documentation]

nginx 재시작
nginx 를 다시 시작하자.
$ sudo /etc/init.d/nginx stop
$ sudo /etc/init.d/nginx start

그리고
  • /var/log/nginx/error.log
를 확인해서 error 가 없는 지 확인하자.


동작 테스트

static file 을 browser 에서 접근해 보면 정상동작 하는지 알 수 있다.
  • http://myprojectis.net:8000/static/test.png



uwsgi 와 연동

위의 nginx 설정에서 upstream django 에 설정한 내용과 port 를 맞추면 된다.

# nginx.conf 
#the upstream component nginx needs to connect to
upstream django {
    # server unix:///home/django/app/myproject/myproject.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}


[uwsgi]
socket=127.0.0.1:8001
processes=5
chdir=/home/django/app/myproject
module=myproject.wsgi:application
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000


uwsgi 를 nginx 와 통신하도록 실행

~/app/myproject$ uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production

이제 browser 를 통해서 django application 의 url 로 접근해 보면 잘 된다.


uwsgi 와 niginx 에서 Unix socket 이용하기


nginx.conf 수정

# nginx.conf 
#the upstream component nginx needs to connect to
upstream django {
    server unix:///tmp/myproject.sock; # for a file socket
    # server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

nginx restart

$ sudo /etc/init.d/nginx restart


uwsgi.ini 수정

socket 의 위치는 /tmp 로 하자. nginx 의 process 중 www-data 로 실행되는 녀석이 접근해야 하는데, local 에 파일을 만들면 접근이 안될 수도 있다. (permission 조절하기 나름이긴 하지만.)

그리고 chmod-socket 은 666 으로 해줘야 한다. 664 로 해준다면 uwsgi 를 실행하는 uid, gid 를 www-data 로 수정해야 한다. 그리고 이렇게 실행하려면 root 권한이 필요하다고 한다.



[uwsgi]
socket=/tmp/yproject.socket
chmod-socket=666
processes=5
chdir=/home/rootbeluga/app/beluga
module=beluga.wsgi:application
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000

uwsgi 실행

$ uwsgi --ini uwsgi.ini --env DJANGO_SETTINGS_MODULE=myproject.settings.production



nginx 를 root 이외의 계정으로 동작하기






댓글 없음:

댓글 쓰기