코딩 개발일지

docker의 기본 (postgresql / gunicorn / 실 배포) 본문

AI 본 교육/AI 12주차

docker의 기본 (postgresql / gunicorn / 실 배포)

호기호 2023. 11. 2. 08:55

postgresql

오픈 소스 데이터베이스로, 무료로 사용 가능

Oracle DB, Mysql, Microsoft SQL에 이어 네번째로 사용량이 많은 데이터베이스 (나머진 유료 ㅠㅠ)

 

장고에서는 기본 데이터베이스로 postgresql을 사용하는 것을 권장하고 있다.

version: '3.8'

volumes:
  postgres: {} # postgresql에서 사용 할 볼륨 지정

services:
  postgres:
    container_name: postgres
    image: postgres:14.5
    volumes:
      - postgres:/var/lib/postgresql/data/
    environment: # postgresql 컨테이너에서 사용할 환경변수 지정해주기
      - POSTGRES_USER=user # 데이터베이스 사용자 지정
      - POSTGRES_PASSWORD=P@ssw0rd # 사용자 비밀번호 지정
      - POSTGRES_DB=django # 데이터베이스 이름 지정
    restart: always

gunicorn

배포용로 사용되는 runserver라고 생각하면 된다.

runserver는 개발용으로 사용되는 명령이고,  runserver에 비해 속도, 안정성 등 다양한 장점을 가지고 있기 때문에 배포 환경에서는 gunicorn을 사용하는 것을 권장하고 있다.

 

장고 프로젝트를 github에서 clone 할때, 맨 끝에 ./django를 붙여주는게 좋다. (안붙이면 나중에 따로 설정)

git clone https://github.com/sparta-course/drf-project.git ./django

django 프로젝트를 배포 시 설정할 것

1. settings.py

ALLOWED_HOSTS = ['*']
STATIC_ROOT = BASE_DIR / "static"

2. timezone 설정

Linux를 처음 설치하면 대부분 표준 시간대가 협정 세계시(UTC)로 설정되어 있다.

프로젝트를 배포할 때는 timezone을 한국 시간대(KST)로 변경해 주는 것이 좋다.

sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

3. backend / Dockerfile 작성

# python 3.10.8버전 이미지를 사용해 빌드
FROM python:3.10.8

# .pyc 파일을 생성하지 않도록 설정합니다.
ENV PYTHONDONTWRITEBYTECODE 1

# 파이썬 로그가 버퍼링 없이 즉각적으로 출력하도록 설정합니다.
ENV PYTHONUNBUFFERED 1

# /app/ 디렉토리를 생성합니다.
RUN mkdir /app/

# /app/ 경로를 작업 디렉토리로 설정합니다.
WORKDIR /app/

# requirments.txt를 작업 디렉토리(/app/) 경로로 복사합니다.
COPY ./django/requirements.txt .

# 프로젝트 실행에 필요한 패키지들을 설치합니다.
RUN pip install --no-cache-dir -r requirements.txt

# gunicorn을 사용하기 위한 패키지를 설치합니다.
RUN pip install gunicorn

4. docker-compose.yml 작성

version: '3.8'

services:
  backend:
    container_name: backend
    build: ./backend/
    # drf_project.wsgi는 프로젝트 경로에 맞게 지정해야 합니다.
    entrypoint: sh -c "python manage.py collectstatic --no-input && python manage.py migrate && gunicorn drf_project.wsgi --workers=5 -b 0.0.0.0:8000"
    ports:
      - 80:8000
    volumes:
      - ./backend/django/:/app/
      - /etc/localtime:/etc/localtime:ro # host의 timezone 설정을 컨테이너에 적용합니다.
      # ro 은 읽기 전용(read only) 속성으로 볼륨을 설정하는 것을 의미합니다.
    restart: always

- entrypoint 간략 설명 -

sh -c : 컨테이너에서 뒤에 작성한 명령어를 실행

&& : 다음 명령어를 실행

python manage.py collectstatic --no-input : 배포를 위해 static 파일을 모아주기. settings.py 설정 필수

python manage.py migrate : 알쥐 이건?

gunicorn project_name.wsgi --workers=5 -b 0.0.0.0:8000 : gunicorn으로 django 프로젝트 실행

  • project_name : django 프로젝트 이름
  • --workers=5 : django를 실행시킬 process 갯수를 입력
    일반적으로 cpu 코어 갯수 * 2 + 1만큼 지정 ex) 2코어면 5설정
  • -b 0.0.0.0:8000 : 8000번 포트로 실행

nginx

뭘까??? 클라이언트의 request 요청을 처리해주는 웹 서버(web server)

reverse proxy, 로드밸런싱, 캐싱 등의 기능을 지원함.

클라이언트의 요청을 nginx가 받은 후 service(django) 데이터를 넘겨주는 역할을 해줌.

 

사용하는 이유 :

1. 로드밸런싱을 활용해 트래픽을 분산할 수 있음

2. SSL 기능을 사용해 데이터를 안전하게 전달 가능

3. reverse proxy 기능을 통해 client에서 서버에 직접적으로 접근하는 것을 막아줌

4. 콘텐츠를 캐싱하여 동일한 요청에 대해 더 빠른 속도로 처리할 수 있게 해줌

 

nginx 디렉토리 내 default.conf에 아래 내용으로 파일을 생성해준다.

server {
  listen 80;
  server_name _; # 모든 도메인 혹은 ip로 들어오는 요청에 대해 처리해 줍니다.

  location / { # nginx로 요청이 들어왔을 때
    proxy_pass http://backend:8000/; # backend 컨테이의 8000번 포트로 전달합니다.
  }

  location /static/ { # 브라우저에서 /static/ 경로로 요청이 들어왔을 때
    alias /static/; # /static/ 경로에 있는 파일들을 보여줍니다.
  }

  location /media/ { # 브라우저에서 /media/ 경로로 요청이 들어왔을 때
    alias /media/; # /media/ 경로에 있는 파일들을 보여줍니다.
  }
}

실제 배포 시 어떻게 설정해야할까??????????

1. settings.py는 이렇게 바꿔줘야 한다. 바꿔서 github에 올려도 됌.

import os

# 환경변수에 따라 DEBUG모드 여부를 결정합니다.
DEBUG = os.environ.get('DEBUG', '0') == '1'

# 접속을 허용할 host를 설정합니다.
ALLOWED_HOSTS = ['backend', ]

# postgres 환경변수가 존재 할 경우에 postgres db에 연결을 시도합니다.
POSTGRES_DB = os.environ.get('POSTGRES_DB', '')
if POSTGRES_DB:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': POSTGRES_DB,
            'USER': os.environ.get('POSTGRES_USER', ''),
            'PASSWORD': os.environ.get('POSTGRES_PASSWORD', ''),
            'HOST': os.environ.get('POSTGRES_HOST', ''),
            'PORT': os.environ.get('POSTGRES_PORT', ''),
        }
    }

# 환경변수가 존재하지 않을 경우 sqlite3을 사용합니다.
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        }
    }

# CORS 허용 목록에 ec2 ip를 추가합니다.
CORS_ORIGIN_WHITELIST = ['http://$ec2_public_ip']
# ex) CORS_ORIGIN_WHITELIST = ['http://43.201.72.190']

# CSRF 허용 목록을 CORS와 동일하게 설정합니다.
CSRF_TRUSTED_ORIGINS = CORS_ORIGIN_WHITELIST

1. DEBUG 바꿔서 작성

2. ALLOWED_HOSTS 추가

3. DB 설정 바꿔서 작성

4. CORS 설정 아래에 붙이면 됌

디렉토리 구조

2. docker-compose.yml

version: '3.8'

volumes:
  postgres: {}
  django_media: {}
  django_static: {}

services:
  postgres:
    container_name: postgres
    image: postgres:14.5
    volumes:
      - postgres:/var/lib/postgresql/data/
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=P@ssw0rd
      - POSTGRES_DB=django
    restart: always

  backend:
    container_name: backend
    build: ./backend/
    entrypoint: sh -c "python manage.py collectstatic --no-input && python manage.py migrate && gunicorn drf_project.wsgi --workers=5 -b 0.0.0.0:8000"
    volumes:
      - ./backend/django/:/app/
      - /etc/localtime:/etc/localtime:ro
      - django_media:/app/media/ # nginx에서 media를 사용할 수 있도록 volume을 지정해줍니다.
      - django_static:/app/static/ # nginx에서 static을 사용할 수 있도록 volume을 지정해줍니다.
    environment: # django에서 사용할 설정들을 지정해줍니다.
      - DEBUG=1
      - POSTGRES_DB=django
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=P@ssw0rd
      - POSTGRES_HOST=postgres
      - POSTGRES_PORT=5432
    depends_on:
      - postgres
    restart: always

  nginx:
    container_name : nginx
    image: nginx:1.23.2
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - django_media:/media/ # django의 media를 사용할 수 있도록 volume을 지정해줍니다.
      - django_static:/static/ # django의 static 사용할 수 있도록 volume을 지정해줍니다.
    depends_on:
      - backend
    restart: always

3. backend / Dockerfile

# python 3.10.8버전 이미지를 사용해 빌드
FROM python:3.10.8

# .pyc 파일을 생성하지 않도록 설정합니다.
ENV PYTHONDONTWRITEBYTECODE 1

# 파이썬 로그가 버퍼링 없이 즉각적으로 출력하도록 설정합니다.
ENV PYTHONUNBUFFERED 1

# /app/ 디렉토리를 생성합니다.
RUN mkdir /app/

# /app/ 경로를 작업 디렉토리로 설정합니다.
WORKDIR /app/

# requirments.txt를 작업 디렉토리(/app/) 경로로 복사합니다.
COPY ./django/requirements.txt .

# 프로젝트 실행에 필요한 패키지들을 설치합니다.
RUN pip install --no-cache-dir -r requirements.txt

# gunicorn과 postgresql을 사용하기 위한 패키지를 설치합니다.
RUN pip install gunicorn psycopg2

이렇게 작성해주면, 배포 구조는 이렇게 된다.