장고를 배포할때마다 WAS(Nginx, Gunicorn)을 세팅하기 너무 귀찮다.

그래서 Docker에 모든 세팅을 딱 만들어놓고 빌드만 하면 되는 세팅을 가지고 싶어서 이 글을 적는다.

참고로 python manage.py runserver 이걸로 배포라고 말하긴 좀 그렇다. 이건 오로지 개발용을 위한거다.

 

  ※ 서버 OS로 Ubuntu를 사용했습니다!

 

1. Django 프로젝트 docker-compose.yml

docker-compose를 활용해서 gunicorn, postgres DB, nginx를 한번에 설정할거다.

 

첫번째 web은 우리의 Django 프로젝트다 여기서 중요한점은 volumes이다 static_volume의 share를 통해서 nginx가 static파일을 처리하게 만들어줘야한다.

 

두번째 db는 말그대로 postgres DB다 별다른 설정이 없다

 

세번째 nginx는 웹서버다 이것도 별다른 설정은 없다.

version: '2.2'

services:
  web:
    build:
      context: ./
      dockerfile: Dockerfile
    command: gunicorn projectFile.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - static_volume:/code/staticfiles/
    expose:
      - 8000
    env_file:
      - ./.env.prod
    depends_on:
      - db
  db:
    image: postgres:12.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.prod.db
  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    volumes:
      - static_volume:/code/staticfiles/
    ports:
      - 80:80
    depends_on:
      - web

volumes:
  postgres_data:
  static_volume:

 

 2. Django 프로젝트 Dockerfile

docker 컨테이너 안에서의 디렉토리는 code

static을 담당하는 디렉토리는 code/staticfiles

FROM python:3.7

# 환경 변수 설정
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# dependencies를 위한 apt-get update
RUN apt-get update && apt-get -y install \
    libpq-dev

RUN apt-get install -y netcat

# requirements.txt install
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/

# static file 
RUN python manage.py collectstatic

 

3. Django 프로젝트 setting을 위한 .env.prod 파일

DEBUG=0
SECRET_KEY=비밀
DJANGO_ALLOWED_HOSTS=11.11.11.11 localhost [::1]
SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=HI
SQL_USER=HI
SQL_PASSWORD=HI
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres

 

 

4. Django 프로젝트 settings.py(.env를 사용)

 

    SECRET_KEY = os.environ.get("SECRET_KEY")
    ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
    DATABASES = {
        "default": {
            "ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
            "NAME": os.environ.get("SQL_DATABASE", os.path.join(BASE_DIR, "db.sqlite3")),
            "USER": os.environ.get("SQL_USER", "user"),
            "PASSWORD": os.environ.get("SQL_PASSWORD", "password"),
            "HOST": os.environ.get("SQL_HOST", "localhost"),
            "PORT": os.environ.get("SQL_PORT", "5432"),
        }
    }

 

5. db를 위한 .env.prod.db 파일

POSTGRES_USER=HI
POSTGRES_PASSWORD=HI
POSTGRES_DB=HI

 

6. ngnix의 Dockerfile

docker-compose를 보면 알수있듯 nginx는 별도의 폴더를 만들어서 Dockerfile과 nginx.conf 파일을 관리한다.

ngnix폴더의 Dockerfile의 설정은 아래와 같다. 단순히 nginx의 이미지를 가져와서 nginx.conf 파일을 복붙!

FROM nginx:1.17.4-alpine

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

 

7. ngnix의 nginx.conf

여기서 중요한 점은 location /staticfiles/를 alias의 /code/staticfiles/로 처리해줘야한다 그래야 ngnix가 static파일들을 잘 처리할 수있다.

 

upstream HI {
    server web:8000;
}

server {

    listen 80;

    location / {
        proxy_pass http://HI;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

    location /staticfiles/ {
        alias /code/staticfiles/;
    }

    location /static/ {
        alias /code/staticfiles/;
    }
}

 

이렇게 하면 Django Docker production 세팅이 끝이다.

여기서는 DB도 만들었지만 실제로는 RDS와 같은 서비스 사용을 권장한다.

'django' 카테고리의 다른 글

Django workers process 메모리 공유  (0) 2021.02.19
Django queryset to json  (0) 2019.12.31
Django related_name(reverse 역참조 )  (0) 2019.11.13
헷가리는 Django Static 간략 정리  (0) 2019.10.18
DRF ForeignKey Update  (0) 2019.06.14

Django는 static file을 깔끔하게 관리하기 위해서 staticfiles app을 사용한다.
헷갈리는 STATIC_URLSTATICFILES_DIRSSTATIC_ROOT를 정리해보자 한다.

 

우선 실제 예제를 살펴보고 하나하나 해석해보자

 

1. STATIC_URL은 template에서 static을 사용하기 전에 {% load static %}할때 사용되는녀석(template tag가 사용한다)

2. STATICFILES_DIRS은 local development용으로 사용한다

3. STATIC_ROOT은 실제 production용으로 사용한다

3-2. python manage.py collectstatic을 실행하면 STATIC_ROOT에 지정된 폴더에 Staitc Assets이 복사되어진다

 

'django' 카테고리의 다른 글

Django workers process 메모리 공유  (0) 2021.02.19
Django queryset to json  (0) 2019.12.31
Django related_name(reverse 역참조 )  (0) 2019.11.13
Django Docker 배포(production)  (0) 2019.10.25
DRF ForeignKey Update  (0) 2019.06.14

 

model Code

 

class Detail(models.Model):
    """
    Order, Release의 부모 클래스
    """
    ymd = models.CharField(max_length=8)
    code = models.CharField(max_length=255)
    codeName = models.CharField(max_length=255)
    count = models.IntegerField()
    amount = models.DecimalField(decimal_places=2, max_digits=19, default=0)
    amount_kg = models.DecimalField(decimal_places=2, max_digits=19, default=0, blank=True, null=True)
    memo = models.TextField(blank=True, null=True)

    class Meta:
        abstract = True

 

 

class Release(Detail):

    """

    출고에 관한 데이터 출고는 주문을 기반으로 생성되거나 독립적으로 생성될 수 있음

    """
    price = models.IntegerField()

    releaseVat = models.IntegerField()
    releaseOrder = models.ForeignKey('order.Order', on_delete=models.CASCADE, null=True, blank=True)

 

class Order(Detail):

    """

    주문 데이터

    """
    orderLocationCode = models.ForeignKey(Location, on_delete=models.CASCADE)
    orderLocationName = models.CharField(max_length=255)
    price = models.DecimalField(decimal_places=1, max_digits=19)

 

django rest framework를 이용해서 Update, Delete를 하고있는데 ForeignKey가 걸려있는 데이터를 Update해달라는 요청이 왔다. 즉 Release Class - releaseOrder의 memo값을 수정해야 한다(주문메모를 출고 데이터 update 시 같이 변경)

 

Serializer Code

 

class ReleaseSerializer(serializers.ModelSerializer):

    class Meta:
        model = Release
        fields = '__all__'

 

이렇게 아름답고 깔끔하게 되어있는 Serializer를 변경하기 싫지만 수정은 해야하니....

프론트 엔드쪽에서는 patch를 이용해 Update를 실시한다 그러므로 update 메소드를 오버라이딩해서 기본 update에 ForeignKey가 걸려있는 Order(주문) 데이터도 함께 변경해보자

 

 

class ReleaseSerializer(serializers.ModelSerializer):
    orderMemo = serializers.CharField(required=False) # 프론트에서 넘어올때 orderMemo로 넘어옴

    class Meta:
        model = Release
        fields = '__all__'

    def update(self, instance, validated_data):
        """
        출고조회 - 수정 시 ForeignKey Order의 메모 수정으로 overRide 실시(orderMemo)

         출고 데이터 중 price(가격), releaseVat(부가세), 주문메모만을 변경함.
        """
        instance.price = validated_data.get('price')
        instance.releaseVat = validated_data.get('releaseVat')
        instance.releaseOrder.memo = validated_data.get('orderMemo')
        instance.releaseOrder.save()
        instance.save()
        return instance

 

ModelSerializer의 update 메소드를 오버라이딩해서 instance.releaseOrder.memo와 같이 접근해서 Order(주문) 데이터를 Release(출고) 데이터와 함께 Update를 실시하고 있다!

'django' 카테고리의 다른 글

Django workers process 메모리 공유  (0) 2021.02.19
Django queryset to json  (0) 2019.12.31
Django related_name(reverse 역참조 )  (0) 2019.11.13
Django Docker 배포(production)  (0) 2019.10.25
헷가리는 Django Static 간략 정리  (0) 2019.10.18

+ Recent posts