개요
마이크로서비스 아키텍처 기반의 프로젝트에서 효율적인 배포를 위한 GitLab CI/CD 파이프라인 구축에 대해 다룬다.
프로젝트는 API Gateway, Auth Service, Relation Service, Profile Service로 구성된 백엔드 서비스들과 React 기반 프론트엔드, 그리고 AI 서비스들로 이루어져 있다.
각 서비스별로 독립적인 배포가 가능하도록 브랜치 기반 배포 전략을 사용하며, Docker를 통한 컨테이너화된 배포 환경을 구축한다.
GitLab Runner를 활용하여 자동화된 빌드와 배포 파이프라인을 구성하고, 환경 변수를 통한 보안적인 설정 관리를 적용한다.
현재 CI/CD 파이프라인 구성:
- 백엔드 서비스: API Gateway (8080), Auth Service (8081), Relation Service (8082), Profile Service (8083)
- 프론트엔드: React 애플리케이션 (80)
- AI 서비스: AI Service (8000), TTS Service (8001), Notice Service (8002)
- 브랜치 전략: BE_dev, FE_dev, AI_dev 브랜치별 독립 배포
- 컨테이너 관리: Docker Compose를 통한 통합 관리
.gitlab-ci.yml
stages:
- deploy
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .m2/
- node_modules/
variables:
DOCKER_BUILDKIT: 1
deploy_backend:
stage: deploy
timeout: 2h
only:
- BE_dev
script:
- echo "Deploying backend services..."
- export CACHEBUST=$(date +%s)
- docker-compose build --parallel --build-arg CACHEBUST=$CACHEBUST api-gateway auth-service relation-service profile-service
- docker-compose stop api-gateway auth-service relation-service profile-service || true
- docker-compose rm -f api-gateway auth-service relation-service profile-service || true
- docker-compose up -d api-gateway auth-service relation-service profile-service
deploy_frontend:
stage: deploy
timeout: 2h
only:
- FE_dev
script:
- echo "Deploying frontend service..."
- docker-compose build --no-cache frontend
- docker-compose stop frontend || true
- docker-compose rm -f frontend || true
- docker-compose up -d frontend
deploy_ai:
stage: deploy
timeout: 2h
only:
- AI_dev
script:
- echo "Deploying AI services..."
- docker-compose build ai-service ai-tts-service ai-notice-service
- docker-compose stop ai-service ai-tts-service ai-notice-service || true
- docker-compose rm -f ai-service ai-tts-service ai-notice-service || true
- docker-compose up -d ai-service ai-tts-service ai-notice-service
GitLab CI/CD 파이프라인의 핵심 설정이다. 브랜치별로 독립적인 배포 작업을 정의하여 각 팀이 자신의 서비스만 배포할 수 있도록 구성한다. Docker BuildKit을 활성화하여 빌드 성능을 향상시키고, 캐시를 활용하여 의존성 다운로드 시간을 단축한다. CACHEBUST 변수를 사용하여 빌드 캐시 무효화를 통해 최신 코드가 반영되도록 보장한다.
docker-compose.yml
version: '3.8'
services:
api-gateway:
build:
context: ./backEnd/api-gateway
dockerfile: dockerfile
container_name: api-gateway
restart: unless-stopped
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- JWT_SECRET=${JWT_SECRET}
- API_GATEWAY_URL=${API_GATEWAY_URL}
volumes:
- api-gateway-data:/app/data
networks:
- app-network
auth-service:
build:
context: ./backEnd/auth-service
dockerfile: dockerfile
container_name: auth-service
restart: unless-stopped
ports:
- "8081:8081"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_URL=${DB_URL}
- DB_USERNAME=${DB_USERNAME}
- DB_PASSWORD=${DB_PASSWORD}
- JWT_SECRET=${JWT_SECRET}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_REGION=${AWS_REGION}
- S3_BUCKET_NAME=${S3_BUCKET_NAME}
- API_GATEWAY_URL=${API_GATEWAY_URL}
volumes:
- auth-service-data:/app/data
networks:
- app-network
relation-service:
build:
context: ./backEnd/relation-service
dockerfile: dockerfile
container_name: relation-service
restart: unless-stopped
ports:
- "8082:8082"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_URL=${DB_URL}
- DB_USERNAME=${DB_USERNAME}
- DB_PASSWORD=${DB_PASSWORD}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_REGION=${AWS_REGION}
- S3_BUCKET_NAME=${S3_BUCKET_NAME}
- API_GATEWAY_URL=${API_GATEWAY_URL}
volumes:
- relation-service-data:/app/data
networks:
- app-network
profile-service:
build:
context: ./backEnd/profile-service
dockerfile: dockerfile
args:
CACHEBUST: ${CACHEBUST}
container_name: profile-service
restart: unless-stopped
ports:
- "8083:8083"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_URL=${DB_URL}
- DB_USERNAME=${DB_USERNAME}
- DB_PASSWORD=${DB_PASSWORD}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_REGION=${AWS_REGION}
- S3_BUCKET_NAME=${S3_BUCKET_NAME}
- API_GATEWAY_URL=${API_GATEWAY_URL}
volumes:
- relation-service-data:/app/data
networks:
- app-network
frontend:
build:
context: ./my-react-app
dockerfile: dockerfile
container_name: frontend-service
restart: unless-stopped
ports:
- "80:80"
networks:
- app-network
ai-service:
build:
context: ./project-ai
dockerfile: dockerfile.manual
container_name: ai-service
restart: unless-stopped
ports:
- "8000:8000"
environment:
- PYTHONUNBUFFERED=1
- MODEL_PATH=/app/models
- PORT=8000
volumes:
- ai-models:/app/models
- /home/gitlab-runner/env-files/.env:/app/config/.env
networks:
- app-network
ai-tts-service:
build:
context: ./project-ai
dockerfile: dockerfile.voice
container_name: ai-tts-service
restart: unless-stopped
ports:
- "8001:8001"
environment:
- PYTHONUNBUFFERED=1
- MODEL_PATH=/app/models
- PORT=8001
volumes:
- ai-models:/app/models
- /home/gitlab-runner/env-files/.env:/app/config/.env
networks:
- app-network
ai-notice-service:
build:
context: ./project-ai
dockerfile: dockerfile.notice
container_name: ai-notice-service
restart: unless-stopped
ports:
- "8002:8002"
environment:
- PYTHONUNBUFFERED=1
- MODEL_PATH=/app/models
- PORT=8002
volumes:
- ai-models:/app/models
- /home/gitlab-runner/env-files/.env:/app/config/.env
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
api-gateway-data:
auth-service-data:
relation-service-data:
ai-models:
모든 마이크로서비스를 통합 관리하는 Docker Compose 설정이다.
각 서비스별로 독립된 컨테이너를 구성하고, 공통 네트워크를 통해 서비스 간 통신을 가능하게 한다.
환경 변수를 통해 데이터베이스, AWS, JWT 등의 민감한 정보를 안전하게 관리한다.
볼륨을 사용하여 데이터 영속성을 보장하고, restart 정책으로 안정적인 서비스 운영을 지원한다.
해당 파일은 .gitlab-ci.yml파일과 같이 레포지토리 루트에 존재해야 한다.
dockerfile
FROM maven:3.9.6-eclipse-temurin-17 AS build
WORKDIR /app
ARG CACHEBUST=1
COPY pom.xml .
RUN mvn dependency:go-offline -q -Dmaven.transfer.listener.disabled=true
COPY src ./src
RUN echo "$CACHEBUST" > /dev/null && \
mvn clean package -q -DskipTests -Dmaven.transfer.listener.disabled=true
# 실행 스테이지
FROM openjdk:17-slim
WORKDIR /app
# 빌드 스테이지에서 생성된 JAR 파일 복사
COPY --from=build /app/target/*.jar app.jar
# 포트 노출
EXPOSE 8080
# 애플리케이션 실행
ENTRYPOINT ["java", "-jar", "app.jar"]
Spring Boot 마이크로서비스들의 공통 Dockerfile이다. 멀티 스테이지 빌드를 사용하여 빌드 환경과 실행 환경을 분리하고 이미지 크기를 최적화한다. Maven 의존성을 먼저 다운로드하여 Docker 레이어 캐싱을 활용하고, CACHEBUST를 통해 필요 시 캐시를 무효화한다. 각 서비스별로 EXPOSE 포트만 변경하여 동일한 Dockerfile을 재사용한다.
서비스별 포트 설정:
- API Gateway: EXPOSE 8080
- Auth Service: EXPOSE 8081
- Relation Service: EXPOSE 8082
- Profile Service: EXPOSE 8083
AI서비스 관련 dockerfile은 생략한다.
브랜치별 배포 전략
# 백엔드 배포 (BE_dev 브랜치)
git checkout BE_dev
git add .
git commit -m "feat: 백엔드 기능 업데이트"
git push origin BE_dev
# 프론트엔드 배포 (FE_dev 브랜치)
git checkout FE_dev
git add .
git commit -m "feat: 프론트엔드 UI 개선"
git push origin FE_dev
# AI 서비스 배포 (AI_dev 브랜치)
git checkout AI_dev
git add .
git commit -m "feat: AI 모델 업데이트"
git push origin AI_dev
각 팀은 담당 브랜치에 코드를 푸시하면 해당 서비스만 자동으로 배포된다.
배포 프로세스
백엔드 서비스 배포 과정:
- 빌드 단계: Maven을 통한 JAR 파일 생성
- 이미지 빌드: Docker 이미지 병렬 빌드 (--parallel 옵션)
- 서비스 중지: 기존 컨테이너 안전한 중지
- 컨테이너 제거: 기존 컨테이너 완전 제거
- 새 서비스 시작: 업데이트된 이미지로 컨테이너 재시작
캐시 무효화 전략:
export CACHEBUST=$(date +%s)
docker-compose build --build-arg CACHEBUST=$CACHEBUST
타임스탬프를 사용하여 Docker 빌드 캐시를 강제로 무효화한다.
환경 변수 관리
GitLab 프로젝트 Settings > CI/CD > Variables에서 다음 변수들을 설정한다.
만약 Gitlab이 아닌 Github환경에서 Github Actions을 사용한다면 SECRET설정을 해주면 된다.
'프로젝트 > [어플리케이션] 토닥' 카테고리의 다른 글
[토닥] 경계선 지능인을 위한 앱 서비스 서버 초기 세팅 및 Redis 설정 (0) | 2025.05.27 |
---|---|
[토닥] 경계선 지능인을 위한 앱 서비스 프로필 서비스 Profile-Service (1) | 2025.05.27 |
[토닥] 경계선 지능인을 위한 앱 서비스 관계 서비스 Relation-Service (1) | 2025.05.27 |
[토닥] 경계선 지능인을 위한 앱 서비스 인증 서비스 Auth-Service (0) | 2025.05.27 |
[토닥] 경계선 지능인을 위한 앱 서비스 API 게이트웨이 (1) | 2025.05.26 |