몰입공간

[Django] EC2 + Nginx + Gunicorn 장고 서버 배포하기 (Deploying server with AWS) 본문

Programming/Django

[Django] EC2 + Nginx + Gunicorn 장고 서버 배포하기 (Deploying server with AWS)

sahayana 2023. 8. 14. 22:00


#1. 준비사항

 

파이썬으로 만들어진 어플리케이션은 대부분 정적 파일 및 프록시를 담당하는 Nginx와 Python 소스코드
그리고 이 사이에 웹 서버 인터페이스인 Gunicorn, uwsgi 혹은 uvicorn이 위치하는 형태로 이루어집니다.

이들을 활용한 프로덕션 서버 배포 가이드는 워낙 양질의 자료가 많기에, 개인적인 아카이빙 목적에 좀 더 
염두하고 글을 공유합니다.

배포를 위한 제반사항은 다음과 같습니다.

  • AWS EC2 (ubuntu 20.04)
  • AWS RDS (MySql 8.0.33)
  • AWS Secret Manger
  • 완성된 Django 프로젝트

#2. EC2 설정

 

 

 

# 우분투 패키지 업데이트 및 파이썬 설치

sudo apt update && sudo apt upgrade
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.7 python3.7-distutils python3-pip python3.7-dev
# AWS CLI 설치 및 설정

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
sudo apt install unzip
unzip awscliv2.zip
sudo ./aws/install
aws --version # 설치 확인
aws configure 
# 이후 access key 및 secret key 입력
# ssh 키 생성 및 Github 연결

ssh-keygen
cat /home/ubuntu/.ssh/id_rsa.pub
# Github - Deploy key 등록
git clone <SSH address>

 

repository - Security - Deploy key

# bash 환경변수 등록

sudo vi /home/ubuntu/.bashrc	# 환경변수 등록
# export DJANGO_SETTINGS_MODULE=myapp.settings.prod
# export AWS_PROFILE=default
source /home/ubuntu/.bashrc		# 변경내용 반영
sudo shutdown -r now			# reboot

export # 환경변수 등록 확인
# 가상환경 설정 및 의존성 패키지 설치

pip3 install --upgrade pip
sudo apt install virtualenv
virtualenv --python=python3.7 venv
source venv/bin/activate
pip3 install -r requirements.txt

#3. RDS 설정

 

최근에 이루어진 AWS 정책에 따라 EC2와 RDS연결이 매우 간편해졌습니다.

RDS 구성 단계에서 연결하려고 하는 EC2만 선택해주면 알아서 보안 그룹 및 연동이 완료됩니다.

 

# DB 생성

sudo apt install mysql-client
mysql -u <RDS 유저네임> -h <RDS 호스트주소> -p
use mysql
CREATE DATABASE <DB 네임>;
quit

#3. gunicorn 설정

 

프로덕션 서버에서 runserver 커맨드는 사용하지 않고, wsgi 인터페이스인 Gunicorn에 바인딩하여 서빙합니다.
(runserver로 실행되는 장고 서버는 개발 환경을 전제하기 때문에 성능, 보안 면에서 실서버에 쓰기 적합하지 않습니다.)

gunicorn —bind 0.0.0.0:8000 --workers 3 myapp.wsgi:application

EC2 컴퓨팅 실행과 함께 백그라운드에서 같이 실행될 수 있도록 systemctl에 등록하여 사용합니다.

여기에 기존에 port 바인딩이 아닌 socket 프로토콜을 사용하도록 하겠습니다.

(속도면에서 조금 더 빠르다고 하네요. https://stackoverflow.com/questions/28379947/what-is-gunicorn-sock)

 

# gunicorn 소켓 생성

sudo vi /etc/systemd/system/gunicorn.socket
# /etc/systemd/system/gunicorn.socket

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target
# gunicorn service 생성

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

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

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/{프로젝트path}
ExecStart=/home/ubuntu/{프로젝트path}/venv/bin/gunicorn --workers 3 --bind unix:gunicorn.sock wanted.wsgi:application


[Install]
WantedBy=multi-user.target

service 등록이 끝나면 systemctl에 등록하고 상태를 확인합니다.

# systemctl 등록 및 로그 확인

sudo systemctl enable gunicorn
sudo systemctl daemon-reload
sudo systemctl start gunicorn 
sudo systemctl status gunicorn

# socket 확인

file /run/gunicorn.sock
/run/gunicorn.sock: socket

# 오류 시 로그 확인
sudo journalctl -u gunicorn.socket

#4. nginx  설정

 

# nginx 설치

sudo apt install nginx
# 프록시 설정

sudo vi /etc/nginx/sites-available/default
server {
        listen 80;
        server_name <DNS주소, IP주소>;

        location = /favicon.ico { access_log off; log_not_found off; }


        location /static {
                alias /home/ubuntu/{프로젝트PATH}/static;
        }

        location / {
                include proxy_params;
                proxy_pass http://unix:/run/gunicorn.sock;
        }
}
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
sudo service nginx restart
sudo systemctl status nginx

#5. 정리

 

가장 기본적이면서도 가장 강력한 nginx - gunicorn - python application 조합입니다.

여기에 추가적으로 오토스케일링, 로드밸런싱, 배포 정책만 추가하면 실제 회사에서 사용 가능한 서버입니다.

데브옵스 엔지니어가 없다면 개발자가 인프라에 좀 더 신경써야할 조합이지만, 이게 싫다면 맘편하게 다 해주는 AWS ElasticBeanstalk 사용합시다!

Comments