공부하고 기록하는, 경제학과 출신 개발자의 노트

프로그래밍/이것저것_개발일지

Django + nginx + Gunicorn으로 AWS EC2에 Deploy하기 (Anaconda)

inspirit941 2019. 11. 10. 21:49
반응형

2019.10 ~ 글로벌경영학과 김영한 교수님 Research Assistant 작업 내용.

환경

AWS EC2 : Ubuntu 16.04
Anaconda : Anaconda3 - Python Version: 3.5
nginx : 1.1.0 (ubuntu)
Gunicorn : 19.9.0
Django : 2.2.1

전제사항

1. django 웹페이지는 manage.py runserver 작업 시 로컬과 EC2 환경에서 정상적으로 작동한다.
2. Elastic IP는 AWS에서 이미 발급받았고, EC2와 연동되어 있다.
3. Anaconda3이 ubuntu에 이미 설치되어 있다.
4. 도메인은 이미 구입해둔 상태이며, AWS Route 53에 등록되어 있다.

5. manage.py collectstatic 명령어로 모든 static파일을 한 곳에 모아 둔 상태.

 

 

1. 가상환경 생성

anaconda가 설치되어 있으니, python 3.5 버전을 제공하는 가상환경을 생성한다. 이름은 python3으로 설정하였음.

 

conda create --n python3 python=3.5

 

해당 가상환경에서 django 웹 페이지가 구동할 수 있게, 라이브러리를 설치한다. django 이외에도 웹서비스 구동에 필요한 라이브러리가 있다면 설치한다.

 

conda install -c anaconda django

 

2. Gunicorn 설치 및 실행하기

manage.py runserver 명령어는 로컬에서 디버깅 및 테스트 목적으로 사용하는 명령어다. production에서는 더 속도가 빠르고 강건하며 안정적으로 서버를 운영할 수 있어야 한다.

 

서버는 크게 웹서버 / 앱서버로 구분됨. 클라이언트(브라우저)가 서버로 요청을 보낼 때 (http를 사용할 예정이니, 80포트로 http request가 도착할 때), nginx나 apache 같은 웹서버가 이를 받아 해석한다. 그 후, 의도로 하는 앱 서버 (django와 같은 프로그램이 작동하는 서버)에 필요한 요청을 전달한다. 이 때, 웹서버와 앱서버가 통신하기 위해 사용하는 인터페이스로 python은 wsgi라는 걸 사용한다.

 

Gunicorn은 manage.py runserver보다 강건하고 안정적인 wsgi 서버를 제공한다.

 

conda install -c anaconda gunicorn

 

설치가 완료되면, manage.py가 있는 디렉토리에서 manage.py runserver 대신

 

gunicorn --bind 0.0.0.0:8000 "django 프로젝트 이름".wsgi:application

 

를 입력해 서버를 실행할 수 있다. 웹 브라우저로 http://서버ip:8000/ 을 입력해 제대로 작동하는지 확인한다. 작동이 확인되면 서버를 꺼 준다.

3. Gunicorn 설정하기

ubuntu에서

 

cd /etc/systemd/system

 

로 경로로 이동한 다음, gunicorn.service 파일을 생성해서 아래와 같이 입력해준다.

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=deploy 
Group=www-data
WorkingDirectory=해당 프로젝트가 설치된 경로 (django의 manage.py 파일이 있는 경로)
ExecStart=gunicorn 실행파일이 있는 경로를 적용해야 함.

[Install]
WantBy=multi-user.target

Service 부분에서

 

- User=ubuntu서버에서 사용자를 누구로 지정할 것인지.

일반적으로 aws ubuntu에 로그인하면 User는 ubuntu, Group도 ubuntu로 지정되어 있다. 리눅스가 애초에 서버를 위한 운영체제이다 보니, 서버에 접근하는 사용자의 권한 설정이 꽤 중요한 이슈다. 권한이 많은 사용자일수록 만약 외부인이 해당 서버를 공격하거나 해킹해 권한을 획득했을 경우 서버의 보안에 큰 위협이 될 수 있다. 별다른 사용자나 그룹 생성 없이 진행한다면 처음 로그인했을 때의 사용자명 / 그룹명을 지정하면 된다. (ubuntu로 로그인하고 사용자나 그룹 설정이 전혀 없었을 경우 User는 ubuntu, Group도 ubuntu다.)

 

서버 사용자 관련한 개념은 처음이어서 무슨 소리인지 이해하느라 꽤 고생하기도 했고, 기본 사용자 / 그룹인 ubuntu / ubuntu 상태로 진행하다가 뒤늦게 설정을 바꾸는 바람에 이후 수정작업에서 꽤 애를 먹었다. 처음부터 사용자 및 그룹설정부터 결정한 뒤 진행하는 게 더 수월했을 거라는 생각이 들었다.

 

(ubuntu 사용자 권한으로 모든 설정을 끝내고 난 뒤에야 deploy라는 사용자를 www-data 그룹에 추가하고 deploy하는 바람에 프로젝트 파일 전체의 소유권 및 접근권한 설정을 변경해야 했고, ubuntu로 서버에 로그인한 다음 sudo 명령어를 써서 모든 작업을 진행해야 하는 불편함을 겪었다.)

 

참고내용
https://kldp.org/node/141854

 

소유권 www-data 관련 | KLDP

안녕하세요. 지금까지 윈도우만 사용하다가 개인용 서버 하나 만들어 보고 싶어서 우분투 서버 12.04 깔고 모르는것 검색하고 공부도 하면서 https://www.digitalocean.com/community/articles/how-to-setup-owncloud-5-on-ubuntu-12-10 이글 보면서 우분투서버 12.04 에 owncloud 설치 했습니다. 저 글에서 나머지는 대충 이해 했는데요 소유권 개념을 거의 모르겠습니다. '소유권' 하니까

kldp.org

Execstart = Anaconda로 Gunicorn을 사용하려면 이 부분에서 anaconda로 설치한 gunicorn 실행파일 경로를 입력해야 한다. aws 로그인했을 때 나오는 디렉토리 (ex) : /home/ubuntu)에 ananconda3을 설치하고 gunicorn을 설치했다고 가정한다면, gunicorn의 경로는 /home/ubuntu/anaconda3/envs/python3/bin/gunicorn이다. 이후에는 gunicorn 실행을 위한 몇 가지 사항을 전달한다.

 

내 경우는

/경로/gunicorn --access-logfile access.log --workers 3 --bind 127.0.0.1:8000 "django_프로젝트이름".wsgi:application이었다. access log는 access.log 파일에 저장하고, 서버 구동은 localhost:8000에서 진행하며, worker process는 3개를 사용한다는 뜻다. --bind 뒤의 설정은 nginx에서도 동일하게 입력해야 하는 부분이므로, 이 부분을 변경했다면 nginx 설정에서도 동일한 내용을 기입해야 한다.

 

상세한 설정은 http://docs.gunicorn.org/en/stable/run.html

 

Running Gunicorn — Gunicorn 20.0.0 documentation

Running Gunicorn You can run Gunicorn by using commands or integrate with popular frameworks like Django, Pyramid, or TurboGears. For deploying Gunicorn in production see Deploying Gunicorn. Commands After installing Gunicorn you will have access to the co

docs.gunicorn.org

에서 확인할 수 있다.

 

설정이 완료되었다면, 실행이 되는지 확인할 수 있다. 아래 명령어를 입력하면 된다.

 

sudo systemctl start gunicorn

sudo systemctl enable gunicorn

 

제대로 작동하는지는 아래 명령어로 확인할 수 있다.

systemctl status gunicorn.service

 

지정한 workers 개수만큼 프로세스가 생성되었는지, 정상적으로 작동하는지 볼 수 있다.

4. nginx 설정하기

nginx를 설치한 뒤, cd /etc/nginx/sites-enabled 명령어로 sites-enabled 경로까지 이동한다.

이 경로에 django 프로젝트명 (settings.py가 있는 폴더 이름)으로 된 파일을 하나 생성하고, 내부에 아래와 같이 입력한다.

server {
    listen 80;
    server_name 탄력적_ip주소_또는_구매한_도메인_주소명;

    charset utf-8;

    location /static {
        root static_file을_collectstatic으로_한_곳에_모아둔_경로.
        # 내 경우 /home/ubuntu/프로젝트폴더;
    }
    location / {
        include proxy_params;
        proxy_pass http://127.0.0.1:8000;
    }

}

대충 해석하면

 

listen 80 : 80번 포트로 들어오는 요청을 받겠다는 의미. http는 80번 포트를 사용하므로, http 프로토콜 기반 요청을 받겠다는 뜻.

 

server_name : 어떤 서버명으로 들어오는 요청을 받을 것인지. 이 부분이 제대로 인식되지 않을 때 502 Bad Gateway 화면이 나왔었다. 설령 여기에 AWS 탄력적 ip를 제대로 입력했더라도, Django의 settings.py에서 ALLOWED_HOST에도 탄력적 ip가 등록되어 있지 않으면 작동하지 않는다.

 

location /static : 정적 파일을 어느 경로에서 찾을 것인지. collectstatic으로 정적 파일을 모아놓은 경로를 입력하면 된다. 로컬에서 작업할 때는 django의 LOAD_STATIC 설정으로 쉽게 해결했지만, nginx에서 적용하려면 다른 설정이 필요하다.

 

location / : 해당 도메인이나 ip주소를 받으면 요청을 어디로 전달할 것인지. 아까 gunicorn 설정에서 django 웹 서버를 돌리는 곳이 127.0.0.1:8000이었으므로, proxy_pass에도 http://127.0.0.1:8000을 입력해준다.

 

cf. nginx에서 root vs alias 는 포스트마다 조금씩 달라서 헷갈리는데, 아래 포스트가 도움이 되었다.

https://ohgyun.com/556

 

nginx: root vs alias

발생일: 2015.01.02 키워드: nginx, root, alias 문제: `root` 디렉티브와 `alias` 디렉티브는 쓸 때마다 헷갈린다. 이참에 정리! 해결책: root: location 으로 넘어온 부분을 root로 설정한 경로에 추가한다. ali..

ohgyun.com

 

5. Gunicorn 실행 / nginx 구동 확인

nginx 문법오류를 확인하는 명령어

 

sudo nginx -t

 

에러가 없으면, 아래 명령어로 nginx를 재시작한다.

 

sudo systemctl restart nginx

 

만약 django 내부 파일을 수정했을 경우, gunicorn을 재시작해야 한다.

 

재시작하는 방법은

sudo systemctl daemon-reload
sudo service gunicorn restart
systemctl status gunicorn.service

이렇게 세 개의 명령어를 사용하면 된다.

각각 daemon 초기화 -> gunicorn 재시작 -> 실행상태 확인 명령어다.

 

 

참고할 만한 포스트

wsgi, nginx, gunicorn 개요 한글설명

http://dveamer.github.io/backend/PythonWAS.html

 

Python WAS 구축하기 ( Django, Nginx, Gunicorn )

Python으로 REST API 서비스를 위한 WAS(Web Application Server) 구축을 진행합니다. Django만으로도 REST API를 오픈할 수 있지만 Django의 runserver는 단순히 테스트만을 위한 기능으로 운영환경에서 사용하면 성능상 문제를 겪게 됩니다. 운영모드에서 Gunicorn 같은 WSGI(Web Server Gateway Interface) 미들웨어와 연동이 필요합니다. 위와 같은 구조에서 Private Physi

dveamer.github.io

Anaconda 환경이 아닐 경우의 방법. socket을 쓴다는 것만 제외하면 거의 동일하다. 이 포스트도 여기서 도움을 많이 받았다.

https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04

 

How To Set Up Django with Postgres, Nginx, and Gunicorn on Ubuntu 16.04 | DigitalOcean

Django is a powerful web framework that can help you get your Python application or website off the ground. Django includes a simplified development server for testing your code locally, but for anything even slightly production related, a more secure

www.digitalocean.com

(이 절차를 거의 그대로 따라서 유튜브에 django를 업로드하는 한글 영상도 있다.)

 

https://dailyheumsi.tistory.com/19#+.-gunicorn-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EC%84%9C%EB%B2%84-run%EC%8B%9C%ED%82%A4%EA%B8%B0.

 

django 웹사이트 배포를 하며 겪은 시행착오

Django로 웹 홈페이지를 만들고, 이를 웹에 배포하는 와중에 겪은 시행착오를 적어본다. 글을 쓰기 전에 이미 준비된 상황은 다음과 같았다. 배포할 웹 페이지가 완성돼있음. local과 amazon ec2 에서 각각 django..

dailyheumsi.tistory.com

https://wikidocs.net/6601#_7

 

위키독스

온라인 책을 제작 공유하는 플랫폼 서비스

wikidocs.net

https://nachwon.github.io/django-deploy-3-nginx/

 

[Deploy] Django 프로젝트 배포하기 - 3. Nginx

지금까지 구축한 구조는 아래와 같다.

nachwon.github.io

https://cjh5414.github.io/nginx/

 

Django에서 Gunicorn, Nginx 이용하기

Jihun's Development Blog

cjh5414.github.io

 

반응형