DEVEL/ETC

Docker 리버스 프록시 사용

codebyai 2025. 4. 14. 13:57
반응형

1. 개요

Docker와 리버스 프록시란?

  • Docker: 애플리케이션을 컨테이너라는 격리된 환경에서 실행할 수 있도록 해주는 플랫폼입니다.
  • 리버스 프록시: 클라이언트의 요청을 받아 내부의 여러 백엔드 서버(컨테이너)로 요청을 전달하고, 응답을 다시 클라이언트에 전달하는 역할을 합니다.
  • 도입 이유:
    • 단일 진입점(예: 도메인, IP, 포트)을 사용해 여러 서비스에 접근할 수 있음
    • SSL 종료(SSL termination) 및 로드 밸런싱 처리 가능
    • 보안 강화: 백엔드 서버의 실제 IP 및 포트를 외부에 노출하지 않음

2. 리버스 프록시 솔루션 소개

대표적인 리버스 프록시 솔루션은 다음과 같습니다.

  • Nginx: 가장 널리 사용되는 웹 서버 및 리버스 프록시 서버로, 성능과 설정의 유연성이 뛰어납니다.
  • Traefik: Docker 환경과의 연동성이 강력하여, 서비스의 자동 탐지(auto discovery) 및 동적 라우팅(label 기반 설정)이 특징입니다.
  • HAProxy: 고성능 로드 밸런싱 솔루션으로, 복잡한 트래픽 분산 시나리오에 적합합니다.

본 가이드에서는 Nginx를 주 예제로 다루고, 간단하게 Traefik 설정 예시도 함께 소개합니다.


3. Nginx를 이용한 리버스 프록시 설정

3.1 Docker Compose 활용하기

Docker Compose를 사용하면 여러 컨테이너(예: 리버스 프록시와 백엔드 애플리케이션)를 하나의 정의 파일로 관리할 수 있습니다.

예시: docker-compose.yml

version: "3.8"

services:
  reverse-proxy:
    image: nginx:latest
    container_name: nginx_proxy
    ports:
      - "80:80"       # HTTP 포트
      - "443:443"     # HTTPS 포트 (SSL 설정 시)
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d  # 커스텀 Nginx 설정 파일을 마운트
      - ./nginx/certs:/etc/nginx/certs    # SSL 인증서 파일 (필요한 경우)
    networks:
      - webnet

  app:
    image: your_backend_image  # 백엔드 애플리케이션 이미지
    container_name: backend_app
    environment:
      - ENV=production
    networks:
      - webnet

networks:
  webnet:
    driver: bridge

 

설명:

  • reverse-proxy 서비스는 최신 Nginx 이미지를 사용하며, ./nginx/conf.d 디렉토리에 사용자 정의 Nginx 설정 파일을 저장합니다.
  • app 서비스는 예시로 백엔드 애플리케이션 컨테이너이며, 동일한 Docker 네트워크(webnet)에 포함되어 Nginx가 도메인 이름(혹은 컨테이너 이름)을 통해 내부적으로 접근할 수 있습니다.

 

3.2 Nginx 설정 파일 구성

Nginx는 conf.d 폴더 내부의 설정 파일들을 읽어들입니다. 예를 들어, ./nginx/conf.d/default.conf 파일을 아래와 같이 작성할 수 있습니다.

예시: nginx/conf.d/default.conf

server {
    listen       80;
    server_name  example.com;  # 실제 도메인명 또는 테스트용으로 localhost

    # 백엔드 서버 정의 (여러 개일 경우 upstream 블록 사용)
    location / {
        proxy_pass         http://backend_app:8080;
        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;
    }
}

설명:

  • listen: 포트 80(HTTP)을 리스닝합니다.
  • server_name: 라우팅할 도메인 이름을 지정합니다. 로컬 테스트의 경우 localhost로 대체할 수 있습니다.
  • proxy_pass: backend_app은 Docker Compose에서 정의한 서비스 이름입니다. 이 이름은 Docker 내부 DNS를 통해 연결됩니다. 백엔드 컨테이너가 8080 포트로 서비스되고 있다고 가정합니다.

 

4. Traefik을 사용한 자동화된 리버스 프록시

Traefik은 Docker 컨테이너 레이블(label)을 활용하여 동적으로 라우팅을 자동으로 구성할 수 있습니다.

예시: docker-compose.yml (Traefik 활용)

version: "3.8"

services:
  traefik:
    image: traefik:v2.9
    container_name: traefik_proxy
    ports:
      - "80:80"
      - "443:443"
    command:
      - "--providers.docker=true"
      - "--providers.docker.network=webnet"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      # ACME 자동 인증서 발급 시 아래 옵션 사용 가능
      #- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      #- "--certificatesresolvers.myresolver.acme.email=your-email@example.com"
      #- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      # SSL 인증서 저장용 볼륨 (필요 시)
      #- "./letsencrypt:/letsencrypt"
    networks:
      - webnet

  app:
    image: your_backend_image
    container_name: backend_app
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`example.com`)"
      - "traefik.http.routers.app.entrypoints=web,websecure"
      # HTTPS 적용 시
      #- "traefik.http.routers.app.tls=true"
      #- "traefik.http.routers.app.tls.certresolver=myresolver"
    networks:
      - webnet

networks:
  webnet:
    driver: bridge

설명:

  • Traefik 서비스: Docker 소켓을 마운트하여 Docker API와 통신하며 자동으로 컨테이너를 탐지합니다.
  • 레이블 설정: 각 백엔드 컨테이너에 라우팅 규칙을 레이블로 부여하여, Traefik이 어떤 요청을 어떤 서비스로 전달할지 자동으로 구성합니다.

 

5. Docker 네트워크 구성

리버스 프록시와 백엔드 애플리케이션이 서로 통신하기 위해서는 같은 Docker 네트워크에 포함되어야 합니다.

  • 위 예시에서는 webnet이라는 사용자 정의 브리지 네트워크를 사용하고 있습니다.
  • Docker Compose는 동일한 Compose 파일 안에서 명시한 네트워크 이름을 기준으로 컨테이너들 간의 도메인 이름(서비스 이름) 기반 통신을 지원합니다.

6. 추가 설정 및 베스트 프랙티스

6.1 SSL/TLS 적용

  • Nginx에서 SSL 사용 시:
    • SSL 인증서와 개인 키 파일을 호스트의 디렉토리에 저장 후, Nginx 컨테이너에 볼륨으로 마운트합니다.
    • listen 443 ssl; 설정과 함께 ssl_certificate 및 ssl_certificate_key 지시문을 추가합니다.
  • Traefik 사용 시:
    • ACME 설정을 활용해 Let's Encrypt와 연동하여 자동으로 SSL 인증서를 갱신할 수 있습니다.

6.2 로드 밸런싱

  • 여러 개의 백엔드 컨테이너가 있을 경우, Nginx의 upstream 설정이나 Traefik의 라우팅 기능을 사용하여 로드 밸런싱 구성이 가능합니다.

6.3 캐시 및 압축 설정

  • Nginx의 설정 파일에 캐싱, gzip 압축 등 성능 최적화를 위한 설정을 추가하면, 클라이언트 응답 속도를 향상시킬 수 있습니다.

6.4 보안 설정

  • Access Control: IP 화이트리스트, 블랙리스트 설정으로 불필요한 접근을 제한합니다.
  • 헤더 설정: X-Real-IP, X-Forwarded-For 등의 헤더를 적절히 설정하여 실제 클라이언트 정보를 전달합니다.
  • 업데이트 관리: 사용 중인 리버스 프록시 소프트웨어(Nginx/Traefik)의 보안 업데이트를 주기적으로 확인합니다.

6.5 로깅 및 모니터링

  • 리버스 프록시 서버의 로그(액세스 로그, 에러 로그)를 별도로 관리하여 문제가 발생했을 때 빠르게 대응할 수 있도록 합니다.
  • Traefik의 대시보드나 Grafana, Prometheus 등의 모니터링 도구를 연동하여 트래픽 및 에러 모니터링이 가능합니다.

7. 결론

Docker에서 리버스 프록시를 사용하면 여러 서비스들을 단일 진입점을 통해 효율적이고 안전하게 배포할 수 있습니다.

  • Nginx를 활용한 방법은 설정 파일을 직접 작성하여 유연한 라우팅과 보안, 성능 최적화를 할 수 있는 장점이 있습니다.
  • 반면, Traefik은 Docker와의 연동성이 뛰어나 컨테이너 레이블을 통해 자동으로 라우팅을 구성할 수 있어 관리가 간편합니다.

필요에 따라 두 가지 방법을 상황에 맞게 선택하여 적용할 수 있으며, 본 가이드를 기반으로 각 환경에 맞는 추가 설정을 진행하면 보다 안정적인 서비스 운영이 가능합니다.

반응형