Project/Nolleogasil

[CI&CD] 놀러가실 백엔드 도커 배포 (blue/green 배포 전략)

작소율 2025. 3. 12. 15:51

✅ GitHub Actions 배포 스크립트

name: nolleogasil backend 배포 자동화

on:
  push:
    branches: [main]  # main 브랜치에 푸시되면 실행

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Make application.yml  # application.yml 파일 생성
        run: |
          cd ./src/main/resources
          echo "${{ secrets.APPLICATION_YML }}" > ./application.yml
        shell: bash

      - name: Grant execute permission for gradlew  # gradlew 실행 권한 부여
        run: chmod +x gradlew

      - name: Build with Gradle
        run: |
          chmod +x gradlew
          ./gradlew clean build -x test

      - name: Set Environment Variables
        run: |
          echo "DOCKER_IMAGE=${{ secrets.DOCKERHUB_USERNAME }}/nolleogasil-backend:latest" >> $GITHUB_ENV

      - name: Log in to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_PASSWORD }}

      - name: Build and Push Docker Image
        run: |
          docker build -t ${{ env.DOCKER_IMAGE }} .
          docker push ${{ env.DOCKER_IMAGE }}

  deploy:
    runs-on: ubuntu-latest
    needs: build  # build가 완료된 후에 실행됨

    steps:
      - name: Checkout Repository
        uses: actions/checkout@v3

      - name: Set Environment Variables
        run: |
          echo "DOCKER_IMAGE=${{ secrets.DOCKERHUB_USERNAME }}/nolleogasil-backend:latest" >> $GITHUB_ENV

      - name: Set up SSH Key and Connect to EC2
        run: |
          echo "${{ secrets.EC2_SSH_KEY }}" > private_key.pem
          chmod 600 private_key.pem

      - name: Deploy to Server
        run: |
          ssh -i private_key.pem -o StrictHostKeyChecking=no ${{ secrets.EC2_USERNAME }}@${{ secrets.EC2_HOST }} << 'EOF'
            cd /home/ubuntu/app

            # 현재 활성 컨테이너 확인 (Blue/Green)
            CURRENT=$(docker ps --filter "name=backend-" --format "{{.Names}}")

            if [ "$CURRENT" = "backend-blue" ]; then
              NEW_CONTAINER="backend-green"
              OLD_CONTAINER="backend-blue"
            else
              NEW_CONTAINER="backend-blue"
              OLD_CONTAINER="backend-green"
            fi

            echo "🔵🟢 현재 실행 중인 컨테이너: $CURRENT"
            echo "➡️ 새 컨테이너: $NEW_CONTAINER"

            # 새로운 컨테이너 실행
            docker pull ${{ env.DOCKER_IMAGE }}
            docker run -d --name $NEW_CONTAINER -p 8080:8080 --restart always ${{ env.DOCKER_IMAGE }}

            # Health Check 대기 (5초)
            sleep 5

            # ALB의 Target Group 변경
            aws elbv2 modify-listener \
                --listener-arn ${{ secrets.ALB_LISTENER_ARN }} \
                --default-actions Type=forward,TargetGroupArn=${{ secrets.GREEN_TARGET_GROUP_ARN }}

            echo "✅ ALB Target Group이 $NEW_CONTAINER로 변경됨"

            # 이전 컨테이너 종료 및 삭제
            docker stop $OLD_CONTAINER
            docker rm $OLD_CONTAINER

            echo "✅ Blue/Green 배포 완료! 현재 실행 중인 컨테이너: $NEW_CONTAINER"
          EOF

✅ GitHub Secrets 설정

Secret Name 과 설명

APPLICATION_YML application.yml 내용을 GitHub Secrets에 저장
DOCKERHUB_USERNAME Docker Hub 계정 이름
DOCKERHUB_PASSWORD Docker Hub 비밀번호
EC2_SSH_KEY  EC2 SSH 개인 키(.pem)
EC2_USERNAME EC2에 접속할 사용자 (ubuntu)
EC2_HOST
EC2 인스턴스 퍼블릭 IP
ALB_LISTENER_ARN AWS ALB 리스너 ARN
BLUE_TARGET_GROUP_ARN backend-blue Target Group ARN
GREEN_TARGET_GROUP_ARN backend-green Target Group ARN

 

하나의 GitHub Actions 파일에서 build와 deploy를 분리하여 실행
빌드가 완료되면 배포가 자동 실행 (needs: build)
Blue/Green 배포 방식 적용 (ALB Target Group 변경)
EC2에서 기존 컨테이너 종료 후 새 컨테이너 실행

 

 

version: '3.8'

services:
  rabbitmq:
    image: rabbitmq:3-management
    container_name: rabbitmq
    ports:
      - "5672:5672"  # AMQP 포트
      - "15672:15672"  # RabbitMQ 관리 UI 포트
      - "61613:61613"
    networks:
      - backend-network

  redis:
    image: redis:latest
    container_name: redis
    ports:
      - "6379:6379"
    networks:
      - backend-network

  backend-blue:
    image: ${DOCKERHUB_USERNAME}/nolleogasil-backend:latest
    container_name: backend-blue
    depends_on:
      - redis
      - rabbitmq
    ports:
      - "8080:8080"
    networks:
      - backend-network

  backend-green:
    image: ${DOCKERHUB_USERNAME}/nolleogasil-backend:latest
    container_name: backend-green
    depends_on:
      - redis
      - rabbitmq
    ports:
      - "8081:8080"
    networks:
      - backend-network

networks:
  backend-network: