배포
개념
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
orIPv4 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 서비스 설정파일 작성
$ 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 가입 후 도메인 추가