NYO_O

도커 배포 사고를 막는 생명줄, 이뮤터블(Immutable) 태그와 롤백 전략 본문

DevOps/CI-CD

도커 배포 사고를 막는 생명줄, 이뮤터블(Immutable) 태그와 롤백 전략

NYO_O 2026. 5. 20. 23:16
반응형

지난 포스팅에서는 빌드된 도커 이미지를 안전하게 보관하는 '컨테이너 이미지 저장소(Registry)'에 대해 알아보았습니다. 코드를 깃허브에 올리듯, 이미지는 ECR이나 GAR 같은 프라이빗 저장소에 보관한다는 것을 알게 되었죠.

2026.05.20 - [Tech/Docker] - 도커 이미지는 어디에 저장될까? 컨테이너 이미지 저장소(Registry) 완벽 이해

 

도커 이미지는 어디에 저장될까? 컨테이너 이미지 저장소(Registry) 완벽 이해

애플리케이션 개발을 마치고 실제 운영 서버에 배포할 때, 최근 실무 환경에서는 대부분의 애플리케이션을 도커(Docker) 이미지로 구워내어 컨테이너 환경에 배포하곤 합니다. 코드를 압축해서

ddangnyo.tistory.com

하지만 실무 환경에서는 단순히 이미지를 저장소에 밀어 넣는 것만으로 끝나지 않습니다. 서비스가 업데이트될 때마다 새로운 이미지가 계속 쌓이게 되는데, 이때 이미지의 '이름표' 역할을 하는 태그(Tag)를 제대로 관리하지 않으면 운영 중 치명적인 배포 사고를 겪을 수 있습니다.

오늘은 실무 배포 환경에서 반드시 알아야 할 '이뮤터블 태그(Immutable tags)'의 개념과, 안전한 롤백을 위한 최적의 이미지 태그 전략에 대해 자세히 알아보겠습니다.

1. 운영 환경에서 :latest 태그를 쓰면 안 되는 이유

도커를 처음 배우고 사용할 때 우리는 무의식적으로 :latest 태그를 많이 사용합니다. 버전을 명시하지 않고 푸시하거나 풀을 당기면 자동으로 붙는 기본 태그이기 때문입니다. 개발이나 테스트 환경에서는 항상 최신 버전을 덮어쓰며 사용할 수 있어서 무척 편리합니다.

하지만 실제 운영(Production) 환경에서 :latest 태그를 덮어쓰는 방식으로 배포를 진행한다면 어떻게 될까요?

만약 새로 배포한 애플리케이션에 치명적인 버그가 발견되어 긴급하게 이전 버전으로 '롤백(Rollback)'을 해야 한다고 가정해 보겠습니다. 우리는 이전 버전의 이미지를 다시 실행해야 하지만, 이미지 저장소에는 이미 버그가 있는 코드가 :latest라는 이름으로 기존 이미지를 덮어써 버린 상태입니다. 이전 버전 이미지는 이름표를 잃어버린 채 미아(Untagged)가 되어버렸고, 우리는 어떤 이미지가 안전했던 바로 직전 버전인지 찾을 길이 막막해집니다.

2. 배포의 안전핀, 이뮤터블 태그(Immutable Tags) 활성화

이러한 대참사를 막기 위해 운영 진입 시점에는 반드시 이뮤터블 태그(Immutable Tags) 기능을 활성화해야 합니다.

이뮤터블(Immutable)이란 '불변의, 변경할 수 없는'이라는 뜻입니다. 즉, 이뮤터블 태그 기능을 켜두면 한 번 저장소에 푸시된 태그는 절대 다른 이미지로 덮어쓸 수 없게 시스템적으로 차단됩니다.

예를 들어 v1이라는 태그로 이미지를 올렸다면, 실수로라도 다시 v1이라는 이름으로 다른 이미지를 덮어씌울 수 없습니다. 강제로 새로운 이름표(v2, v3 또는 고유한 해시값)를 달아서 올려야만 하죠.

이 설정을 활성화하면 자연스럽게 배포할 때마다 새로운 태그가 생성되어 차곡차곡 쌓이게 됩니다. 덕분에 배포에 실패하더라도 직전에 사용했던 명확한 태그 이름(예: 어제 배포했던 고유 태그)을 지정하여 빠르고 안전하게 롤백할 수 있습니다. 롤백 안전성이 비약적으로 상승하는 것입니다.

3. 실무 상황별 도커 이미지 태그 전략 비교

그렇다면 매번 바뀌는 이 태그 이름을 어떻게 짓는 것이 가장 효율적일까요? 실무에서 주로 사용하는 세 가지 태그 패턴과 각각의 장단점을 비교해 보았습니다.

  패턴 장점 단점
A {git-sha-short} 만 사용


(예: a1b2c3d)
매우 단순합니다. Git 커밋 해시와 동일하므로 어떤 코드로 빌드되었는지 즉시 추적할 수 있습니다. 배포 시스템(예: Cloud Run 등)에서 매번 새로운 sha 변수를 주입해주어야 합니다. 직관적으로 '가장 최신'을 가리키는 태그가 없습니다.
B :main + :main-{sha} 이중 태그 CD(지속적 배포) 명령에 :main을 고정해두면 자동으로 최신 배포가 이루어집니다. 동시에 sha 태그로 영구 보존이 가능하여 롤백이 쉽습니다. 빌드마다 저장소에 태그를 두 번씩 달아야 합니다. 또한, 나중에 이미지를 정리(Cleanup)하는 정책을 세울 때 조금 복잡해질 수 있습니다.
C v{버전} (SemVer 방식)


(예: v1.2.0)
소프트웨어 버전 관리가 매우 명확해집니다. 릴리스 노트를 작성하는 정규 배포 환경에 적합합니다. 작은 학습용 프로젝트나 개인 프로젝트에는 과한 감이 있습니다. 버전 번호를 올리는 과정을 자동화하기 다소 까다롭습니다.

어떤 것을 선택해야 할까요? 완벽하게 자동화된 CI/CD 파이프라인을 구축하고 있다면 고유성이 보장되는 옵션 A를 추천합니다. 반면, 배포 스크립트를 조금 더 단순하게 유지하면서 롤백을 대비하고 싶다면 옵션 B가 좋은 선택이 될 수 있습니다.

4. 주의할 점: 이미지 정리 정책(Cleanup Policy)의 함정

태그를 덮어쓰지 않고 매번 새로 만들다 보면 이미지 저장소의 용량이 금방 가득 차게 됩니다. 클라우드 환경에서는 용량이 곧 비용이므로, 오래된 이미지를 자동으로 삭제해 주는 '정리 정책(Cleanup Policy)'을 반드시 설정해야 합니다.

보통 "가장 최근 이미지 3개만 유지하고 나머지는 삭제"와 같이 정책을 설정하는데, 여기서 우리가 흔히 겪는 함정이 하나 있습니다. "버전 3개 유지"라는 말의 의미가 두 가지로 해석될 수 있다는 점입니다.

  • (a) 태그된(Tagged) 이미지 3개 유지: :v1, :v2, :v3 처럼 정상적인 이름표가 붙은 이미지 3개를 남긴다는 뜻입니다. 우리가 원하는 '안전한 롤백 후보 3개 보존'의 목적에 완벽히 부합합니다.
  • (b) 물리적인 총 이미지 3개 유지: 태그가 없는(Untagged) 매니페스트(Manifest) 파일이나 보안 증명(Attestation) 데이터 등 보이지 않는 껍데기 파일들까지 모두 합쳐서 3개만 남긴다는 뜻입니다.

클라우드 저장소 가이드북이 의도하는 안전한 보존 방식은 당연히 (a) 태그된 이미지 기준입니다. 최근 도커 빌드 툴을 사용하면 메타데이터나 Attestation 파일들이 Untagged 상태로 함께 생성되는 경우가 많습니다. 만약 정리 정책을 (b) 기준으로 잘못 설정하면, 정작 중요한 롤백용 태그 이미지는 다 날아가 버리고 쓸모없는 메타데이터 파일만 3개 남는 황당한 상황이 벌어질 수 있습니다.

따라서 Cleanup Policy를 작성하실 때는 반드시 "Untagged 이미지는 즉시 삭제하고, 명시적인 태그가 달린 이미지를 N개 유지한다"는 기준으로 명확하게 설정해야 합니다.

5. 마치며

오늘은 운영 환경 배포 시 :latest 태그가 가지는 위험성과, 이를 극복하기 위한 이뮤터블 태그 설정 및 상황별 태그 전략에 대해 알아보았습니다.

당장은 덮어쓰고 배포하는 것이 빠르고 편해 보일 수 있습니다. 하지만 서비스가 커지고 사용자가 많아질수록 언제든 이전 버전으로 안전하게 돌아갈 수 있는 '생명줄(롤백 전략)'을 미리 튼튼하게 만들어 두는 것이 좋습니다.

반응형