ECS 서비스 자동 배포 구현하기 (feat. Git Action)

앞선 포스팅에서 ECS Service 까지 생성을 완료하고 확인까지 마쳤다.
이번에는 Git을 통해 ECS Service 자동 배포를 구현하고자 한다.

Task.json 파일 생성

먼저 서비스 생성에 성공한 Task의 Json을 긁어온다.

태스크 정의 - 태스크를 선택하고 JSON - 클립보드 복사 진행

 

그 다음 프로젝트 루트에 [.ecr] -> [prod] -> [task.json] 파일을 생성한다.

{
  "taskDefinitionArn": "arn:aws:ecs:ap-northeast-2:448648424519:task-definition/sample-next-app:latest",
  "containerDefinitions": [
    {
      "name": "sample",
      "cpu": 0,
      "portMappings": [
        {
          "name": "sample-7000-tcp",
          "containerPort": 7000,
          "hostPort": 7000,
          "protocol": "tcp",
          "appProtocol": "http"
        }
      ],
      "essential": true,
      "environment": [],
      "mountPoints": [],
      "volumesFrom": []
    }
  ],
  "family": "sample-next-app",
  "executionRoleArn": "arn:aws:iam::448648424519:role/ecsTaskExecutionRole",
  "networkMode": "awsvpc",
  "revision": 5,
  "volumes": [],
  "status": "ACTIVE",
  "requiresAttributes": [
    {
      "name": "com.amazonaws.ecs.capability.ecr-auth"
    },
    {
      "name": "ecs.capability.execution-role-ecr-pull"
    },
    {
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
    },
    {
      "name": "ecs.capability.task-eni"
    }
  ],
  "placementConstraints": [],
  "compatibilities": ["EC2", "FARGATE"],
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "runtimePlatform": {
    "cpuArchitecture": "X86_64",
    "operatingSystemFamily": "LINUX"
  },
  "registeredAt": "2023-10-27T01:49:45.973Z",
  "registeredBy": "arn:aws:iam::448648424519:root",
  "tags": []
}

AWS에 있던 Task json에서 containerDefinitions -> image 부분은 삭제한다.
ECR에 Docker Image가 계속 갱신되어서 이미지 버전이 계속 변경되기 때문에 task.json에 고정으로 사용하는건 의미가 없다.

workflow.yml 파일 수정

ECS 자동 배포를 위한 workflow를 추가해준다.

name: Staging # 워크플로 Action의 이름
on:
  push:
    branches: [main] #github main 브런치에 푸시 발생 시 실행 ( main 외 다른브런치 이용시 이름변경)
jobs:
  staging: #staging이라는 작업
    name: deploy to staging # 작업의 이름
    runs-on: ubuntu-latest # 실행될 작업환경을 말함.
    steps:
      - name: Checkout
        uses: actions/checkout@v3 #체크아웃 받기
      - name: HelloWorld
        uses: actions/hello-world-javascript-action@v1 # 헬로월드 찍어보기
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # Github Secret 이름
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # Github Secret 이름
          aws-region: ap-northeast-2 # AWS 리전 선택
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: sample # ecr 이름
          IMAGE_TAG: ${{ github.run_number }} # git 커밋넘버를 이미지 이름 구분을 위해 넣어줌
        run: |
          # Build a docker container and
          # push it to ECR so that it can
          # be deployed to ECS.
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
      - name: Fill in the new image ID in the Amazon ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: .ecs/prod/task.json # task파일
          container-name: sample #이미지 컨테이너 이름
          image: ${{ steps.build-image.outputs.image }}
      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: ${{ steps.task-def.outputs.task-definition }}
          service: sample-ecs-service #클러스터 서비스 명
          cluster: sample-cluster # 클러스터 명
          wait-for-service-stability: true

ECS task definition 부분부터 추가해주면 된다.

page.tsx 내용 수정

이제 next app의 내용을 수정해서 자동 배포 후 정상적으로 적용되는지 확인해본다.

export default function Home() {
  return (
    <div>
      <h1>Hello Next.js!</h1>
      <h2>feat. CI/CD with AWS-ECS</h2>
    </div>
  );
}

결과

이로써 ECS 자동배포까지 구현이 완료되었다.

다음 포스팅에서는 Route53으로 그럴싸한 도메인을 붙이는 과정을 진행해보고자 한다.

–끝–

Next.js 프로젝트 생성

설치 및 실행

vscode를 열고 원하는 폴더에 접근한 후 다음 명령어를 실행한다.

$npx create-next-app

globals.css 파일에서 tailwind CSS 관련된 설정만 남겨두고 나머지는 전부 삭제한다.
page.tsx에서도 “Hello Next.js!” 라는 문구만 작성한다.

$npm run dev

위 명령어를 실행해서 정상적으로 웹 페이지가 열리는지 확인한다.


Github workflow 작성

생성한 Next.js 프로젝트 최상단에 다음과 같은 폴더 및 파일을 추가한다.

  1. .github
  2. .github/workflows
  3. .github/workflows/workflow.yml

이후 workflow.yml 파일에 다음과 같은 내용을 추가한다.

name: Staging # 워크플로 Action의 이름
on:
  push:
    branches: [main] #github main 브런치에 푸시 발생 시 실행 ( main 외 다른브런치 이용시 이름변경)
jobs:
  staging: #staging이라는 작업
    name: deploy to staging # 작업의 이름
    runs-on: ubuntu-latest # 실행될 작업환경을 말함.
    steps:
      - name: Checkout
        uses: actions/checkout@v3 #체크아웃 받기
      - name: HelloWorld
        uses: actions/hello-world-javascript-action@v1 # 헬로월드 찍어보기

git에 push하여 Action이 잘 동작하는지 확인한다.

커밋 메세지가 이상하지만 Action은 정상적으로 동작한다!


다음 포스팅에서는 AWS 연동을 진행할 예정이다.
AWS에서 제공하는 다양한 서비스에 대해 가능하면 최대한 짚어볼 예정이다.

+ Recent posts