스택메모리

 

각 함수에서 사용하는 지역 변수, 매개 변수 등을 임시적으로 저장하는 공간이다.

스택 메모리의 크기는 프로그램 빌드 시에 결정되며 위치는 실행 시에 결정된다.

 

간단한 예제(포큐 아카데미 C 강좌)

 

위의 간단한 예제로 설명하자면 main 함수의 int a, int b 그리고 add 함수로 넘겨주는 매개변수 a, b 모두 지역, 매개변수 임으로 스택메모리에 값이 저장된다.

 

C언어에서는 New라는 키워드가 없는데 이는 기본적으로 변수를 선언하면 변수가 스택메모리에 할당되기 때문이다.

C언어 기본 자료형 변수(char, int, float)는 스택 메모리에 할당되며 기본 자료형을 함수 매개변수로 전달하면 스택에 복사본을 만든다(값복사, 값형) 

반대로 다른언어에서 처럼 malloc을 쓰면 Heap 영역에 할당된다. Heap 영역에 메모리를 할당하면 운영체제가 프로그래머가 요구한 메모리 사이즈를 검색하고 반환하며 크기가 가변적이라 메모리에 구멍이 숭숭뚫린다.

 

 

스택 메모리 조금 더 자세히

스택 메모리(포큐 아카데미 C 강좌)

 

1. 스택은 큰주소에서 작은 주소로 쌓인다

2. EBP(Extended Base Pointer) : 현재 스택 프레임의 첫 주소(Base 주소)

3. ESP(Extened Stack Pointer) : 현재 스택 포인터

4. 스택 프레임(stack frame) : 각 함수가 사용하는 스택 메모리의 범위

 

스택 메모리 + 어셈블리어

 

어셈블리어 Mov(포큐 아카데미 C 강좌)

왼쪽은 어셈블리어 오른쪽은 그에 대응되는 스택 메모리의 그림이다.

1. esp를 ebp로 Move해라! 그러니깐 같은 것을 가르켜라

 

 

어셈블리어 메모리 영역 확장(포큐 아카데미 C 강좌)

2. esp를 14h(16진수) 즉 십진수 20만큼 sub(빼라) -> ESP 영역을 20만큼 확장해라 한 블럭이 4바이트니 5칸 밑으로 ESP를 내려라

 

어셈블리어 값 할당 (포큐 아카데미 C 강좌)

3. 주소 ebp - 4 즉 0x0073FE68에 0을 넣어라. ebp - 8 주소에 1을 넣어라, ebp -0Ch 주소에 2를 넣어라

 

어셈블리어 매개변수 전달 (포큐 아카데미 C 강좌)

4-1. eax에 ebp-0Ch의 값을 넣고, ecx에 ebp-8의 값을 넣어라(eax, ecx는 CPU 레지스터 영역임) 

4-2. 아까 담은 ecx의 값을 현재 스택 포인터인 esp에 넣어라 그리고 esp+4에는 eax를 넣어라

 

방금 4줄의 어셈블리어가 add 함수에 매개변수를 전달하는 방식이다

 

add 함수 Call 및 돌아갈 주소 push (포큐 아카데미 C 강좌)

5. 00011040이라는 주소를 Call한다(add 함수) 그리고 다시 돌아올 주소 0001102D를 ESP-14h 주소에 add한다.

 

add 함수 시작 전(포큐 아카데미 C 강좌)

6. 호출자 함수의 EBP를 PUSH 한다. 호출된 add 함수가 끝나고 다시 main함수로 돌아가야하니깐

 

add 함수 시작 전(포큐 아카데미 C 강좌)

7. EBP를 ESP로 move한다

 

add 함수 스택 메모리 확보 (포큐 아카데미 C 강좌)

 

8. ESP를 0c(12) 만큼 늘림으로서 add 함수의 스택 메모리 영역 확보

 

add 함수 res 변수 생성(포큐 아카데미 C 강좌)

 

9-1. eax, ecx, edx 에 2,1,1을 담고 dex에 ebp+0Ch 값을 더한다 1+2 = 3 

9-2. edx의 값을 ebp-4에 할당한다 즉(res 변수)

 

 

add 함수 인자 생성 (포큐 아카데미 C 강좌)

 

10-1. edx에 ebp-4를 할당(의미없음)

10-2. eax의 값(2)를 ebp -8에 할당

10-3, edx의 값을 eax에 할당(의미없음)

10-4, ecx의 값(1)을 ebp-0c에 할당 

 

add 함수 스택 영역 해제(포큐 아카데미 C 강좌)

11. esp에 0c를 add 함으로서 add 함수의 스택 영역을 해제한다. 여기서 중요한점은 3,2,1과 같은 값을 지우지 않는다는 점이다. 나중에 다른 함수가 해당 주소를 다시  읽었을때 3,2,1 같은 쓰레기 데이터가 남아있는 이유가 이때문이다.

 

add 함수 스택 영역 해제(포큐 아카데미 C 강좌)

12. 0x0073FE6C의 주소로 ebp를 이동하면서 pop

 

add 함수 종료 return (포큐 아카데미 C 강좌)

13. return 명령어 실행 : 0x0001102D 의 주소로 return (add 함수 종료)

 

14-1. esp, 14h 만큼 add : esp가 ebp를 가르키게함 (메모리 축소)

14-2. ebp를 pop

14-3. return 후 종료

'C' 카테고리의 다른 글

C언어 구조체  (0) 2019.12.18
C언어 포인터 배열  (0) 2019.12.13
C 포인터 const  (0) 2019.12.12
C언어 배열과 포인터 차이점  (0) 2019.12.12
C언어 Char, int 정리  (0) 2019.12.05
Char

 

C언어에서 Char는 보통 8비트를 쓴다. 0000 0000 ~ 1111 1111까지 표현한다는 말

Only 양수로(unsigned) 포현하면 0~255(2의 8승), 음수도 표현하면(signed) -128 ~ 127까지이다.

 

보통 char의 디폴트 값은 signed 이나 그 보통은 컴파일러에 따라 다르다. 그러면 내 상황에서 signed인지 unsigned인지 어떻게 아느냐?

포큐아카데미

MIN값에서 -128이면 내 기본값은 signed이다. 왜냐 최소값이 -128이니깐.

 

 

INT

 

C언어 표준에 따르면 int값은 32bit가 아니라 최소 16비트 그리고 short 크기 이상인 정수형이다.

 

C언어에서 int는 기본 정수이다. 그래서 int를 기준으로 short, long이 존재한다. int 보다 작거나 크거나

CPU에게 '정수 처리해'라고 하면 CPU가 편하게 처리 할 수있는 크기여야 한다. 그 크기란 것은 CPU의 산술논리장치가 사용하는 기본 데이터이다. 이 데이터를 워드라고 하고 그 크기를 워드 크기라 한다. 워드 크기는 레지스터 크기랑 같다. 그래서 내가 사용하는 CPU에 따라 다르고 예전에는 16bit 컴퓨터를 많이 사용해서 최소 16비트 이상이다. 그러나 요즘은 거의 모든 컴퓨터가 32bit 이상이라 int는 그냥 32bit라고 말한다.

 

근데 내가 사용하는 PC는 64bit인데? 그래도 32bit에 머무른다. 왜냐? 너무 오랫동안 32bit로 머물러서 그 많은 코드를 다 수정할 수도 없고 32bit에서 64bit로 바꾼다고 해서 무조건 성능이 빨라지는 건 아니기 때문이다.

'C' 카테고리의 다른 글

C언어 구조체  (0) 2019.12.18
C언어 포인터 배열  (0) 2019.12.13
C 포인터 const  (0) 2019.12.12
C언어 배열과 포인터 차이점  (0) 2019.12.12
C 스택 메모리 해부(어셈블리어)  (3) 2019.12.09

Everything is object in Python 이라는 말이있다. 근데 정확히 무슨말인지 이해하기가 좀 까다롭다.

C언어는 메모리를 바로 까볼수 있어서 느낌이 팍팍 오는데 Python은 뭔가 애매하고 한글로된 자료가 많이 없어서 정리하고자 한다.

 

 

1.  Everything is object의 핵심 개념

 

변수와 object의 관계

1번(빨간색)

C언어에서 x = 10 이렇게 변수를 할당하면 메모리에 해당 값이 바로 박히지만 파이썬에서는 10이라는 int object를 만들어 놓고 변수 x가 그것을 가르키는 형태이다.(보통 레퍼런스라고 하며 Pointer의 개념, 진짜 중요한 말이다 이게 바로 Everything is object in Python의 핵심 개념!

 

 

그리고 y = x 라고 하면 x에 의해서 이미 만들어진 10 이라는 int object를 y는 그냥 가르키기만 한다. 그래서 x와 y는 같은 object를 가르킨다 라고 말한다. 결국 10 int object를 가르키는건 x, y 2개

 

2번(하늘색)

x = x +1은 11(10 + 1)이라는 새로운 int object를 생성한다. 그리고 x는 새롭게 만들어진 int object를 가르킨다.

그리고 z = 10은 10이라는 int object를 가르키는데 10 int object는 이미 생성되어 있으니 만들 필요 없고 그냥 가르키기만 한다.

 

3번(보라색)

z = Car()는 Car라는 object를 생성하고 z는 car object를 가르킨다.(아주 단순)

 

 

2-1.  메모리 할당(Stack, Heap)

메모리 할당

 

main 함수

main 함수에서 y=5( 5 int object 생성 and 가르키기)과 f1(y)함수를 Call 한다. f1(y)를 호출하면 Stack 영역에 f1()영역이 생성 된다.

 

f1 함수

f1 함수에서 x = x * 2(5 * 2)로 10 int object 생성 및 가르키기를 하고 f2(x)를 호출하면 Stack 영역에 f2()영역이 생성 된다.

 

f2 함수

f2 함수에서 x = x +1 (10 + 1)로 11 int object 생성 및 가르키기를 한다.

 

 

2-2.  메모리 할당 해제

 

메모리 할당 해제

 

할당 해제

우선 Stack의 가장 위에 있는 f2함수가 해제 된다.(특이사항 없다)
그다음 f1함수가 해제 되는데 f1함수의 변수 x가 없어짐에 따라 10 int object도 없어진다.(10 int object를 아무도 가르키지 않기 때문) 이것이 바로 reference counting이 0이 됨에 따라 object가 없어지는 가비지 컬랙터이다. 파이썬은 레퍼런스 카운팅을 이용해서 메모리를 관리한다. 원리는 f1함수가 해제될때 10 int object가 사라지는 것이 대표적이 예이다.

 

마지막으로 main 함수의 변수 z는 11을 가르킨다.

 

3. Class instance 메모리 관리(self는 정확히 무엇인가)

 

Class instance memory

 

할당 해제

main에서 c = Car(4)은 class instance를 생성하는데 처음에 생성자 함수 __init__이 호출된다.

여기서 self, w 2개를 매개변수로 받는데 이는 매개변수 즉 지역변수 이기 때문에 Stack 영역에 생성된다.

 

w는 당연히 4인데, self는 정확히 무엇일까? 그림에서 보듯 Car instance(object)의 주소(reference) 값이다. 그러니깐 모든 class 메소드는 self를 매개변수로 가지는데 self는 자신의 Class instance의 주소 값이다. 너무나 중요한 말이고 너무나 당연한 말이다. self를 매개변수로 받지 않으면 어떻게 instance값을 참조 할 것인가? 찾지를 못한다.

 

그리고 self.wheels은 instance의 변수 즉 속성(attribute)이다. attribute는 Heap 영역에 할당된다. 왜냐하면 __init__ 함수가 없어지고 Stack 영역이 사라져도 self.wheels은 존재해야 하니깐! 어려운 말인데 잘 생각해 보길 바란다. 

마지막으로 self.wheels은 w가 가르키는 4를 가르킨다.

 

 

 

메소드 실행

 

메소드 실행

c.getWheels()를 실행하면 Stack 영역이 만들어지고 매개변수로 self가 생성된다. self는 instance의 주소 값을 가지고 있는 변수이니 self를 통해 Heap 영역의 wheels 변수에 접근한다. 접근 값은 4이고 main함수의 n 값은 Heap영역의 4를 가르킨다.

 

4. 결론 및 정리

본 글은 Everything is object in Python을 이해하기 위한 글이다.

C의 메모리(Stack, Heap), 포인터의 개념이 있어야 확실히 정리가 될 것이다.

정말 기본중에 기본이니 알고 있는 것이 좋을듯하다!

 

참조 영상 : https://www.youtube.com/watch?v=arxWaw-E8QQ

인도 아저씬데 기가맥히다.....

'python' 카테고리의 다른 글

파이썬 데코레이터 활용(로깅)  (1) 2021.09.02
python oracle 데이터 json serialize(django)  (0) 2020.02.25
python super  (0) 2019.12.26
클래스 관계 IS-A 상속  (0) 2019.11.07
python openpyxl을 이용한 Django DB insert  (0) 2019.06.21

Django ORM related_name, 역참조 삽질기 남긴다.. (피가 거꾸로 솟을뻔 했다)

 

 

아래와 같은 Model이 있다고 하자

차량(Car)이 있고 해당 차량에 적재할 수 있는 팔레트(Pallet)가 있다고 하자.

class Car(models.Model):
    car_number = models.CharField(max_length=50)
    type = models.CharField(max_length=50)

    def __str__(self):
        return f"{self.car_number}({self.type})_팔레트개수:{self.pallet.count()}"


class Pallet(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE, related_name='pallet')
    seq = models.PositiveIntegerField()

    def __str__(self):
        return f"{self.car}({self.seq})번째"
        
        
class OrderList(models.Model):
    codeName = models.CharField(max_length=255)
    pallet = models.ForeignKey(Pallet, on_delete=models.CASCADE, related_name='order_list', null=True, blank=True)

 

Car에서 자기에게 할당된 팔레트를 찾으려면 어떻게 하면 좋을까?

related_name을 활용한 역참조(reverse relation)를 쓰면된다.

Car.objects.first().pallet.all()

이런식으로 첫번째 차량의 모든 팔레트를 가져 오고 싶으면 여기서 pallet는 내가 related_name에서 pallet라고 명시해서 그렇다! love면 love로 참조하면 된다.

 

그렇다면 역참조 annotate는 어떻게 할까? 예를들어 모든 차량의 팔레트 수를 알고 싶을때 어떻게 할까?

Car.objects.all().annotate(pallet_count=Count(F('pallet')))

이런식으로 annotate를 쓰고 pallet로 참조해주면 된다.

 

 

이걸 쿼리로 풀면 아래와 같다. 진짜 간단한 쿼리다...

SELECT "release_car"."id", "release_car"."car_number", "release_car"."type", COUNT("release_pallet"."id") AS "pallet_count" FROM "release_car" LEFT OUTER JOIN "release_pallet" ON ("release_car"."id" = "release_pallet"."car_id") GROUP BY "release_car"."id"

 

 

마지막으로 역참조 filter + 역참조 annotate까지 붙이려면 어떻게 할까?

예를들면 해당 차량(car_id)의 모든 팔레트를 구하고싶은데 팔레트에 적재된 주문의 일자(주문 내역은 order_list로 역참조)로 filter하고 order_list 역참조의 주문 내역 Count를 알고싶을때는 아래와 같이 하면 된다.

 

상당히 복잡하게 말했는데 filter에서 order_list는 Pallet의 컬럼이 아니다 그런데 역참조로 인해서 컬럼처럼 쓰고있고(filter에서) annotate에서 또한 order_list를 마치 자신의 컬럼인양 사용하고 있다. 편하다 편해

pallets = Pallet.objects.filter(car__id=car_id).filter(order_list__ymd=ymd).annotate(counts=Count(F('order_list')))

 

 

결론 : 역참조는 좋다. 근데 헷갈린다.

'django' 카테고리의 다른 글

Django workers process 메모리 공유  (0) 2021.02.19
Django queryset to json  (0) 2019.12.31
Django Docker 배포(production)  (0) 2019.10.25
헷가리는 Django Static 간략 정리  (0) 2019.10.18
DRF ForeignKey Update  (0) 2019.06.14

HAS-A는 뭐냐? ~이 ~을 가진다. 컴퓨터는 CPU와 RAM을 가진다, 경찰은 총을 가진다.

HAS의 의미 그대로 "가진다"의 뜻이다.

HAS-A 관계는 두가지의 종류가 있는데 하나는 합성(composition) 다른 하나는 통합(aggregation)이다.

합성관계는 없어서는 안될 아주 강한 결합 상태고, 통합은 없어도 괜찮아~ 정도의 약한 결합 상태이다.

 

합성의 예를 들면 컴퓨터와 CPU의 관계이다. 컴퓨터는 CPU 없이는 존재할 수 없다. 왜냐? 아무것도 못하니깐

통합의 예는 경찰과 총의 관계이다. 근육맨 경찰들은 총이 없어도 그만이지 않는가

 

1. 합성의 예시

합성의 관계

class CPU:
    print('빵빵한 CPU')


class RAM:
    print('든든한 RAM')

class Computer:
    def __init__(self):
        self.cpu = CPU()
        self.ram = RAM()
        print('CPU와 RAM 없이는 존재 할 수 없으니 나는 합성 관계야!!')

computer = Computer()

 

2. 통합의 예시

통합의 관계

class Gun:
    def __init__(self, gun):
        self.gun = gun

    def bbang(self):
        print(self.gun + ' 빵야 빵야')


class Police:
    def __init__(self):
        self.gun= None

    def get_gun(self, gun):
        self.gun = gun

    def fire_gun(self):
        if self.gun:
            self.gun.bbang()
        else:
            print('총 없다 손으로 맞자')


police = Police()
police.fire_gun()
police.get_gun(Gun('M16'))
police.fire_gun()

통합의 예시는 이미 설명했듯이 있어도 그만 없어도 그만이다. 경찰이 총이없으면 손으로 총이 있으면 총으로!(경찰이 M16을 들면 일반 시민은 바로 복종할 듯 하다)

'컴퓨터 기본' 카테고리의 다른 글

Thread 란?  (0) 2020.05.07
컴퓨터 하드웨어 구성(CPU)  (0) 2020.02.11
class의 static이란?(실무에서 바로 통하는 자바)  (0) 2019.10.28
유니코드 vs 아스키코드  (0) 2019.06.14
운영체제 32bit vs 64bit  (0) 2019.06.14

한번씩 기술 블로그를 볼때마다 IS-A , HAS-A 어쩌고 저쩌고 하던데 컴퓨터 사이언스 부트캠프 with 파이썬 책에 잘 나와있어서 정리해본다

 

IS-A: 상속

 - IS-A는 ~은 ~의 종류다 라는 뜻인데 A laptop IS-A computer 즉 랩탑(노트북)은 컴퓨터의 한 종류다! 이 예시가 제일 적절하다. 그러니깐 컴퓨터는 부모 클래스고 노트북은 자식 클래스이다.

 

컴퓨터와 노트북은 IS-A 상속 관계

class Computer:

    def __init__(self, cpu, ram):
        self.cpu = cpu
        self.ram = ram

    def browse(self):
        print('브라우저로 웹서칭')

    def work(self):
        print('일하기')


class Laptop(Computer):

    def __init__(self, cpu, ram, battery):
        super().__init__(cpu, ram)
        self.battery = battery

    def move(self):
        print('노트북은 이동 가능해요')


laptop = Laptop('2core', '4GB', '100%')
print(laptop.cpu)
laptop.move()

위와 같은 관계를 IS-A라고 부른다! ~은 ~의 한종류다.

이상하게 프로그래밍 하면서 static을 많이 쓸 일이 많이 없었다. 내가 하수라서 쓸 타이밍을 모르는건지 자주 안쓰이는 건지는 모르겠지만 한번씩 static이 나올때마다 약간의 두려움을 없애고자 이 글을 작성한다(실무에서 바로 통하는 자바를 읽다가)

 

 

static이란?

인스턴스들은 똑같은 클래스를 바탕으로 하더라도 인스턴스마다 내부의 변숫값과 메서드의 행동이 다르지만 static을 붙이면 변수와 메서드를 클래스에서 유일한 것으로 다룰 수 있다

static 변수는 클래스에서 인스턴스를 몇 개 만들어도 메모리에는 단 하나만 생성된다. static 변수는 모든 인스턴스에서 같은 값을 공유한다.

 

아래의 그림을 보다싶이 Dog Class의 인스턴스들은 각각의 name을 가지지만 type은 포유류 단 하나다. 왜냐? static이 붙었으니깐! 내 생각엔 클래스가 인스턴스 될때 name과 같은 인스턴스 변수들은 메모리에 할당될때 새롭게 생성+할당되지만 type과 같은 static변수는 기본값으로 static 변수의 주소값 즉 포인터 변수 같은 그런 느낌이 살짝쿵 든다. 

 

실무에서 바로 통하는 자바

 

 

아래의 그림은 static 변수를 변경했을때다 모든 인스턴스 type 변수는 static 변수를 Point 함으로 한놈이 변경하면 바로 모든 인스턴스에 영향을 미친다. 느낌이 그냥 딱 포인터다

실무에서 바로 통하는 자바

 

그리고 static 메서드를 사용할떄는 인스턴스화 안해도 쓸수 있다. 사용법 : 클래스명.메서드명(인수) 이건 뭐 다 아는사실이니.

 

마지막으로 JAVA 초보지만 System.out.println의 out은 System 클래스의 static 변수이고, PrintStream 클래스의 인스턴스다. 결과적으로 System.out.println은 PrintStream 객체의 메서드인 println을 실행하는 것이다. 이 말이 무엇이냐? 지금 System 클래스에서 바로 out을 사용했다.. System은 클래슨데?? 인스턴스도 안만들었는데?? 그렇다 static이니깐! 

'컴퓨터 기본' 카테고리의 다른 글

Thread 란?  (0) 2020.05.07
컴퓨터 하드웨어 구성(CPU)  (0) 2020.02.11
클래스 관계 HAS-A 상속(합성, 통합)  (0) 2019.11.08
유니코드 vs 아스키코드  (0) 2019.06.14
운영체제 32bit vs 64bit  (0) 2019.06.14

장고를 배포할때마다 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

+ Recent posts