Django-Deploy_EC2(uwsgi/nginx)

본 문서는 패스트캠퍼스 ‘Web-Programming School’ 수업 자료를 바탕으로 작성되었습니다.


[summary]

Nginx (Web server)
    80번 포트 요청을 받아서 uWSGI와 서로 통신

uWSGI (Web Server Gateway Interface)
    Nginx로부터 받아온 요청을 Django에서 처리한 후 돌려줌

---
Service
    우리가 직접 실행한 프로그램이 아닌, 백그라운드에서 실행되고 있는 프로세스
    Nginx의 경우에는 기본적으로 서비스에 등록되어있음
    uWSGI는 아님
직접 등록하는 Service의 경우
    /etc/systemd/system/<서비스명>.service 파일에 작성

uWSGI의 Service에 대한 정보 파일
    /etc/systemd/system/uwsgi.service
        -> 이후 sudo systemctl <명령어> uwsgi <- 이부분에 사용 가능

---
EC2-Deploy 프로젝트
 프로젝트 경로
    /srv/ec2-deploy
 프로젝트 소스 루트 (파이썬 환경에서의 최상위 폴더, 파이썬 애플리케이션의 위치)
    /srv/ec2-deploy/app
 파이썬 가상환경
    /home/ubuntu/.pyenv/versions/fc-ec2-deploy
 uWSGI프로그램의 위치
    /home/ubuntu/.pyenv/versions/fc-ec2-deploy/bin/uwsgi

EC2-Deploy 프로젝트의 '배포용' 설정들
 Nginx 가상서버 설정
    /srv/ec2-deploy/.config/nginx-app.conf
 uWSGI 설정
    /srv/ec2-deploy/.config/uwsgi.ini
 uWSGI의 '서비스'설정
    /srv/ec2-deploy/.config/uwsgi.service

1. Django runserver (0:8000) 접속 확인
2. uwsgi에 직접 옵션붙여서 실행 후 접속 확인
3. 옵션들을 정리한 ini파일을 사용해서 uwsgi --ini <ini파일경로>로 실행 후 접속 확인
4. uwsgi서비스를 등록후 접속 확인
    파일을 /etc/systemd/system/ 폴더에 복사
    sudo systemctl enable uwsgi
    sudo systemctl daemon-reload
    sudo systemctl restart uwsgi
    -> /tmp/app.sock파일을 리눅스 소켓으로 사용해서 uwsgi를 실행하도록 함
5. /tmp/app.sock파일과 통신하는 Nginx 가상서버 설정을 생성 및 링크
    5-1. 파일 복사
        sudo cp -f /srv/ec2-deploy/.config/nginx-app.conf \
            /etc/nginx/sites-available/nginx-app.conf
    5-2. sites-enabled폴더의 모든 링크 삭제
        sudo rm -rf /etc/nginx/sites-enabled/*.*
    5-3. 복사한 파일의 링크를 sites-enable에 생성
        sudo ln -sf /etc/nginx/sites-available/nginx-app.conf \
                        /etc/nginx/sites-enabled/nginx-app.conf
    5-4. sudo systemctl daemon-reload
            sudo systemctl restart nginx

Django 새 프로젝트 시작하기

주의 AWS서버가 아니라 로컬에서 설정
아래와 같은 구조로 Django 새 프로젝트 시작하기

.
├── ec2-deploy
│   ├── app
│   │   ├── config
│   │   │   ├── __init__.py
│   │   │   ├── settings.py
│   │   │   ├── urls.py
│   │   │   └── wsgi.py
│   │   └── manage.py
│   └── requirements.txt  / gitignore도 포함

ALLOWED_HOSTS 설정

# app/config/seetings.py

ALLOWED_HOSTS = [
    '.amazonaws.com'
]

SECRET 파일 관리하기

  • app과 같은 위치에 .secrets 디렉토리를 생성
  • app/config/settings.py에서 SECRET_KEY 복사
  • .secrets/base.json 파일 생성
/* 주의 항상 ""(큰따옴표)사용하고, 뒤에 ,(쉼표)가 붙으면 안됨 */
{
  "SECRET_KEY" : "YOUR DJANGO SECRET_KEY"
}
  • app/config/settings.py json 로드 및 설정
# config/settings.py
import json
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# ec2-deploy
ROOT_DIR = os.path.dirname(BASE_DIR)
# ec2-deploy/.secrets
SECRET_DIR = os.path.join(ROOT_DIR, '.secrets')
# ec2-deploy/.secrets/base.json
SECRET_BASE = os.path.join(SECRET_DIR, 'base.json')

# base.json 파일을 읽어온 결과를 파이썬 객체로 변환
secrets_base = json.loads(open(SECRET_BASE, 'rt').read())
print(secrets_base)
  • ./manage.py 명령어로 secrets_base 가 출력되는지 확인
  • .gitignore.secrets 추가
  • app과 같은 위치에 README.md 작성
  • 그리고 commit and push

EC2-Deploy nginx, uwsgi파일 설정

  1. pip install uwsgi 설치
  2. requirements.txt 파일 업데이트
  3. app과 같은 위치에 .config 디렉토리 생성
  4. nginx.conf / uwsgi.ini/ uwsgi.service 파일 생성
<!-- app과 같은 위치 확인 -->
.
├── ec2-deploy
|   ├── .config
|   |
│   ├── app
│   │   ├── config
│   │   │   ├── __init__.py
│   │   │   ├── __pycache__
│   │   │   │   ├── __init__.cpython-36.pyc
│   │   │   │   └── settings.cpython-36.pyc
│   │   │   ├── settings.py
│   │   │   ├── urls.py
│   │   │   └── wsgi.py
│   │   └── manage.py
│   ├── README.md
│   └── requirements.txt

nignx.conf 파일
server {
    listen 80;
    server_name *.amazonaws.com localhost;
    charset utf-8;
    client_max_body_size 128M;

    location / {
        uwsgi_pass unix:///tmp/app.sock;
        include uwsgi_params;
    }

    location /media/ {
        alias /srv/ec2-deploy/.media/;
    }

    location /static/ {
        alias /srv/ec2-deploy/.static/;
    }
}
uwsgi.ini 파일
;EC2-Depoly Django project uwsgi setting file

[uwsgi]
chdir = /srv/ec2-deploy/app
home = /home/ubuntu/.pyenv/versions/fc-ec2-deploy
module = config.wsgi
;http = :8000
;unix소켓으로 통신으로 하기 위해서
uid=ubuntu
git=ubuntu
socket = /tmp/app.sock
chmod-socket=666
chwon-socket=ubuntu:ubuntu

master = true
vacuum = true
logto = /tmp/uwsgi.log
log-reopen = true
uwsgi.service 파일
[Unit]
Desciption = EC2 Deploy uWSGI service
After = syslog.target

[Service]
ExecStart = /home/ubuntu/.pyenv/versions/fc-ec2-deploy/bin/uwsgi -i /srv/ec2-deploy/.config/uwsgi.ini

Restart = always
KillSignal = SIGQUIT
Type = notfiy
StandardError = syslog
NotifyAccess = all

[Install]
WnatedBy = multi-user.target

SCP로 서버에 파일 옮기기

시큐어 카피(Secure copy) 또는 SCP는 로컬 호스트와 원격 호스트 간 또는 두 개의 원격 호스트 간에 컴퓨터 파일을 안전하게 전송하는 수단이다. 시큐어 셸(SSH) 프로토콜 기반

  • 명령어 :scp 원본파일 사용자@호스트주소:디렉터리/대상파일
  • 기존의 파일을 덮어쓰우긴 하지만, 만약 파일을 삭제하고 업데이트 하면 복사된 장소에는 그 파일이 여전히 남아 있다. 그래서 SCP 로 같은 파일을 업데이트하는 경우 삭제 후, 다시 복사를 하는것이 좋다.
>> scp -i ~/.ssh/<your private key (.pem)> \
-r ~/projects/django/depoly/ec2-deploy \
ubuntu@<DNS주소>\
:/srv/ec2-deploy

>> ssh -i ~/.ssh/<your private key (.pem)> \
ubuntu@e<DNS주소> rm -rf /srv/ec2-deploy
SCP명령어 zshell alias로 설정하기

주의 AWS서버가 아니라 로컬에서 설정

  • SCP를 위해 매번 위 명령어를 실행하는 것이 번거롭기 때문에, zshell alias로 긴 명령어를 짧게 사용하자.
  • ~/.zshrc 저장 후엔 재접속
<!-- vim ~/.zshrc -->
#scp
EC2_USER="ubuntu"
EC2_DOMAIN="<your AWS domain>"
EC2_PEM="~/.ssh/<your private key(.pem)>"
EC2_DIR="~/projects/django/deploy/ec2-deploy"

#ssh 서버 접속
alias con-ec2="ssh -i $EC2_PEM $EC2_USER@$EC2_DOMAIN"
#scp 파일 복사
alias copy-ec2="scp -i $EC2_PEM -r $EC2_DIR $EC2_USER@$EC2_DOMAIN:/srv"
#ssh 파일 삭제 후, 파일 복사 실행
alias deploy-ec2="con-ec2 rm -rf /srv/ec2-deploy; copy-ec2"
  • deploy-ec2 명령어 실행
>> deploy-ec2
README.md                                     100%  337     0.3KB/s   00:00
.gitignore                                    100% 3603     3.5KB/s   00:00
requirements.txt                              100%  279     0.3KB/s   00:00
COMMIT_EDITMSG                                100%    7     0.0KB/s   00:00
master                                        100%  151     0.2KB/s   00:00
master                                        100%  141     0.1KB/s   00:00
HEAD                                          100%  151     0.2KB/s   00:00
config                                        100%  202     0.2KB/s   00:00
description                                   100%   73     0.1KB/s   00:00
master                                        100%   41     0.0KB/s   00:00
master                                        100%   41     0.0KB/s   00:00
exclude                                       100%  240     0.2KB/s   00:00
HEAD                                          100%   23     0.0KB/s   00:00
  • 서버에서 /srv/ec2-deploy 파일있는지 확인

서버 ec2-deploy 설정하기

  1. fc-ec2-deploy pyenv 가상 환경 적용하기
  2. pip install -r requirements.txt 설치

EC2 -> Django (:8000)

  • aws 도메인주소:8000 접속 시, 장고 welcome 을 보면 정상 작동
>> ./manage.py runserver 0:8000

EC2 -> uWSGI (:8000) -> Django

명령어 실행
>> /home/ubuntu/.pyenv/versions/fc-ec2-deploy/bin/uwsgi \
--http :8000 \
--chdir /srv/ec2-deploy/app \
--home /home/ubuntu/.pyenv/versions/fc-ec2-deploy \
--module config.wsgi
EC2 -> Nginx <->(Unix Socket) uWSGI-> Django
uwsgi.service 설정을 통해 uWSGI실행

Nginx 와 Unix socket통신이 이루어짐

>> sudo cp -f /srv/ec2-deploy/.config/uwsgi.service \ /etc/systemd/system/uwsgi.service
>> sudo systemctl enable uwsgi
>> sudo systemctl daemon-reload
>> sudo systemctl restart uwsgi

명령어를 통해 현재 위의 서비스가 잘 실행되고 있는지 확인

>> systemctl | grep running

uwsgi.service                                     loaded active running
nginx.service                                     loaded active running   A high performance web server and a reverse proxy server

/tmp/app.sock파일과 통신하는 Nginx 가상서버 설정을 생성 및 링크

uwsgi에서 오는 소켓과 통신하기 위한 Nginx 가상서버 설정을 한다. nginx에 설정 내용을 적용한뒤, 브라우저 도메인 주소로 접속하면 장고의 웰컴 페이지를 볼 수 있다!

>> sudo cp -f /srv/ec2-deploy/.config/nginx-app.conf \
/ect/nginx/sites-abailable/nginx-app.conf
<!-- 통신 방해요소가 될 수 있으므로 지움 -->
>> sudo rm -rf /etc/nginx/sites-enable/*
<!-- 심볼릭 링크 생성 -->
>> sudo ln -sf /etc/nginx/sites-available/nginx-app.conf \
/etc/naginx/sites-enabled/nginx-app.conf

>> sudo systemctl daemon-reload
>> sudo systemctl restart nginx
daemon

멀티태스킹 운영 체제에서 데몬은 사용자가 직접적으로 제어하지 않고, 백그라운드에서 돌면서 여러 작업을 하는 프로그램을 말한다. 시스템 로그를 남기는 syslogd처럼 보통 데몬을 뜻하는 ‘d’를 이름 끝에 달고 있으며, 일반적으로 프로세스로 실행된다. 데몬은 대개 부모 프로세스를 갖지 않으며, 즉 PPID가 1이며, 따라서 프로세스 트리에서 init 바로 아래에 위치한다. 데몬이 되는 방법은 일반적으로 자식 프로세스를 포크(fork)하여 생성하고 자식을 분기한 자신을 죽이면서 init이 고아가 된 자식 프로세스를 자기 밑으로 데려가도록 하는 방식이다. 이러한 방법을 ‘fork off and die’라 부르기도 한다.