[AWS] Lightsail을 사용하여 Django 프로젝트 배포하기(2) - Gunicorn으로 장고 서버 실행하기

itisny·2024년 1월 13일
0
post-thumbnail

서버 시간 설정하기

ubuntu@eatwell :~ $ date
Thu Jan 11 13:09:32 UTC 2024

터미널에서 date 명령을 쳐보면 UTC 시간이 나옵니다.
UTC 시간은 국제 표준 시간이므로, 한국에서 서비스를 운영하려면 한국시간으로 변경해줘야 합니다.

ubuntu@eatwell :~ $ sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
ubuntu@eatwell :~ $ date
Thu Jan 11 22:09:57 KST 2024

한국 시간으로 설정하려면 sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime을 입력하면 됩니다.
다시 터미널에서 date 명령을 쳐보면 KST 시간이 나옴으로써 한국시간으로 변경된 것을 확인할 수 있습니다.

프로젝트 받아오기

git에서 프로젝트 clone해오기

pwd는 현재 경로를 확인하는 명령어 입니다. 나중에 /home/ubuntu 경로가 쓰이는 곳이 있으니 잘 알아두면 좋습니다.

git clone [깃 저장소 HTTPS]으로 프로젝트를 /home/ubuntu에 클론(복사)해줍니다.

python 가상환경 설정해주기

python으로된 프로젝트이므로 python 설치도 필요합니다.
아래 명령어를 순서대로 입력해주세요. (Ubuntu 22.04 LTS에서 python3 --version으로 파이썬 버전을 확인하면 3.10버전대인 것을 확인할 수 있습니다.)

sudo apt install python3-pip -y
sudo apt install python3.10-venv -y

python3 -m venv venv # 가상환경 생성

source venv/bin/activate # 가상환경 진입

pip install -r requirements.txt # requirement.txt 기반 라이브러리 설치

여기서 잠깐!

만약 sudo apt install python3.10-venv를 안하고, python3 -m venv venv를 한다면 다음과 같은 메시지가 뜹니다.

ubuntu@eatwell:~$ python3 -m venv venv
verifypip가 아니기 때문에 가상 환경이 성공적으로 생성되지 않았습니다.
사용 가능. Debian/Ubuntu 시스템에서는 python3-venv를 설치해야 합니다.
다음 명령을 사용하여 패키지를 만듭니다.

    sudo apt install python3.10-venv

해당 명령에 sudo를 사용해야 할 수도 있습니다. python3-venv를 설치한 후
패키지를 만들고 가상 환경을 다시 만드세요.

실패한 명령: /home/ubuntu/venv/bin/python3

python3 -m venv venv을 하기 전에 sudo apt install python3.10-venv도 꼭 해주세요.

env로 감춰둔 시크릿키 넣기

만약, 장고 시크릿키를 env로 감춰뒀다면 아래와 같이 해주세요.

cd [클론한 프로젝트 이름]을 해주고 ls -al로 모든 파일을 확인해보면 .env 파일이 없는 것을 확인할 수 있습니다.
그래서 vim .env 명령어를 입력하여 새로 .env파일을 생성해줍니다.

env로 감춰둔 내용을 넣어주세요. 참고로 배포할때는 DEBUG가 True가 아닌 False로 해야합니다.
pip list을 확인하여 django-environ이 설치되었는지 확인해주세요.
만약 없다면, pip install django-environ 명령어로 설치해주시길 바랍니다.

Gunicorn 실행하기

8000번 포트로 WSGI 서버 수행하기

Gunicorn은 장고 애플리케이션을 서빙하는 애플리케이션 서버로 작동합니다. 이는 (1)WSGI를 구현하여 장고 애플리케이션과 통신합니다.

Gunicorn은 개발이 아니라 서버에 필요한 도구이므로 로컬 환경에 설치할 필요가 없습니다. 서버환경에 pip install gunicorn 명령어를 통해 Gunicorn을 설치하면 됩니다.

gunicorn --bind 0:8000 {프로젝트명}.wsgi:application 명령어를 입력하여 Gunicorn이 정상으로 실행되는지 확인해봅니다.
--bind 0:8000은 8000번 포트로 WSGI 서버를 수행한다는 의미이고, {프로젝트명}.wsgi:application은 WSGI 서버와 연결된 WSGI 애플리케이션은 {프로젝트명}/wsgi.py 파일의 application이라는 의미입니다.

{프로젝트명}.wsgi:application 이 부분은 Django의 프로젝트 폴더에서 settings.py 파일을 확인하면 됩니다.
그러면 WSGI_APPLICATION = '{프로젝트명}.wsgi.application' 부분을 찾아서 알 수 있습니다.

웹 브라우저로 http://{서버주소}:8000에 접속해 보면 사이트에 연결할 수 없음으로 보입니다.
다른 사람은 되는데 나는 왜 안될까에 대한 고민을 하다가, 8000번 포트를 등록해주질 않았다는 것을 깨닫게 되었습니다. 외부에서 8000번 포트로 접속하려면 '방화벽 해제 작업'을 해야 합니다.

[네트워킹] 탭을 선택하고 +규칙 추가(+Add rule)를 클릭합니다.
포트 번호 '8000'을 입력하고 생성하기를 눌러줍니다.

8000 포트에 대한 방화벽 해제한 것을 확인할 수 있습니다.

다시 gunicorn --bind 0:8000 {프로젝트명}.wsgi:application 명령어를 입력하여 Gunicorn이 정상으로 실행되는지 확인해봅니다.
그리고 브라우저에서 다시 새로 고침을 누르면 정상적으로 접근이 가능해지는 것을 확인할 수 있습니다.
다만, Gunicorn이 정적 파일들을 읽지 못했기 때문에 이렇게 css와 js, 이미지 등이 보이지 않는 상태입니다.

유닉스 소켓 방식으로 WSGI 서버 수행하기

Gunicorn은 앞에서 본 것처럼 포트(8000)를 이용하여 서버를 띄울수 있지만, Unix 계열 시스템에서는 포트로 서비스하기보다는 유닉스 소켓(Unix socket)을 사용하는 것이 빠르고 효율적입니다.

💡 포트보다는 유닉스 소켓(Unix socket)을 사용하는 것이 빠른 이유?
파일 시스템에 위치한 소켓 파일을 통해 통신이 이루어지고 네트워크 스택을 거치지 않고 직접 프로세스 간 통신이 이루어져서 오버헤드가 적습니다.
따라서, 동일 시스템이고 단독으로 구니콘을 실행할 이유가 없다면, 유닉스 소켓을 통한 연결방식이 성능상 유리합니다.

gunicorn --bind unix:/tmp/gunicorn.sock {프로젝트명}.wsgi:application
# 성공
# [2024-01-08 15:20:38 +0000] [8255] [INFO] Starting gunicorn 21.2.0
# [2024-01-08 15:20:38 +0000] [8255] [INFO] Listening at: unix:/tmp/gunicorn.sock
# [2024-01-08 15:20:38 +0000] [8255] [INFO] Using worker: sync
# [2024-01-08 15:20:38 +0000] [8256] [INFO] Booting worker with pid: 8256
# [2024-01-08 15:30:11 +0000] [8255] [INFO] Handling signal: winch

유닉스 소켓 방식으로 Gunicorn 서버를 실행하면 단독으로 Gunicorn 서버에 접속하여 실행할 수 없습니다. 유닉스 소켓 방식으로 실행한 Gunicorn 서버는 Nginx와 같은 웹 서버가 반드시 필요합니다.

우분투에 Gunicorn 서비스 등록하기

AWS 서버를 다시 시작할 때 Gunicorn을 자동으로 실행하기 위해서 AWS 서버에 Gunicorn을 서비스로 등록할 수 있습니다.
Gunicorn을 서비스로 등록하려면 환경 변수 파일과 서비스 파일을 작성해야 합니다.

# 서비스 파일
sudo vim /etc/systemd/system/{프로젝트명}.service
# {프로젝트명}.service

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

[Service]
User=ubuntu # 유저이름 확인해주세요.
Group=ubuntu
WorkingDirectory=/home/ubuntu/{프로젝트 디렉토리} # 프로젝트 루트 디렉터리
EnvironmentFile=/home/ubuntu/{프로젝트 디렉토리}/.env # 환경변수 파일 위치 확인
ExecStart=/home/ubuntu/{프로젝트 디렉토리}/venv/bin/gunicorn \ #가상환경에 설치 위치 확인된 gunicorn
        --workers 2 \ # Gunicorn 프로세스 갯수, 월 사용료 5달러 사양의 서버에는 이 정도가 적당
        --bind unix:/tmp/gunicorn.sock \ # WSGI실행 명령
        {프로젝트명}.wsgi:application # WSGI(Django) 애플리케이션

[Install]
WantedBy=multi-user.target

# 예제
[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/EatWell
EnvironmentFile=/home/ubuntu/EatWell/.env
ExecStart=/home/ubuntu/venv/bin/gunicorn \
        --workers 2 \
        --bind unix:/tmp/gunicorn.sock \
        config.wsgi:application

[Install]
WantedBy=multi-user.target

# 서비스 실행
sudo systemctl start {프로젝트명}.service
sudo systemctl start /etc/systemd/system/{프로젝트명}.service 

# 실행확인 (정상실행이면 active 상태)
sudo systemctl status {프로젝트명} # .service 빼고입니다.

# 만약 fail이라면..
sudo vim /etc/systemd/system/{프로젝트명}.service # 파일 잘못된 부분있는지 확인
# 만약 수정했으면 다시 실행(restart) 해주기
sudo systemctl restart {프로젝트명}

# 서버가 재실행 될 때 Gunicorn 서비스가 자동 실행 (서비스 등록)
sudo systemctl enable {프로젝트명}

# 서버 재실행
sudo reboot

# 다시 접속
ssh ubuntu@{ip주소}

# 서버 상태 확인
sudo systemctl status {프로젝트명}

AWS 서버가 다시 시작될 때 Gunicorn이 자동 실행되도록 enable 옵션을 주어 서비스로 등록하면 됩니다.
그리고 다시 서버에 접속하여 Gunicorn이 잘 실행되는지 확인하면됩니다.

🗒️ 용어

(1) WSGI : Web Server Gateway Interface로, 웹서버와 웹 애플리케이션의 인터페이스를 위한 파이썬 프레임워크다. 즉, 모든 웹 서버와 Python 계열의 프레임 워크가 통신할 수 있게 해주는 미들웨어다.
흔히 웹 서버로 사용되는 Apach와 Tomcat은 Java 기반이므로 python코드를 읽을 수 없다.

📚 참고

0개의 댓글