Docker&K8s

CH_04_04_ 리버스 프록시 구축

dding-shark 2025. 7. 30. 08:32
728x90

4.4 리버스 프록시 구축

클라이언트에서 받은 HTTP 요청을 Nginx의 리버스 프록시 기능을 사용해 백엔드로 전달하고, 웹에서 API로 요청을 전송하기 위해 사용합니다.

다음은 Nginx 설정 디렉터리 및 파일 구조입니다.

.
├── nginx-api
│   ├── Dockerfile
│   └── etc
│       └── nginx
│           └── templates
│               ├── 10-log.conf.template
│               ├── 20-upstream.conf.template
│               └── 30-vhost.conf.template
├── nginx-web
│   ├── Dockerfile
│   └── etc
│       └── nginx
│           └── templates
│               ├── 10-log.conf.template
│               ├── 20-upstream.conf.template
│               └── 30-vhost.conf.template

 

 

 

 

 


 

 

 

4.4.1 Nginx 컨테이너 템플릿 구조

Nginx 컨테이너의 /etc/nginx/conf.d 디렉터리에 설정 파일을 복사하면 가상 호스트 등에 임의의 설정 파일을 추가할 수 있습니다. 하지만 이 방법은 설정 내용을 바꿀 때마다 컨테이너 이미지를 다시 빌드해야 하는 번거로움이 있습니다. Nginx 컨테이너는 이를 해결하기 위한 템플릿 구조를 제공합니다.

envsubst로 Nginx에 컨테이너 환경변수 설정하기

Nginx 컨테이너는 envsubst라는 커맨드 라인 도구를 제공하여, 텍스트 파일 내의 특정 패턴($VAR 또는 ${VAR})을 컨테이너의 환경변수 값으로 치환할 수 있습니다. 이를 활용하면 이미지 빌드 시 /etc/nginx/templates에 있는 템플릿 파일을, 컨테이너 실행 시점의 환경변수 값으로 채워 /etc/nginx/conf.d에 동적으로 생성할 수 있습니다.

또한, conf.d 디렉터리의 파일들은 파일명의 오름차순으로 로드되므로, 설정의 로딩 순서를 고려하여 파일 이름을 정하는 것이 중요합니다. (예: 10-, 20-, 30-)

이제 구체적으로 템플릿 파일들을 살펴보겠습니다.

10-log.conf.template

이 파일은 Nginx 액세스 로그 포맷을 JSON 형식으로 새롭게 정의합니다. 구조화된 JSON 로그는 로그 분석 시스템과 연동할 때 매우 유용합니다.

# 'json'이라는 이름의 새로운 로그 포맷을 정의합니다. escape=json 옵션은 값에 포함된 특수문자를 JSON 형식에 맞게 이스케이프 처리합니다.
log_format json escape=json '{'
    '"time": "$time_local",'           # 요청 처리 시간 (서버 로컬 시간)
    '"remote_addr": "$remote_addr",'   # 클라이언트의 IP 주소
    '"host": "$host",'                 # 요청된 호스트 이름
    '"remote_user": "$remote_user",'   # HTTP 인증을 사용한 경우의 사용자 이름
    '"status": "$status",'             # 응답 상태 코드 (예: 200, 404)
    '"server_protocol": "$server_protocol",' # 사용된 프로토콜 (예: HTTP/1.1)
    '"request_method": "$request_method",' # 요청 메소드 (예: GET, POST)
    '"request_uri": "$request_uri",'   # 매개변수를 포함한 전체 요청 URI
    '"request": "$request",'           # "메소드 URI 프로토콜" 형식의 전체 요청 라인
    '"body_bytes_sent": "$body_bytes_sent",' # 클라이언트에 전송된 본문의 바이트 수
    '"request_time": "$request_time",' # 요청 처리 시간 (밀리초)
    '"upstream_response_time": "$upstream_response_time",' # 백엔드 서버로부터 응답을 받는 데 걸린 시간
    '"http_referer": "$http_referer", '# 이전 페이지의 주소 (Referer 헤더)
    '"http_user_agent": "$http_user_agent",' # 클라이언트의 User-Agent 정보
    '"http_x_forwarded_for": "$http_x_forwarded_for",' # X-Forwarded-For 헤더 값
    '"http_x_forwarded_proto": "$http_x_forwarded_proto"'  # X-Forwarded-Proto 헤더 값 (http/https)
'}';

20-upstream.conf.template

upstream 블록을 사용하여 백엔드 서버 그룹을 정의합니다. 이렇게 하면 여러 서버로 로드 밸런싱을 구성하거나 장애 조치(failover) 설정을 유연하게 관리할 수 있습니다.

# 'backend'라는 이름으로 프록시 서버 그룹(upstream)을 정의합니다.
upstream backend {
   # 실제 백엔드 서버의 주소를 환경 변수로부터 받아옵니다.
   # max_fails: 지정된 횟수만큼 연결 실패 시 서버가 비활성화됩니다.
   # fail_timeout: 서버 비활성화 후 다시 정상으로 간주하기까지의 시간(초)입니다.
   server ${BACKEND_HOST} max_fails=${BACKEND_MAX_FAILS} fail_timeout=${BACKEND_FAIL_TIMEOUT};
}

30-vhost.conf.template (API 리버스 프록시)

API 서버를 위한 리버스 프록시 구성 파일입니다. 모든 요청을 백엔드 서버로 전달하는 역할을 합니다.

server {
    # ${NGINX_PORT} 환경 변수로부터 포트 번호를 받아와 요청을 수신 대기합니다.
    listen ${NGINX_PORT};
    # ${SERVER_NAME} 환경 변수로부터 서버의 도메인 이름을 설정합니다.
    server_name ${SERVER_NAME};

    # '/' 경로로 들어오는 모든 요청을 처리합니다.
    location / {
        # 요청을 'backend'라는 이름의 upstream으로 전달합니다.
        proxy_pass http://backend;

        # 원본 요청의 Host 헤더를 백엔드로 전달합니다.
        # 이를 통해 백엔드 애플리케이션이 실제 요청된 도메인 이름을 알 수 있습니다.
        proxy_set_header Host $host;

        # 클라이언트의 실제 IP 주소를 'X-Forwarded-For' 헤더에 담아 백엔드로 전달합니다.
        # 이 헤더가 없으면 백엔드는 모든 요청이 Nginx 프록시로부터 온 것으로 인식하게 됩니다.
        proxy_set_header X-Forwarded-For $remote_addr;

        # 'json' 형식으로 정의한 액세스 로그를 표준 출력(stdout)으로 보냅니다.
        access_log /dev/stdout json;
        # 에러 로그를 표준 에러(stderr)로 보냅니다.
        error_log  /dev/stderr;
    }
}

30-vhost.conf.template (WEB 리버스 프록시)

웹 서버를 위한 리버스 프록시 구성 파일입니다. 정적 파일은 직접 제공하고, 나머지 동적 요청만 백엔드로 전달하여 효율성을 높입니다.

server {
    # ${NGINX_PORT} 환경 변수로부터 포트 번호를 받아와 요청을 수신 대기합니다.
    listen ${NGINX_PORT};
    # ${SERVER_NAME} 환경 변수로부터 서버의 도메인 이름을 설정합니다.
    server_name ${SERVER_NAME};

    # '/assets/' 경로로 들어오는 요청을 처리합니다. (CSS, JS, 이미지 등)
    location /assets/ {
        # 요청된 URI를 파일 시스템의 특정 경로에 매핑합니다.
        # 예를 들어 /assets/style.css 요청은 ${ASSETS_DIR}/style.css 파일을 찾습니다.
        # 이를 통해 정적 파일을 백엔드를 거치지 않고 Nginx가 직접 빠르게 제공합니다.
        alias ${ASSETS_DIR}/;

        # 정적 파일에 대한 액세스 로그와 에러 로그 설정
        access_log /dev/stdout json;
        error_log  /dev/stderr;
    }

    # '/assets/' 이외의 모든 요청을 처리합니다.
    location / {
        # 요청을 'backend'라는 이름의 upstream으로 전달합니다.
        proxy_pass http://backend;

        # 원본 요청의 Host 헤더를 백엔드로 전달합니다.
        proxy_set_header Host $host;
        # 클라이언트의 실제 IP 주소를 백엔드로 전달합니다.
        proxy_set_header X-Forwarded-For $remote_addr;

        # 동적 요청에 대한 액세스 로그와 에러 로그 설정
        access_log /dev/stdout json;
        error_log  /dev/stderr;
    }
}

 

 

 

 

 


 

 

 

4.4.2 Dockerfile

Nginx 컨테이너 이미지를 생성하기 위한 Dockerfile입니다.

# 기반(Base) 이미지로 공식 Nginx 1.25.1 버전을 사용합니다.
# 특정 버전을 명시하여 빌드 재현성을 확보하고 예기치 않은 변경을 방지합니다.
FROM nginx:1.25.1

# 호스트 머신의 ./etc/nginx 디렉터리(템플릿 포함)를 
# 컨테이너 내부의 /etc/nginx 경로로 복사합니다.
COPY ./etc/nginx /etc/nginx

# Nginx에 기본적으로 포함된 default.conf 설정 파일을 삭제합니다.
# 이 파일을 삭제하지 않으면 우리가 추가할 30-vhost.conf 파일과 충돌하여
# 설정이 올바르게 적용되지 않을 수 있습니다.
RUN rm /etc/nginx/conf.d/default.conf
728x90