Web Project/e-commerce

도커화 (Docker Compose + Nginx)

hmmmmmmmmmmmm 2025. 8. 24. 18:13

Django REST Framework + React 기반 프로젝트를 도커(Docker) 로 컨테이너화하여 프론트엔드·백엔드·프록시(Nginx)를 분리 실행하는 환경 구축

 

# 목표 아키텍처

컨테이너 3개로 나누기

1. backend: Django + Gunicorn (REST API)

2. frontend: React (빌드 후 Nginx에서 정적 파일 제공)

3. nginx: 리버스 프록시 (React와 Django API를 라우팅)

 

요청 흐름:

브라우저 → Nginx → (정적 요청: React, API 요청: Django)

 

 

# 목적

1. 서버 (backend)

Django + Gunicorn 컨테이너 → API 담당

필요하면 RDS(MySQL/Postgres) 같은 AWS DB랑 연결

 

2. 프론트(frontend)

React 빌드된 정적 파일을 nginx로 서비스

이걸 S3 + CloudFront로 따로 배포할 수도 있고, 지금처럼 Nginx 컨테이너에 넣을 수도 있음

 

3. Nginx(프록시)

들어오는 요청을 앞에서 다 받아서

/api는 backend로

그 외 요청은 frontend로 전달

실제 서비스 주소(http://도메인.com)는 하나인데, 내부적으로는 역할이 나눠져 있음

 

# 장점

트래픽 많아지면 백엔드만 여러 개 늘릴 수 있음.

프론트만 고치면 frontend 컨테이너만 다시 배포하면 됨.

기업들이 보통 AWS에서 똑같이 Nginx + Gunicorn + Django 패턴 씀.

→ 도커로 서버/프론트/nginx 나눈 건, AWS 같은 클라우드에 배포해서 운영 환경과 똑같이 만들려고

 

# 프로젝트 구조

ecommerce/
├── client/                # React (프론트엔드)
│   └── Dockerfile
├── server/                # Django (백엔드)
│   └── Dockerfile
├── nginx/
│   └── default.conf       # Nginx 설정
├── docker-compose.yml
└── requirements.txt

 

 

# Backend (Django)

 

server/Dockerfile

FROM python:3.11-slim

WORKDIR /app

RUN pip install --upgrade pip

COPY requirements.txt /app/

# torch는 따로 설치 (cpu 전용)
RUN pip install torch==2.1.0+cpu torchvision==0.16.0+cpu torchaudio==2.1.0+cpu \
    --index-url https://download.pytorch.org/whl/cpu

RUN pip install --default-timeout=100 --retries=5 -r requirements.txt

COPY . /app

CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]

 

Django 실행 환경 만들기

Python 설치 → 필요한 라이브러리 설치 → 소스코드 복사 → Gunicorn 서버 실행

 

 

 

settings.py 주요 설정

ALLOWED_HOSTS = ["*", "localhost", "127.0.0.1", "backend"]

CORS_ALLOW_ALL_ORIGINS = True

USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'http')

 

ALLOWED_HOSTS: 어떤 주소에서 접속을 허용할지 지정

CORS_ALLOW_ALL_ORIGINS: 다른 도메인(React)에서 API를 호출할 수 있게 허용

USE_X_FORWARDED_HOST, SECURE_PROXY_SSL_HEADER: 프록시(Nginx) 뒤에서 동작할 때 주소 처리를 올바르게 하기 위한 옵션

 

 

# Frontend (React)

 

client/Dockerfile

FROM node:18 as build

WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install --legacy-peer-deps
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html

 

React 앱 빌드 (개발용 소스를 실제로 배포 가능한 정적 파일로 변환)

빌드된 파일을 Nginx에 넣어서 서비스하도록 만들기

 

 

 

# Nginx 설정

 

nginx/default.conf

server {
    listen 80;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri /index.html;
    }

    location /api {
        proxy_pass http://backend:8000;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

 

 

# Docker Compose

 

docker-compose.yml

version: '3.8'

services:
  backend:
    build: ./server
    container_name: django_app
    command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - ./server:/app
    expose:
      - "8000"

  frontend:
    build: ./client
    container_name: react_app
    expose:
      - "80"

  nginx:
    image: nginx:alpine
    container_name: nginx_proxy
    ports:
      - "80:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - backend
      - frontend

 

프로젝트 전체 컨테이너 실행을 관리 파일

 

backend: Django API 서버

frontend: React 정적 파일 서버

nginx: 라우팅(앞단에서 프론트/백 구분해 전달) → 요청을 받아서 React 또는 Django로 전달

 

 

 

# 실행 과정

 

1) 빌드 & 실행

docker-compose up -d --build

 

2) 컨테이너 확인

docker-compose ps

 

실행 결과:

nginx_proxy (포트 80 열림)

django_app (Gunicorn, 8000 내부 포트)

react_app (Nginx, 정적 파일 제공)

 

 

# 결과

http://localhost/ → React 프론트엔드 정상 동작

http://localhost/api/products/ → Django API 응답

 

 

# 마무리

로컬 개발 환경에서 프론트엔드, 백엔드, Nginx 프록시를 컨테이너로 분리해 실행 가능

다음 단계는:

1. DEBUG=False 설정 후 정적/미디어 파일 서빙 확인

2. AWS EC2, Lightsail, 혹은 클라우드에 배포

3. CI/CD 파이프라인 추가

까지 이어가면 실제 서비스 운영 환경과 유사한 구성이 완성된다.