본문 바로가기

django/정리

AWS 배포(1) - Django, Nginx, Gunicorn

기본정리

나보다 잘 정리한 사람도 많고...그냥 이해한대로 최대한 정리해봤다.


# 배포 아키텍처

배포 아키텍처

  • WSGI(Web Server Gateway Interface) : Application Server를 호출하여 동적인 요청을 처리할 수 있는 서버
  • python은 Gunicorn을 사용한다. Django의 runserver와 같은 역할!
  • NGINX : Client에게 받은 정적인 요청을 Gunicorn으로 전달하여 처리하는 Web Server.
  • 즉, 이 프로젝트에서 NGINX는 정적인 요청은 알아서 처리하여 사용자에게 return하고, 동적인 요청을 처리하기 위해 Application Server를 불러올 수 있는 Gunicorn을 통해 처리한다.

# Docker

  • OS에 관계없이 내가 만든 프로젝트가 같은 환경에서, 동일하게 실행할 수 있도록 도와주는 가상 컨테이너 기술
  • 가상 컨테이너란 소프트웨어 구동 환경을 뜻하는데, 즉 나의 application과 관련된 라이브러리들을 함께 묶어 패키지로 만든다.
  • 가상컨테이너는 Dockerfile을 통해 명시한다. Dockerfile을 실행함으로써 실행에 필요한 설정값, 파일(라이브러리)들을 가지고 있는 Image를 정의한다.
  • Image==나의 application 환경 정도로 이해했다.
  • 파일을 분석해보자.
#Dockerfile
FROM python:3.8.3-alpine
ENV PYTHONUNBUFFERED 1

RUN mkdir /app
WORKDIR /app

RUN apk add --no-cache mariadb-connector-c-dev
RUN apk update && apk add python3 python3-dev mariadb-dev build-base && pip3 install mysqlclient && apk del python3-dev mariadb-dev build-base

COPY requirements.txt /app/requirements.txt

RUN pip install -r requirements.txt

COPY . /app/
  • FROM python:3.8.3-alpine : Docker의 기반이 될 이미지다
  • https://hub.docker.com/ <- 여기에서 여러 이미지를 찾을 수 있는데, alpine가벼워서 많이 쓰는 듯
  • ENV PYTHONUNBUFFERED 1 : 환경변수(모드). 이미지와의 충돌을 막고 출력 로그 버퍼링을 없애고...뭐 그렇다고 한다.
  • RUN  mkdir /app : 현재 경로(mkdir)에 빈 디렉토리(app) 생성
  • WORKDIR /app : default directory 변경
  • RUN apk ~~ : 자세한 설명은 없지만...데이터베이스(mysql) 사용을 위한 환경을 만들고, 설치하고 실행하기
  • COPY requirements.txt~~ : 이전에 pip freeze > requirements.txt로 필요한 라이브러리를 모아둔 파일을 app 디렉토리로 복사한다.
  • RUN pip install ~~ : 필요한 라이브러리들 가상환경에 설치
  • COPY . /app/ : 내가 짠 코드들을 app에 복사하고 실행하기           
  • 여러 명령어들...처음 보는 것들도 있다.
  • 참고로 모두 가상 컨테이너를 만들고 거기에서 실행하는 것이므로, 오류가 나면 아래 명령어와 해결법을 참고하여 꼭 Dockerfile에 적어주자!!! 괜히 내 프로그램에다가 설치하고 왜 해결이 안되지~~이러지말자
명령어 용도
FROM  base 이미지 설정
WORKDIR 작업 디렉토리 설정
RUN 이미지 빌드 시 실행할 커멘드
ENTRYPOINT 이미지 실행 시 항상 실행되어야 하는 커멘드
CMD 이미지 실행 시 디폴트 커멘드 또는 파라미터 설정
EXPOSE 컨테이너가 리스닝할 포트 및 프로토콜 설정
COPY/ADD 이미지의 파일 시스템으로 파일 또는 디렉터리 복사
ENV 환경변수 설정
ARG 빌드 시 넘어올 수 있는 인자 설정

# docker-compose.yml

  • Dockerfile에서 만든 이미지들을 쉽게 실행하기 위한 도구이다.
  • 이미지를 여러개 띄워서 네트워크를 만들거나, 컨테이너 밖의 호스트와 연결하는 등의 여러 제어를 담당한다.
version: '3'
services:

  db:
    container_name: db
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_HOST: '%'
      MYSQL_ROOT_PASSWORD: mysql
    expose:
      - 3306
    ports:
      - "3307:3306"
    env_file:
      - .env
    volumes:
      - dbdata:/var/lib/mysql

  web:
    container_name: web
    build: .
    command: sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
    environment:
      MYSQL_ROOT_PASSWORD: mysql
      DATABASE_NAME: mysql
      DATABASE_USER: 'root'
      DATABASE_PASSWORD: mysql
      DATABASE_PORT: 3306
      DATABASE_HOST: db
      DJANGO_SETTINGS_MODULE: django_rest_framework_17th.settings.dev
    restart: always
    ports:
        - "8000:8000"
    volumes:
      - .:/app
    depends_on:
      - db
volumes:
  app:
  dbdata:
  • Docker-compose의 version : 3
  • service : 다음줄부터 서비스를 설정한다(port, volumes 등)
  • 나는 db와 web 컨테이너를 설정해주었다. (container_name으로 이름 따로 설정 가능)
  • web
    • build : . -> project root안에 있는 모든 것들을 build함.
    • volumes : 프로젝트가 업데이트되면 docker를 재실행할 필요없이 자동으로 container에 업데이트 된다.(로컬과 매핑)
    • command : docker cotainer안에서 실행할 command (sh == shell, -c == command)
    • ports : -> port번호
  • db
    • 뭐...적혀진대로 이해하면 된다.
    • 다만 프로젝트가 업데이트되면 db는 다른 경로로 업데이트 됨

# docker-compose.prod.yml

  • 이전에 작성한 yml파일은 로컬에서 실행하기 위한 파일이다.
  • 이 파일은 실제 배포를 위한 파일로, 나중에 github action을 통해 실행해줄 것이다.
  • 데이터 해킹 방지를 위해 db컨테이너가 없고, 대신 배포를 위한 nginx 컨테이너가 존재한다.
  • nginx도 마찬가지로 nginx Dockerfile이 존재하고, 또 Dockerfile에서 COPY하기 위한 nginx의 환경설정(config)파일도 프로젝트 내에 작성해주었다.
  • 추가로 비용이 큰 static과 media 파일은 따로 정의
version: '3'
services:

  web:
    container_name: web
    build:
      context: ./
      dockerfile: Dockerfile
    command: gunicorn django_rest_framework_17th.wsgi:application --bind 0.0.0.0:8000
    environment:
      DJANGO_SETTINGS_MODULE: django_rest_framework_17th.settings.prod
    env_file:
      - .env
    expose:
      - 8000
    volumes:
      - static:/home/app/web/static
      - media:/home/app/web/media
    entrypoint:
      - sh
      - config/docker/entrypoint.prod.sh

  nginx:
    container_name: nginx
    build: ./config/nginx
    volumes:
      - static:/home/app/web/static
      - media:/home/app/web/media
    ports:
      - "80:80"
    depends_on:
      - web

volumes:
  static:
  media:

 

  • entrypoint : collectstatic을 수행하기 위해 넣어준 파일
  • static파일을 한 곳에 모아 처리하기 위함.
  • 필요하면 python manage.py migrate을 넣어줄 수도 있다.
  • 나는 직접 EC2에 연결하고, docker-compose 명령어를 통해 migrate를 실행했었는데...정리면서 보니까 이렇게 하는 방법도 있었구나...😂 담에는 이걸로 해봐야지...
#!/bin/sh

python manage.py collectstatic --no-input

exec "$@"

# 로컬에서 실행

  • docker-compose -f docker-compose.yml up --build를 통해 실행해준다.
  • 여러 명령어가 있다.

  • -d 옵션으로 terminal을 닫아도 계속 실행되게 할수도 있다.(down -v로 닫아줌)
  • 여러 명령어들은...필요하면 공부하자.

  • 잘 실행된다!!
  • 이제 로컬에서 docker가 잘돌아가는 것을 확인했으니, 실제 서버에 배포해보자~~

# 참고

 

[Docker CE] docker-compose 문법 간단 정리 (1) (image, build, command, entrypoint, links)

docker-compose는 여러개의 컨테이너 설정 내용을 하나의 파일에 모아서 사용하는 YAML 파일 입니다. 이 docker-compose는 컨테이너의 서비스(services:), 네트워크(networks:), 볼륨(volumes:)을 정의 합니다. docker

nirsa.tistory.com