Log to grow

[Django] nginx, uwsgi 이용하여 배포하기 (aws ec2, rds) 본문

BE/Django

[Django] nginx, uwsgi 이용하여 배포하기 (aws ec2, rds)

kkkrrr 2021. 1. 10. 16:37

아래 시리즈를 직접 해보며 안되는 부분을 수정하며 작성한 글입니다.

aws에서 EC2와 RDS 인스턴스를 생성했다는 가정하에 진행합니다.

nachwon.github.io/django-deploy-1-aws/

 

[Deploy] Django 프로젝트 배포하기 - 1. AWS

AWS EC2에 장고 프로젝트 올리기

nachwon.github.io

 

 

pyenv 설치 & 가상환경 설정

1. pyenv 설치

1.1 필요한 패키지 우선 설치

아래 명령어로 apt를 업데이트 해줍니다.

apt는 (Advanced Package Tool) 리눅스에서 추가적인 패키지를 설치하고 제거하는 역할을 하는 툴입니다.

sudo apt update

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 tk-dev libffi-dev liblzma-dev python-openssl git libedit-dev python

 

1.2 pyenv 설치

직접 클론합니다.

git clone https://github.com/pyenv/pyenv.git ~/.pyenv

환경변수도 설정해줍니다

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

1.3 pyenv-update 설치

git clone git://github.com/pyenv/pyenv-update.git ~/.pyenv/plugins/pyenv-update

pyenv update

1.4 pyenv-virtualenv 설치

git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv

환경변수도 설정해주세요.

echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bash_profile

source ~/.bash_profile

 

2. 가상환경 설치 

# python 3.6.9 버전 설치 => ubuntu에 설치된 버전과 같게 해주세요
pyenv install 3.6.9 
# production이라는 이름의 가상환경 설치
pyenv virtualenv 3.6.9 production

- 가상환경 실행

pyenv shell production

 

git 저장소에서 장고 프로젝트 클론

1. 프로젝트 클론

srv 폴더를 만들어주고, 권한을 부여합니다.

mkdir ~/srv

sudo chown -R ubuntu:ubuntu ~/srv

 

srv 폴더 안에 프로젝트를 클론합니다

git clone <저장소 주소>

 

2. pip 설치

sudo apt-get install python3-pip

 

 

2. 가상환경에 requirements 설치

requirements.txt가 있는 폴더로 이동하여 필요한 패키지를 설치해주세요

pip3 install -r requirements.txt

 

*** mysqlclient 설치중 오류

    Complete output from command python setup.py egg_info:
    /bin/sh: 1: mysql_config: not found
    /bin/sh: 1: mariadb_config: not found
    /bin/sh: 1: mysql_config: not found
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-077uf8wx/mysqlclient/setup.py", line 15, in <module>
        metadata, options = get_config()
      File "/tmp/pip-build-077uf8wx/mysqlclient/setup_posix.py", line 70, in get_config
        libs = mysql_config("libs")
      File "/tmp/pip-build-077uf8wx/mysqlclient/setup_posix.py", line 31, in mysql_config
        raise OSError("{} not found".format(_mysql_config_path))
    OSError: mysql_config not found
    mysql_config --version
    mariadb_config --version
    mysql_config --libs

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-077uf8wx/mysqlclient/

 

아래 명령어로 필요한 패키지 설치

sudo apt-get install libmysqlclient-dev
sudo apt install default-libmysqlclient-dev

 

** grpcio 설치 중 멈춤 현상

패키지 업데이트

pip3 install --upgrade pip
pip3 install --upgrade setuptools

 

개발 서버 구동

1. secrets.json 복사

secrets.json은 레포에 올라가있지 않으므로 수동으로 만들어줍니다.

vim secrets.json

 

2. DB Migrate

python3 manage.py migrate

 

2. 개발 서버 구동

포트번호 앞에 0:을 붙여주어야 외부에 공개한다는 뜻입니다.

python manage.py runserver 0:8000

 

** 이 때, mysql과 연결할 수 없다는 오류가 발생한다면

django.db.utils.OperationalError: (2002, "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)")

두 가지 해결책이 있습니다. 1) 개발 서버 구동을 위해 ubuntu에 mysql을 설치하는 방법, 2) aws rds를 연결해주는 방법이 있습니다.

 

혹은 우분투에 설치된 파이썬 버전이 맞지 않아 생기는 문제일수도 있습니다.

ex. 우분투에 설치된 파이썬 3.6, 가상환경 파이썬 3.8

 

** 한글 깨짐이 발생한다면

sudo vi /etc/default/locale

(i 누르고 맨 아래에 다음 내용 저장)

LC_CTYPE="en_US.UTF-8"
LC_ALL="en_US.UTF-8"
LANG="en_US.UTF-8"

 

Django 프로젝트 개발 환경 분리

1. setting 파일 분리 

settings.py파일을 아래와 같은 형태로 분리합니다. 기존에 있던 settings.py의 내용을 base.py에 복사 후 붙여넣습니다.

settings/
├── __init__.py
├── base.py
├── dev.py
└── prod.py

 

dev와 prod의 세팅을 분리하기 위함이며 공통적인 부분은 base에 작성하여 dev와 prod에서 import 해줍니다.

from .base import * #dev.py와 prod.py의 최상단

 

dev.py

from .base import *

DEBUG = True

ALLOWED_HOSTS = ['*']


DATABASES = {
    'default': {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "",
        "USER": "",
        "PASSWORD": "",
        "HOST": "localhost",
        "PORT": "3306"
    }
}

 

prod.py

에러를 추적하기 위해 sentry를 세팅해주었습니다.

실제 DB setting은 secrets.json 파일에 저장 후 불러옵니다.

import os
from .base import *

import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration

DEBUG = False  # important

sentry_sdk.init(
    dsn="",
    integrations=[DjangoIntegration()],

    send_default_pii=True
)


# ALLOWED_HOSTS = secrets['ALLOWED_HOST']
ALLOWED_HOSTS = ['*']


DATABASES = secrets['DB_SETTINGS']

WSGI_APPLICATION = 'config.uwsgi.application'

 

__init__.py

dev환경과 prod 환경을 선택합니다.

from .prod import *

 

2.2 manage.py / wsgi.py

새로운 세팅 파일을 위해 manage.py의 내용을 변경해주고, wsgi의 세팅파일을 prod.py로 설정합니다.

manage.py

#!/usr/bin/env python
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")

    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

wsgi.py

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.prod")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

 

uwsgi

위에서 배포한 서버는 개발 서버로 배포한 것은 실제 웹서버로 사용할 수 없습니다.

우리가 사용할 웹서버는 nginx이며, 이 nginx(웹서버)와 django(웹 앱)을 연결해줄 인터페이스가 필요한데,

이게 바로 wsgi(Web Server Gateway Interface)다. 우리는 uwsgi라는 wsgi를 설치하여 사용할 것입니다.

 

일단 설치 전 필요한 패키지를 설치한다.

sudo apt-get install libpcre3

sudo apt-get install libpcre3-dev

- uwsgi 설치

pip3 install uwsgi

 

** uwsgi command not found

pip3 install uwsgi

 

- 서버 배포

uwsgi가 성공적으로 설치됐다면 uwsgi로 서버를 열 수 있게 된다.

프로젝트 경로는 manage.py가 있는 경로이다.

uwsgi  --http :8000 --home <가상환경 경로> --chdir  <프로젝트 경로> -w <wsgi 파일이 있는 폴더 경로>.wsgi

 

 

- ini 파일로 실행

위 명령어로 uwsgi를 실행하는 것이 번거로우므로 ini파일을 정의하여 이 파일을 통해 uwsgi를 실행할 수 있습니다.

루트 디렉토리에 .config 폴더를 만들고 그 안에 uwsgi 폴더를 만듭니다.

그리고 uwsgi 폴더 안에 mysite.ini 파일을 만듭니다.

[uwsgi]
chdir = home/ubuntu/srv/<루트 디렉토리>/<프로젝트 디렉토리>
module = config.wsgi:application
home = /home/ubuntu/<가상환경 경로>

uid = deploy
gid = deploy

http = :8080

enable-threads = true
master = true
vacuum = true
pidfile = /tmp/mysite.pid
logto = /var/log/uwsgi/mysite/@(exec://date +%%Y-%%m-%%d).log
log-reopen = true

아래쪽을 보면 log를 남길 경로를 설정했으므로 로그가 저장될 폴더를 만들어준다.

sudo mkdir -p /var/log/uwsgi/mysite

 

그리고 아래 명령어로 uwsgi를 실행한다.

sudo /home/ubuntu/srv/clique-server/<가상환경 경로>/uwsgi -i /home/ubuntu/srv/<루트 디렉토리>/.config/uwsgi/mysite.ini

 

생성된 로그파일은 아래 명령어로 확인할 수 있습니다.

sudo cat /var/log/uwsgi/mysite/<로그파일명>.log

 

4. nginx

지금까지 uwsgi를 실행하여 uwsgi가 django로 사용자의 요청을 전달하게 했습니다.

이제 마지막으로 nginx를 구성하여 사용자의 요청을 nginx 웹서버가 받아 uwsgi로 전달하게 하면 완성입니다.

 

여기서부터는 아래 링크에 나온대로 ...

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

 

Comments