Cloud 과제 4단계: Docker 컨테이너화 배포 - 100-hours-a-week/5-yeosa-wiki GitHub Wiki
1. 업무 개요
기존 단일 인스턴스 환경에서는 성능 저하, 유지보수 어려움, 배포 자동화 한계 등의 문제가 있었습니다.
- 다양한 기술 스택(Java, JS , Python 등)이 동일 환경에 혼재되어 있어 의존성 충돌과 환경 불일치로 인한 오류 다발
- 서비스 배포 시 수동 명령 기반의 운영으로 인한 반복 업무와 배포 사고 위험 증가
이를 개선하기 위해, 서비스 전반을 Docker 컨테이너화하여, 환경 일관성 확보, 배포 자동화 기반 마련, 확장성 향상을 목표로 합니다.
2. 아키텍쳐 개요 (3-Tier Architecture)
Tier (계층) | 구성 요소 | 설명 |
---|---|---|
Presentation Tier | Next.js (프론트엔드) | 사용자 요청을 처리하는 SSR 기반 인터페이스 제공. GCP VM의 3000번 포트에서 서비스됨 |
Application Tier | Spring Boot (백엔드), FastAPI (AI 서버) | API 요청 처리, AI 기반 분류 결과 생성 등 핵심 로직 실행 |
Data Tier | Cloud SQL (MySQL), Redis, GCS | 메타데이터 저장, 캐시 처리, 이미지 객체 저장소 역할 수행 |
3. GCP 인프라 및 Docker 환경 개요
- 컴퓨팅 자원: GCP Compute Engine (e2-standard-4, 4vCPU, 16GB RAM)
- 컨테이너화: 모든 서비스 구성 요소는 독립된 Dockerfile을 통해 컨테이너화되며, docker-compose로 연동 관리
- 네트워크 구성:
- Public Subnet: 프론트엔드
- Private Subnet: 백엔드, AI 서버, 데이터베이스
- 스토리지 및 데이터:
- Cloud SQL: 영구적인 메타데이터 저장소
- Redis: 세션 및 분류 결과 캐시
- GCS: 이미지 파일 저장 및 AI 분석 대상
- 모니터링 및 보안:
- Cloud Monitoring, Logging을 통한 로그 및 성능 모니터링
- IAM, 서비스 계정, 방화벽 설정으로 접근 제어
4. 설계 과제
1. Docker 도입 결정 및 범위
-
서비스의 안정성 및 신속한 대응력
- 서비스가 안정화되어 유저가 늘어나게 될 경우, 기존의 단일 인스턴스에서는 새 인스턴스를 추가하게 되고, 추가할 때마다 환경 설정을 처음부터 다시 수작업으로 진행해야한다.
→ Docker 도입 시, 표준화된 이미지를 기반으로 빠르게 새로운 서버를 준비할 수 있어 트래픽이 몰리는 시점에 즉각적으로 서버 증설이 가능
→ 장애 발생 시에도 동일 이미지를 이용해 다른 컨테이너로 빠르게 복구할 수 있어 장애 복구 시간(MTTR: Mean To Recovery) 을 최소화할 수 있다.
-
환경 일관성: 개발/운영 환경 차이로 인한 오류 제거
- AI 서버는
torch
,opencv
,transformers
,pillow
등 다양한 Python 라이브러리와 그 버전 종속성이 복잡하게 얽혀 있어, 배포 환경에서 Python 버전 차이, CUDA 드라이버 미설치, 패키지 설치 누락 등으로 AI 모델이 로드되지 않거나 추론 오류 발생
→ Docker 컨테이너에서 실행하면서 정확히 같은 환경에서 실행되므로 환경 불일치 문제를 해소할 수 있다.
- AI 서버는
-
배포 자동화 기반 마련: GitHub Actions와 연동해 CI/CD 구성 가능
- 기존에는 단일 인스턴스에 접속해 수동으로
git pull
,npm run build
,java -jar
,uvicorn main:app
등 각각의 실행 명령어를 수작업으로 수행해야 했고, 종종 빌드 누락이나 실행 순서 문제로 서비스가 정상 동작하지 않음.
→ Docker 기반으로 각 서비스를 컨테이너화하면서, 컨테이너 이미지를 빌드/배포하는 과정을 자동화할 수 있다. GitHub Actions와 연동하여 push시 자동으로 도커 이미지를 생성하고 서버에 배포해, 배포오류를 최소화한다.
- 기존에는 단일 인스턴스에 접속해 수동으로
-
확장성 확보: 향후 Kubernetes 기반 확장 준비
- 단일 인스턴스에 모든 기능이 얹혀 있어서, 한 컴포넌트의 부하(예: AI 분류 작업 시 CPU 점유율 상승)가 전체 서비스의 성능에 영향을 줌. 수평 확장이나 자원 분리도 어렵고, 장애 발생 시 단일 장애점(SPOF) 발생.
→ 컨테이너 단위로 분리된 아키텍쳐는 서비스 별 독립 실행한다. 향후 K8s 같은 오케스트레이션 도구로 AI 서버만 확장하거나 백엔드만 교체 배포하는 등의 유연한 확장성 확보에 유리해진다.
-
분리된 아키텍처 구성 용이: AI / Backend / DB / 프론트 분리
- 모든 프로세스가 단일 서버의 같은 OS 환경에서 실행되다 보니, 구성요소 간 충돌이나 리소스 경합(CPU, 포트 등) 발생 가능. 서비스 단위로 격리 실행/모니터링/관리가 어려움.
→ 각 구성요소를 독립된 컨테이너로 분리하면서, 네트워크, 포트, 환경변수도 각자 명확하게 관리가 가능하다.
2. 컨테이너 배포 전략 설계
1. 컨테이너 이미지 빌드 및 관리 전략
- Next.js 프론트 엔드
- Node.js 기반 Dockerfile 작성
- npm run build → npm start
- SpringBoot 백엔드
- Gradle 빌드 후 . jar 파일을 기반으로 이미지 실행
- AI 서버
- Python 기반으로
requirements.txt
설치 후 FastAPI 실행
- Python 기반으로
- MySQL
- 개발 환경 기준 개발 시 컨테이너로 관리, 운영에서는 RDS 등 외부 사용
- Redis
- 추후 세션 관리, 캐시, 메시지 처리용, 개발에선 컨테이너로 충분
- 모든 컨테이너는 Github Acrions에서 자동 빌드
2. 이미지 태깅 전략
{service_name}:{env}-{version}
ex) ongi-be:dev-0.1.0
, ongi-ai:prod-1.2.1
버전 관리
SemVer(유의적 버전: MAJOR.MINOR.PATCH
) 형식 사용
예시:
- 버그 수정 →
patch
증가 (1.0.0 → 1.0.1) - 기능 추가 →
minor
증가 (1.0.1 → 1.1.0) - 구조적 변경 →
major
증가 (1.1.0 → 2.0.0)
latest 태그 활용
develop
브랜치에서 빌드된 최신 이미지는latest
태그로 푸시- 단, 운영 환경에서는
latest
태그 사용 금지 → 명시적 버전만 배포 - 개발 환경은
dev-latest
, 운영 환경은prod-버전
으로 명시적 태깅
3. 이미지 저장소
- 초기: Docker Hub 사용 예정 (
ongi-team/*
) - 향후 프라이빗 레지스트리(GitHub Container Registry 등)로 이전
4. 여러 컨테이너 간 연동방법
GCP 환경에서의 VM 통신 기본 방식
- VM 간에는 VPC 내부 통신 (내부IP)으로 가능
- Zone이 달라도 같은 VPC/Subnet 이면 문제 없음
- DNS 이름 또는 고정 IP를 통해 서로 연결
발신자 | 수신자 | 목적 |
---|---|---|
Front (Next.js) | Back (Spring Boot) | API 호출 |
Back (Spring Boot) | AI 서버 (CPU/GPU) | 이미지 분류 요청 |
Back (Spring Boot) | DB | 메타데이터 저장 |
AI 서버 | Back (Spring Boot) | 이미지 호출 |
Back (Spring Boot) | GCS | 이미지 가져오기 |
5. 호스트 자원 할당
구성 요소 | 예상 동작량 | CPU | RAM | 디스크 | GCP 머신 타입 추천 |
---|---|---|---|---|---|
Front (Next.js SSR) | SSR/CSR 혼합, 외부 요청 많음 | 2 vCP | 4~8GB | 10~20GB | e2-medium |
Back (Spring Boot) | REST API, DB 트래픽 집중 | 4 vCPU | 8~16GB | 20~30GB | e2-standard-4 |
AI 서버 (CPU) | 모델 추론, 이미지 분류 | 4 vCPU | 16~32GB | 50GB 이상 | n1-standard-4 |
AI 서버 (GPU) | 이미지 생성 | 4 vCPU + 1 GPU | 32GB 이상 | 100GB 이상 | n1-standard-1 |
Cloud SQL (MySQL) | 메타데이터 저장, 내부 API 통신 | - | 4~8GB | 자동 (GCP 관리형) | db-n1-standard-2 이상 |
Redis | 태그 캐시, 추론 결과 캐싱 등 | - | 1~2GB | - | Memorystore Basic Tier |
OpenVPN 서버 | 개발자 접근 전용 | 1 vCPU | 1GB | 10GB | e2-micro |
3. 컨테이너 구성도
1. 3-Tier 아키텍쳐
<온기>는 비용절감을 위해 GCP 크레딧을 최대한 활용하는 방안으로 GCP내에서 서비스 설계를 진행하였습니다.
구성 요소 | 설명 |
---|---|
Next.js Front | SSR 기반 프론트 컨테이너, 포트 3000 |
Spring Boot Backend | REST API 서버, 포트 8080 |
FastAPI AI Server | 이미지 분류 서버, 포트 8000 |
MySQL | 내부 DB용 컨테이너, 포트 3306 (개발 전용) |
Redis | 캐시 및 세션 처리용, 포트 6379 |
Cloud SQL | 운영 환경에서 사용하는 외부 관리형 DB |
GCS | 정적 이미지 저장소, Cloud Storage API 통신 |
- 컨테이너 구성 및 이미지 태그 전략
서비스 | 이미지 이름 | 태그 형식 | 컨테이너 수 |
---|---|---|---|
Front | ghcr.io/ongi/front | dev-0.1.0, prod-1.0.0 | 1 (Auto Scaling 대상) |
Backend | ghcr.io/ongi/backend | dev-0.1.0, prod-1.0.0 | 1 (Auto Scaling 대상) |
AI | ghcr.io/ongi/ai | dev-0.1.0, prod-1.0.0 | 2 (CPU/GPU 분리) |
MySQL | mysql:8.0 | 공식 이미지 사용 | 1 (로컬 개발용) |
Redis | redis:7 | 공식 이미지 사용 | 1 (개발 및 운영 모두 사용) |
- 태그는 env-version 형태로 관리
- 운영 배포 시 명시적 태그 사용 (prod-1.2.3)
- 개발 환경은 dev-latest 활용 가능
2. Dockerfile 주요 구성 예시
frontend/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install && npm run build
CMD ["npm", "start"]
backend/Dockerfile
FROM openjdk:17
WORKDIR /app
COPY build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
ai/Dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
3. 배포 절차 변화
구분 | 기존 방식 | Docker 기반 방식 |
---|---|---|
배포 방법 | SSH 접속 후 수동 배포 | GitHub Actions로 CI/CD 자동화 |
실행 방식 | 직접 실행 (java -jar, npm run) | docker run 혹은 docker-compose up |
실패 가능성 | 명령어 누락, 의존성 충돌 | 동일 이미지 실행으로 문제 제거 |
상태 확인 | 각 서버 직접 접근 | docker ps , docker logs 로 간편 모니터링 |
4. 개선 효과 (정량적 근거 포함)
항목 | 개선 전 | 개선 후 | 효과 |
---|---|---|---|
전체 배포 시간 | 평균 20분 | 약 5분 내외 | 약 75% 단축 |
환경 설정 오류율 | 약 30% 이상 | 0% | 동일 이미지 실행 |
신규 인스턴스 확장 시 소요 시간 | 15분 이상 | 1분 내외 | Auto Scaling 대응 가능 |
운영/개발 구성 격차 | 수동 OS 설정 | 이미지 기반 통일 | 협업 효율 증가 |