[AWS/배포] Nginx + GitHub Actions로 Spring Boot & FastAPI CI/CD 자동 배포하기 (3) - Nginx reverse proxy / docker-compose.yml 생성

2025. 8. 7. 01:26CS

 

 

 

 

 

 

지난 시간에 BE와 AI 레포지토리의 GitHub Actions 설정을 모두 완료했습니다.
이제는 인프라 설정을 관리하는 infra 레포지토리에서 다음 작업을 진행하겠습니다


1. docker-compose.yml
Spring Boot, FastAPI, Nginx를 하나의 EC2에서 컨테이너로 함께 실행

2. nginx.conf
API 요청을 각각의 서버로 리버스 프록시 설정

3. deploy.yml
GitHub Actions를 활용한 EC2 자동 배포 워크플로우 작성

 

 

Infra repository 구성


프로젝트이름/.github/workflows/deploy.yml

BE/AI 레포지토리 githubActions에서 빌드를 통해서 생성한 도커이미지를 토대로 EC2에 배포하여야하기 때문에
infra repo의 deploy.yml에는 docker 배포 관련 워크플로우를 작성합니다.

또한, BE/AI repo와 달리 infra는 관리만 하는 레포이기 때문에 main 브랜치에 push 될 때 해당 플로우가 실행되도록 설정합니다.
REPO_AI 와 REPO_BE에서 사용하는 환경변수(.yml 과 .env)는 하나로 통합하여, secrets에 PROJECTNAME_ENV로 저장해줍니다.
이렇게 설정하면, 따로 EC2 서버 내에서 .env를 작성하지 않고, git clone만 하면 자동으로 .env 파일이 만들어집니다.
name: Deploy REPO_infra

on:
  workflow_dispatch:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Deploy on EC2
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
            cd ~/REPO-infra
            echo "${{ secrets.EVERTALE_ENV }}" > .env

            sudo docker-compose down
            sudo docker-compose pull
            sudo docker-compose up -d
            sudo docker image prune -f

nginx/nginx.conf

nginx.conf 파일은 Nginx를 리버스 프록시 서버로 설정하여
Spring Boot 서버와 FastAPI 서버를 하나의 도메인(IP)에서 경로(/api/, /ai/) 기준으로 분기해주는 설정
events {}

http {
    upstream spring {
        server REPO-be:8080;
    }

    upstream fastapi {
        server REPO-ai:8000;
    }

    server {
        listen 80;
        server_name _;  # IP 기반 사용 시는 이대로 두거나 생략 가능

        location /api/ {
            proxy_pass http://spring/;
            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;
        }

        location /ai/ {
            proxy_pass http://fastapi/;
            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;
        }

        location / {
            return 200 'REPO Infra Server Running!';
            add_header Content-Type text/plain;
        }
    }
}

events {}
  • nginx 필수 블록 중 하나이지만, 여기서는 기본 이벤트 설정 없이 비워둔 상태입니다 (문제 없음)

http 블록

http {
    ...
}
  • HTTP 요청 처리에 필요한 모든 설정이 이 블록 안에 들어갑니다.
  • 여기서는 upstream, server, location 설정 등이 포함되어 있습니다.

1. upstream 설정

upstream spring {
    server REPO-be:8080;
}

upstream fastapi {
    server REPO-ai:8000;
}
  • upstream은 백엔드 서버 그룹을 정의하는 블록입니다.
  • 도커 컴포즈에서 evertale-be, evertale-ai는 각각의 컨테이너 이름이고, 포트는 컨테이너 내부 포트를 의미합니다.
  • 이후 proxy_pass에서 http://spring/ 또는 http://fastapi/로 참조합니다.

2. server 블록 (포트 80)

server {
    listen 80;
    server_name _;
  • 80번 포트로 들어오는 요청을 처리합니다.
  • server_name _; 은 도메인 없이 IP 기반으로 접속할 경우에도 요청을 수락하겠다는 의미입니다.
    • _는 wildcard처럼 사용됨.

3. location 블록

/api/ 경로 → Spring Boot 서버로 프록시

location /api/ {
    proxy_pass http://spring/;
    ...
}
  • /api/로 시작하는 요청은 upstream spring 즉, REPO-be:8080 (Spring Boot) 으로 전달됩니다.
  • 예: http://<ip>/api/users → http://repo-be:8080/users로 전달됨

/ai/ 경로 → FastAPI 서버로 프록시

location /ai/ {
    proxy_pass http://fastapi/;
    ...
}
  • /ai/로 시작하는 요청은 FastAPI 컨테이너(REPO-ai:8000) 로 전달됩니다.
  • 예: http://<ip>/ai/generate → http://repo-ai:8000/generate 로 전달

/ 루트 경로 → 상태 메시지 반환

location / {
    return 200 'REPO Infra Server Running!';
    add_header Content-Type text/plain;
}
  • 기본 루트 요청 (http://<ip>/)은 단순히 상태 메시지를 반환합니다.
  • HTML이 아니라 plain text로 응답함

공통 proxy 설정

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;
  • 이 설정들은 클라이언트의 원래 IP 정보 및 요청 헤더를 백엔드 서버로 전달하기 위한 설정입니다.
  • 실제 사용자가 누군지 로그에서 식별 가능하도록 도와줍니다.
  • 보안 및 로깅에 필수적입니다.

docker-compose.yml

이 docker-compose.yml 파일은 하나의 EC2 인스턴스에서 다음 3개의 서비스를 함께 운영하도록 구성된 멀티컨테이너 애플리케이션 설정입니다
- Spring Boot 서버 (REPO-be)
- FastAPI 서버 (REPO-ai)
- Nginx 프록시 서버 (REPO-nginx)

이러한 구조를 통해 사용자 요청이 EC2로 들어오면 Nginx가 요청을 분석하여 적절한 서버(SB or FastAPI)로 전달하게 됩니다.
version: "3.8"

services:
  REPO-be:
    container_name: REPO-be
    image: dockerusernmae/REPO-be:latest
    restart: always
    ports:
      - "8080:8080"
    env_file:
      - .env
    environment:
      - SPRING_PROFILES_ACTIVE=prod

  REPO-ai:
    container_name: REPO-ai
    image: dockerusername/REPO-ai:latest
    ports:
      - "8000:8000"
    env_file:
      - .env
    command: uvicorn app.main:app --host 0.0.0.0 --port 8000
    restart: always

  nginx:
    container_name: REPO-nginx
    image: nginx:latest
    restart: always
    ports:
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - REPO-be
      - REPO-ai

 

1. 서비스 분리

  • 각 기능(SpringBoot, FastAPI, Nginx)을 독립된 컨테이너로 나누어 관리합니다.
  • 이를 통해 서비스 간 충돌 없이 안정적으로 운영할 수 있습니다.

2. 포트 설정

  • EC2 외부 요청은 Nginx가 80번 포트에서 받고,
  • 내부적으로는 Spring Boot는 8080, FastAPI는 8000 포트를 사용합니다.
  • 포트 충돌 없이 각 서버를 독립적으로 운영할 수 있습니다.

3. 리버스 프록시

  • Nginx는 /api/ 경로로 들어온 요청은 Spring Boot로, /ai/ 경로는 FastAPI로 전달합니다.
  • 이렇게 경로 기반으로 서비스 라우팅을 구성하여 하나의 도메인 또는 IP로 두 서버를 동시에 서비스할 수 있게 합니다.

4. Docker 이미지 배포 자동화 기반

  • REPO-be, REPO-ai는 미리 GitHub Actions 등을 통해 Docker Hub에 빌드 & 푸시된 이미지를 가져와 실행합니다.
  • 인프라 레포지토리는 실제 배포 환경을 정의하며, 이 파일을 통해 EC2 서버에서 전체 서비스를 구성할 수 있습니다.
1. 하나의 EC2 안에서 여러 백엔드 서비스를 컨테이너로 분리 운영
2. Nginx를 통한 경로 기반 리버스 프록싱
3. GitHub Actions와 연계하여 자동화된 배포 환경 구성

 

 

 

2025.08.07 - [CS] - [AWS 배포 가이드] Nginx + GitHub Actions로 Spring Boot & FastAPI CI/CD 자동 배포하기 (4) - 인스턴스 연결 / GithubActions 테스트

 

[AWS 배포 가이드] Nginx + GitHub Actions로 Spring Boot & FastAPI CI/CD 자동 배포하기 (4) - 인스턴스 연결 / Git

이제 모든 레포지토리의 설정이 완료되었으므로,EC2 인스턴스에 연결하여 GitHub Actions가 정상적으로 작동하는지 확인하고,배포된 서버가 실제로 잘 동작하는지 테스트해보겠습니다. EC2 서버에서

hhongyeahh.tistory.com