메인 콘텐츠로 건너뛰기

Spring Boot 앱을 ECS에 GitHub Actions로 자동 배포하기

설탕사과
설탕사과
조회수 81
요약

AWS 리소스 준비 개요

Spring Boot 앱을 ECS에 자동 배포하려면, 여러 AWS 리소스를 미리 만들어야 해요. 대표적으로 보안 그룹, 로그 그룹, IAM 역할, ECR 저장소, ECS 클러스터, 태스크 정의, 그리고 서비스가 필요합니다. 각각의 리소스가 어떻게 연결되는지 이해하면 전체 흐름이 명확해져요.

보안 그룹 생성 및 포트 허용

ECS 서비스가 외부에서 접속될 수 있도록 보안 그룹을 만들고, 필요한 포트를 엽니다. AWS CLI를 사용해 아래와 같이 수행합니다.

aws ec2 create-security-group --group-name ecs-demo-sg ...
aws ec2 authorize-security-group-ingress --group-id <sg-ID> --protocol tcp --port 80 --cidr 0.0.0.0/0 ...
aws ec2 authorize-security-group-ingress --group-id <sg-ID> --protocol tcp --port 8080 --cidr 0.0.0.0/0 ...

이렇게 하면 80번과 8080번 포트로 트래픽이 들어올 수 있습니다.

로그 그룹 생성과 보존 정책

앱의 로그를 중앙에서 보기 위해 로그 그룹을 만들고, 2주간 로그를 보관하도록 설정합니다. 다음과 같이 진행합니다.

aws logs create-log-group --log-group-name ecs/demo-app ...
aws logs put-retention-policy --log-group-name ecs/demo-app --retention-in-days 14 ...

로그와 관련된 문제를 빠르게 파악하는 데 도움이 돼요.

IAM 역할과 정책 설정

ECS 태스크가 이미지 다운로드, 로그 업로드 등 역할을 수행하려면 적절한 권한이 필요해요. IAM 역할을 만들고 관련 정책을 붙입니다.

aws iam create-role --role-name ecsTaskExecutionRole ...
aws iam attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

이 역할을 태스크에서 사용합니다.

ECR 저장소 및 ECS 클러스터 만들기

Docker 이미지를 저장할 ECR 저장소와, 앱이 배포될 ECS 클러스터를 만듭니다.

aws ecr create-repository --repository-name demo-app ...
aws ecs create-cluster --cluster-name demo-app-cluster ...

이미지는 여기 업로드 되고, 클러스터에 앱이 실행돼요.

태스크 정의 및 서비스 생성

앱 실행에 필요한 CPU/메모리, 이미지 정보, 로그 설정, 포트, 역할 등을 포함한 ECS 태스크 정의를 만듭니다.

aws ecs register-task-definition 
  --family demo-app-task 
  ...

이어 클러스터와 태스크 정의 정보를 이용해 서비스를 생성합니다. 처음에는 실제 이미지가 없으므로 desired count를 0으로 두었다가 나중에 올립니다.

GitHub OIDC 역할 및 권한 구성

GitHub Actions가 AWS를 안전하게 접근하려면 OIDC(연동 로그인을 위한 OpenID Connect)를 설정합니다. AWS IAM에서 Github의 OIDC를 신뢰하도록 만들고, 특정 리포지토리·브랜치만 접근할 수 있게 제한할 수 있습니다. 권한 정책은 이미지 푸시와 ECS 서비스 업데이트·확인을 포함해야 해요.

{
  Version: 2012-10-17,
  Statement: [
    {
      Sid: AllowUpdateSpecificService,
      Effect: Allow,
      Action: [
        ecs:UpdateService,
        ecs:DescribeServices
      ],
      Resource: arn:aws:ecs:ap-southeast-1:123456789:service/demo-app-cluster/demo-app-service
    },
    {
      Sid: AllowDescribeCluster,
      Effect: Allow,
      Action: ecs:DescribeClusters,
      Resource: arn:aws:ecs:ap-southeast-1:123456789:cluster/demo-app-cluster
    }
  ]
}

GitHub Actions 워크플로우 구성

코드를 main 브랜치에 푸시하면, 아래와 같은 GitHub Actions 워크플로우가 자동으로 시작돼요.

name: Deploy to ECS
on:
  push:
    branches: [ main ]
env:
  AWS_REGION: ap-southeast-1
  ECR_REPO: demo-app
  ECS_CLUSTER: demo-app-cluster
  ECS_SERVICE: demo-app-service
  DOCKER_FILE: Dockerfile-liberica-multi-stage
  IAM_ROLE: arn:aws:iam::123456789:role/GH-ECS-DEPLOY
jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Configure AWS Credentials via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ env.IAM_ROLE }}
          aws-region: ${{ env.AWS_REGION }}
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Cache Docker layers
        uses: actions/cache@v4
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.repository }}
          restore-keys: |
            ${{ runner.os }}-buildx-
      - name: Build Docker image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ${{ env.DOCKER_FILE }}
          push: false
          load: true
          tags: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPO }}:latest
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
      - name: Push Docker image to ECR
        run: docker push ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPO }}:latest
      - name: Move cache for next build
        run: |
          rm -rf /tmp/.buildx-cache
          mv /tmp/.buildx-cache-new /tmp/.buildx-cache
      - name: Deploy to ECS
        run: |
          aws ecs update-service 
            --cluster ${{ env.ECS_CLUSTER }} 
            --service ${{ env.ECS_SERVICE }} 
            --force-new-deployment

이 워크플로우는 소스 코드 푸시 → Docker 이미지 생성 및 캐싱 → ECR에 저장 → ECS 서비스 업데이트 절차를 자동화합니다.

배포 결과와 운영 팁

이렇게 세팅하면, 깃허브에서 코드를 최신화할 때마다 ECS에 새로운 버전 앱이 자동으로 배포돼요. 직접 IP를 통해 서비스 접속도 가능하죠. 첫 세팅은 조금 복잡해도, 한번 해두면 이후부터는 반복되는 배포에 큰 시간을 절약할 수 있습니다. 배포 실패나 새 서비스 배포를 감지하는 알람 설정을 추가해두는 것도 좋아요.


출처 : Deploying Spring Boot application to ECS using GitHub actions | by Fahim Fahad | Aug, 2025 | Medium