๐Ÿ’ช๋„์ „! ํ”„๋ฆฌํ‹ฐ์–ด๋กœ AWS ECS ์‚ฌ์šฉํ•˜๊ธฐ: Next.js ๋ฐฐํฌ ์ž๋™ํ™” ๊ตฌํ˜„ํ•˜๊ธฐ (feat. github actions)

ํ—ˆ์ง€์˜ˆยท2024๋…„ 8์›” 8์ผ
0

์ „์— ๐Ÿ’ช๋„์ „! ํ”„๋ฆฌํ‹ฐ์–ด๋กœ AWS ECS ์‚ฌ์šฉํ•˜๊ธฐ: ECS ํด๋Ÿฌ์Šคํ„ฐ์— EC2 ์ธ์Šคํ„ด์Šค ์—ฐ๊ฒฐ + ๊ฐ„๋‹จ ๋ฐฐํฌ์—์„œ AWS ์ฝ˜์†”์—์„œ ๊ฐ„๋‹จํžˆ ECS ์‹ค์Šต์„ ํ–ˆ์—ˆ๋‹ค.

์ด์ œ github actions์„ ํ™œ์šฉํ•ด์„œ ์ง„์งœ ์ตœ์ข… ๋ชฉํ‘œ์ธ ๋ฐฐํฌ ์ž๋™ํ™”๋ฅผ ๋‹ฌ์•„๋ณด์ž!

๋ฐ”๋กœ ์‹œ์ž‘!!


1. ๋ฐฐํฌ ์„ค๊ณ„ํ•˜๊ธฐ

๋จผ์ € ๋‚˜๋Š” ํ”„๋ฆฌํ‹ฐ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ , EC2 ์ธ์Šคํ„ด์Šค ํ•˜๋‚˜๋ฅผ ECS ํด๋Ÿฌ์Šคํ„ฐ์— ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

๋ฐฐํฌ ์ ˆ์ฐจ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. release ๋ธŒ๋žœ์น˜ ๋ฒ„์ „, dev ๋ธŒ๋žœ์น˜ ๋ฒ„์ „์„ ๊ฐ๊ฐ ๋ฐฐํฌํ•œ๋‹ค.
  2. ๊ฐ๊ฐ release ํƒœ๊ทธ, dev ํƒœ๊ทธ๋ฅผ ๋ถ™์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.
  3. AWS ECS service์— ๊ฐ ํƒœ๊ทธ์˜ ์ด๋ฏธ์ง€ URI๋กœ ๋ฏธ๋ฆฌ ์ž‘์„ฑํ•ด ๋‘” AWS ECS task๋ฅผ ์—ฐ๊ฒฐํ•ด๋‘”๋‹ค.
  4. AWS ECS service๋ฅผ ๊ฐ•์ œ ์žฌ์‹œ์ž‘ํ•ด์„œ ์ƒˆ๋กœ์šด image๋ฅผ ๋ฐฐํฌํ•œ๋‹ค.

2. github actions์—์„œ AWS ์ธ์ฆํ•˜๊ธฐ

github actions์—์„œ AWS์˜ ECR, ECS๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ธ์ฆ ๊ณผ์ •์„ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค.

๋‚˜๋Š” aws-actions/configure-aws-credentials@v4์„ ์‚ฌ์šฉํ•˜๊ณ  github actions์—์„œ ์‚ฌ์šฉํ•œ IAM Role์„ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค.

2-1. github actions์—์„œ ์‚ฌ์šฉํ•  IAM Role ์ƒ์„ฑํ•˜๊ธฐ

(1) ๋จผ์ € Identity providers ์ƒ์„ฑํ•˜๊ธฐ

๐Ÿ–ฑ AWS ์ฝ˜์†” > IAM > Access management >Identity providers > [Add provider]

GitHub Actions์˜ OIDC(OpenID Connect) ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ AWS์—์„œ ์ž„์‹œ ์ž๊ฒฉ ์ฆ๋ช…์„ ์–ป์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด Identity providers์„ ๋จผ์ € ์ƒ์„ฑํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

  • ๊ณต๊ธ‰์ž ์œ ํ˜•: OpenID Connect
  • ๊ณต๊ธ‰์ž URL: https://token.actions.githubusercontent.com
  • ๋Œ€์ƒ: sts.amazonaws.com

(2) IAM Role ์ƒ์„ฑ

๐Ÿ–ฑ ์ƒ์„ฑํ•œ ์ž๊ฒฉ ์ฆ๋ช… ๊ณต๊ธ‰์ž > [์—ญํ•  ํ• ๋‹น] > โ—Ž ์ƒˆ ์—ญํ•  ์ƒ์„ฑ

  • ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์—”ํ„ฐํ‹ฐ ์œ ํ˜•: โ—Ž ์›น ์ž๊ฒฉ ์ฆ๋ช…
  • ์ž๊ฒฉ ์ฆ๋ช… ๊ณต๊ธ‰์ž: token.actions.githubusercontent.com
  • Audience: sts.amazonaws.com
  • ๊ถŒํ•œ ์ •์ฑ… ์„ ํƒ
    • AmazonEC2ContainerRegistryFullAccess
    • AmazonECS_FullAccess

2-2. Github Repository Setting์—์„œ ๋ณ€์ˆ˜ ์„ค์ •ํ•˜๊ธฐ

๐Ÿ–ฑ Repository Setting > Security > Secrets and variables

  • Repository secrets
    • AWS_ROLE_NAME: ์ƒ์„ฑํ•œ Role์˜ ARN
  • Repository variables
    • AWS_DEFAULT_REGION: region (์„œ์šธ์€ ap-northeast-2)
    • REPOSITORY: ์‚ฌ์šฉํ•  ECR ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ ์ด๋ฆ„

2-3. github actions์—์„œ AWS ์ธ์ฆํ•˜๊ธฐ

.github/workflows/CD.yml ์ž‘์„ฑํ•˜๊ธฐ

name: CD

on:
  push:
    branches: [dev, release]

# ์ด ๋ถ€๋ถ„ ๋นผ๋จน์œผ๋ฉด ์•ˆ๋จ ##
permissions:
  id-token: write
  contents: read
#######################

jobs:
  build:
    name: ๐Ÿณ ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œ & ํ‘ธ์‹œ
    runs-on: ubuntu-latest

    steps:
      - name: โ‘  ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ ์ฒดํฌ์•„์›ƒ
        uses: actions/checkout@v3

      - name: โ‘ก AWS ์ž๊ฒฉ ์ฆ๋ช…
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_NAME }}
          aws-region: ${{ vars.AWS_DEFAULT_REGION }}

3. docker image ๋นŒ๋“œํ•˜๊ณ  AWS ECR์— ํ‘ธ์‹œํ•˜๊ธฐ

์ด์ œ ํ˜„์žฌ ๋ฒ„์ „์„ ECR์— docker image์— push ํ•ด๋ณด์ž~!

3-1. Dockerfile ์ž‘์„ฑ

ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ํด๋”์— Dockerfile์„ ์ž‘์„ฑํ•œ๋‹ค.

FROM node:18-alpine

WORKDIR /app

RUN apk add --no-cache curl

COPY package.json pnpm-lock.yaml ./

RUN npm install -g pnpm

RUN pnpm install

COPY . .

RUN pnpm run build

EXPOSE 3000

ENV PORT 3000

CMD ["pnpm", "run", "start"]

3-2. docker image ๋นŒ๋“œํ•˜๊ณ  ECR์— ํ‘ธ์‹œํ•˜๋Š” workflow ์ž‘์„ฑ

  • ์ด๋ฏธ์ง€ ํƒœ๊ทธ๋ฅผ ๋ธŒ๋žœ์น˜ ์ด๋ฆ„ (release, dev)๋ฅผ ์ด๋ฏธ์ง€ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
name: CD

on:
  push:
    branches: [dev, release]

permissions:
  id-token: write
  contents: read

jobs:
  build:
    name: ๐Ÿณ ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œ & ํ‘ธ์‹œ
    runs-on: ubuntu-latest

    steps:
      - name: โ‘  ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ ์ฒดํฌ์•„์›ƒ
        uses: actions/checkout@v3

      - name: โ‘ก AWS ์ž๊ฒฉ ์ฆ๋ช…
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_NAME }}
          aws-region: ${{ vars.AWS_DEFAULT_REGION }}

      - name: โ‘ข AWS ECR ๋กœ๊ทธ์ธ
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: โ‘ฃ ์ด๋ฏธ์ง€ ํƒœ๊ทธ ์„ค์ •
        run: |
          BRANCH_NAME=$(echo "${{ github.ref }}" | sed 's|refs/heads/||')
          echo "IMAGE_TAG=${BRANCH_NAME}" >> $GITHUB_ENV

      - name: โ‘ค ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œ
        env:
          REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          REPOSITORY: ${{ vars.REPOSITORY }}
          IMAGE_TAG: ${{ env.IMAGE_TAG }}
        run: |
          docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .

      - name: โ‘ฅ AWS ECR ํ‘ธ์‹œ
        env:
          REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          REPOSITORY: ${{ vars.REPOSITORY }}
          IMAGE_TAG: ${{ env.IMAGE_TAG }}
        run: |
          docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG

4. ECS์— ๋ฐฐํฌํ•˜๊ธฐ

ECS ๋ฐฐํฌ๋Š” ๊ฐ„๋‹จํ•˜๋‹ค!

  depoly:
    name: ๐Ÿณ ECS ๋ฐฐํฌ
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: โ‘  ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ ์ฒดํฌ์•„์›ƒ
        uses: actions/checkout@v3

      - name: โ‘ก AWS ์ž๊ฒฉ ์ฆ๋ช…
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_NAME }}
          aws-region: ${{ vars.AWS_DEFAULT_REGION }}

      - name: โ‘ข ๋ธŒ๋žœ์น˜ ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ
        run: |
          BRANCH_NAME=$(echo "${{ github.ref }}" | sed 's|refs/heads/||')
          echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITHUB_ENV

      - name: โ‘ฃ ECS ๋ฐฐํฌ
        env:
          CLUSTER: ${{ vars.AWS_ECS_CLUSTER }}
          SERVICE: ${{ vars.REPOSITORY }}-${{ env.BRANCH_NAME }}-service
        run: |
          aws ecs update-service \
            --cluster $CLUSTER \
            --service $SERVICE \
            --force-new-deployment


๋!

์ „์ฒด ๋„์ปค ํŒŒ์ผ

name: CD

on:
  push:
    branches: [dev, release]

permissions:
  id-token: write
  contents: read

jobs:
  build:
    name: ๐Ÿณ ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œ & ํ‘ธ์‹œ
    runs-on: ubuntu-latest

    steps:
      - name: โ‘  ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ ์ฒดํฌ์•„์›ƒ
        uses: actions/checkout@v3

      - name: โ‘ก AWS ์ž๊ฒฉ ์ฆ๋ช…
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_NAME }}
          aws-region: ${{ vars.AWS_DEFAULT_REGION }}

      - name: โ‘ข AWS ECR ๋กœ๊ทธ์ธ
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: โ‘ฃ ์ด๋ฏธ์ง€ ํƒœ๊ทธ ์„ค์ •
        run: |
          BRANCH_NAME=$(echo "${{ github.ref }}" | sed 's|refs/heads/||')
          echo "IMAGE_TAG=${BRANCH_NAME}" >> $GITHUB_ENV

      - name: โ‘ค ๋„์ปค ์ด๋ฏธ์ง€ ๋นŒ๋“œ
        env:
          REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          REPOSITORY: ${{ vars.REPOSITORY }}
          IMAGE_TAG: ${{ env.IMAGE_TAG }}
        run: |
          docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .

      - name: โ‘ฅ AWS ECR ํ‘ธ์‹œ
        env:
          REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          REPOSITORY: ${{ vars.REPOSITORY }}
          IMAGE_TAG: ${{ env.IMAGE_TAG }}
        run: |
          docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG

  depoly:
    name: ๐Ÿณ ECS ๋ฐฐํฌ
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: โ‘  ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ ์ฒดํฌ์•„์›ƒ
        uses: actions/checkout@v3

      - name: โ‘ก AWS ์ž๊ฒฉ ์ฆ๋ช…
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_NAME }}
          aws-region: ${{ vars.AWS_DEFAULT_REGION }}

      - name: โ‘ข ๋ธŒ๋žœ์น˜ ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ
        run: |
          BRANCH_NAME=$(echo "${{ github.ref }}" | sed 's|refs/heads/||')
          echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITHUB_ENV

      - name: โ‘ฃ ECS ๋ฐฐํฌ
        env:
          CLUSTER: ${{ vars.AWS_ECS_CLUSTER }}
          SERVICE: ${{ vars.REPOSITORY }}-${{ env.BRANCH_NAME }}-service
        run: |
          aws ecs update-service \
            --cluster $CLUSTER \
            --service $SERVICE \
            --force-new-deployment
profile
๋Œ€ํ•™์ƒ์—์„œ ์ทจ์ค€์ƒ์œผ๋กœ ์ง„ํ™”ํ–ˆ๋‹ค๊ฐ€ ์ง€๊ธˆ์€ ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž๋กœ 2์ฐจ ์ง„ํ™”ํ•จ

0๊ฐœ์˜ ๋Œ“๊ธ€

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด