CampusMeet

[AWS] ECR 을 활용한 Docker Image 저장

dong_seok 2024. 10. 10. 19:03
1. ECR 이란
2. ECR Docker Image Push

 

1. ECR 이란

ECR은 Elastic Container Registry 의 약자로 AWS에서 지원하는 관리형 컨테이너 이미지 레지스트리 서비스입니다. IAM 권한을 이용하여 리소스 기반 권한을 가진 프라이빗 레포지토리를 지원하여 EC2 인스턴스가 컨테이너 레포지토리 및 이미지에 접근할 수 있습니다.

 

ECR 구성요소

 

Registry

ECR private registry 하나에 여러개의 레포지토리, 도커 이미지, Open Container Initiative(OCL) 이미지 등을 저장할 수 있습니다.

 

사용자 권한 토큰

클라이언트는 ECR Private registry 에 AWS 사용자 인증후에 이미지 푸시 및 풀이 가능합니다.

 

Repository

ECR 레포지토리에는 Docker 이미지, OCI 이미지 및 OCI 호환 아티팩트가 포함되어 있습니다.

 

Repository policy

레포지토리 정책을 사용하여 레포지토리 및 내부 컨텐츠에 대한 엑세스 제어가 가능합니다.

 

이미지

레포지토리에 컨테이너 이미지를 푸시하고 가져올 수 있습니다.

 

처음에는 ECR이 AWS에서 제공하는 서비스이다 보니 비용 부담을 줄이기 위해 Docker Hub를 사용하려 했습니다. 하지만, Private Subnet에 위치한 EC2 인스턴스에서 Docker Hub에 접근하려면 NAT Gateway나 NAT Instance가 필수적이라는 점을 알게 되었습니다. 이에 따라 비용 절감을 위해 AWS ECR에 도커 이미지를 저장하고, VPC Endpoint를 활용해 이미지를 가져와 컨테이너화하는 방법으로 진행하게 되었습니다.

 

2. ECR Docker Image Push

ECR 을 사용하기 위해 가장 먼저 리포지토리를 생성해주도록 하겠습니다. private 과 public이 있는데 저는 외부에서 인터넷 접근을 해야할 가능성을 열어두기 위해 public 리포지토리로 생성해었습니다. AWS ECR -> public 리포지토리 -> 리포지토리 생성을 클릭해줍니다.

리포지토리 이름을 작성하고 콘텐츠 유형을 혹시 몰라 선택해두었습니다.

 

 

그리고 생성 버튼을 누르면 잘 생성된 모습을 볼 수 있습니다.

 

 

ECR Public Repository에 이미지를 Push하기 위해서는 ECR Public Repository에 대한 권한이 필요합니다. ECR Repository에 대해 액세스 토큰을 발급받을때 AWS Configure에서 설정한 유저에대해 ECR Public Repository에 대한 권한이 없다면 denied를 반환합니다.

 

그렇기 때문에 IAM에서 유저를 하나 생성해 권한을 부여한 후 해당 액세스 키 와 시크릿 액세스 키로 AWS Configure를 설정해 주도록 하겠습니다.  IAM 콘솔 -> 사용자 -> 사용자 생성 을 클릭합니다. 사용자 이름을 적어주고 넘어갑니다. 직접 정책 연결을 클릭하고 "AmazonElasticContainerRegistryPublicFullAccess"을 지정하고 다음으로 넘어갑니다.

 

 

그리고 다음을 누르고 사용자를 생성해줍니다. 그러면 액세스 키를 발급 받지않았기 때문에 비활성화라고 나옵니다. 클릭해서 생성하도록 하겠습니다.

 

 

CLI 로 클릭해서 확인을 누르면 방금 생성한 ECR Access Key 에 대한 공개키와 비밀키가 발급됩니다. 이는 다시 확인할 수 없으니 안전한 곳에서 따로 보관해주도록합니다.

 

 

Access Key 를 발급받았으니 AWS Configure에서 설정한 유저에대해 ECR Public Repository에 대한 권한을 부여하도록 하겠습니다.

먼저, 아래 코드를 실행시켜줍니다.

 

aws configure

aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/<alias> //alias는 ECR Public에서 사용자의 고유 alias 를 의미

 

성공적으로 코드가 실행된 모습을 볼 수 있습니다.

 

 

이제 본격적인 이미지 build , push 를 진행해 보도록 하겠습니다. 규칙이 있는데 이미지의 이름은 반드시 위에서 생성한 Public Repository명으로 지정해줘야합니다. 따라서 이미지 구분을 위해 모든 서비스의 이미지명은 "public.ecr.aws/u8i2f6l2/integration/db" 로 작성해줘야합니다. 그리고 이미지 구분을 위해 tag를 서비스별로 다르게 지정해줍니다.

방금 말한대로 이미지명을 docker compose 파일에서 수정해주고 이미지 빌드를 진행해주겠습니다.

 

여기서 주의할점은 저의 도커 컴포즈 파일에 있는 서비스들을 빌드하게 되면 코드 구조상 postgres , redis는 빌드가 되지 않습니다. build 섹션이 따로 지정되어있지않기 때문입니다. 따라서 docker pull 로 해당 이미지를 외부에서 다운로드 해줍니다.

 

docker compose -f docker-compose.db.yml build //build 섹션 있는 서비스만 빌드
docker pull redis:latest
docker pull postgres:16

 

 

 

위의 과정을 거치고나면 reids, postgres 는 인터넷에서 가져온 이미지이기 때문에 name,tag 가 우리에게 필요한 형식으로 지정되어있지 않습니다.

 

 

따라서 이 부분도 수정하기 위해 코드를 조금 더 작성해주도록 하겠습니다. 

 

# redis 이미지 태그 변경
docker tag redis:latest public.ecr.aws/u8i2f6l2/integration/db:redis-latest

# postgres 이미지 태그 변경
docker tag postgres:16 public.ecr.aws/u8i2f6l2/integration/db:postgres-16

 

 

 

위의 명령어를 실행하고 나면 새로운 이미지들이 생성됩니다. 다소 번거롭긴하지만 기존 이미지들을 지워주고 새로 생성된 이미지들만 남겨줍니다. 그러면 아래처럼 로컬에 ECR 에 push 하기 위한 이미지가 모두 준비됩니다.

 

 

각 이미지들을 하단 명령어를 사용해 ECR에 push 해주도록 하겠습니다.

 

# worker 이미지 푸시
docker push public.ecr.aws/u8i2f6l2/integration/db:worker-latest

# beat 이미지 푸시
docker push public.ecr.aws/u8i2f6l2/integration/db:beat-latest

# redis 이미지 푸시
docker push public.ecr.aws/u8i2f6l2/integration/db:redis-latest

# postgres 이미지 푸시
docker push public.ecr.aws/u8i2f6l2/integration/db:postgres-16

 

 

그리고 ECR 레지스트리를 확인해보면 이미지가 성공적으로 저장되어 있는 모습을 볼 수 있습니다.

 

 

이제 다음 포스팅에서 Private subnet에 위치한 인스턴스에서 VPC EndPoint를 이용해 ECR에 있는 이미지를 가져와 실행시키는걸 해보도록 하겠습니다.

 

참고자료

https://velog.io/@seoky1219/AWS-ECR

 

https://yoo11052.tistory.com/146