Nginx Reverse Proxy (w. docker)

H.GOO·2024년 11월 7일

🪴 Reverse Proxy 사전적 의미

Reverse
뒤집다 (여기서 reverse 의 뜻은 "역전, 꺼꾸로"의 뜻이 아닌 "배후, 뒷쪽"의 뜻)
proxy
대리

네트워크에서 proxy 서버
클라이언트가 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템이나 응용 프로그램을 가리킨다.
=> 서버와 서버사이의 중계기 역할

Reverse Proxy의미
웹 서버 앞에 위치하여 클라이언트(예: 웹 브라우저) 요청을 해당 웹 서버에 분배해주는 서버




🪴 Forward Proxy 와 비교하여 이해하기

Forward Proxy (클라이언트 앞)
클라이언트 대신 프록시 서버가 목적 서버에 통신해주는 구성

아래 그림처럼, 같은 내부망에 존재하는 클라이언트의 요청을 받아 인터넷을 통해 외부 서버에서 데이터를 가져와 클라이언트에게 응답하는 구조


Reverse Proxy (본 서버 앞)
클라이언트가 웹서비스에 접근할때 웹서버에 요청하는 것이 아닌, 프록시로 요청하게 되고, 프록시가 배후(reverse)의 서버로부터 데이터를 가져오는 방식


Reverse Proxy를 사용하면

  • [보안] 클라이언트는 리버스 프록시 서버를 먼저 호출하게 되기에 실제 서버의 IP를 알 수 없다.
  • [성능] 리버스 프록시 서버를 여러개의 본 서버들 앞에 두면 특정 서버가 과부화 되지 않게 로드밸런싱이 가능하다.
  • [성능] 프록시 서버의 기본 기능인 "캐싱"을 활용하여 더 빠른 통신이 가능하다.
  • [성능] SSL 암호화, 복호화를 할 경우 본서버에서 직접하지 않고 프록시 서버에서 진행한다면 서버의 부담을 줄일 수 있다.

이미지 출처




🪴 Docker로 Nginx와 여러 서비스들 구성

docker 서비스를 좀 더 쉽게 정의할 수 있는 docker-compose.yml 파일을 활용하여 아래 서비스들을 구성하는 예시이다.

(docker 서비스를 사용하면, 호스트 PC에 직접 nginx 등을 설치할 필요 없음)

  • Nginx
  • FastAPI
  • MongoDB
version: "3.8"

services:
  nginxproxy:  # 도커 서비스명
    depends_on: # 의존 서비스(아래 서비스들이 모두 구동된 후에 nginxproxy 서비스 구동)
      - fastapi
      - mongodb
    image: nginx:alpine  # 도커 이미지
    container_name: proxyserver  # 도커 컨테이너 이름
    restart: always  # 재시작 규칙
    ports:  # 포트 포워딩
      - "1000:80"  # 호스트 포트(접속 포트):도커 내부 포트
    volumes:  # 볼륨 마운트
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf  # 호스트 볼륨 경로:도커 내부 볼륨 경로
      - ./frontend:/usr/share/nginx/html


  fastapi:
    build:  # 따로 Dockerfile을 사용하여 커스텀 빌드할 경우
      context: ./fastapi  # Dockerfile 상대 경로
      dockerfile: Dockerfile  # Dockerfile의 파일 이름
    container_name: fastapi
    restart: always
    command: uvicorn app.main:app --workers 40 --host 0.0.0.0 --port 7000 --reload  # uvicorn 사용할 경우 command
    ports:
      - "7000:7000"
    volumes:
      - ./fastapi/app:/code/app
  
  
  mongodb:
    image: mongo:7.0.5
    container_name: mongodb
    restart: always
    ports:
      - "27017:27017"
    volumes:
      - ./mongodb/db:/data/db  # 데이터 베이스 폴더 (도커 서비스를 중지 시켜도 데이터를 유지하기 위한..)
    env_file:
      - ./mongodb/mongodb.env  # mongoDB env 파일 (데이터베이스 설정 환경 변수 등 정의된..)

도커 서비스로 nginx, fastapi, mongodb 를 정의하고, nginx 설정을 사용자 정의하는 경우이다.

./nginx/nginx.conf 파일의 내용 예시이다.

user nginx;  # Nginx 프로세스 실행 사용자 지정
worker_processes auto; # Nginx가 사용할 워커 프로세스 수를 자동으로 설정 (CPU 코어 수에 맞게 조정)

error_log  /var/log/nginx/error.log warn;  # 에러 로그 파일 경로 및 로그 레벨 설정 (warn 이상의 에러만 기록)
pid        /var/run/nginx.pid;  # Nginx 프로세스 ID 파일 경로 설정

# 네트워크 이벤트 설정 블록
events {
    worker_connections 128;  # 각 워커 프로세스에서 동시에 처리할 수 있는 최대 연결 수 설정
}

# HTTP 관련 설정 블록
http {
    include       /etc/nginx/mime.types;  # MIME 타입 파일을 포함하여 응답의 Content-Type 설정
    default_type  application/octet-stream;  # 기본 MIME 타입 설정 (명시되지 않은 파일에 대해 이 타입 사용)

    # 로그 포맷 정의 (접속 로그 형식 지정)
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" "$request_uri" "$uri"'
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;  # 접속 로그 파일 경로와 사용할 로그 포맷 지정

    sendfile on;  # 파일을 전송할 때 sendfile 사용 (성능 향상)

    keepalive_timeout 500;  # 클라이언트와의 keep-alive 연결 유지 시간 설정 (초 단위)

    upstream docker-fastapi {
        server fastapi:7000;  # 도커 컨테이너 이름 `fastapi`와 포트 7000으로 연결
    }

    # 서버 블록 시작 (HTTP 요청을 처리하는 가상 서버 설정)
    server {
        listen 80;  # IPv4에서 포트 80으로 요청 수신
        listen [::]:80;  # IPv6에서 포트 80으로 요청 수신
        server_name $host:1000;  # 서버 이름 설정 (호스트 이름 및 포트)

        error_page   500 502 503 504 /50x.html;  # 에러 페이지 설정 (500, 502, 503, 504 에러 발생 시 사용자 정의 HTML 페이지 사용)
        location = /50x.html {
            root   /usr/share/nginx/html;  # 사용자 정의 에러 페이지의 루트 디렉토리 설정
        }

        # 기본 루트 경로 처리 설정
        location / {
            root   /usr/share/nginx/html;  # 정적 파일의 루트 디렉토리 설정
            index  index.html index.htm;  # 기본 인덱스 파일 설정
            try_files $uri $uri/ /index.html;  # 요청된 파일이 존재하지 않으면 index.html로 대체 (SPA 지원)
        }

        # /api/ 경로로 들어오는 요청을 FastAPI 서버로 프록시
        location /api/ {
            rewrite ^/api(/.*)$ $1 break;  # /api 접두어를 제거하고 나머지 경로를 유지
            proxy_pass         http://docker-fastapi/;  # 프록시 서버로 요청을 전달 (docker-fastapi 업스트림으로 연결)
            proxy_buffering    off;  # 프록시 버퍼링 비활성화 (실시간 데이터 전송에 유리)
            proxy_redirect     off;  # 자동으로 URL 리다이렉트 비활성화
            proxy_set_header   Host $host;  # 원래 요청의 Host 헤더 전달
            proxy_set_header   X-Real-IP $remote_addr;  # 클라이언트의 실제 IP 주소 전달
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;  # 프록시를 거친 IP 목록 전달
            proxy_set_header   X-Forwarded-Host $host;  # 원래 요청의 호스트 정보 전달
            proxy_set_header   X-Forwarded-Proto $scheme;  # 요청의 프로토콜 정보 전달 (http 또는 https)
        }
    }
}

0개의 댓글