AWS EC2, RDS, Gunicorn, Nginx를 이용해 배포하기

Han07·2021년 4월 19일
2
post-thumbnail

이 포스트는 내가 배포를 하며 생겼던 의문들과 해결법, 그리고 참고했던 자료들을 정리한 글이다.

1. EC2 연결하기

  1. AWS 계정 생성하기(회원가입)
  1. 인스턴스 생성하기
  1. AWS 인스턴스 연결
  1. 가상환경 생성

ec2 파이썬 가상환경을 검색하면 여러 내용이 나올 것이다. 그중에서 내가 오류가 나지 않았던 유일한 방법은 아래 방법이다.

$ cd {프로젝트 폴더명}
$ sudo apt-get install virtualenv
$ virtualenv -p python3 venv
$ source venv/bin/activate #virtualenv 환경으로 진입
  1. secret.json, my_settings.py 등 .gitignore 에 있지만 필요한 파일 처리
  1. cat 명령어를 이용해 옮기기
  2. filezila 를 이용해 파일 복사

1번이 더욱 쉽고 빠르다.

(로컬에서 프로젝트 폴더 안에서)
cat my_settings.py(또는 secret.json)
이 명령어를 치면 파일 내용이 보인다. 복사한 뒤
(ec2 폴더 안에 진입해서)
cat > my_settings.py(또는 secret.json)
을 한 뒤, 복사한 내용을 붙여넣기 한다.

만약 filezila 를 이용한다면 이 포스트를 참고하면 된다.


2. RDS 설정

  1. RDS 설정하기

위 포스트에서 기본적으로 DB 이름만 바꿔주면 된다. 나는 mysql 로 바꿔주었다.
설정이 끝난 뒤, 바뀐 my_settings.py(또는 secret.json)을 꼭 업데이트 해주자. 이 때, 삭제하고 다시 생성해도 되지만 vi 에디터를 사용하면 편하다.
(ec2 my_setings.py 가 있는 폴더에서)
vi my_settings.py
i를 누르면 insert 모드가 된다. esc + :wq를 하면 저장한 뒤 나갈 수 있고, esc + :q를 하면 저장하지 않고 나갈 수 있다.

  1. EC2에서 RDS 접속하기

ec2 서버에 접속 후, 프로젝트 폴더로 가 가상환경 안으로 들어간다.
mysql -h {RDS 엔드포인트} -u {RDS 계정 이름} -p
비밀번호를 치면 접속된다. 만약 ERROR 2003 (HY000): Can't connect to MySQL server 등과 같이 2003 에러가 난다면 RDS 보안 설정을 다시 해준다.

  1. ERROR 2003 (HY000): Can't connect to MySQL server 해결하기

AWS에 접속해 VPC 서비스에 들어간다. 보안 그룹 탭을 클릭해 이름이 default 인 곳에 들어간다(또는 RDS 에서 데이터베이스를 클릭해 보안 편집을 한다.)

인바운드 규칙에서 위치 무관인 것을 추가해준다.

ec2 서버에서 접속에 성공하면 자동으로 사용자 지정 위치로 바뀐다.

  1. 로컬에 있는 mysql db ec2로 옮기기

! 먼저 ec2 에서 mysql 에 접속한 뒤 스키마를 생성해야 한다. !

mysql -h {RDS 엔드포인트} -u {RDS 계정 이름} -p
create database {스키마 이름};

로컬에서 개발을 완료한 후 배포할 때에 유용한 방법이다.

만약 아래 명령어를 입력했을 때 2003 에러가 발생한다면 8번을 다시 해주면 된다. 그래도 안된다면 데이터베이스의 퍼블릭 엑세스 가능성을 '예'로 바꿔준다.

(로컬에서)

mysqldump -u {db 계정 이름} -p {스키마 이름} > {파일명}.sql
mysql -h {RDS 엔드포인트} -u {RDS 계정 이름} -p {스키마 이름} < {파일명}.sql

다시 ec2 서버에 접속한 뒤, mysql 에 연결해 잘 옮겨졌는지 확인한다.

mysql -h {RDS 엔드포인트} -u {RDS 계정 이름} -p
show databases;
use (스키마 이름);
show tables;

3. Gunicorn 연결하기

Gunicorn 을 사용해야 하는 이유

  1. runserver 는 배포용이 아닌 개발용이다. 따라서 1개의 프로세스만 사용하기 때문에 속도가 느리고, 안전하지 않다.
  2. Django 는 Nginx 웹 서버와 직접적으로 통신할 수 없어 중간에서 Gunicorn server 를 설치해주어야 한다.

Gunicorn 과 Nginx 를 같이 사용하는 이유?

기본적으로 서버는 웹 서버와 앱 서버로 이루어져 있다.
웹 서버는 서버로 들어오는 http request 를 가장 먼저 처리하는 것이고 앱 서버는 django 내장 서버와 같이 어플리케이션을 위한 서버이다.

즉, 요청이 들어오면 웹 서버가 해석을 해 적당한 포트를 이용해 특정 앱 서버로 요청을 하는 것이다.

대략 이런 느낌이라고 보면 된다.

이 때, 웹 서버와 앱 서버를 연결해주는 것을 WSGI(Web Server Gateway Interface) server(혹은 middleware)라고 한다.

Gunicorn 은 이 WSGI middleware 의 일종이다. WSGI middleware는 아래와 같은 일들을 한다.

  1. 환경변수가 바뀌면 타겟 URL 에 따라서 리퀘스트의 경로 지정(
  2. 같은 프로세스에서 여러 애플리케이션과 프레임워크가 실행됨
  3. XSLT 스타일시트를 적용하는 것과 같이 전처리
  4. 로드밸런싱

즉, Nginx는 웹 서버이고 Gunicorn은 웹 서버를 웹앱과 연결해주는 wsgi middleware이기 때문에 같이 사용해야 한다.

WSGI Middleware 중 Gunicorn을 선택한 이유?

WSGI Middleware로는 아래와 같은 것들이 있다.

  1. Bjoern - 매우 빠름(C로 작성됨). 가벼움. HTTP/1.1 지원 안함.
  2. uWSGI - 확장성이 뛰어나며 강력함. 다양한 언어 위에서 작동. 무거울 수 있음.
  3. Mod_wsgi
  4. Gunicorn - 빠른 속도 + 가벼움. django 에서 자동으로 돌아감

내가 Gunicorn을 선택한 이유는 아래와 같다.

  1. django에서 자동으로 돌아간다.
  2. Bjoern과 같이 빠르고 가볍지만 HTTP/1.1까지 지원한다.
  3. 자료가 많다.

Gunicorn 설치하고 테스트 하기

(ec2 서버에서 가상환경 킨 뒤)

pip3 install gunicorn

(프로젝트 루트 폴더에서)

mkdir run
sudo chown ubuntu:www-data run

테스트 하기

gunicorn --bind 0.0.0.0:8888 {장고프로젝트이름}.wsgi:application

서버를 킨 뒤 브라우저에서 http://서버고정아이피:8888 에 접속하면 실행이 잘 되는 것을 볼 수 있다.

이 때 서버 고정 아이피는 ec2 인스턴스의 퍼블릭 ip 이다. (settings.py 의 allowed host 도 이것으로 바꿔야 한다.)

system 에 gunicorn 등록하기

(venv 빠져나오기 - deactivate)

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

(복붙 후 편집 - i)

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

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/{프로젝트 폴더 경로}
ExecStart=/home/ubuntu/{프로젝트 폴더 경로}/{가상환경 이름}/bin/gunicorn \
        --workers 3 \
        --bind unix:/home/ubuntu/{프로젝트 폴더 경로}/run/gunicorn.sock \
        {프로젝트 폴더 이름}.wsgi:application

[Install]
WantedBy=multi-user.target

여기서 workers 는 프로세스 개수 옵션이라고 한다.

sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl status gunicorn

4. Nginx 연결

설치 및 테스트하기

sudo apt install nginx
sudo vi /etc/nginx/sites-available/{프로젝트이름}
server {
        listen 80;
        server_name {퍼블릭 ip 주소};

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

        charset utf-8;

        location /static/ {
                root /home/ubuntu/{프로젝트 폴더 경로};
        }

        location / {
                include proxy_params;
                proxy_pass http://unix:/home/ubuntu/{프로젝트 폴더 경로}/run/gunicorn.sock;
        }
}
sudo ln -s /etc/nginx/sites-available/{프로젝트 폴더 경로} /etc/nginx/sites-enabled

문법 검사 후 실행

sudo nginx -t
sudo systemctl restart nginx

0개의 댓글