본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 19. · 3 Views
ECR에 이미지 푸시 완벽 가이드
Docker 이미지를 AWS ECR에 안전하게 푸시하는 전체 과정을 초급자 관점에서 쉽게 설명합니다. 로그인부터 취약점 스캔까지 실무에서 바로 활용할 수 있는 완벽한 가이드입니다.
목차
1. ECR 로그인하기
어느 날 김개발 씨가 처음으로 Docker 이미지를 AWS에 올리는 임무를 받았습니다. "ECR에 이미지를 푸시해주세요"라는 선배의 말에 김개발 씨는 당황했습니다.
ECR이 뭐지? 어떻게 로그인하는 거지?
ECR 로그인은 AWS의 프라이빗 Docker 레지스트리인 ECR에 접근하기 위한 인증 과정입니다. 마치 회원제 도서관에 들어갈 때 회원증을 보여주는 것처럼, Docker가 ECR에 이미지를 올리려면 먼저 로그인 절차를 거쳐야 합니다.
AWS CLI를 통해 자동으로 비밀번호를 받아와서 Docker에 전달하는 방식으로 작동합니다.
다음 코드를 살펴봅시다.
# AWS CLI를 사용한 ECR 로그인
# 계정 ID와 리전을 실제 값으로 변경하세요
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com
# 로그인 성공 메시지 확인
# Login Succeeded 메시지가 나타나면 성공입니다
# ECR 리포지토리 목록 확인
aws ecr describe-repositories --region ap-northeast-2
김개발 씨는 입사 2개월 차 주니어 개발자입니다. 이제 막 Docker를 배워서 로컬에서 컨테이너를 띄우는 것까지는 성공했습니다.
하지만 오늘 받은 임무는 조금 달랐습니다. "개발한 애플리케이션을 ECR에 올려주세요." 선배 개발자 박시니어 씨가 다가와 화면을 봅니다.
"ECR은 AWS의 컨테이너 이미지 저장소예요. 푸시하기 전에 먼저 로그인해야 합니다." 그렇다면 ECR 로그인은 정확히 무엇일까요?
쉽게 비유하자면, ECR 로그인은 마치 은행 금고에 접근하기 위해 신분증과 비밀번호를 확인받는 것과 같습니다. 여러분의 소중한 Docker 이미지를 안전하게 보관하는 저장소이기 때문에 당연히 인증이 필요합니다.
이 인증 과정을 거쳐야만 이미지를 올리거나 내려받을 수 있습니다. ECR 로그인이 필요한 이유는 무엇일까요?
Docker Hub 같은 퍼블릭 레지스트리에서는 누구나 이미지를 올리고 내려받을 수 있습니다. 하지만 회사의 비즈니스 로직이 담긴 애플리케이션을 공개 저장소에 올릴 수는 없습니다.
보안이 중요한 엔터프라이즈 환경에서는 프라이빗 레지스트리가 필수입니다. 또한 ECR은 AWS 리소스와 긴밀하게 통합되어 있습니다.
EC2, ECS, EKS 같은 서비스에서 이미지를 빠르게 가져올 수 있고, IAM을 통해 세밀한 권한 관리가 가능합니다. 바로 이런 이유로 프라이빗하고 안전한 ECR 로그인 과정이 필요합니다.
ECR 로그인은 일반적인 Docker 로그인과 조금 다릅니다. 일반 Docker Hub에서는 고정된 사용자명과 비밀번호를 사용하지만, ECR은 임시 인증 토큰을 사용합니다.
이 토큰은 12시간 동안만 유효하며, 보안을 위해 주기적으로 갱신해야 합니다. 위의 명령어를 살펴보겠습니다.
먼저 aws ecr get-login-password 명령어가 실행됩니다. 이 명령은 여러분의 AWS 자격 증명을 확인하고 ECR 로그인용 임시 비밀번호를 생성합니다.
파이프 기호를 통해 이 비밀번호가 docker login 명령에 전달됩니다. --password-stdin 옵션은 비밀번호를 안전하게 표준 입력으로 받아들이도록 합니다.
명령어 히스토리에 비밀번호가 남지 않아 보안상 안전합니다. 마지막 부분의 긴 URL은 여러분의 ECR 레지스트리 주소입니다.
123456789012는 AWS 계정 ID이고, ap-northeast-2는 서울 리전을 의미합니다. 이 주소는 여러분의 환경에 맞게 변경해야 합니다.
실제 현업에서는 어떻게 활용할까요? 많은 기업에서 CI/CD 파이프라인을 구축할 때 ECR 로그인을 자동화합니다.
예를 들어 GitHub Actions나 Jenkins에서 코드가 푸시되면 자동으로 Docker 이미지를 빌드하고 ECR에 로그인하여 푸시합니다. 이때 AWS 자격 증명은 환경 변수나 시크릿 매니저를 통해 안전하게 관리됩니다.
또한 개발, 스테이징, 프로덕션 환경마다 별도의 ECR 리포지토리를 운영하는 경우가 많습니다. 각 환경에 맞는 IAM 권한을 설정하여 실수로 프로덕션 이미지를 덮어쓰는 일을 방지합니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 AWS 자격 증명이 제대로 설정되지 않은 상태에서 로그인을 시도하는 것입니다.
"aws configure" 명령으로 먼저 Access Key와 Secret Key를 설정해야 합니다. 또한 해당 IAM 사용자나 역할에 ECR 접근 권한이 있는지 확인해야 합니다.
또 다른 실수는 리전을 잘못 지정하는 것입니다. 이미지를 올릴 ECR 리포지토리가 서울 리전에 있다면 반드시 ap-northeast-2를 명시해야 합니다.
기본 리전이 다르게 설정되어 있으면 리포지토리를 찾을 수 없다는 오류가 발생합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨는 터미널에 명령어를 입력했습니다. 잠시 후 "Login Succeeded"라는 메시지가 나타났습니다.
"와, 됐다!" 김개발 씨가 환하게 웃었습니다. ECR 로그인은 이미지를 푸시하기 위한 첫 번째 관문입니다.
이 과정을 제대로 이해하면 AWS 기반의 컨테이너 운영 환경을 자신 있게 다룰 수 있습니다.
실전 팁
💡 - ECR 로그인 토큰은 12시간마다 만료되므로, 장시간 작업 시 중간에 다시 로그인해야 합니다
- IAM 사용자에게 ecr:GetAuthorizationToken 권한이 있는지 확인하세요
- 여러 리전의 ECR을 사용한다면 각 리전마다 별도로 로그인해야 합니다
2. 이미지 태깅
로그인에 성공한 김개발 씨는 이제 이미지를 푸시하면 된다고 생각했습니다. 하지만 선배가 고개를 저으며 말합니다.
"잠깐, 이미지에 ECR 주소를 태그로 붙여야 해요." 태그를 붙인다고요? 김개발 씨는 또 혼란스러워졌습니다.
이미지 태깅은 로컬에 있는 Docker 이미지에 ECR 리포지토리 주소를 포함한 새로운 이름을 부여하는 작업입니다. 마치 택배 상자에 받는 사람의 정확한 주소를 적는 것처럼, 이미지가 어디로 전송되어야 하는지 명확하게 표시하는 것입니다.
이 태그가 있어야만 Docker가 어느 레지스트리로 이미지를 푸시해야 하는지 알 수 있습니다.
다음 코드를 살펴봅시다.
# 로컬에 빌드된 이미지 확인
docker images
# ECR 형식으로 이미지 태깅
# 형식: [계정ID].dkr.ecr.[리전].amazonaws.com/[리포지토리명]:[태그]
docker tag my-app:latest 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com/my-app:latest
# 버전별 태그 추가 (선택사항)
docker tag my-app:latest 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com/my-app:v1.2.3
# 태그가 정상적으로 생성되었는지 확인
docker images | grep my-app
김개발 씨는 이미 "my-app:latest"라는 이름으로 Docker 이미지를 빌드해둔 상태였습니다. 로컬 환경에서는 이 이름으로 컨테이너를 실행할 수 있었습니다.
하지만 이제 이 이미지를 AWS로 보내야 합니다. 박시니어 씨가 화이트보드에 그림을 그리며 설명합니다.
"Docker 이미지의 이름은 레지스트리 주소, 리포지토리 이름, 태그로 구성돼요. ECR로 푸시하려면 이미지 이름 앞에 ECR 주소를 붙여야 합니다." 이미지 태깅은 정확히 무엇일까요?
쉽게 비유하자면, 이미지 태깅은 마치 국제 우편물에 수신자의 전체 주소를 적는 것과 같습니다. 국내 우편은 간단한 주소만 적어도 되지만, 국제 우편은 나라, 도시, 상세 주소까지 모두 명확하게 적어야 합니다.
Docker 이미지도 마찬가지입니다. 로컬 레지스트리는 짧은 이름으로 충분하지만, 원격 레지스트리로 보내려면 정확한 경로를 포함한 전체 이름이 필요합니다.
태깅이 없던 시절에는 어땠을까요? 사실 Docker는 처음부터 레지스트리 개념을 염두에 두고 설계되었습니다.
하지만 초기에는 Docker Hub만 사용했기 때문에 문제가 단순했습니다. 이미지 이름만 적으면 자동으로 Docker Hub로 전송되었습니다.
그러나 프라이빗 레지스트리가 등장하면서 상황이 복잡해졌습니다. ECR, Google Container Registry, Azure Container Registry 등 다양한 레지스트리 서비스가 생겨났습니다.
Docker는 이미지 이름에 레지스트리 주소를 포함시키는 방식으로 이 문제를 해결했습니다. 바로 이런 이유로 ECR로 푸시하기 전에 반드시 태깅 과정이 필요합니다.
태깅은 이미지를 복사하거나 변경하는 것이 아닙니다. 단순히 동일한 이미지에 새로운 별명을 추가하는 것입니다.
원본 이미지는 그대로 유지되며, 같은 이미지를 가리키는 태그만 하나 더 생깁니다. 마치 한 사람이 본명과 별명을 모두 가지고 있는 것과 같습니다.
위의 명령어를 자세히 살펴보겠습니다. docker tag 명령의 첫 번째 인자는 원본 이미지 이름입니다.
여기서는 "my-app:latest"입니다. 두 번째 인자가 새로운 태그인데, 이것이 핵심입니다.
ECR 주소의 형식은 계정ID.dkr.ecr.리전.amazonaws.com/리포지토리명:태그입니다. 계정 ID는 AWS 콘솔 우측 상단에서 확인할 수 있는 12자리 숫자입니다.
리전은 ECR 리포지토리가 생성된 AWS 리전 코드입니다. 서울은 ap-northeast-2, 버지니아는 us-east-1입니다.
리포지토리명은 ECR에서 미리 생성해둔 리포지토리의 이름입니다. 마지막 태그는 버전이나 환경을 나타내는 레이블입니다.
보통 "latest", "v1.0.0", "production" 같은 값을 사용합니다. 실제 현업에서는 어떻게 활용할까요?
많은 기업에서 시맨틱 버저닝을 사용하여 이미지를 관리합니다. 예를 들어 v1.2.3 형식으로 태그를 붙이고, 메이저 버전이 올라갈 때마다 v2.0.0으로 증가시킵니다.
이렇게 하면 배포 히스토리를 명확하게 추적할 수 있습니다. 또한 동일한 이미지에 여러 태그를 붙이는 것도 일반적입니다.
"latest" 태그와 함께 "v1.2.3", "production" 태그를 모두 붙여서 다양한 방식으로 참조할 수 있게 합니다. Kubernetes나 ECS에서 배포할 때 환경에 따라 다른 태그를 사용하면 관리가 편리합니다.
Git 커밋 해시를 태그로 사용하는 방식도 인기가 많습니다. 예를 들어 "my-app:a3f2b1c" 처럼 짧은 커밋 해시를 태그로 붙이면, 이미지가 어떤 코드 버전에서 빌드되었는지 정확하게 추적할 수 있습니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수는 계정 ID나 리전을 잘못 입력하는 것입니다.
복사-붙여넣기를 할 때 공백이 들어가거나 오타가 생기면 푸시가 실패합니다. 명령어를 실행하기 전에 한 번 더 확인하는 습관을 들이세요.
또 다른 실수는 존재하지 않는 리포지토리 이름을 사용하는 것입니다. ECR 리포지토리는 미리 생성되어 있어야 합니다.
AWS 콘솔이나 AWS CLI로 리포지토리를 먼저 만든 후 태깅해야 합니다. "latest" 태그를 남용하는 것도 문제가 될 수 있습니다.
프로덕션 환경에서는 "latest" 같은 변동 가능한 태그보다는 명확한 버전 번호를 사용하는 것이 안전합니다. 롤백이 필요할 때 어떤 버전으로 돌아가야 하는지 명확해집니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 신중하게 명령어를 입력했습니다.
"docker images" 명령으로 확인해보니 같은 이미지 ID를 가진 두 개의 태그가 보였습니다. "아, 같은 이미지에 이름만 하나 더 붙은 거군요!" 이미지 태깅을 제대로 이해하면 복잡한 컨테이너 레지스트리 환경에서도 혼란 없이 이미지를 관리할 수 있습니다.
실전 팁
💡 - 이미지 태깅은 디스크 공간을 추가로 사용하지 않습니다 (같은 이미지를 가리키는 포인터일 뿐)
- 여러 환경(dev, staging, prod)별로 다른 태그를 사용하면 배포 관리가 쉬워집니다
- CI/CD 파이프라인에서는 빌드 번호나 Git 커밋 해시를 자동으로 태그에 포함시키세요
3. docker push 명령
이제 드디어 이미지를 푸시할 차례입니다. 김개발 씨는 설렘 반 긴장 반으로 키보드에 손을 올렸습니다.
"이제 docker push만 하면 되는 거죠?" 박시니어 씨가 고개를 끄덕입니다. "네, 하지만 네트워크 상태에 따라 시간이 좀 걸릴 수 있어요."
docker push는 태그가 붙은 Docker 이미지를 원격 레지스트리로 전송하는 명령어입니다. 마치 택배 기사가 포장된 상자를 목적지까지 배송하는 것처럼, 로컬에 있는 이미지를 ECR로 업로드하는 과정입니다.
이미지의 각 레이어가 순차적으로 압축되어 전송되며, 이미 존재하는 레이어는 건너뛰어 효율적으로 업로드됩니다.
다음 코드를 살펴봅시다.
# 태그가 붙은 이미지를 ECR로 푸시
docker push 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com/my-app:latest
# 여러 태그를 동시에 푸시하려면 각각 실행
docker push 123456789012.dkr.ecr.ap-northeast-2.amazonaws.com/my-app:v1.2.3
# 푸시 진행 상황 확인
# The push refers to repository [...] 메시지와 함께
# 각 레이어의 업로드 진행률이 표시됩니다
# latest: digest: sha256:... size: 1234 메시지가 나오면 성공
김개발 씨가 엔터 키를 눌렀습니다. 터미널에 여러 줄의 메시지가 빠르게 스크롤되기 시작했습니다.
"Preparing", "Pushing", "Pushed"라는 단어들이 보였습니다. "이게 뭐예요?" 김개발 씨가 물었습니다.
박시니어 씨가 화면을 가리키며 설명합니다. "Docker 이미지는 여러 개의 레이어로 구성되어 있어요.
지금 각 레이어가 하나씩 업로드되고 있는 거예요." docker push 명령은 정확히 무엇을 할까요? 쉽게 비유하자면, docker push는 마치 큰 파일을 클라우드 스토리지에 업로드하는 것과 같습니다.
하지만 일반 파일 업로드와 다른 점이 있습니다. Docker는 이미지를 통째로 보내지 않고 레이어 단위로 분할해서 전송합니다.
이미 서버에 존재하는 레이어는 건너뛰기 때문에 업로드 시간이 크게 단축됩니다. 예를 들어 Ubuntu 베이스 이미지 위에 여러분의 애플리케이션을 얹은 이미지를 푸시한다고 가정해봅시다.
Ubuntu 레이어는 이미 ECR에 다른 이미지를 통해 업로드되어 있을 가능성이 높습니다. 이 경우 Docker는 Ubuntu 레이어는 건너뛰고 여러분의 애플리케이션 레이어만 업로드합니다.
레이어 공유가 없던 시절에는 어땠을까요? 초기의 컨테이너 시스템들은 이미지를 하나의 거대한 파일로 취급했습니다.
작은 코드 수정만 해도 전체 이미지를 다시 업로드해야 했습니다. 수 기가바이트짜리 이미지를 매번 올리는 것은 시간도 오래 걸리고 네트워크 대역폭도 많이 소모했습니다.
Docker의 레이어 시스템은 이 문제를 혁신적으로 해결했습니다. 각 Dockerfile 명령이 하나의 레이어를 만들고, 변경되지 않은 레이어는 재사용됩니다.
이는 증분 업로드를 가능하게 만들었습니다. 바로 이런 효율성 덕분에 docker push가 실무에서 빠르고 편리하게 작동합니다.
푸시 과정을 단계별로 살펴보겠습니다. 먼저 Docker는 이미지의 모든 레이어를 식별합니다.
각 레이어는 고유한 SHA256 해시값을 가지고 있습니다. 그 다음 ECR 서버에 연결하여 어떤 레이어가 이미 존재하는지 확인합니다.
이 과정이 "Preparing" 단계입니다. ECR에 없는 레이어만 압축하여 업로드를 시작합니다.
이것이 "Pushing" 단계입니다. 각 레이어마다 진행률이 표시되며, 크기에 따라 업로드 시간이 다릅니다.
모든 레이어 업로드가 완료되면 "Pushed" 상태가 됩니다. 마지막으로 이미지 매니페스트를 업로드합니다.
매니페스트는 이미지를 구성하는 레이어들의 목록과 설정 정보를 담고 있습니다. 이 매니페스트에는 다이제스트 값이라는 고유 식별자가 부여됩니다.
실제 현업에서는 어떻게 활용할까요? 대부분의 기업에서는 CI/CD 파이프라인에 docker push를 통합합니다.
GitHub Actions, GitLab CI, Jenkins 등에서 코드가 머지되면 자동으로 이미지를 빌드하고 ECR에 푸시합니다. 이때 네트워크 오류를 대비해 재시도 로직을 추가하는 경우가 많습니다.
또한 멀티 아키텍처 이미지를 지원하는 경우도 증가하고 있습니다. AMD64와 ARM64 아키텍처용 이미지를 각각 빌드하고 푸시한 후, 매니페스트 리스트로 묶어서 플랫폼에 관계없이 사용할 수 있게 만듭니다.
푸시 속도를 높이기 위해 Docker 빌드 캐시를 적극 활용하는 것도 중요합니다. Dockerfile을 작성할 때 자주 변경되지 않는 레이어를 앞쪽에 배치하면, 대부분의 레이어가 캐시되어 푸시 시간이 크게 단축됩니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수는 네트워크 타임아웃을 고려하지 않는 것입니다.
수 기가바이트짜리 이미지를 느린 네트워크에서 푸시하면 중간에 연결이 끊길 수 있습니다. 이 경우 Docker는 자동으로 재시도하지만, 완전히 실패하면 처음부터 다시 푸시해야 합니다.
또 다른 실수는 불필요하게 큰 이미지를 만드는 것입니다. 개발 도구나 빌드 캐시를 이미지에 포함시키면 푸시 시간이 길어집니다.
.dockerignore 파일을 활용하여 불필요한 파일을 제외하고, 멀티 스테이지 빌드를 사용하여 최종 이미지 크기를 최소화하세요. 권한 오류도 자주 발생합니다.
ECR 리포지토리에 대한 ecr:PutImage 권한이 없으면 푸시가 실패합니다. IAM 정책을 확인하여 필요한 권한이 모두 부여되어 있는지 점검하세요.
다시 김개발 씨의 이야기로 돌아가 봅시다. 몇 분 후 터미널에 "digest: sha256:..." 메시지가 나타났습니다.
"푸시 성공했어요!" 김개발 씨가 기쁨을 감추지 못하며 외쳤습니다. 박시니어 씨가 웃으며 말합니다.
"축하해요. 이제 AWS 콘솔에서 확인해볼까요?" docker push를 제대로 이해하면 컨테이너 기반 배포 파이프라인을 자신 있게 구축할 수 있습니다.
실전 팁
💡 - 이미지 크기를 줄이면 푸시 시간도 줄어듭니다 (alpine 베이스 이미지 사용 권장)
- 푸시가 너무 느리다면 Dockerfile을 최적화하여 레이어 캐싱을 개선하세요
- 중요한 배포는 다이제스트 값으로 참조하면 불변성을 보장할 수 있습니다
4. 푸시 확인하기
푸시는 성공했지만, 정말 이미지가 ECR에 올라갔는지 확인하고 싶었습니다. 김개발 씨는 박시니어 씨를 따라 AWS 콘솔을 열었습니다.
"어디서 확인하면 되나요?" 김개발 씨가 물었습니다. "ECR 서비스로 가서 리포지토리를 클릭하면 돼요."
푸시 확인은 업로드된 이미지가 ECR에 정상적으로 저장되었는지 검증하는 과정입니다. 마치 택배를 보낸 후 배송 완료 알림을 확인하는 것처럼, AWS 콘솔이나 CLI를 통해 이미지 목록, 태그, 업로드 시간, 크기 등의 정보를 확인할 수 있습니다.
이 단계에서 이미지가 정확한 태그로 올라갔는지 반드시 확인해야 합니다.
다음 코드를 살펴봅시다.
# AWS CLI로 ECR 이미지 목록 확인
aws ecr list-images --repository-name my-app --region ap-northeast-2
# 특정 이미지의 상세 정보 확인
aws ecr describe-images --repository-name my-app --region ap-northeast-2
# 최근 푸시된 이미지만 확인 (JSON 출력 포맷)
aws ecr describe-images --repository-name my-app --region ap-northeast-2 --query 'sort_by(imageDetails,&imagePushedAt)[-5:]'
# 특정 태그로 이미지 검색
aws ecr describe-images --repository-name my-app --image-ids imageTag=latest --region ap-northeast-2
김개발 씨는 AWS 콘솔에서 ECR 서비스 페이지를 열었습니다. 화면에 리포지토리 목록이 나타났고, "my-app"이라는 이름이 보였습니다.
클릭하자 방금 푸시한 이미지가 목록에 표시되었습니다. "와, 여기 있네요!" 박시니어 씨가 화면을 가리킵니다.
"보세요. 태그, 푸시된 시간, 이미지 크기가 모두 나와 있죠?
이 정보들을 확인해서 올바른 이미지가 올라갔는지 검증해야 해요." 푸시 확인은 왜 중요할까요? 쉽게 비유하자면, 푸시 확인은 마치 온라인 쇼핑 후 주문 내역을 확인하는 것과 같습니다.
결제는 완료되었지만, 주문한 상품이 맞는지, 수량이 맞는지, 배송지가 정확한지 확인하는 과정입니다. Docker 이미지도 마찬가지입니다.
푸시 명령이 성공했다고 해서 끝이 아닙니다. 실제 현업에서 문제가 발생하는 경우를 보면 이해가 쉽습니다.
어느 날 개발팀이 새로운 기능을 배포했습니다. 하지만 프로덕션 환경에서는 여전히 이전 버전이 실행되고 있었습니다.
알고 보니 이미지를 푸시할 때 태그를 잘못 지정했고, 배포 스크립트는 다른 태그를 바라보고 있었습니다. 푸시 후 제대로 확인했다면 즉시 발견할 수 있었던 실수였습니다.
또 다른 사례로, 이미지가 예상보다 훨씬 크게 업로드되어 스토리지 비용이 급증한 경우도 있습니다. 개발자가 실수로 불필요한 파일들을 포함시켰는데, 푸시 확인 과정에서 이미지 크기를 체크했다면 조기에 문제를 파악할 수 있었을 것입니다.
바로 이런 이유로 푸시 후 반드시 확인하는 습관을 들여야 합니다. AWS 콘솔에서 확인하는 방법은 직관적입니다.
ECR 서비스로 이동하여 리포지토리를 클릭하면 이미지 목록이 나타납니다. 각 이미지는 태그, 다이제스트, 크기, 푸시 시간, 취약점 스캔 결과 등의 정보를 제공합니다.
CLI를 사용하면 더 자세한 정보를 얻거나 자동화할 수 있습니다. aws ecr describe-images 명령은 JSON 형식으로 모든 메타데이터를 반환합니다.
여기에는 이미지 다이제스트, 레지스트리 ID, 리포지토리 이름, 태그 목록, 이미지 크기, 푸시된 시간 등이 포함됩니다. 특히 유용한 것은 --query 옵션입니다.
JMESPath 문법을 사용하여 원하는 정보만 필터링할 수 있습니다. 예를 들어 최근 5개의 이미지만 푸시 시간순으로 정렬해서 볼 수 있습니다.
CI/CD 스크립트에서 "latest" 태그가 방금 푸시한 이미지를 가리키는지 자동으로 검증할 수도 있습니다. 실제 현업에서는 어떻게 활용할까요?
많은 기업에서 배포 전 검증 스크립트를 작성합니다. 이미지를 푸시한 후 자동으로 ECR을 조회하여 예상한 태그와 다이제스트가 일치하는지 확인합니다.
일치하지 않으면 배포를 중단하고 알림을 보냅니다. 또한 모니터링 도구와 통합하여 새 이미지가 푸시될 때마다 Slack이나 이메일로 알림을 받도록 설정하는 경우도 많습니다.
AWS EventBridge를 사용하면 ECR 푸시 이벤트를 감지하여 자동화된 작업을 트리거할 수 있습니다. 이미지 크기를 추적하는 것도 중요한 관행입니다.
시간이 지나면서 이미지 크기가 증가하는 경향이 있습니다. 주기적으로 크기를 확인하고 최적화 기회를 찾아야 합니다.
일부 팀은 이미지 크기에 임계값을 설정하여, 크기가 갑자기 증가하면 경고를 발생시킵니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수는 태그만 확인하고 다이제스트는 확인하지 않는 것입니다. 같은 태그를 여러 번 푸시할 수 있기 때문에, 태그만으로는 정확히 어떤 이미지가 올라갔는지 알 수 없습니다.
다이제스트 값을 함께 확인해야 불변성이 보장됩니다. 또 다른 실수는 리전을 혼동하는 것입니다.
ECR 리포지토리는 리전별로 분리되어 있습니다. 서울 리전에 푸시했는데 도쿄 리전에서 확인하려고 하면 당연히 이미지가 보이지 않습니다.
AWS CLI의 --region 옵션을 올바르게 지정했는지 확인하세요. 시간대 차이도 혼란을 줄 수 있습니다.
AWS 콘솔에 표시되는 푸시 시간은 보통 UTC 기준입니다. 로컬 시간과 비교할 때 시간대 변환을 고려해야 합니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. AWS 콘솔에서 이미지 정보를 확인한 김개발 씨는 안도의 한숨을 쉬었습니다.
"태그도 맞고, 크기도 적당하네요. 이제 정말 끝난 거죠?" 박시니어 씨가 미소를 지으며 말합니다.
"아직 하나 더 남았어요. 보안 취약점 스캔 결과도 확인해야 합니다." 푸시 확인을 제대로 하면 배포 오류를 미연에 방지하고 운영 안정성을 높일 수 있습니다.
실전 팁
💡 - 배포 스크립트에 이미지 다이제스트 검증 로직을 추가하세요
- AWS 콘솔보다 CLI가 자동화에 유리하며, jq와 함께 사용하면 더욱 강력합니다
- EventBridge를 활용하여 ECR 푸시 이벤트를 실시간으로 모니터링하세요
5. 이미지 스캔
이미지가 ECR에 잘 올라간 것을 확인한 김개발 씨는 이제 모든 작업이 끝났다고 생각했습니다. 하지만 박시니어 씨가 화면을 가리키며 말합니다.
"여기 보세요. 취약점 스캔 상태가 'PENDING'이에요.
스캔이 완료될 때까지 기다려야 해요."
이미지 스캔은 Docker 이미지에 포함된 운영체제 패키지와 소프트웨어 라이브러리의 보안 취약점을 자동으로 검사하는 기능입니다. 마치 공항 보안 검색대에서 위험 물품을 스캔하는 것처럼, 이미지 내부의 알려진 보안 취약점을 데이터베이스와 대조하여 찾아냅니다.
ECR은 푸시 시 자동 스캔 또는 수동 스캔 두 가지 방식을 지원합니다.
다음 코드를 살펴봅시다.
# 수동으로 이미지 스캔 시작
aws ecr start-image-scan --repository-name my-app --image-id imageTag=latest --region ap-northeast-2
# 스캔 상태 확인
aws ecr describe-image-scan-findings --repository-name my-app --image-id imageTag=latest --region ap-northeast-2
# 리포지토리에 푸시 시 자동 스캔 활성화
aws ecr put-image-scanning-configuration --repository-name my-app --image-scanning-configuration scanOnPush=true --region ap-northeast-2
# 모든 이미지의 스캔 결과 요약 확인
aws ecr describe-images --repository-name my-app --region ap-northeast-2 --query 'imageDetails[*].[imageTags[0],imageScanStatus.status,imageScanFindingsSummary.findingSeverityCounts]'
김개발 씨는 처음 보는 용어에 당황했습니다. "취약점 스캔이요?
제가 작성한 코드에는 문제가 없는데요." 김개발 씨가 자신 있게 말했습니다. 박시니어 씨가 고개를 저으며 설명합니다.
"여러분이 작성한 코드만 문제가 아니에요. Docker 이미지에는 운영체제, 라이브러리, 의존성 패키지가 모두 포함되어 있죠.
그 안에 알려진 보안 취약점이 있을 수 있어요." 이미지 스캔은 정확히 무엇일까요? 쉽게 비유하자면, 이미지 스캔은 마치 건강검진과 같습니다.
겉으로 보기에는 멀쩡해 보여도 내부에 숨어 있는 문제를 조기에 발견하는 것입니다. Docker 이미지도 마찬가지입니다.
애플리케이션은 잘 동작하지만, 내부에 사용된 라이브러리에 심각한 보안 취약점이 있을 수 있습니다. 예를 들어 여러분이 Node.js 애플리케이션을 개발했다고 가정해봅시다.
코드 자체는 완벽하지만, 의존하는 npm 패키지 중 하나가 오래된 버전이고 그 안에 원격 코드 실행 취약점이 있다면 어떻게 될까요? 공격자가 이 취약점을 악용하여 서버를 장악할 수 있습니다.
취약점 스캔이 없던 시절에는 어땠을까요? 과거에는 보안팀이 수동으로 이미지를 검사했습니다.
각 패키지의 버전을 일일이 확인하고, CVE 데이터베이스와 대조하는 작업이었습니다. 매우 시간이 오래 걸렸고, 사람이 하는 일이다 보니 실수도 잦았습니다.
더 큰 문제는 새로운 취약점이 매일 발견된다는 점입니다. 어제는 안전했던 이미지가 오늘은 위험해질 수 있습니다.
수동 검사로는 이런 변화를 따라잡기 불가능했습니다. 바로 이런 문제를 해결하기 위해 자동화된 이미지 스캔이 등장했습니다.
ECR의 이미지 스캔은 두 가지 엔진을 제공합니다. 기본 스캔은 Common Vulnerabilities and Exposures(CVE) 데이터베이스를 기반으로 작동합니다.
향상된 스캔은 Amazon Inspector와 통합되어 더 정확하고 포괄적인 검사를 수행합니다. 스캔 과정은 자동으로 진행됩니다.
이미지의 각 레이어를 분석하여 설치된 패키지 목록을 추출합니다. 그 다음 각 패키지의 버전을 식별하고 알려진 취약점 데이터베이스와 비교합니다.
매칭되는 취약점이 발견되면 심각도에 따라 분류됩니다. 심각도는 CRITICAL, HIGH, MEDIUM, LOW, INFORMATIONAL로 구분됩니다.
CRITICAL과 HIGH는 즉시 조치가 필요한 심각한 취약점입니다. 원격 코드 실행, 권한 상승, 데이터 유출 같은 위험이 있습니다.
실제 현업에서는 어떻게 활용할까요? 대부분의 기업에서는 scanOnPush 옵션을 활성화하여 이미지가 푸시될 때마다 자동으로 스캔하도록 설정합니다.
이렇게 하면 모든 이미지가 항상 최신 취약점 정보로 검사됩니다. 또한 CI/CD 파이프라인에 취약점 검사 단계를 추가합니다.
스캔 결과에서 CRITICAL 취약점이 발견되면 배포를 자동으로 중단하도록 설정하는 경우가 많습니다. 이를 Shift Left Security라고 하며, 문제를 프로덕션 환경에 배포하기 전에 조기에 차단하는 전략입니다.
정기적인 재스캔도 중요합니다. 이미 배포된 이미지라도 새로운 취약점이 발견될 수 있습니다.
주기적으로 모든 이미지를 다시 스캔하여 새로운 위협을 감지해야 합니다. AWS Lambda를 사용하여 매일 밤 자동으로 재스캔을 실행하는 방식이 일반적입니다.
취약점이 발견되면 어떻게 해야 할까요? 가장 좋은 방법은 영향받는 패키지를 최신 버전으로 업데이트하는 것입니다.
베이스 이미지를 업데이트하거나, 의존성 버전을 올리거나, 패치된 라이브러리로 교체합니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수는 모든 취약점을 즉시 해결하려고 하는 것입니다. 현실적으로 모든 LOW 수준 취약점까지 완벽하게 제거하기는 어렵습니다.
우선순위를 정하여 CRITICAL과 HIGH부터 해결하는 것이 효율적입니다. 또 다른 실수는 False Positive를 고려하지 않는 것입니다.
스캔 도구가 완벽하지 않기 때문에 실제로는 영향받지 않는 취약점이 보고될 수 있습니다. 각 취약점을 평가하여 실제 위험도를 판단해야 합니다.
스캔 시간도 고려해야 합니다. 대형 이미지는 스캔에 수 분이 걸릴 수 있습니다.
배포 파이프라인이 스캔 완료를 기다리도록 설계해야 합니다. 타임아웃 설정이 너무 짧으면 스캔이 완료되기 전에 배포가 진행될 수 있습니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 몇 분 후 스캔이 완료되었습니다.
박시니어 씨가 결과를 확인하며 말합니다. "MEDIUM 취약점 3개가 발견됐네요.
나중에 시간 날 때 업데이트하면 됩니다. CRITICAL은 없으니 일단 배포해도 괜찮아요." 김개발 씨는 안도하며 고개를 끄덕였습니다.
보안이 이렇게 중요한 줄 처음 알았습니다. 이미지 스캔을 제대로 활용하면 보안 사고를 사전에 예방하고 컴플라이언스 요구사항을 충족할 수 있습니다.
실전 팁
💡 - scanOnPush를 활성화하여 모든 이미지를 자동으로 스캔하세요
- 베이스 이미지를 정기적으로 업데이트하면 대부분의 취약점을 예방할 수 있습니다
- Alpine Linux 같은 최소화된 베이스 이미지를 사용하면 취약점 노출 범위가 줄어듭니다
6. 취약점 확인
스캔이 완료된 후 김개발 씨는 결과를 자세히 살펴보고 싶었습니다. "이 취약점들이 정확히 뭔지 어떻게 알 수 있나요?" 박시니어 씨가 스캔 결과를 클릭하며 설명합니다.
"각 취약점에는 CVE 번호가 붙어 있어요. 이걸 검색하면 자세한 정보를 볼 수 있습니다."
취약점 확인은 스캔 결과를 분석하여 발견된 보안 취약점의 세부 정보를 파악하고 조치 계획을 수립하는 과정입니다. 마치 건강검진 결과지를 의사와 함께 검토하는 것처럼, 각 취약점의 심각도, 영향받는 패키지, CVE 상세 정보, 해결 방법을 확인합니다.
이 정보를 바탕으로 어떤 취약점을 우선 해결할지 결정합니다.
다음 코드를 살펴봅시다.
# 특정 이미지의 취약점 상세 정보 조회
aws ecr describe-image-scan-findings --repository-name my-app --image-id imageTag=latest --region ap-northeast-2 --output json > scan-results.json
# 심각도별 취약점 개수 확인
aws ecr describe-image-scan-findings --repository-name my-app --image-id imageTag=latest --region ap-northeast-2 --query 'imageScanFindings.findingSeverityCounts'
# CRITICAL 취약점만 필터링
aws ecr describe-image-scan-findings --repository-name my-app --image-id imageTag=latest --region ap-northeast-2 --query 'imageScanFindings.findings[?severity==`CRITICAL`]'
# 취약점 정보를 CSV 형식으로 추출 (jq 사용)
aws ecr describe-image-scan-findings --repository-name my-app --image-id imageTag=latest --region ap-northeast-2 | jq -r '.imageScanFindings.findings[] | [.name, .severity, .uri] | @csv'
김개발 씨는 AWS 콘솔에서 스캔 결과 페이지를 열었습니다. 화면에 여러 개의 CVE 번호와 함께 MEDIUM이라는 심각도 레이블이 표시되어 있었습니다.
"CVE-2023-12345가 뭐죠?" 김개발 씨가 물었습니다. 박시니어 씨가 CVE 번호를 클릭하여 상세 페이지를 보여줍니다.
"CVE는 Common Vulnerabilities and Exposures의 약자예요. 각 보안 취약점에 부여되는 고유 식별자죠." 취약점 확인은 왜 중요할까요?
쉽게 비유하자면, 취약점 확인은 마치 자동차 안전 리콜 공지를 확인하는 것과 같습니다. "브레이크에 문제가 있다"는 말만 듣고 끝나면 안 됩니다.
어떤 모델이 영향받는지, 얼마나 위험한지, 언제 수리해야 하는지 구체적으로 알아야 조치를 취할 수 있습니다. Docker 이미지의 취약점도 마찬가지입니다.
스캔 도구가 "취약점 10개 발견"이라고만 알려주면 무엇을 어떻게 해야 할지 막막합니다. 각 취약점의 성격을 이해하고 우선순위를 정해야 합니다.
취약점 정보는 어떻게 구성되어 있을까요? 각 취약점은 여러 정보를 포함합니다.
가장 중요한 것은 CVE 번호입니다. 이것은 전 세계적으로 통용되는 취약점 식별자입니다.
CVE-2023-12345 같은 형식으로, 연도와 일련번호로 구성됩니다. 다음으로 **심각도(Severity)**가 있습니다.
CVSS(Common Vulnerability Scoring System) 점수를 기반으로 CRITICAL, HIGH, MEDIUM, LOW로 분류됩니다. CRITICAL은 CVSS 점수 9.0 이상으로, 즉각적인 조치가 필요한 매우 위험한 취약점입니다.
영향받는 패키지 정보도 중요합니다. 어떤 라이브러리의 어떤 버전이 문제인지 명확하게 표시됩니다.
예를 들어 "openssl 1.1.1k"라고 나오면, OpenSSL 라이브러리의 1.1.1k 버전에 취약점이 있다는 의미입니다. 수정 버전(Fixed in version) 정보는 문제를 해결할 방법을 알려줍니다.
"openssl 1.1.1l"로 업데이트하면 취약점이 패치된다는 것을 알 수 있습니다. **설명(Description)**에는 취약점의 성격이 기술되어 있습니다.
"원격 코드 실행 가능", "권한 상승", "서비스 거부 공격" 같은 내용입니다. 이 정보를 읽으면 실제 위험도를 평가할 수 있습니다.
URI는 해당 취약점에 대한 자세한 정보가 있는 웹 페이지 링크입니다. NIST NVD, Ubuntu Security Notices, Red Hat CVE 데이터베이스 같은 공식 출처로 연결됩니다.
실제 현업에서는 어떻게 활용할까요? 많은 기업에서 취약점 관리 프로세스를 운영합니다.
새 이미지가 스캔되면 보안팀이 결과를 검토합니다. CRITICAL과 HIGH 취약점은 즉시 개발팀에 전달되어 긴급 패치 작업이 시작됩니다.
일부 조직에서는 **취약점 SLA(Service Level Agreement)**를 정의합니다. 예를 들어 "CRITICAL 취약점은 발견 후 24시간 내 해결, HIGH는 7일 내 해결"같은 규칙을 만듭니다.
이렇게 하면 보안 위험이 오래 방치되지 않습니다. 자동화 도구를 활용하는 경우도 많습니다.
Slack이나 Jira와 연동하여 CRITICAL 취약점이 발견되면 자동으로 티켓을 생성하거나 알림을 보냅니다. 담당자가 실시간으로 대응할 수 있게 됩니다.
취약점을 추적하는 대시보드를 구축하는 것도 좋은 방법입니다. 모든 리포지토리와 이미지의 취약점 현황을 한눈에 볼 수 있습니다.
시간이 지나면서 취약점이 증가하는지 감소하는지 트렌드를 파악할 수 있습니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수는 숫자에만 집중하는 것입니다. "취약점 100개"라는 말에 겁을 먹지만, 실제로는 대부분 LOW 수준이고 실제 영향은 미미할 수 있습니다.
반대로 "취약점 1개"라도 CRITICAL이면 매우 위험합니다. 개수보다는 심각도와 실제 영향을 평가해야 합니다.
또 다른 실수는 맹목적으로 모든 패키지를 업데이트하는 것입니다. 최신 버전으로 올리면 취약점은 해결되지만, 호환성 문제가 발생할 수 있습니다.
특히 메이저 버전 업그레이드는 API가 변경될 수 있어 애플리케이션이 작동하지 않을 수 있습니다. 업데이트 후 반드시 테스트를 거쳐야 합니다.
False Positive에 대한 이해도 필요합니다. 예를 들어 취약점이 웹 서버 관련인데 여러분의 애플리케이션이 웹 서버 기능을 사용하지 않는다면 실제로는 영향받지 않습니다.
이런 경우 예외 처리를 하거나 우선순위를 낮출 수 있습니다. 일부 취약점은 특정 설정에서만 활성화됩니다.
예를 들어 "관리자 권한으로 실행 시에만 악용 가능"한 취약점이 있습니다. 컨테이너를 비권한 사용자로 실행하면 실제 위험이 없습니다.
취약점의 활성화 조건을 이해하는 것이 중요합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
CVE 상세 페이지를 읽어본 김개발 씨는 이해가 되기 시작했습니다. "아, 이 취약점은 특정 기능을 사용할 때만 문제가 되는군요.
우리는 그 기능을 안 쓰니까 당장은 괜찮겠네요." 박시니어 씨가 만족스럽게 웃으며 말합니다. "정확해요.
취약점 확인은 단순히 목록을 보는 게 아니라, 각 항목을 평가하고 우선순위를 정하는 거예요. 이제 제대로 이해하셨네요." 취약점 확인을 제대로 하면 보안 위험을 효과적으로 관리하고 한정된 리소스를 가장 중요한 문제에 집중할 수 있습니다.
실전 팁
💡 - CVE 번호를 검색하여 공식 문서와 패치 정보를 반드시 확인하세요
- CVSS 점수뿐만 아니라 실제 악용 가능성과 영향 범위를 함께 고려하세요
- 취약점 추적 시스템을 구축하여 발견부터 해결까지의 전 과정을 기록하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
쿠버네티스 아키텍처 완벽 가이드
초급 개발자를 위한 쿠버네티스 아키텍처 설명서입니다. 클러스터 구조부터 Control Plane, Worker Node, 파드, 네트워킹까지 실무 관점에서 쉽게 풀어냅니다. 점프 투 자바 스타일로 술술 읽히는 이북 형식으로 작성되었습니다.
EFK 스택 로깅 완벽 가이드
마이크로서비스 환경에서 로그를 효과적으로 수집하고 분석하는 EFK 스택(Elasticsearch, Fluentd, Kibana)의 핵심 개념과 실전 활용법을 초급 개발자도 쉽게 이해할 수 있도록 정리한 가이드입니다.
Grafana 대시보드 완벽 가이드
실시간 모니터링의 핵심, Grafana 대시보드를 처음부터 끝까지 배워봅니다. Prometheus 연동부터 알람 설정까지, 초급 개발자도 쉽게 따라할 수 있는 실전 가이드입니다.
분산 추적 완벽 가이드
마이크로서비스 환경에서 요청의 전체 흐름을 추적하는 분산 추적 시스템의 핵심 개념을 배웁니다. Trace, Span, Trace ID 전파, 샘플링 전략까지 실무에 필요한 모든 것을 다룹니다.