Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

94장. 이미지 빌드 자동화 — CodeBuild · GitHub Actions

이 장에서 말하고자 하는 것

ECR에 이미지를 올리려면 다음을 매번 한다.

1. 코드 변경
2. docker build
3. docker tag
4. docker push
5. ECS Task Definition 갱신
6. ECS Service update

사람이 매번 손으로 하면 실수가 나고, 시간도 든다.

이걸 자동화하는 게 CI (Continuous Integration) 다.

AWS의 두 가지 주류:

  • AWS CodeBuild — AWS 자체 빌드 서비스
  • GitHub Actions — GitHub 호스팅 (사실상의 표준)

이 장은 둘의 자리를 잡고, 운영 패턴을 정리한다.


1. 빌드 자동화의 목적

코드가 머지되면 자동으로 이미지가 만들어져 ECR에 올라간다

git push
  ↓
[CI: 빌드 · 테스트]
  ↓
docker build → 태그 = sha-{commit}
  ↓
docker push to ECR
  ↓
(다음 장: 배포 트리거)
  • 사람의 손이 닿지 않는다 → 재현성
  • 어떤 코드로 어떤 이미지가 만들어졌는지 추적 가능
  • 테스트 실패 시 배포가 자동으로 막힌다

2. CodeBuild vs GitHub Actions

항목CodeBuildGitHub Actions
위치AWS 내GitHub 호스팅 (또는 self-hosted)
인증IAM Role 자연스러움OIDC로 Role 받기
시작 속도약간 느림빠름
가격빌드 시간 기준무료 한도 + 분당 과금
코드와 거리별도 console코드 옆 (PR 통합)
도입 비용약간 큼매우 낮음

코드가 GitHub에 있다면 거의 항상 GitHub Actions가 자연스럽다
CodeBuild는 AWS CodePipeline · CodeDeploy와 한 묶음으로 갈 때 유리


3. OIDC — CI에서 키 없이 Role 받기

가장 중요한 보안 패턴.

[GitHub Actions]
  ↓ OIDC 토큰 (워크플로우당 발급)
[AWS IAM OIDC Provider]
  ↓ AssumeRoleWithWebIdentity
[Role: GitHubBuildRole]
  ↓ 임시 자격증명 (15분)
[ECR push, ECS update]
  • GitHub Secrets에 AWS 키를 박지 않는다
  • 어느 워크플로우 · 어느 브랜치인지 IAM Condition으로 제한
"Condition": {
  "StringEquals": {
    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
  },
  "StringLike": {
    "token.actions.githubusercontent.com:sub": "repo:my-org/orders:ref:refs/heads/main"
  }
}

4. 표준 빌드 단계

1. 소스 체크아웃
2. 의존성 캐시 복원
3. 테스트 실행
4. (실패 시) 빌드 중단
5. 이미지 빌드 (multi-stage, 빌드 캐시 활용)
6. 이미지 스캔
7. 이미지 태그 = git commit sha
8. ECR 로그인 (OIDC Role)
9. push
10. ECS update-service 또는 다음 단계로

각 단계가 명시적으로 보여야 디버깅이 쉽다.


5. 빌드 캐시 — 속도의 절반

캐시 없이 매번 처음부터 빌드하면 5분 이상 걸린다.

GitHub Actions:
  - actions/setup-node + cache
  - docker/build-push-action + cache

CodeBuild:
  - S3 캐시
  - Local 캐시 (DOCKER_LAYER)
  • 의존성 라이브러리
  • 도커 레이어
  • 컴파일 결과물

캐시가 잘 돌아가면 빌드 시간이 1/3 이하로 줄어든다.


6. 이미지 스캔과 배포 차단

푸시 후 ECR이 자동 스캔 (43장).

CRITICAL CVE 발견 → 배포 워크플로우 실패

ECR 스캔 결과를 받아 다음 단계 진행 여부를 결정한다.


7. 우리 서비스에서

.github/workflows/orders.yml
  on: push to main (paths: services/orders/**)

steps:
  1. checkout
  2. node setup + cache
  3. test (jest)
  4. docker buildx build (cache from GHCR)
  5. OIDC AssumeRole → AWS
  6. ECR push (orders:sha-abc123)
  7. ECS update-service --force-new-deployment

각 서비스마다 동일 패턴의 workflow.

서비스가 늘어도 같은 템플릿 복사만 하면 끝


8. 직접 확인해보기 — GitHub Actions 워크플로우 (예)

name: orders-ci

on:
  push:
    branches: [main]
    paths: ['services/orders/**']

permissions:
  id-token: write
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123:role/GitHubBuildRole
          aws-region: ap-northeast-2

      - uses: aws-actions/amazon-ecr-login@v2

      - name: Build & Push
        uses: docker/build-push-action@v5
        with:
          context: services/orders
          push: true
          tags: |
            ${{ secrets.ECR_REGISTRY }}/orders:sha-${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Deploy
        run: |
          aws ecs update-service \
            --cluster msa \
            --service orders \
            --force-new-deployment

9. CodeBuild 예 (buildspec.yml)

version: 0.2

phases:
  pre_build:
    commands:
      - aws ecr get-login-password --region $AWS_REGION \
          | docker login --username AWS --password-stdin $ECR_REGISTRY
  build:
    commands:
      - docker build -t orders:$CODEBUILD_RESOLVED_SOURCE_VERSION services/orders
      - docker tag orders:$CODEBUILD_RESOLVED_SOURCE_VERSION $ECR_REGISTRY/orders:sha-$CODEBUILD_RESOLVED_SOURCE_VERSION
      - docker push $ECR_REGISTRY/orders:sha-$CODEBUILD_RESOLVED_SOURCE_VERSION
  post_build:
    commands:
      - aws ecs update-service --cluster msa --service orders --force-new-deployment

CodePipeline의 한 Stage로 자연스럽게 묶인다.


10. 이렇게 쓰면 망한다 — 안티패턴

안티패턴 1. CI에 AWS 키를 박는다

유출 시 사고가 크다. OIDC로 푼다.

안티패턴 2. latest 태그로 푸시

어떤 커밋이 어떤 이미지인지 추적 불가.

태그는 sha-{commit} 또는 시맨틱 버전

안티패턴 3. 테스트 없이 빌드만 한다

운영에 깨진 이미지가 올라간다.

안티패턴 4. 빌드 시간이 30분

캐시를 안 살리고 매번 처음부터 빌드한다.

캐시 적용은 거의 항상 큰 효과


11. 한 줄로 정리

이미지 빌드 자동화의 핵심은 OIDC + 캐시 + 명시 태그이며,
사람이 손대지 않는 자동화가 운영의 토대다


12. 이 장의 핵심 정리

  1. CI 자동화는 재현성 · 추적성 · 빠른 피드백을 만든다.
  2. CodeBuild는 AWS 네이티브, GitHub Actions는 사실상 표준.
  3. CI 인증은 OIDC + IAM Role 이 거의 항상 정답.
  4. 이미지 태그는 commit sha 또는 시맨틱 버전 — latest 금지.
  5. 빌드 캐시가 시간의 절반을 결정한다.
  6. 이미지 스캔 실패는 배포를 자동 중단시킨다.