환경

Docker ECR buildspec.yml 태그의 중요성

왈왈디 2025. 5. 25. 23:15
728x90

최근 ECR Docker 이미지를 사용해, code pipeline으로 배포 자동화해둔 서버에서

상용 인스턴스 추가 시 테스트 도커 이미지를 사용될 수 있는 이슈가 발견됐다.

 

아래가 이슈가 있던 buildspec.yml 이다.

( 참고로 이 buildspec은 아래와 같은 조건 하에서 사용된다. )

  • 코드파이프라인, 코드빌드, ECR, 빈스톡을 사용하여 배포할 때 사용
  • ECR 리전과 코드빌드 리전이 동일해야 함
  • 코드빌드 환경변수에 DATABASE_URL 설정 필요
  • Dockerfile 별도 작성 필요
version: 0.2
phases:
  pre_build:
    commands:
      - export AWS_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
      - export ECR_REPO_NAME="ecr repo 이름"
      - export ECR_URI="${AWS_ACCOUNT}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
      - export ECR_REPO_URI="${ECR_URI}/${ECR_REPO_NAME}"

  build:
    commands:
      - aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | docker login --username AWS --password-stdin ${ECR_URI}
      - docker build --build-arg DATABASE_URL="${DATABASE_URL}" -t ${ECR_REPO_NAME} -f "api-server.Dockerfile" .
      - docker tag ${ECR_REPO_NAME}:latest ${ECR_REPO_URI}:latest
      - docker push ${ECR_REPO_URI}:latest
      
  post_build:
    commands:
      - |
        cat > Dockerrun.aws.json <<EOM
        {
          "AWSEBDockerrunVersion": "1",
          "Image": {
            "Name": "${ECR_REPO_URI}:latest",
            "Update": "true"
          },
          "Ports": [
            {
              "ContainerPort": "80"
            }
          ],
          "Logging": "/var/log/nginx"
        }
        EOM
artifacts:
  files:
    - Dockerrun.aws.json

 

ecr 레포지토리 uri와 latest 만 붙여 docker 이미지 태그 이름을 지정하여

test 환경과 상용 환경이 구분되지 않는다.

 

테스트 환경을 가장 마지막에 배포하고, 상용 환경에서 인스턴스 추가가 발생한다면

상용과 테스트 환경의 이미지 태그가 동일하므로, 테스트 환경의 이미작 상용에서 사용되는 것이다.

 

아래가 수정된 buildspec.yml이다.

version: 0.2

phases:
  pre_build:
    commands:
      - export DOCKERFILE_PATH="api-server.Dockerfile"
      - export AWS_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
      - export ECR_REPO_NAME="ecr repo 이름"
      - export ECR_URI="${AWS_ACCOUNT}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
      - export ECR_REPO_URI="${ECR_URI}/${ECR_REPO_NAME}"
      - export TAG="${ECR_REPO_URI}:${CODEBUILD_RESOLVED_SOURCE_VERSION}"

  build:
    commands:
      - aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | docker login --username AWS --password-stdin ${ECR_URI}
      - docker build --build-arg DATABASE_URL="${DATABASE_URL}" -t ${TAG} -f "${DOCKERFILE_PATH}" .
      - docker push ${TAG}

  post_build:
    commands:
      - |
        cat > Dockerrun.aws.json <<EOM
        {
          "AWSEBDockerrunVersion": "1",
          "Image": {
            "Name": "${TAG}",
            "Update": "true"
          },
          "Ports": [
            {
              "ContainerPort": "80"
            }
          ],
          "Logging": "/var/log/nginx"
        }
        EOM

artifacts:
  files:
    - Dockerrun.aws.json

 

태그명에 사용된 CODEBUILD_RESOLVED_SOURCE_VERSION

Codebuild에서 기본으로 제공하는 환경 변수다.

Git 레포지토리에서 코드를 가져올 때, 소스의 정확한 커밋 SHA (해시) 값이 이 변수에 담긴다. (예: e3a5fcd5a0c8a93f7b63e9f54a2f9175e418b6a8)

 

이렇게 커밋 해시로 이미지 태그를 지정하면

커밋 단위로 이미지 추적이 가능하고,

코드와 빌드 결과(이미지)를 1:1로 매핑 가능해서 디버깅에 유리하다.

 

:latest 와 같이 상태를 덮어쓰는 mutable tag를 사용하면

Elastic Beanstalk의 어플리케이션 버전 롤백 기능도 사용할 수 없다.

 

Beanstalk은 배포할 때 Dockerrun.aws.json에서 ECR 이미지의 정확한 태그를 읽고,

해당 이미지를 사용해 어플리케이션 버전(AWSEB Version)을 생성하는데,

이때 이미지가 :latest라면 매번 같은 주소이므로 어떤 빌드에서 어떤 이미지를 썼는지 구분이 불가능하고

문제가 생겨도 “이전 버전” 이미지가 무엇이었는지 추적 불가능하기 때문이다.

 

태그에 커밋 해시를 넣으면 매 배포마다 고유한 이미지 주소가 사용되어

Beanstalk 어플리케이션 버전도 고유하므로

문제가 생겼을 때 이전 배포 버전의 이미지가 무엇인지 정확히 기록되어 있어 롤백이 가능하다.

 

참고 자료

 

Preparing your Docker image for deployment to Elastic Beanstalk - AWS Elastic Beanstalk

The two files must be at the root, or top level, of the .zip archive. Don't build the archive from a directory containing the files. Instead, navigate into that directory and build the archive there. When you provide both files, don't specify an image in t

docs.aws.amazon.com

 

 

Environment variables in build environments - AWS CodeBuild

For a GitHub or GitHub Enterprise Server build that is triggered by a webhook pull request event, it is pr/pull-request-number.

docs.aws.amazon.com

 

 

 

 

Pushing a Docker image to an Amazon ECR private repository - Amazon ECR

Thanks for letting us know this page needs work. We're sorry we let you down. If you've got a moment, please tell us how we can make the documentation better.

docs.aws.amazon.com

 

728x90