Django는 WAS(Web Application Server)의 일종으로, DB 조회 등의 다양한 로직 처리 및 동적인 컨텐츠 제공을 위해 어플리케이셔을 수행해주는 미들웨어라고 생각하면 된다. Django 혼자만으로는 웹 서버를 구동할 수 없다. (django에서 제공하는 runserver는 개발용으로 사용되는 경량 웹 서버로, 실제 production 용으로는 적합하지 않다.)
실제 Django 어플리케이션을 서비스할 때에는 NginX, Apache 등의 웹 서버를 사용하고, 그 웹 서버와 Django 어플리케이션을 연결해 주는 Gunicorn, uWSGI 등의 WSGI를 이용하여 배포해야 한다.
Gunicorn과 같은 WSGI만 있어도 HTTP Request를 처리할 수 있지만, Web Server에서 제공하는 다음과 같은 기능들은 지원되지 않으므로, 실제 production 환경에서는 Web Server를 함께 사용하는 것이 좋다.
- Static, Dynamic Request에 대한 처리: media, css등 static한 요청을 직접 처리하고, dynamic한 요청을 WSGI로 넘긴다. (WSGI로 요청이 넘어가는 순간 크게 느는 자원 사용을 줄일 수 있다.)
- 적은 메모리 사용: NginX는 C로 구현되어 있기 때문에 속도나 메모리 사용 측면에서 뛰어나다. - SSL Termination: HTTPS에 대한 처리가 가능하다.
웹 서버와 WSGI를 함께 연동하여 서비스를 제공하면, 동시에 많은 요청을 처리할 수 있고, 훨씬 안정화된 서버를 구축할 수 있다.
Gunicorn
다음 명령어를 통해 Gunicorn 모듈을 설치할 수 있다.
(env) $ pip install gunicorn
설치가 완료되면, Gunicorn을 이용하여 Django 어플리케이션을 실행시켜 보자.
(env) $ gunicorn --bind 0.0.0.0:8000 config.wsgi:application
실행이 완료되면, 브라우저를 통해 접속이 가능한지 확인한 후, 해당 모듈을 requirements.txt 에 추가한다.
(env) $ pip freeze > requirements.txt
Dockerfile for Django
Django 어플리케이션을 위한 Docker 파일을 생성해 보자. 프로젝트 최 상위 위치에 Dockerfile 을 생성하고 다음과 같이 작성한다.
FROM python:3.6
# 컨테이너 내 프로젝트 root directory 설정
WORKDIR /usr/src/app
# 필요한 module 설치
COPY requirements.txt ./
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
# 프로젝트 코드 복사
COPY . .
### 이 아래 command들은 docker-compose에 작성할 내용이므로, 확인 후 삭제한다.
# 포트 설정
EXPOSE 8000
# gunicorn 실행
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "config.wsgi:application"]
이미지를 빌드해 보고 정상적으로 수행이 되는지 확인해 보자.
$ docker build -t 'account'/'image':'version' .
account, image, version 에는 적절한 값을 넣어 빌드한다.
$ docker run -it -d -p 8000:8000 'account'/'image':'version'
로컬 PC의 브라우저에서 127.0.0.1:8000 으로 접속해 보자. 페이지에 접근이 가능하면, 정상적으로 빌드 및 실행이 된 것이다. (아직 static file들은 처리가 되지 않았으므로, format이 깨져 보일 수 있다.)
Docker-compose
하나의 Container안에 Djanago 어플리케이션과 NginX를 함께 실행할 수도 있지만, 각각의 Container로 분리하고 따로 관리하는 것이 효율적이다. Docker-compose를 이용하면 쉽게 여러 개의 Container를 생성하고, 이들을 연결해 줄 수 있다.
우선 NginX 를 위한 conf 파일을 작성해 보자. 원하는 위치에 적당한 이름의 디렉터리를 생성하고(이 예제에서는 프로젝트 최 상위 위치에 nginx 라는 디렉터리를 생성), nginx.conf 파일을 생성하고 다음과 같이 작성한다.
# nginx/nginx.conf
upstream web {
ip_hash;
server web:8000;
}
server {
location / {
proxy_pass <http://web/;>
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
alias /.static_root/;
}
listen 80;
server_name localhost;
}
upstream 및 proxy_pass 에 작성된 web 은 이후 docker-compose에서 작성할 서비스 이름을 의미한다. (listen 포트를 80으로 설정하고, upstream 으로는 8000으로 전달하므로, 브라우저에서는 포트번호 없이 접속이 가능하다.)
Dockerfile과 마찬가지로 프로젝트 최 상위 위치에 docker-compose.yaml 파일을 생성하고 다음과 같이 작성한다.
# docker-compose.yml
version: "2"
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80/tcp"
volumes:
- ./nginx:/etc/nginx/conf.d
- ./.static_root:/.static_root
depends_on:
- web
web:
build:
context: .
dockerfile: Dockerfile
container_name: web
command: >
bash -c "python manage.py collectstatic --noinput
&& python3 manage.py migrate
&& gunicorn config.wsgi:application --bind 0.0.0.0:8000 --log-level=debug --access-logfile=- --log-file=-"
volumes:
- ./.static_root:/usr/arc/app/staticfiles
expose:
- "8000"
nginx와 web , 두 개의 서비스를 작성하였다. nginx 에서는 NginX 설정 파일 및 static 파일들의 경로를 설정해 준다. web 에서는 앞서 작성한 Dockerfile 을 설정해 주고, gunicorn을 통해 Django 어플리케이션을 실행시킨다. (DB를 이용하는 경우, DB도 별도의 서비스로 구성하는 것이 좋다.)
다음 명령어를 통해 빌드 및 실행을 할 수 있다.
$ docker-compose up --build
'일하는 > Cloud, Web' 카테고리의 다른 글
[Testing] 웹 서버 성능 테스트 / Performance Testing (0) | 2021.12.13 |
---|---|
[Testing][웹 서버 성능 테스트 도구] Wrk (1) | 2021.11.11 |
[Testing][웹 서버 성능 테스트 도구] Apache Bench (0) | 2021.11.11 |
Django REST Framework API Key 사용법 (0) | 2021.06.25 |
[AWS] EC2 인스턴스에서 CodeCommit 사용 설정하기 (0) | 2021.06.07 |