-
Django + Docker + NginX + gunicorn 배포etc 2022. 7. 10. 00:47
🙌 서론
원티드 프리온보딩이 시작한지 벌써 2주가 지났다.
2주차에는 내가 서비스 배포를 담당했다.
과제 요구사항은 도커로 배포하기였고, 이전에 엘리스에서 도커를 이용해 배포한 프로젝트가 있긴 했지만, 내가 아니라 다른 팀원이 담당했었다.
그래서 나는 도커에 대해 아무것도 모르는 상태와 같았다. 이번 기회에 제대로 공부해보자는 마음으로 배포를 담당하였다.우선 우리 서비스는 가계부앱 이다.
배포용 서버는 AWS를 이용했고, 도커 + Nginx + gunicorn 구성으로 배포를 진행했다.
Dockerfile과 docker-compose.yml, nginx 설정 파일을 작성하는게 어려웠기 때문에 이 부분에 대해서 정리한 내용이다.
👉 본론
AWS 서버의 프로젝트 구조는 다음과 같다.
home 디렉토리에 payhere(과제 내준 기업 이름)폴더가 있고, payhere 폴더 안에 프로젝트 폴더(git clone한 프로젝트)가 있다.
Dockerfile은 장고앱, nignx
1. 장고앱의 Dokcerfile 작성하기
02_Payhere_TeamH는 Github에서 clone하여 받은 프로젝트 폴더이다.
02_Payhere_TeamH 폴더 안에 Dockerfile이 있다. 이 Dockerfile은 장고 앱을 띄워주기 위해 필요하다.
FROM python:3.9 # (1) ENV PYTHONUNBUFFERED RUN apt-get -y update # (2) RUN apt-get -y install vim RUN mkdir /srv/docker-server #(3) ADD . /srv/docker-server #(4) WORKDIR /srv/docker-server # (5) RUN pip install --upgrade pip # (6) RUN pip install -r requirements.txt # (7) #EXPOSE 8000 # (8) #CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
- 파이썬 3.9 버전을 사용하겠다는 뜻이다. 우리 프로젝트가 파이썬 3.9 버전을 이용해서 버전을 3.9로 맞추었다.
- 도커 서버도 리눅스를 사용하기 때문에 apt-get 업데이트를 해준다. (vim 설치 명령어는 입력하지 않아도 되지만 나는 편의상 적어주었다.)
- 도커 서버 환경에서 폴더를 생성해주는 부분이다. /srv/가 루트경로이고, srv 아래에 docker-server라는 이름으로 폴더를 생성해 주었다.
- 현재 경로(이 Dockerfile이 있는 경로 = 02_Payhere_TeamH)에 있는 모든 내용들을 /srv/docker-server로 복사해준다.
- 도커 서버에서 작업디렉토리 경로를 /srv/docker-server로 지정해 준다. /docker-server 폴더 안에 장고 프로젝트가 담겨있기 때문이다.
- pip를 설치하고 업그레이드 해준다.
- /docker-server에는 02_Payhere_TeamH와 동일하게 requirements.txt파일이 있다. 장고 프로젝트에 필요한 모든 패키지들을 requirements.txt 로 설치한다.
- 이 부분은 주석처리 되어있는데, 8000번 포트를 사용한다는 뜻이다. 아래 라인은 장고 앱을 실행하는 명령어 인데, nginx와 gunicorn을 쓰지 않고 도커에 장고 앱만 올릴것이라면 이 라인들을 주석 해제하면 된다.
처음에는 이렇게 장고앱을 위한 Dockerfile만 작성하고 이미지를 빌드하고 컨테이너를 올렸다.
그러면 EC2의 '아이피 주소:8000'으로 접속했을때 제대로 접속 된다.
❗️ (EC2 인스턴스의 보안 그룹에서 8000번 포트로 접속이 가능하도록 보안 규칙을 추가해줘야 한다!)
2. NginX 붙이기
그리고 nginx 설정을 위한 파일을 작성하기 위해 nginx라는 이름으로 폴더를 생성해 주는데, 위치는 위의 사진과 같이 /payhere에 만들어 주었다.
그러면 /payhere/nginx 폴더로 이동해서 nginx.conf 파일을 작성해준다.
upstream django { # (1) ip_hash; server django:8000; # (2) } server { location / { proxy_pass http://django/; # (3) } location /media { alias /srv/docker-server/.media/; } location /static { alias /static/; # (4) } listen 80; # (5) server_name localhost; }
- 이 부분은 docker-compose.yml 파일에서 장고앱을 띄우는 서비스의 이름과 관련있다. 뒤에 나오겠지만, 나는 django 라는 이름으로 서비스를 작성했기 때문에 'upstream django' 라고 해주었다.
- 이 부분도 1번처럼 docker-compose.yml 파일의 장고앱 서비스 이름을 적어준다. 포트번호는 장고가 8000번을 쓰기 때문에 8000으로 적어준다.
- 이 부분 또한 앞의 내용과 동일하게 django로 적어준다.
- static 파일 관련된 라인이다. 어디에 있는 static 파일들을 가져와서 쓸지 정해주는 것이다. 여기서 완전 헤맸다. docker-compose.yml 파일에 관련된 내용이 있으니 뒤에 추가로 설명하겠다.
3. docker-compose.yml 파일 작성하기
docker-compose.yml 파일은 여러개의 컨테이너를 한번에 올리고 싶을때 필요한 파일이다.
(docker-compose가 설치되어 있어야 하므로, 미리 설치해놓자. 설치 과정은 쉽게 찾을 수 있다.)
version: '3' services: nginx: # (1) container_name: nginx-con # (2) image: nginx:latest # (3) restart: always ports: - "80:80" # volumes: - ./nginx:/etc/nginx/conf.d - ./02_Payhere_TeamH:/srv/docker-server - ./log:/var/log/nginx - /home/ubuntu/payhere/.static_root/:/static # (4) depends_on: - django # (5) django: # (6) container_name: django-con build: ./02_Payhere_TeamH # (7) image: django # (8) restart: always command: gunicorn config.wsgi:application --bind 0.0.0.0:8000 # (9) volumes: - ./02_Payhere_TeamH:/srv/docker-server expose: - "8000"
- 서비스 이름을 적는 부분으로 마음대로 네이밍 하면 된다. 나는 nginx로 지었다.
- 컨테이너 이름을 정해주는 부분으로 마찬가지로 원하는대로 작성하면 된다.
- 나는 nginx를 위한 Dockerfile을 따로 작성하지 않고, 도커 허브에서 nginx 최신 버전 이미지를 다운받았기 때문에 이렇게 작성했다.
- 여기가 완전 헤맸다는 그 부분이다. 여기를 제대로 설정해 주지 않으면 장고의 기본 static 파일들이 적용이 안되서 완전 날것의 html 형태로 페이지가 띄워진다. /home/ubuntu/payhere/.static_root/ 이 부분은 EC2 서버에서 static 파일들이 모여 있는 폴더의 경로이다. .static_root 이라는 폴더에 static 파일들이 모아져 있는데, 이건 프로젝트 폴더에서 python manage.py collectstatic 명령어를 입력하면 자동으로 .static_root라는 폴더가 생성되면서 그 안에 모든 static 파일들이 모아진다. 4 번의 :/static 은 도커 서버에서 /static이라는 폴더에 앞의 내용물들을 담겠다는 뜻이다. 그래서 nginx.conf에서 alias /static/; 이 부분이 도커 서버에 /static 폴더를 가리키는 것이다. 이 경로를 잘 지정해 줘야 css와 js가 적용된 페이지를 볼 수 있다.
- 이 부분은 아래의 django 서비스에 depends_on 한다는 것이다.
- 위의 nginx.conf 내용에서 django라는 이름의 서비스가 바로 이것이다. (다른 블로그에서는 이걸 컨테이너 이름이라고 해서 헷갈렸는데 컨테이너 이름이 아니라 서비스 이름이다!)
- nginx 컨테이너와 달리 장고는 내가 직접 Dockerfile을 작성해 주었기 때문에 그 Dockerfile이 있는 경로를 적어준다. 그러면 그 Dockerfile대로 이미지를 빌드해준다.
- 이미지의 이름을 지정해 준 부분다.
- nginx와 장고를 이어주는 다리 역할을 gunicorn이 해준다. gunicorn을 실행하는 명령어 이다.
4. docker-compose 실행하기
위의 파일들을 다 작성해 주었다면, docker-compose.yml 파일이 있는 경로에서 아래의 명령어들을 차례로 입력하고 확인하면 된다.
docker-compose up -d --build # -d 플래그로 daemon 모드로 컨테이너를 올린다. docker ps # 모든 파일들이 제대로 작성 되었다면 nginx-con과 django-con이 잘 올라가 있을 것이다.
(❗️ nginx는 80번 포트를 이용하기 때문에 EC2 인스턴스의 보안규칙을 추가해주어야 한다. 80번 포트도 열어주자.)
👏 결론
엘리스에서 마지막 팀프로젝트를 할때는 도커에 대한 이해가 아예 없어서 DB만 올리는데도 며칠이 걸렸었다.
이제는 도커로 api 서버 배포는 쉽게 할 수 있을것 같다.
이번 기회롤 통해 도커, nginx, gunicorn에 대한 기본적인 이해가 된것 같다.
아직 nginx에 대해 완벽하게 이해한 것은 아니다. conf 파일을 작성할때 모든 라인이 어떤 의미로 쓰인건지는 몰라서 추가적으로 공부를 해야겠다.