배포

개념

AWS > EC2 > Nginx (web server)
	1. static 파일은 Nginx 직접 컨트롤
	2. dynamic 파일은 WSGI를 통해 django로 포팅(WSGI 게이트)
Ubuntu Linux
서버의 OS
Nginx
웹 서버, 클라이언트로부터 HTTP요청을 받아 정적인 페이지/파일을 돌려준다.
Django
웹 애플리케이션, 웹 요청에 대해 동적데이터를 돌려준다.
uWSGI
웹 서버(Nginx)와 웹 애플리케이션(Django)간의 연결을 중계해준다. (Nginx에서 받은 요청을 Django에서 처리하기 위한 중계인 역할을 해준다)
WSGI
Web Server Gateway Interface, 파이썬에서 웹 서버와 웹 애플리케이션간의 동작을 중계해주는 인터페이스

프로젝트 생성

  • Helloword 출력하는 간단한 어플리케이션 생성
  • 테스트 코드 작성
  • .conf-secret 폴더 생성하여 키 분리

SSH를 사용하여 리눅스 인스턴스에 연결

Instance 생성

  • AWS에서 가입
  • EC2 메뉴로 이동 (상단바에 서울인지 확인)
  • Key Pairs 메뉴로 이동 후 ‘Create Key Pair’ > .pem 파일 자동으로 다운로드(다시 다운로드 받을 수 없으므로 잘 관리)
  • 다운받은 .pem 파일은 .ssh 폴더에 보관
$ cp ~/Downloads/wps-deploy.pem ~/.ssh
  • Instances 메뉴로 이동 > Launch Instance > Ubuntu Server > Free tier eligible > Review and Launch
  • 메시지가 뜸: Improve your instances’ security. Your security group, launch-wizard-1, is open to the world.
    • Edit security groups > SSH IP를 My IP로 설정, 이름 변경
  • 만들었던 Key를 사용 > Launch Instance
    • Public DNS or IPv4 Public IP로 접속 가능
  • 위에서 다운받은 .pem 파일을 소유주 권한으로 바꿔주기
# -rw-r--r--@  1 limhm  staff   1.7K  3  6 12:27 wps-deploy.pem

# chmod 400 file : Read by owner
$ chmod 400 wps-deploy.pem
# -r--------@  1 limhm  staff   1.7K  3  6 12:27 wps-deploy.pem
  • 접속하기
# sshi -i ~/.ssh/your.pem ubuntu@YOUR_PublicDNS
$ ssh -i ~/.ssh/wps-deploy.pem ubuntu@YOUR_PublicDNS
  • 언어팩 설치
$ sudo apt-get install language-pack-ko
$ sudo locale-gen ko_KR.UTF-8

핑거 프린트 확인

중간자 공격을 막기 위해 핑거 프린트방식을 사용한다. 핑거프린트는 서버의 공개키와 로컬의 개인키로 조합하여 나온다.

다음과 같이 핑거 프린트를 확인 할 수 있다.

$ cd deploy_ec2
$ aws ec2 get-console-output --instance-id YOUR_instanceID

# ...
----BEGIN SSH HOST KEY FINGERPRINTS-----
-----END SSH HOST KEY FINGERPRINTS-----
# ...

Ubuntu 기본설정

# 패키지 인덱스 인덱스 정보를 업데이트
$ sudo apt-get update

# pip 설치
$ sudo apt-get install python-pip

# zsh 설치
$ sudo apt-get install zsh

# oh-my-zsh 설치
$ sudo curl -L http://install.ohmyz.sh | sh

# 기본 shell 변경
# sudo chsh username -s shell
$ sudo chsh ubuntu -s /usr/bin/zsh

# 재접속 후 zsh 설치 확인
$ exit

# pyenv 설치
$ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils
$ curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash
$ vi ~/.zshrc
# .zshrc
export PATH="/home/ubuntu/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
$ source ~/.zshrc

# Pillow 라이브러리 설치
$ sudo apt-get install libtiff5-dev libjpeg8-dev zlib1g-dev \
    libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python-tk

로컬에서 서버로 파일보내기

root 위치의 폴더를 만들기 위해 권한받기

리눅스 디렉토리 구조

# AWS SERVER
# root로 이동
$ cd /
$ pwd
/

$ l
drwxr-xr-x   2 root root 4.0K Jan 13 14:20 srv

# chown [option] 변경할유저이름:변경할그룹이름 파일명
# -R : 하위 디렉토리의 모든 권한을 변경
$ sudo chown -R ubuntu:ubuntu /srv/
$ l
drwxr-xr-x   2 ubuntu ubuntu 4.0K Jan 13 14:20 srv

$ cd srv
$ mkdir app
$ l
drwxrwxr-x  2 ubuntu ubuntu 4.0K Mar  6 05:41 app

내 PC에서 서버로 전송

# MY PC
# 프로젝트 폴더로 이동
$ l
total 24
drwxr-xr-x   9 limhm  staff   306B  3  6 11:40 .
drwxr-xr-x  21 limhm  staff   714B  3  6 11:17 ..
drwxr-xr-x   4 limhm  staff   136B  3  6 11:51 .conf-secret
drwxr-xr-x  12 limhm  staff   408B  3  6 12:09 .git
-rw-r--r--   1 limhm  staff   2.7K  3  6 11:40 .gitignore
drwxr-xr-x   8 limhm  staff   272B  3  6 12:23 .idea
-rw-r--r--   1 limhm  staff    11B  3  6 11:21 .python-version
drwxr-xr-x   6 limhm  staff   204B  3  6 11:40 django_app
-rw-r--r--   1 limhm  staff    31B  3  6 11:29 requirements.txt


$ scp -r -i ~/.ssh/wps-deploy.pem . ubuntu@YOUR_PublicDNS:/srv/app/

서버에서 환경설정

# AWS SERVER
$ pyenv install 3.5.2
$ pyenv virtualenv 3.5.2 deploy_ec2
$ exit

# 가상환결 설정 후 나갔다 들어와서
$ pip install  -r requirements.txt

Security Groups > Inbound rules 추가

  • Custom TCP Rule
  • TCP
  • 8000
  • Anywhere

ALLOWED_HOSTS 설정 변경

$ cd /srv/app/.conf-secret
$ vi settings_local.json
"allowed_hosts": [
		'<ec2 domain name>',
        or
    	'.amazonaws.com',
 ]
$ ./manage.py runserver 0.0.0.0:8000

YOUR_PublicDNS:8000으로 접속 후, 동작하는 것을 확인한다.

패키지 업데이트

# 설치된 패키지 의존성검사하며 설치
$ sudo apt-get dist-upgrade

# 재부팅
$ sudo shutdown -r now
# 재접속
$ ssh -i ~/.ssh/wps-deploy.pem ubuntu@YOUR_PublicDNS
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-64-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.

uWSGI 설정

uWSGI 작동 확인

uWSGI TCP port socket을 사용한 방법

$ sudo adduser nginx
# 비밀번호만 설정

# virtualenv 설정 디렉토리 이동
$ cd /srv/app
$ pip install uwsgi

# uwsgi --http :8000 --home (virtualenv경로) --chdir (django프로젝트 경로) -w (프로젝트명).wsgi
$ uwsgi --http :8000 --home ~/.pyenv/versions/deploy_ec2 --chdir /srv/app/django_app -w deploy_ec2.wsgi

# YOUR_PublicDNS:8000/ 접속해서 작동확인

uWSGI 사이트 파일 작성

uWSGI Unix socket을 사용하는 방법이다. 이 방법은 오버헤드가 더 적기 때문에 좋다.

$ sudo mkdir /etc/uwsgi
$ sudo mkdir /etc/uwsgi/sites
$ sudo vi /etc/uwsgi/sites/app.ini
[uwsgi]
# Django application folder
chdir = /srv/app/django_app
# Django project name.wsgi
module = deploy_ec2.wsgi:application
# VirtualEnv location
home = /home/ubuntu/.pyenv/versions/deploy_ec2

# 서버만 돌리는 권한을 가진 유저를 따로 설정하는 것이 좋음
uid = nginx
gid = nginx

socket = /tmp/app.sock
# 권한이 없어 Permission Denied가 발생하는 것을 방지하기 위해
# 666 : 해당 파일에 대해 읽기, 쓰기 권한
chmod-socket = 666
chown-socket = nginx:nginx

enable-threads = ture
master = true
vacuum = true
pidfile = /tmp/mysite.pid
$ sudo /home/ubuntu/.pyenv/versions/deploy_ec2/bin/uwsgi --http :8000 -i /etc/uwsgi/sites/app.ini

# YOUR_PublicDNS:8000/ 접속해서 작동확인

uWSGI 서비스 설정파일 작성

systemctl

$ sudo vi /etc/systemd/system/uwsgi.service
[Unit]
Description=uWSGI Emperor service
After=syslog.target

[Service]
# /bin/sh is normally a symbolic link to bash
# -c option : Read commands from the following string and assign
# -p option : 존재하지 않는 중간 디렉터리를 자동 생성(계층 구조 생성시 유용)
ExecPre=/bin/sh -c 'mkdir -p /run/uwsgi; chown nginx:nginx /run/uwsgi'

# emperor 모드 : uWSGI config files의 디렉토리를 감시하고
# 변경사항이 발견되면 vassals 인스턴스 생성
# 즉, config files이 수정될 때마다 자동 재시작
ExecStart=/home/ubuntu/.pyenv/versions/deploy_ec2/bin/uwsgi --uid nginx --gid nginx --master --emperor /etc/uwsgi/sites

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

[Install]
WantedBy=multi-user.target
  • systemctl : init 시스템을 제어하기위한 중앙 관리 도구
  • init 시스템 : 또한 시스템이 실행되는 동안 서버의 서비스와 데몬을 관리하는 데 사용
  • 작업의 대상은 “units”
  • 서비스 관리 작업의 경우 .service 파일
$ sudo systemctl restart uwsgi
# ps : 실행중인 프로세스 리스트 출력
# -a : 다른 사용자의 프로세스도 출력
# -x : 사용자가 로그아웃 한 이후에도 실행중인 프로세스 출력
# grep : 특정패턴을 찾는 명령
$ ps -ax | grep uwsgi

$ cd /tmp
$ l
total 36K
drwxrwxrwt  8 root  root  4.0K Mar  6 08:11 .
drwxr-xr-x 23 root  root  4.0K Mar  6 06:32 ..
-rw-r--r--  1 nginx nginx    6 Mar  6 08:48 app.pid
srwxr-xr-x  1 nginx nginx    0 Mar  6 07:37 app.sock
drwxrwxrwt  2 root  root  4.0K Mar  6 06:32 .font-unix
drwxrwxrwt  2 root  root  4.0K Mar  6 06:32 .ICE-unix
-rw-r--r--  1 root  root     5 Mar  6 07:37 mysite.pid
drwx------  3 root  root  4.0K Mar  6 06:32 systemd-cd.service-qzIeDF
drwxrwxrwt  2 root  root  4.0K Mar  6 06:32 .Test-unix
drwxrwxrwt  2 root  root  4.0K Mar  6 06:32 .X11-unix
drwxrwxrwt  2 root  root  4.0K Mar  6 06:32 .XIM-unix

번외: nginx 이름 변경 (nginx > www-data)

# sudo vi /etc/uwsgi/sites/app.ini

# ...
uid = www-data
gid = www-data

socket = /tmp/app.sock
chomd-socket = 666
chmod-secket = www-data:www-data

# ...
# sudo vi /etc/systemd/system/uwsgi.service

# ...
[Service]
ExecPre=/bin/sh -c 'mkdir -p /run/uwsgi; chown www-data:wwww-data /run/uwsgi;'
ExecStart=/home/ubuntu/.pyenv/versions/deploy_ec2/bin/uwsgi --uid www-data --gid www-data --master --emperor /etc/uwsgi/sites

# ...
$ cd /tmp
# 기존 파일 삭제
$ sudo rm app.pid
$ sudo rm app.sock

$ sudo systemctl daemon-reload
$ sudo systemctl restart uwsgi
$ ps -ax | grep uwsgi
# 프로세스 uid, gid 확인

과제

  • 서버생성 다시 해보기
  • 도메인 사기
  • Cloudflare 가입 후 도메인 추가