Django 서비스 AWS로 배포하기 - [1] 프로젝트 준비와 AWS 서버 대여
Django 서비스 AWS로 배포하기 - [2] github과 프로젝트 업로드
지난 포스트 까지 서버에 나의 프로젝트를 git을 통해 업로드 해보았습니다. 이제 슬슬 프로젝트를 웹 서버와 이어주는 작업을 해야하는데, 그 전에 Django는 웹 서버와 직접적으로 통신할 수 없기 때문에 이를 중간에서 이어줄 python 프레임워크인 WSGI(Web Server Gateway Interface) server를 설치해 주어야 합니다. 이번 포스트는 uWSGI python 패키지를 이용해 WSGI 서버를 Django와 연결해 보도록 하겠습니다.
runserver 해보기
사실 우리가 옮긴 프로젝트를 바로 runserver 하여 화면을 띄워볼 수 있습니다. 지금 서버 컴퓨터에는 프로젝트를 실행하기 위한 패키지들이 깔려 있지 않으니, 로컬 컴퓨터에서와 동일하게 가상환경을 만들어 주고 패키지 버전들을 저장한 requirements.txt를 통해 패키지를 깔아보도록 하겠습니다.
먼저, 가상환경을 만들기 전에 python3-venv를 설치합니다.
$ sudo apt-get install python3-venv
가상환경의 위치는 현재 사용하고 있는 유저인 ubuntu의 홈 폴더에 만들도록 하겠습니다.
$ cd ~
$ python3 -m venv myvenv
가상환경을 활성화 하고,
$ source myvenv/bin/activate
프로젝트 폴더에 있는 requirememts.txt 파일을 통해 패키지를 설치합니다.
$ cd /srv/django-deploy-test/
$ pip3 install -r requirements.txt
그러면 자동으로 Django를 포함한 requirements.txt에 써져있는 패키지들이 깔리기 시작합니다. 그 다음 프로젝트 폴더에 있는 manage.py를 이용해 runserver를 아래와 같이 해주세요.
$ python3 manage.py runserver 0:8080
그리고 자신의 퍼블릭 DNS 주소 뒤에 포트 번호를 의미하는 :8080을 붙여 브라우저에 접속해보세요.
http://ec2-15-164-212-231.ap-northeast-2.compute.amazonaws.com:8080/
그러면 아마 로딩만 하고 페이지가 띄워지지 않는 것을 볼 수 있습니다. 우리가 만든 서버의 8080 포트가 열려있지 않기 때문입니다. AWS 로 접속하여 EC2 화면으로 가봅시다. 여기서 우리가 생성한 인스턴스를 클릭하고 하단에 보면 보안 그룹이라고 있습니다. 각자 보안 그룹이 하나씩 걸려있을 것인데, 그 보안 그룹을 클릭해 주세요.
그럼 이런 화면이 나오는데, Edit inbound rules를 클릭해주세요.
이런식으로 새로운 8080 포트를 추가해주시고 저장해줍니다.
그리고 다시 접속해볼게요.
http://ec2-15-164-212-231.ap-northeast-2.compute.amazonaws.com:8080/
그럼 이런 화면이 나오긴 하지만, 오류가 납니다. 지금 쓰고 있는 주소가 settings.py에 추가되어 있지 않아서 그렇습니다. 추가해주고 다시 들어가 볼게요.
로컬 컴퓨터에 있는 프로젝트의 settings.py에 ALLOWED_HOSTS에 주소를 추가합니다.
mysite/settings.py
ALLOWED_HOSTS = [
".ap-northeast-2.compute.amazonaws.com"
]
저장하고 github에 업로드합니다. manage.py가 있는 폴더로 이동한 뒤,
$ git add .
$ git commit -m "allowed host update"
$ git push origin master
다시 서버 컴퓨터로 접속해서 manage.py가 있는 폴더로 가서,
$ git pull origin master
하면 프로젝트 파일들이 업데이트 됩니다.
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 4 (delta 3), reused 4 (delta 3), pack-reused 0
Unpacking objects: 100% (4/4), done.
From https://github.com/nero96in/django-deploy-test
af3eb87..cdbcb98 master -> origin/master
Updating af3eb87..cdbcb98
Fast-forward
mysite/settings.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
다시 runserver를 해봅시다.
$ python3 manage.py runserver 0:8080
그러면 우리가 만들었던 페이지가 나오는 것을 확인할 수 있습니다!! 짝짝...... 그렇지만 보이는 메세지처럼 배포를 성공한 것은 아닙니다. runserver는 개발용이지 배포용이 아니기 때문이에요. Django가 제공해주는 작은 웹 서버에 불과합니다. 우리는 nginx라는 웹 서버를 이용해서 안정적인 배포를 할 필요가 있습니다.
uWSGI 서버 연결하기
우선, 도입부에 설명했듯이 Django는 웹 서버와 직접 통신할 수 없어서 둘 사이에 WSGI를 두어야 합니다.. 이를 위해서는 uWSGI라는 Python 패키지를 설치해야 하여 Django와 연결해 주어야 합니다.
아까 만든 가상환경을 활성화 하고 uwsgi 패키지를 설치합니다.
$ source ~/myvenv/bin/activate
$ pip3 install uwsgi
(+ 2020.11.20 "김현준"님의 코멘트로 트러블 슈팅 내용 추가) uwsgi 설치 과정에서 에러가 생기는 경우에 이 더보기 내용을 참고해 주시길 바랍니다.
아래의 오류가 생기는 경우, (저의 경우) 무시하고 진행해도 배포에는 문제가 되지 않았지만 오류다 보니 해결해야할 필요는 있어보입니다.
... 중략
warnings.warn(msg)
usage: -c [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
or: -c --help [cmd1 cmd2 ...]
or: -c --help-commands
or: -c cmd --help
error: invalid command 'bdist_wheel'
----------------------------------------
Failed building wheel for uwsgi
Running setup.py clean for uwsgi
Failed to build uwsgi
Installing collected packages: uwsgi
Running setup.py install for uwsgi ... done
Successfully installed uwsgi-2.0.19.1
제 생각엔 uwsgi 버전이 바뀌면서 생긴 문제라고 예상하고 있습니다. 이 에러를 해결하려면, 아래와 같이 wheel 패키지를 설치해주시면 해결할 수 있습니다.
$ pip3 install wheel
그리고 uwsgi를 재설치 해주세요.
$ pip3 uninstall uwsgi
$ pip3 install uwsgi
또한, uwsgi 설치중 아래와 같은 오류가 생기기도 하는 것 같습니다. 제 생각엔, 기본적인 파이썬 언어를 위한 빌드 파일 중 하나로 추정이 됩니다.
Python.h: No such file or directory
이 경우, 아래와 같이 python3-dev 패키지를 서버 컴퓨터에 설치하시면 됩니다.
$ sudo apt install python3-dev
저의 경우에는 위의 에러가 생기더라도 배포하는 과정에서는 큰 문제가 없었습니다. 그래도 에러가 났으니, 우선 아카이브 한다는 생각으로 남겨 놓습니다. 피드백 남겨주신 김현준님 감사합니다 :)
uwsgi 서버를 이용해 Django 프로젝트를 연결해 보겠습니다. 다음 형식의 명령어를 실행해 주시면 됩니다.
uwsgi --http :[포트번호] --home [가상환경 경로] --chdir [장고프로젝트폴더 경로] -w [wsgi 모듈이 있는 폴더].wsgi
- 포트번호: 8080
- 가상환경 경로: uwsgi를 설치한 myvenv의 경로입니다. ~/myvenv/ 이지만 홈 폴더를 절대 경로로 지정해 주는 것이 좋습니다. ~는 /home/ubuntu/이니까 /home/ubuntu/myvenv/ 가 가상환경 경로입니다.
- 장고 프로젝트 폴더 경로: /srv/django-deploy-test/, srv 폴더 내의 각자의 프로젝트 폴더 명을 입력하면 됩니다.
- wsgi 모듈이 있는 폴더: 프로젝트 폴더에 mysite 안에 wsgi.py가 있을겁니다. 그 경로이기 때문에 mysite를 입력해줍니다.
즉, 그대로 적용하게 되면 저의 명령어는 다음과 같이 됩니다.
$ uwsgi --http :8080 --home /home/ubuntu/myvenv/ --chdir /srv/django-deploy-test/ -w mysite.wsgi
그러면 다음과 같은 내용과 함께 서버가 켜집니다.
*** Starting uWSGI 2.0.18 (64bit) on [Sun Mar 15 08:27:52 2020] ***
compiled with version: 7.5.0 on 15 March 2020 08:27:18
os: Linux-4.15.0-1057-aws #59-Ubuntu SMP Wed Dec 4 10:02:00 UTC 2019
nodename: ip-172-31-26-18
machine: x86_64
clock source: unix
detected number of CPU cores: 1
current working directory: /home/ubuntu
detected binary path: /home/ubuntu/myvenv/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
chdir() to /srv/django-deploy-test/
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 3840
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :8080 fd 4
spawned uWSGI http 1 (pid: 1940)
uwsgi socket 0 bound to TCP address 127.0.0.1:44211 (port auto-assigned) fd 3
Python version: 3.6.9 (default, Nov 7 2019, 10:44:02) [GCC 8.3.0]
PEP 405 virtualenv detected: /home/ubuntu/myvenv/
Set PythonHome to /home/ubuntu/myvenv/
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x557cd6278b80
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72904 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x557cd6278b80 pid: 1939 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 1939, cores: 1)
이제 다시 각자의 서버 주소:8080으로 접속을 하면,
http://ec2-15-164-212-231.ap-northeast-2.compute.amazonaws.com:8080/
runserver를 실행하지 않아도 Django 프로젝트에 접속한 것을 볼 수 있습니다. 하지만, 매번 저 복잡한 명령어를 쳐서 서버를 열 수는 없으니 파일로 옵션들을 정해서 실행할 수 있도록 하겠습니다.
* 2022.01.30 업데이트
아래 deploy라는 계정을 만들고 진행을 하게되면 기존의 ubuntu 계정 (기본 계정)으로 로그인하여 git pull을 한 파일들에 웹서버가 엑세스 할 수 없는 문제가 발생하는 것을 확인했습니다 (예를 들어, db.sqlite3의 read only 오류). 이렇게 deploy 계정을 아래와 같이 만들어서 진행할 것이었으면, 아예 처음부터 계정을 만들고 나서 이걸로 로그인을 하고 git pull을 한 뒤 진행을 했어야 했습니다. 현 업데이트 부로, deploy라는 계정은 우선 잊어주시고 배포도 ubuntu 계정으로 진행한다고 인지해주시면 좋을 것 같습니다. (따로 계정이 있는 것은 좋은데, 이 게시글들을 쓰고 이후게 그래야 하는지 의문이 많이 드네요.. 처음 배포하는 입장에서는 우선 다른 계정으로도 배포할 수 있다~ 정도로 염두해주시면 되겠습니다.)
이에 맞게 이후의 진행사항에서 deploy가 모두 ubuntu로 변경됩니다. 기존에 참고하셨던 분들은 유의해주세요!
기존글:
그 전에 슬슬 배포할 계정을 만들어봅시다. 서버 컴퓨터 내에 ubuntu 말고 다른 계정을 만들 수 있는데, 배포를 위한 계정을 따로 만드는 것이 좋습니다.
서버 컴퓨터에서 deploy라는 이름의 계정을 만들고, 비밀번호는 알맞게 쳐주세요. 비밀번호 입력후, 이름이나 이메일 등을 물어보는데 그냥 모두 엔터 치고 넘어가셔도 됩니다.
$ sudo adduser deploy
이제 deploy 계정이 배포를 담당하게 될 것이라는 것 정도만 인지해주세요. 그 다음 파일로 uwsgi 옵션을 저장해 사용해보도록 하겠습니다.
로컬 컴퓨터로 돌아와서 manage.py가 있는 폴더에서 .config 폴더를 만들고 그 안에 uwsgi 폴더를 만듭니다.
$ ls
db.sqlite3 manage.py requirements.txt
main mysite
$ mkdir .config
$ cd .config
$ mkdir uwsgi
그리고 uwsgi 폴더에서 mysite.ini 를 만들고 다음을 추가합니다. 저는 아까 길게 친 uwsgi 명령을 바탕으로 다음과 같이 작성했습니다.
.config/uwsgi/mysite.ini
[uwsgi]
chdir = /srv/django-deploy-test/
module = mysite.wsgi:application
home = /home/ubuntu/myvenv/
uid = ubuntu
gid = ubuntu
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
- chdir: 장고 프로젝트 폴더의 경로. 아까 uwsgi 명령어를 칠 때 chdir 다음에 왔던 경로와 동일합니다.
- modeule: 아까 입력했던 -w 옵션 뒤의 값과 같으나 뒤에 :application을 붙여주세요.
- home: 아까 입력했던 가상환경의 경로와 동일합니다.
- uid: uwsgi를 사용할 계정입니다. 아까 만들어 둔 배포용 계정 ubuntu를 입력해주세요.
- gid: uwsgi를 사용할 그룹입니다. 아까 만들어 둔 배포용 계정 ubuntu를 입력해주세요.
- http: 사용할 포트 번호이고
- logto: uwsgi 서버의 로그를 저장할 폴더입니다.
저장하고 github에 올리신 뒤에 서버 컴퓨터에 돌아가서 다시 git pull 하여 변경 사항(mysite.ini 추가)을 업데이트 해주세요. 먼저 logto 경로에 폴더 (/var/log/uwsgi/mysite/)가 없기 때문에 만들어주어야 합니다.
$ sudo mkdir -p /var/log/uwsgi/mysite
그리고 이 로그는 uwsgi 실행자는 현재 기본 계정인 ubuntu의 소유여야 로그를 작성할 수 있습니다. 만든 로그 폴더 전체를 ubuntu의 소유로 변경합니다.
$ sudo chown -R ubuntu:ubuntu /var/log/uwsgi/mysite/
mysite.ini에 있는 옵션을 이용해 uwsgi 서버를 다시 켜봅니다. 관리자 권한으로 실행해야 하기 때문에 ubuntu의 홈 폴더에 있는 가상환경 내의 uwsgi를 직접 실행합니다. 설치한 uwsgi는 가상환경 폴더 안의 bin 폴더에 있습니다. 즉, 저는 다음 명령어로 실행할 수 있습니다.
$ sudo /home/ubuntu/myvenv/bin/uwsgi -i /srv/django-deploy-test/.config/uwsgi/mysite.ini
그러면 이렇게 서버가 켜지고
[uWSGI] getting INI configuration from /srv/django-deploy-test/.config/uwsgi/mysite.ini
서버 컴퓨터의 8080 포트로 접속하시면 정상적으로 작동함을 확인할 수 있습니다.
오류 내용을 확인하고 싶을 때는 다음과 같이 로그 폴더를 관리자 권한으로 확인할 수 있습니다.
sudo cat /var/log/uwsgi/mysite/2020-03-15.log
이렇게 Django 프로젝트와 uwsgi를 연결해 봤습니다! 쉽지 않으시죠 ㅠㅠ 진행하다가 생기는 오류는 댓글로 남겨주세요. 다음 포스트에서는 Django와 연결된 uwsgi 서버와 짱짱한 웹 서버인 nginx를 연결해보도록 하겠습니다.
'웹 > Django' 카테고리의 다른 글
Django 서비스 AWS로 배포하기 - [6] https 적용하기 (31) | 2020.03.27 |
---|---|
Django 서비스 AWS로 배포하기 - [5] 도메인 연결하기 (가비아) (10) | 2020.03.26 |
Django 서비스 AWS로 배포하기 - [4] nginx 연결하기 (74) | 2020.03.15 |
Django 서비스 AWS로 배포하기 - [2] github과 프로젝트 업로드 (6) | 2020.03.15 |
Django 서비스 AWS로 배포하기 - [1] 프로젝트 준비와 AWS 서버 대여 (17) | 2020.03.15 |