[Docker] Docker Compose를 이용해 Docker + Nginx + SpringBoot + React(w/ Vite) + CertBot 배포하기

반응형
SMALL

서론

이번 프로젝트를 진행하면서 SSL 인증을 포함한 프로젝트를 한 번에 배포하기 위해 Docker Compose를 이용한 것을 기록하기 위해 작성하였습니다.

모든 것이 정답이 아닐 수 있기 때문에, 틀린 부분이 있다면 댓글로 알려주세요! 감사합니다.

 

Docker Compose를 사용하여 React (Vite)와 SpringBoot를 함께 배포하는 방법을 다뤘습니다.

이를 위해 Nginx를 중심으로 요청이 들어오면 React의 정적 파일을 서빙하고, SpringBoot Api를 프록시 하는 환경을 설정하는 과정을 나타냅니다.

etc-image-0

이전에는 Spring Boot 만을 독자적으로 실행하였는데 매번 애플리케이션들을 따로하기가 힘들어서 고민하였습니다.

Docker Compose를 이용해 한 번에 여러 이미지를 배포할 수 있는 방법을 알게되었습니다.

 


 

본론

프로젝트 구조

우선, Docker Compose를 사용하여 React, Spring Boot, 그리고 Nginx를 모두 통합하여 관리할 수 있도록 디렉터리를 구성합니다. 이때 React는 Vite로 빌드하여 Nginx가 정적 파일을 서빙하며, SpringBoot는 Api 서버로 동작합니다.

 

프로젝트 구조는 다음과 같습니다.

/my-project
  ├── Dockerfile                # Spring Boot의 Dockerfile
  ├── docker-compose.yml        # Docker Compose 파일
  ├── nginx.conf                # Nginx 설정 파일
  ├── project.jar               # 배포할 jar 파일
  └── /frontend                 # React (Vite) 프로젝트 디렉토리
        └── /dist               # Vite 빌드 결과물이 저장될 디렉토리 (자동 생성됨)

 

DockerFile

도커 파일을 이전에 작성한 아래 링크를 확인해 주세요!

2024.10.02 - [Server/Docker] - [Docker] DockerFile과 실행 스크립트를 이용해 Spring Boot 배포하기

 

[Docker] DockerFile과 실행 스크립트를 이용해 Spring Boot 배포하기

서론도커 파일을 이용해 Spring Boot 이미지 내 디렉터리 생성 및 권한 부여 그리고 이미지 생성하고,실행 스크립트를 통해 서버 내 디렉토리와 도커 이미지 내 디렉터리를 마운트 하는 부분을 기

abuuu.tistory.com

Nginx (nginx.conf)

Nginx는 React 애플리케이션의 정적 파일을 서빙하고, API 요청은 SPring Boot 서버로 전달하는 역할을 한다.

또한, HTTPS 설정을 위해 Let's Encrypt의 SSL 인증서를 적용했습니다.

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;  # MIME 타입 설정 파일 포함
    default_type text/html;  # 기본 MIME 타입을 text/html로 설정

    server {
        listen 80;
        server_name your_site;

        # HTTP → HTTPS 리다이렉트
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl;
        server_name mpark.site;

        ssl_certificate /etc/letsencrypt/live/your_site/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/your_site/privkey.pem;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;

        # Vite로 빌드된 React 정적 파일을 서빙
        location / {
            root /usr/share/nginx/html;
            try_files $uri $uri/ /index.html;  # React 라우팅 처리
        }

        # Spring Boot 서버로 API 요청을 프록시
        location /su/api/ {
            proxy_pass http://your_site:9808;
            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;
        }

        # CORS 설정
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization';

        # Certbot에서 SSL 인증서를 발급받을 때 사용하는 경로 설정
        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }
    }
}

 

각 부분의 의미는 아래와 같다!

 

  • events 블록
    • 이벤트 블록 내 내용은 필수로 설정할 필요는 없다.
    • 공백으로 해도 적용 된다.
    • 필자는 worker_connections 1024
      • Nginx가 동시에 처리할 수 있는 최대 연결 수를 1024로 설정한다.
      • 이 설정은 Nginx의 성능에 영향을 주며, 한 번에 많은 사용자를 처리할 수 있는 정도를 조절한다.
  • http 블록
    • include /etc/nginx/mime.types
      • 다양한 파일 형식을 처리하기 위해 MIME 타입 설정 파일을 포함
    • default_type text/html
      • MIME 타입을 따로 지정하지 않은 파일은 기본적으로 HTML로 처리한다.
      • 필자는 처음 작성할 때, HTML로 디폴트 설정하지 않아서 서빙된 파일이 계속 다운로드되는 상황이 발생했었다;;
  • http > server 첫 번째 블록
    • listen 80
      • HTTP 트래픽 처리하기 위해 80 포트를 연다
    • server_name your_site
      • 서버 블록이 처리할 도메인 이름은 your_site로 지정
      • your_site에 자기가 사용할 도메인을 대입하면 된다.
    • returen 301 https://$host$request_uri
      • HTTP로 요청이 들어올 경우, HTTPS로 리다이렉트 합니다.
      • $host는 요청된 호스트 이름, $request_uri는 요청된 URI를 의미합니다.
  • http > server 두 번째 블록
    • HTTPS 처리 및 리버스 프록시
    • listen 443 ssl
      • HTTPS 트래픽을 처리하기 위해 443번 포트를 열고, SSL을 활성화합니다.
    • server_name your_site
      • 이 서버 블록이 처리할 도메인 이름을 your_site로 설정합니다.
    • SSL 설정
      • ssl_certificate
        • Let’s Encrypt에서 발급받은 SSL 인증서 경로입니다.
      • ssl_certificate_key
        • 인증서의 비밀키 경로입니다.
      • ssl_protocols
        • 지원할 SSL/TLS 프로토콜을 TLS 1.2와 TLS 1.3으로 설정합니다.
      • ssl_ciphers
        • SSL 암호화 방식 중 안전하지 않은 방식을 제외하고 안전한 암호화 방식만 사용합니다.
    • React 정적 파일 서빙
      • location /
        • 기본 경로(/)로 들어오는 요청을 처리합니다.
      • root /usr/share/nginx/html
        • 정적 파일이 위치한 디렉토리를 /usr/share/nginx/html로 설정합니다.
      • try_files $uri $uri/ /index.html
        • 요청한 파일이 없으면 index.html을 반환하여, React의 라우팅을 처리합니다.
    • Spring Boot API 서버로 프록시
      • location /su/api/
        • /su/api/로 들어오는 요청을 처리합니다.
      • proxy_pass http://your_site:9808
        • 요청을 내부의 Spring Boot 서버(your_site:9808)로 프록시합니다.
      • proxy_set_header
        • 여러 헤더 값을 설정하여 실제 요청자의 정보를 Spring Boot 서버에 전달합니다.
        • Host: 원래 요청의 호스트 이름을 전달.
        • X-Real-IP: 클라이언트의 실제 IP 주소.
        • X-Forwarded-For: 프록시를 거친 클라이언트 IP 목록.
        • X-Forwarded-Proto: 요청이 HTTPS인지 HTTP인지 전달.
    • CORS 설정
      • add_header: CORS(Cross-Origin Resource Sharing) 헤더를 추가하여 다른 도메인에서의 요청을 허용합니다.
        • Access-Control-Allow-Origin '*': 모든 출처에서의 요청을 허용.
        • Access-Control-Allow-Credentials 'true': 자격 증명(쿠키, 인증 정보 등)을 허용.
        • Access-Control-Allow-Methods: 허용할 HTTP 메소드(GET, POST, PUT, DELETE, OPTIONS)를 지정.
        • Access-Control-Allow-Headers: 허용할 HTTP 헤더를 지정.
    • Certbot 경로 설정
      • location /.well-known/acme-challenge/
        • Certbot에서 SSL 인증서를 발급받을 때 사용하는 경로입니다.
      • root /var/www/certbot
        • 이 경로에 있는 파일은 Certbot이 관리하는 SSL 인증서 관련 파일들입니다.

Docker Compose 파일

Docker compose를 통해 React, SpringBoot, 그리고 Nginx를 함께 실행합니다.

react-build 서비스는 React(Vite)를 빌드하고, Nginx는 정적 파일을 서빙하며 API 요청을 SPringBoot로 전달합니다.

version: '3'
services:
  springboot-app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: springboot-app
    ports:
      - "9808:9808"
    networks:
      - app-network

  nginx:
    image: nginx:latest
    container_name: nginx-container
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - /etc/letsencrypt:/etc/letsencrypt
      - /var/www/certbot:/var/www/certbot
      - ./frontend/dist:/usr/share/nginx/html
    depends_on:
      - springboot-app
    networks:
      - app-network

  react-build:
    image: node:16
    container_name: react-build
    working_dir: /app
    volumes:
      - ./frontend:/app
    command: /bin/sh -c "rm -rf node_modules package-lock.json && npm install && npm run build"
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

 

실행 방법

docker-compose up --build

 

설정 완료 후 터미널에서 위 명령어로 모든 서비스 빌드하고 실행 가능

 


 

결론

Docker와 Nginx를 활용하여 React + Spring Boot 애플리케이션을 배포하는 방법을 설명했습니다.

각 서비스는 Docker Compose를 통해 함께 관리되며, Nginx가 리버스 프록시 및 정적 파일 서빙을 담당합니다. 이 방법을 활용하면, React와 Spring Boot 애플리케이션을 손쉽게 배포할 수 있습니다.

반응형
LIST