AWS 해부 (5) 컨테이너 배포: ECR에서 EC2까지
ECR repository 생성과 이미지 push, Apple Silicon에서 빌드할 때의 아키텍처 불일치 문제, EC2에서 이미지를 pull 받아 Docker Compose로 구동하는 배포 동선을 정리합니다.
AWS 해부 시리즈의 5편입니다. 전체 목차는 0편에 있습니다.
ECR이 필요한 이유
머신러닝 실전 워크플로 10편에서 만든 이미지는 로컬에만 있습니다. EC2에서 그 이미지를 돌리려면 중간에 이미지 저장소(registry)가 필요합니다. Docker Hub 공개 저장소는 코드가 노출되고, ECR은 계정 안의 프라이빗 registry라서 IAM 권한으로 접근이 통제됩니다. 로컬에서 push하고 EC2에서 pull하는 중계 지점입니다.
repository 생성과 push
ECR은 이미지 이름 하나당 repository 하나를 만듭니다.
1
aws ecr create-repository --repository-name taxi-serving
push는 로그인, 태그, push 세 단계입니다.
1
2
3
4
5
6
7
8
9
# 1. ECR 로그인 (토큰 유효기간 12시간)
aws ecr get-login-password --region ap-northeast-2 \
| docker login --username AWS --password-stdin <account-id>.dkr.ecr.ap-northeast-2.amazonaws.com
# 2. 로컬 이미지에 ECR 주소 형식의 태그를 붙임
docker tag taxi-serving:v1 <account-id>.dkr.ecr.ap-northeast-2.amazonaws.com/taxi-serving:v1
# 3. push
docker push <account-id>.dkr.ecr.ap-northeast-2.amazonaws.com/taxi-serving:v1
ECR의 이미지 주소는 <account-id>.dkr.ecr.<region>.amazonaws.com/<repository>:<tag> 형식이고, docker tag는 이 주소를 로컬 이미지의 별칭으로 붙이는 것입니다.
아키텍처 불일치: Apple Silicon의 함정
Apple Silicon Mac의 docker build는 기본으로 ARM(arm64) 이미지를 만듭니다. x86(amd64) CPU인 t3 instance에서 이 이미지를 실행하면 exec format error로 죽습니다. push와 pull은 성공하기 때문에 실행 시점에야 드러납니다.
해결은 둘 중 하나입니다.
- 빌드 시 대상 아키텍처를 지정합니다:
docker buildx build --platform linux/amd64 -t taxi-serving:v1 . - instance를 ARM(
t4g등)으로 맞춥니다. 이 경우 모든 이미지가 arm64여야 합니다
어느 쪽이든 빌드 머신과 실행 머신의 아키텍처를 의식적으로 맞추는 것이 핵심입니다.
EC2에서 pull과 구동
instance에 Docker를 설치하고, 4편의 IAM role에 ECR 읽기 권한(AmazonEC2ContainerRegistryReadOnly)을 추가하면 access key 없이 pull이 됩니다.
1
2
3
4
5
# EC2 안에서
sudo apt-get update && sudo apt-get install -y docker.io docker-compose-v2
aws ecr get-login-password --region ap-northeast-2 \
| sudo docker login --username AWS --password-stdin <account-id>.dkr.ecr.ap-northeast-2.amazonaws.com
sudo docker pull <account-id>.dkr.ecr.ap-northeast-2.amazonaws.com/taxi-serving:v1
compose 파일의 image:를 ECR 주소로 바꾸면 Airflow 해부 6편의 Docker Compose 구성이 EC2에서 그대로 돕니다. 서비스 포트는 security group에서 여는데, 전체 공개가 아니라 내 IP로 제한하는 것이 기본입니다.
자주 밟는 함정
exec format error로 컨테이너가 즉시 죽습니다. 이미지와 instance의 CPU 아키텍처 불일치입니다.docker inspect로 이미지의Architecture를 확인하고--platform linux/amd64로 다시 빌드합니다- 어제는 되던 push가 인증 에러를 냅니다. ECR 로그인 토큰의 유효기간이 12시간이라 만료된 것입니다.
get-login-password로그인을 다시 실행합니다. 자동화 스크립트라면 로그인 단계를 스크립트 안에 포함합니다 latest태그 하나로만 push합니다. EC2에서 돌고 있는 이미지가 어떤 코드인지 알 수 없게 되고, 롤백도 불가능해집니다. NYC 택시 프로젝트 8편의 CI처럼 커밋 해시나 버전을 태그로 씁니다
다음 편에서 이 리소스들의 요금을 통제하는 법을 다룹니다.