본문 바로가기
Linux,Cloud

[AWS] EC2 우분투에 파이썬 장고 프로젝트 배포하기

by 돈민찌 2022. 3. 1.
반응형

파이썬의 강력한 웹프레임워크인 장고를 우분투 20.04 버전으로 배포하겠습니다. 

우선 개발 서버에서 사용 중인 라이브러리들을 requirements.txt에 저장할 것입니다. 대부분의 자동 배포 프로그램에서도 준수하는 이름이니 파일명은 그대로 사용해 주세요.

pip freeze > requirements.txt

만들어진 requirements.txt 파일을 확인하고, 개발 서버에서만 사용하거나 이제 더 이상 사용하지 않을 파일들을 정리해줍니다. 참고로 이번 배포에서는 GUnicorn이라는 모듈을 사용해 배포할 것이므로 이 모듈도 추가해줍니다. 제 예시를 보여드리자면, 이런 모듈들을 사용했습니다.

asgiref==3.5.0
beautifulsoup4==4.11.1
cachetools==5.0.0
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.12
cryptography==36.0.2
Django==4.0.4
django-cors-headers==3.11.0
django-ninja==0.17.0
django-ninja-extra==0.14.8
django-ninja-jwt==5.2.0
django-sslserver==0.22
dnspython==2.2.1
email-validator==1.1.3
google-analytics-data==0.11.2
google-api-core==2.7.2
google-api-python-client==2.44.0
google-auth==2.6.4
google-auth-httplib2==0.1.0
google-auth-oauthlib==0.5.1
googleapis-common-protos==1.56.0
grpcio==1.44.0
grpcio-status==1.44.0
gunicorn==20.1.0
httplib2==0.20.4
idna==3.3
injector==0.19.0
mariadb==1.0.11
mysqlclient==2.1.0
ninja-schema==0.12.8
oauthlib==3.2.0
packaging==21.3
proto-plus==1.20.3
protobuf==3.20.1
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.21
pydantic==1.9.0
PyJWT==2.3.0
pyparsing==3.0.8
python-dotenv==0.20.0
requests==2.27.1
requests-oauthlib==1.3.1
rsa==4.8
six==1.16.0
soupsieve==2.3.2.post1
sqlparse==0.4.2
typing_extensions==4.2.0
tzdata==2022.1
uritemplate==4.1.1
urllib3==1.26.9

먼저 주의해야 할 것이 있습니다. 현재 배포하고자 하는 프로젝트에 대한 중요한 정보(데이터베이스 주소나 비밀번호 등)가 프로젝트 git에 업데이트 되어 있지는 않나요? 그런 경우에는

git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch 삭제하고자하는 file명' --prune-empty -- --all

이렇게 파일을 모든 깃히스토리에서 지운 후 forced push로 원격 리포지토리까지 적용합니다. 장고 프로젝트의 경우 저는 django-environ 이라는 라이브러리를 사용해 특정 변수 등을 숨깁니다. settings.py에 불필요한 정보를 모두 노출할 경우 위험할 수 있으니 이 부분을 유의합니다. ignore되어야 할 파일들이 잘 되어 있는지 한번 더 확인하고 다음 단계로 넘어갑니다.

AWS의 EC2 우분투 20.04 이미지를 사용해 배포할 것입니다. 이번에 리뉴얼된 AWS 템플릿 예쁘네요..

알맞은 머신(AMI)과 네트워크 설정 선택 후 키페어를 선택합니다. 보안그룹에는 내가 사용 중인 컴퓨터의 IP를 22번 포트로 열어두고, 그 외 모든 IP로는 80포트와 443포트로 접속할 수 있도록 설정합니다. 그리고 터미널(윈도우의 경우 깃배시 설치)을 통해 해당 인스턴스에 접속합니다. 

SSH 호스트를 등록하고 (yes 입력) 접속합니다.

다음 코드부터 하나씩 입력해 나갑니다. 파이썬 3.10버전을 설치하고 nginx와 같이 배포에 필수적인 도구들을 설치하는 과정입니다. 제 프로젝트는 외부에 RDS 서버(mariaDB)를 두고 있기 때문에 관련 도구들도 포함되어 있는데, 이것을 제외하고 sqlite3로 배포하셔도 좋습니다. MySQL 같은 다른 데이터베이스들은 직접 도구를 설치하셔야 합니다.

sudo apt update && sudo apt upgrade -y

sudo apt install software-properties-common -y

sudo add-apt-repository ppa:deadsnakes/ppa -y 

sudo apt-get install build-essential python3.10 python3.10-dev python3.10-venv \
libssl-dev libssl1.1 libssl1.1=1.1.1f-1ubuntu2 mariadb-client -y

sudo apt install python3-pip python3-dev libpq-dev nginx curl libmariadbclient-dev -y

/home/ubuntu/ 가 이 서버의 루트 페이지가 될 것입니다. 상위 폴더로 넘어가면 시스템 로그를 확인하거나 서버 관리를 할 수 있고, 프로젝트 파일들은 모두 여기에 저장됩니다.

깃을 이용해 프로젝트를 복사합니다. 완료되면 폴더 안으로 이동합니다.

git clone https://github.com/AndrewDongminYoo/mobile-market-ranker.git

cd app-rank/

다음부터는 clone이 아닌 pull을 사용해 프로젝트 파일들을 가져올 것입니다. 그 떄에는 이렇게 폴더 안으로 들어와서 진행해야 합니다. 그리고 혹시 위에서 말씀드린 대로 gitignore에 등록한 파일들은 지금 다운로드가 되지 않았기 때문에 직접 STFP를 가지고 설치해줘야 합니다. 저는 파일질라를 사용했습니다.

파일질라는 간편하게 드래그로 로컬/원격 컴퓨터 간 파일을 옮길 수 있는 응용프로그램입니다. 주의할 점은 로컬에 있는 파일을 더블클릭하면 서버로, 서버에 있는 파일을 더블클릭하면 로컬로 복제되는데, 이 때 중요한 파일끼리 덮어쓰이지 않도록 유의해야 합니다. 실수로 삭제한 건 복원이 쉽지만 덮어쓰인 것은 복원하기 어렵습니다... 저도 알고 싶지 않았습니다.

.env를 비롯해 필요한 파일들을 모두 업로드했으니 다음 단계를 진행하겠습니다. (위의 캡처는 지금 이 단계를 먼저 실행한 캡쳐이니 헷갈리지 마시길...)

sudo -H pip3 install --upgrade pip

sudo -H pip3 install virtualenv

virtualenv venv

source venv/bin/activate

pip3를 이용해 가상환경 virtualenv를 설치하고 폴더 안에 venv 가상환경 폴더를 생성합니다. 그리고 source 명령어를 이용해 가상환경을 활성화시켜줍니다. 가상환경을 실행한 후에 모듈들을 설치하는 것과 그렇지 않고 설치하는 것은 결과물이 다릅니다. 주의하세욥

pip3 install -r requirements.txt

이 명령어를 통해 requirements.txt에 있는 모듈(라이브러리)들을 설치해줍니다. 그리고 다음 단계로 마이그레이션을 진행할 것인데, requirements와 실제 프로그램에서 사용한 라이브러리 구성이 다르면 에러가 발생하니, 잘 맞춰 설치하도록 합니다. 물론 하나하나 pip install로 설치할 수도 있습니다.

python3 manage.py makemigrations

python3 manage.py migrate

python3 manage.py collectstatic

Django 최신 버전은 manage.py 파일을 사용해 명령어를 실행합니다. 코드에 오류가 있거나 할 때는 첫번째 명령어부터 걸리게 될 것입니다. 해결할 수 있는 문제는 해결하고 다음 단계를 진행합니다. 그리고 마이그레이션을 진행하고, 정적 파일들을 서버 컴퓨터에 다운로드합니다(collect static)

저는 리눅스 환경에서 사용하는 에디터로 nano를 선호합니다. 에디터마다 단축키가 조금씩 다른데, Nano의 경우 파일을 작성하고 Ctrl+x, Shift+Y, Enter로 나가면 저장됩니다. 세개 정도의 파일을 작성해야 합니다.

sudo nano /etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

이 파일은 따로 텍스트를 편집할 필요가 없이 그대로 작성하면 됩니다.

sudo nano /etc/systemd/system/gunicorn.service

daemon으로 실행할 서비스를 만들어줍니다.

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

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/프로젝트루트폴더
ExecStart=/home/ubuntu/프로젝트루트폴더/venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          베이스폴더.wsgi:application

[Install]
WantedBy=multi-user.target

여기서 프로젝트 루트폴더는 /home/ubuntu/ 에 생성한 프로젝트 전체를 담은 폴더를 이야기하는 것이고, 베이스 폴더는 그 안에 있는 wsgi, asgi, settings 등이 들어있는 폴더입니다. 다음을 '차례대로' 입력합니다. 한번에 입력하려다 누락되는 경우가 있을 수 있습니다.

sudo systemctl start gunicorn.socket

sudo systemctl enable gunicorn.socket

sudo systemctl daemon-reload

sudo systemctl restart gunicorn

sudo nano /etc/nginx/sites-available/베이스폴더명
server {
    listen 80;
    server_name IP주소 영문도메인;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/ubuntu/프로젝트루트폴더;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

도메인네임을 가지고 있는 경우 도메인네임서버에 등록 후 영문도메인에 입력합니다. 생략 가능합니다. IP주소는 퍼블릭 IPv4 주소로 입력합니다. listen을 443도 등록해야 HTTPS 서버가 되는 것 아닌가- 할 수 있는데 그 부분은 자동으로 제너레이트되게 할 것입니다. 다음 코드를 입력해 베이스폴더 이름으로 만든 파일을 복사(정확히는 바로가기 링크)합니다.

sudo ln -s /etc/nginx/sites-available/베이스폴더 /etc/nginx/sites-enabled
sudo systemctl restart gunicorn.socket gunicorn.service

sudo nginx -t && sudo systemctl restart nginx

sudo ufw allow 'Nginx Full'

이 코드까지 입력하면, 정상적으로 배포된 경우 http://IP주소를 입력하면 장고가 인덱스 페이지를 열어줄것입니다.

도메인을 가지고 있는 경우 이 다음으로 HTTPS 인증을 시도해 볼 수 있습니다.

sudo add-apt-repository ppa:certbot/certbot

sudo apt-get install python-certbot-nginx

sudo certbot --nginx -d 도메인주소

까지 입력하고, 1과 2 중 선택하라는 창이 나타나면, 1을 입력하면 http를 https로 리다이렉트 시키지 않고, 2은 리다이렉트합니다. certbot은 인증서 설치 및 인증 과정을 단순화시켜주는 도구인데, 90일마다 크론 작업(백그라운드 예약 작업)을 통해 인증서를 알아서 갱신할 것입니다. 이메일 등을 입력하라고 하면 하면 됩니다

저 보기 좋으라고 적어두는 파일이라 틀린 내용이 있을지도 모르는데, 혹시 발견하셨다면 바쁘시더라도 지적해주시면 감사하겠습니다. 

반응형

댓글