들어가며
AWS ECR에 빌드한 Docker Image를 업로드할 때 tag를 latest로 설정했습니다. 그 후 latest 태그가 붙은 이미지를 이용해서 배포하는 과정에서 문제가 생겼는데, 어떤 문제가 생겼고 문제를 어떻게 해결했는지 공유하고자 합니다.
문제 정리
첫 번째, 롤백이 안 되는 문제가 있었습니다. 배포 과정에서 문제가 생기면 롤백해야 했는데, ECR에는 모두 latest 태그가 붙은 이미지만 존재했습니다. 그래서 문제가 발생하는 latest 버전이 아닌 이전 버전으로 롤백을 하려고 하더라도, 현재 문제가 발생하는 latest 태그의 Docker 이미지로 컨테이너를 만들어야 했습니다. 즉 latest 태그를 유지함으로써 서버를 롤백할 수 없는 문제가 있었습니다.
두 번째는 버전 관리가 제대로 안 되는 문제가 있었습니다. 이미지 태그를 모두 latest로 관리하기 때문에, 어떤 Docker 이미지가 어떤 기능을 포함하고 있는 이미지인지 판별하기 어려웠습니다.
세 번째는 오토 스케일링을 처리할 때 문제가 있었습니다. 지표가 특정 수치 이상이 되면 EC2가 자동적으로 생성됐고 그 과정에서 latest 태그가 붙은 이미지의 컨테이너가 실행되었습니다. 만약 운영 환경에 배포되어서는 안 되는 이미지가 먼저 ECR에 들어가 있다면 오토스케일링이 될 때 latest가 붙은 배포되어서는 안 되는 이미지가 배포될 것이고 이는 서버의 장애로 이어질 수 있는 문제가 있었습니다.
개발 방법
문제 해결을 위해 아래와 같이 ECR에 빌드된 Docker 이미지를 push 하고, 고유한 태그를 생성하도록 구성했습니다.
(... 생략)
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Get current time
uses: josStorer/get-current-time@v2.1.1
id: current-time
with:
format: YYYY-MM-DD-HH-mm-ss
utcOffset: '+09:00'
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: (사용할 ECR 이름)
IMAGE_TAG: ${{ github.sha }}-${{ steps.current-time.outputs.formattedTime }}
run: |
docker compose build
docker tag (사용할 태그 이름):latest $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"
# Elastic Beanstalk에서 Docker 실행 시 체크하는 설정
- name: AWS EB Dockerrun.aws.json 태그 변경
run: |
sed -i "s|1234567890.dkr.ecr.ap-northeast-2.amazonaws.com/ECR 이름:latest|${{ steps.build-image.outputs.image }}|g" Dockerrun.aws.json
GitHub Actions의 스크립트를 위와 같이 작성했습니다. AWS ECR에 로그인하도록 설정하고 레지스트리 정보를 steps.login-ecr.outputs.registry 변수에 저장합니다. 그 후 Get current time 단계를 설정해서 현재 시간을 가져옵니다. 이 정보는 이후 Docker 이미지 태그에 사용됩니다.
그 후 Docker 이미지를 빌드하고, 태그를 지정한 후, ECR에 푸시합니다. IMAGE_TAG 변수는 GitHub의 커밋 SHA와 현재 시간을 조합하여 생성된 이미지 태그입니다. 이 이미지는 Docker Compose를 사용해 빌드되고, 특정 태그로 태그가 지정된 후, ECR 레지스트리에 푸시됩니다. 마지막으로 푸시된 이미지의 경로를 출력 변수로 설정합니다.
그리고 Elastic Beanstalk에서 사용하는 Dockerrun.aws.json 파일을 수정합니다. Dockerrun.aws.json 파일은 Elastic Beanstalk가 사용할 Docker 이미지를 정의하는 파일입니다. 이 스크립트에서는 sed 명령어를 사용하여 파일 내에서 기존의 Docker 이미지 태그(예: latest)를 새로 푸시된 이미지 태그로 바꿉니다.
Dockerrun.aws.json 파일은 아래와 같이 구성되어 있었습니다.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "1234567890-.dkr.ecr.ap-northeast-2.amazonaws.com/ECR 이름:latest",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "80",
"HostPort": "80"
}
]
}
여기에 작성된 Image.Name 프로퍼티의 값을 Github Action에서 생성한 Docker 이미지 태그로 변경합니다.
이렇게 설정한 결과 ECR에 등록된 이미지 태그는 위와 같이 고유한 값이 설정될 수 있었습니다.
만약 동일한 태그가 등록될 수 있기 때문에, ECR의 태그 변경 불가능 옵션을 활용해서 태그가 중복으로 저장되지 않도록 구성할 수 있었습니다.
마치며
위와 같이 설정함으로써 AWS EB에서 롤백을 설정할 수 있도록 구성할 수 있었고, tag의 버전도 제대로 관리할 수 있었습니다. 그리고 마지막으로 오토 스케일링이 될 때 특정 태그의 버전으로 EC2를 생성함으로써 오토 스케일링 과정에서 배포되어서는 안 되는 버전이 배포되는 일을 막을 수 있었습니다. 만약 ECR에 도커 이미지를 push 할 때 latest 태그로 올리고 계시다면, 고유한 태그로 ECR 이미지를 관리하는 것을 제안드립니다.
참고 링크
'Project > 서버 개발' 카테고리의 다른 글
[Project] 프로젝트 삽질기67 (feat DOO 단위 테스트) (0) | 2024.07.16 |
---|---|
[Project] 프로젝트 삽질기66 (feat DOO, Enum 클래스) (0) | 2024.07.11 |
[Project] 프로젝트 삽질기65 (feat 나이스 인증 3) (0) | 2024.06.24 |
[Project] 프로젝트 삽질기64 (feat 나이스 인증 2) (0) | 2024.06.24 |
[Project] 프로젝트 삽질기63 (feat 나이스 인증 1) (0) | 2024.06.24 |