Docker 입문 | 3. Docker 이미지 관리


앞에서 Dockerfile에서 이미지를 빌드하는 방법을 소개하였다. 로컬에서 빌드한 이미지는 Docker Engine에 캐시되어 있을 뿐이고 다른 사람은 사용할 수 없다. 이미지를 다른 사람이 사용할 수 있게 하려면, 이용자가 접근 할 수 있는 위치에 이미지를 공개해야 한다. Docker 회사나 AWS를 비롯한 각종 클라우드 벤더는 Docker 이미지를 관리하고 공유하는 구조로, “레지스트리"라는 서비스를 제공하고 있다. 이번에는 Docker 이미지의 레지스트리로 Docker Hub 및 AWS ECR (EC2 Container Registry)의 개요, 간단한 이미지 등록 · 취득 방법 및 팀 내에서 이미지를 관리 할 때 고려해야 할 사항에 대해 소개한다.

레지스트리에 이미지를 공유

첫째, 팀의 이미지 관리 방식에 대한 개요를 이해하기 위해, 벤더 중립적인 수준에서의 리지스토리의 개요를 소개한다. 개별 서비스에 의존하는 부분에 대해서는 서비스 별 섹션에서 설명한다.

레지스트리는 팀에서 이미지를 관리 · 공유하기 위해 주로 두 가지 역할을 제공한다.

  • 이미지 등록 및 공유
    • 이미지 저장소로 이미지를 등록 할 수 있다.
    • 다른 이용자에게 이미지를 공개 할 수 있다.
  • 이미지에 대한 액세스 제한 (인증 · 허가)
    • 특정 사람에게만 이미지의 읽기 및 쓰기를 허용한다. 다음은 레지스트리 서비스의 개념도이다.

저장소

  • “레지스트리"는 이미지를 등록하는 서비스 전체를 말한다.
  • 레지스트리에 게시할 이미지(Nginx와 Node.js 등)의 범주에 대해 “저장소"가 실제 이미지 저장소에 등록된다.
  • 저장소에 이미지를 복수 등록할 수 있고, 각 이미지는 태그로 구분된다. 버전 번호별로 이미지를 구별하고 싶은 경우 등에는 태그에 버전 번호를 지정한다. 예를 들어, Docker 공식 Node.js 이미지의 경우, 14.17.1 및 14.17.1-alpine 등으로 Node.js의 버전 번호와 Linux 배포판 등 이미지의 내용을 태그로 표현하고 있다.
    • 주의: 태그가 동일한 이미지는 덮어 쓰기버리기 때문에 저장소에 이미지를 push 할 때는 주의가 필요한다.
  • 먼저 레지스트리에 액세스 할 때 인증이 필요하다. 또한 push 및 pull 등 저장소에 대한 작업에 대한 사용자별로 접근 권한을 설정할 수 있다. 따라서 이미지를 관리하는 사람에게는 저장소에 push 권한을 부여하여 이미지를 이용하는 사람은 pull 권한을 부여하는 것이 가능하다.

Docker Hub - Docker 회사의 공식 레지스트리

다음 개별 레지스트리에 대해 설명한다. 먼저 Docker 회사가 클라우드 서비스로 제공하는 Docker Hub 을 소개한다.

Docker Hub이란?

Docker Hub는 Docker 회사가 제공하는 이미지 관리용 클라우드 서비스이다. 특징은 다음과 같다.

  • 완전 관리형
    • Docker 회사에서 관리하는 클라우드 서비스를 이고, 이를 사용하면 직접 서버를 관리할 필요가 없어진다.
  • Web UI
    • 이미지와 Docker Hub 계정 관리를 브라우저에서 할 수 있다.
  • 메타 데이터 저장소
    • 사용자 간의 의사 소통 지원을 위한 저장소에 댓글을 달거나, 스타(Facebook의 “좋아요"에 해당)을 줄 수 있다.
  • 인증 · 인가
    • 저장소에 액세스하는 다른 사용자에게 이미지의 읽기 · 쓰기 · 관리 등의 액세스 제한을 걸 수 있다.
  • 팀에서의 저장소 공유 · 관리
    • 팀에서 저장소를 공유하고 공동으로 관리 할 수 있다.
  • Webhook
    • CI/CD 환경과 연동하기 위한 Webhook을 제공한다.

Docker Hub에 이미지를 push/pull 해 보자

여기에서 실제로 공개 저장소를 만들고 해당 저장소에 이미지를 push해 보록 하자. 앞전에 빌드한 이미지를 이용할 것이기에, “Docker 이미지 빌드” 연습을 실시하지 않았다면, 먼저 실습을 하고 오길 바란다.

리포지토리 만들기

저장소를 작성하려면 Docker Hub 계정이 필요한다. Docker Hub에 접속하여 사전에 계정을 만들어야 한다.
(Docker Hub에 가입을 하면, 이메일 주소로 인증을 진행하게 된다. 인증이 완료되어야 계정 생성이 최종 완료된 것이다.)

다음 Docker Hub에 로그인 후 화면에서 “Create Repository"를 클릭하여 리포지토리 생성 화면을 표시한다. 저장소 이름은 이미지와 같은 “myfirstapp"를 지정한다. Visibility는 “public (공개)“로 해도 괜찮다.

저장소 생성

레지스트리 인증하기

저장소에 이미지를 push하기 전에 레지스트리를 인증해야 한다. username과 password를 입력하라는 메시지가 나오면, Docker Hub에 가입한 대로 입력하면 된다. Login Succeeded라고 표시되면 로그인 성공된 것이다.

% docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: devkuma
Password:
Login Succeeded

저장소에 이미지를 push한다

저장소에 push하는 이미지 이름은 “저장소 이름/이미지 이름"이라고 해야 한다. Docker Hub의 경우 저장소 이름은 계정 이름(필자의 경우 dekuma)이다.

앞에서 로컬에서 빌드한 이미지에는 저장소 이름이 명시되어 있지 않기 때문에 다음과 같은 docker tag 명령으로 Docker Hub에 push 할 별명을 설정해야 한다. 또한, 그러고 첫번째 인수에 별칭을 설정하고 싶은 “이미지 ID"를 넣고 두번째에 별칭을 지정한다. 각각 자신의 환경에 맞게 변경하면 된다.

% docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
myfirstapp   latest    ca9348c3dcd2   47 hours ago   67.7MB
% docker tag ca9348c3dcd2  devkuma/myfirstapp

docker images 이미지 목록을 표시하면 docker tag 결과 “devkuma/myfirstapp"가 추가 된 것을 확인 할수 있다. 여기서 “myfirstapp"과 “devkuma/myfirstapp"는 “IMAGE ID”(이미지 식별자)가 동일하기 때문에 모두 동일한 이미지임을 알 수 있다.

% docker images
REPOSITORY           TAG       IMAGE ID       CREATED        SIZE
devkuma/myfirstapp   latest    ca9348c3dcd2   47 hours ago   67.7MB
myfirstapp           latest    ca9348c3dcd2   47 hours ago   67.7MB

다음은 docker push 명령으로 저장소에 이미지를 push한다.

% docker push devkuma/myfirstapp
Using default tag: latest
The push refers to repository [docker.io/devkuma/myfirstapp]
59714c8e53ee: Pushed
8b0d10b320d2: Pushed
8fd4f6c343b1: Pushed
29f7edf0d8fd: Pushed
38f96c395e73: Pushed
c311a1e10929: Pushed
f566c57e6f2d: Mounted from library/alpine
latest: digest: sha256:5a06d6baf0481446a51c590099608145935d6f3e903aa2472c081fde0a12d6fe size: 1783

그럼 다시 브라우저에서 Docker Hub 대시 보드를 열고 push한 저장소 myfirstapp의 Tags(태그 목록)을 보면 태그 latest으로 이미지가 push 된 것을 확인 할수 있다. 이것은 조금 전에 push를 하여 이미지의 tag를 생략하여서 최신 이미지를 가리키는 기본 tag인 latest로 지정되었기 때문이다.

저장소에 push 된 이미지

이미지의 버전 관리 등의 목적으로 태그를 명시적으로 지정하려면 다음과 같이 이미지 이름으로 리포지토리 이름/이미지 이름:태그라고 태그를 명시적으로 넣어서 다시 push를 해보도로 하자.

% docker tag ca9348c3dcd2 devkuma/myfirstapp:0.0.1
% docker push devkuma/myfirstapp:0.0.1
The push refers to repository [docker.io/devkuma/myfirstapp]
59714c8e53ee: Layer already exists
8b0d10b320d2: Layer already exists
8fd4f6c343b1: Layer already exists
29f7edf0d8fd: Layer already exists
38f96c395e73: Layer already exists
c311a1e10929: Layer already exists
f566c57e6f2d: Layer already exists
0.0.1: digest: sha256:5a06d6baf0481446a51c590099608145935d6f3e903aa2472c081fde0a12d6fe size: 1783

다시 Docker Hub 대시 보드를 확인해 보면 TAG가 “0.0.1"인 이미지가 추가된 것을 확인 할 수 있을 것이다.

개인 저장소를 팀과 공유하려면?

지금까지는 개인의 공개 저장소에 이미지를 push하는 방법을 소개하였다. 공개 저장소이므로 다음 명령을 입력하면 누구나 이미지를 pull 받을 수 있게 된다.

% dokcer pull devkuma/myfirstapp

그다지 중요하지 않는 개인 프로젝트라면 개인 계정에 공개 저장소로 하여도 상관 없겠지만, 실제 개발은 팀의 개인 저장소를 제공하여 팀 구성원만 액세스 할 수 있게 해야 할 것이다.

Docker Hub는 비공개 저장소를 만들 수 있는데, 1개까지 무료고 그 이상은 유료이다. 요금은 Docker Hub 대시 보드에서 Pricing 페이지를 참조하도록 하자.

Docker Hub에는 다음 팀의 저장소를 만들기 위해 Organization와 Team 이라는 기능이 있다. Organization은 팀 멤버가 속한 조직을 의미하고, Team은 그 조직의 특정 역할을 가진 팀을 의미한다.

구체적인 예로서 문제를 방지하기 위해 이미지 관리자만 이미지를 push 할 수 있도록 하고, 다른 멤버는 pull만 할 수 있도록 하려면 다음과 같이 Organization 및 Team을 제공한다.

  • Organization으로 팀 구성원 모두를 등록한다. 이제 그 Organization 부하에 마련한 개인 저장소를 모든 구성원이 열람 할 수 있게 된다.
  • 이미지 관리자의 Team에 저장소에 대한 쓰기 권한을 부여하여, 그 Team에 이미지 관리자를 등록한다. 이제 이미지 관리자는 저장소에 이미지를 push를 할 수 있게 된다.
  • 이미지 이용자의 Team에 저장소에 대한 읽기 권한을 부여하여, 그 Team에 이미지 이용자로 등록한다. 이제 이미지 이용자는 저장소에 이미지를 pull를 할 수 있게 된다.

자세한 내용은 Docker 문서를 참조하도록 하자.

AWS ECR을 이용한 이미지 관리

다음 AWS에서 제공되는 이미지 저장소로 AWS ECR(EC2 Container Registry) 를 소개한다.

ECR이란?

ECR은 AWS에서 제공하는 이미지 관리용 클라우드 서비스이다. 다른 AWS 서비스와 쉽게 연동할 수 있기 때문에 AWS를 활용하고 있는 사람은 매우 사용하기 쉬운 서비스이다.

구체적으로는 다음과 같은 기능을 가지고 있다.

  • 완전 관리 형
    • AWS에서 관리 서비스로 관리되는 클라우드 서비스를 위해 직접 서버를 관리 할 필요는 없다.
  • Web UI
    • 브라우저를 사용하여 AWS 관리 콘솔에서 이미지 관리를 할 수 있다.
  • 다른 AWS 서비스와 쉽게 통합 할 수 있다.
  • 인증, 인가
    • IAM을 사용하여 이미지에 대한 인증 · 인가를 설정한다.
  • 팀에서 저장소 관리
    • 팀에서 공유 저장소를 만들 수 있다(IAM 기능을 사용하여 DockerHub의 Organization 및 Team에 해당되는 기능을 실현할 수 있다).

또한, ECR에 이용 요금은 없지만, 리포지토리에 저장하는 데이터 및 인터넷에 전송하는 데이터의 양에 따 부과된다. 자세한 내용은 요금표 를 확인하시기 바란다.

ECR에 이미지를 push/pull 해 보자

ECR을 사용하려면 다음을 사전에 준비해야 한다.

  • AWS 계정을 준비한다.
  • IAM 사용자를 생성한다.
    • 저장소에 대한 액세스는 IAM을 사용하여 인증 · 인가를 하기 위해 IAM 사용자가 필요하다. AWS 문서를 참고하여 IAM 사용자를 생성한다.
  • AWS CLI(커멘드 라인 인터페이스) 설치
    • 저장소 작업을 CLI로 수행하기 위해 AWS 문서를 참고하여 CLI를 사전에 설치한다.
    • aws configure 명령으로 키 및 지역의 설정도 하도록 한다.

주의: 이후에는 AdministratorAccess 정책이 부여된 IAM 사용자로 작업해야 한다.

레지스트리의 인증하기

이미지를 ECR에 push하려면 사전에 CLI에서 레지스트리에 대한 인증을 수행해야 한다. 인증은 Docker Hub와 동일하게 docker login 명령을 사용한다.

주의: ECR에 로그인 docker login 명령은 AWS 고유의 인증 정보를 부가 할 필요가 있고, AWS CLI 명령을 자동 생성하는 점에 주의한다.

다음 명령을 실행하여 docker login 명령을 받아온다. -region 후에는 저장소를 만들 영역을 지정한다. 로그인에 성공하면 docker login 명령이 표시된다. (참고: 아래는 인증 정보를 생략한다. 실제로 긴 문자열이 표시된다.)

$ aws ecr get-login --region us-west-2
docker login -u AWS -p xxx -e none
 https://xxx.dkr.ecr.us-west-2.amazonaws.com

다음 표시된 docker login 명령을 실행한다. 성공하면 “Login Succeeded"가 표시된다

$ docker login -u AWS -p xxx -e none
 https://xxx.dkr.ecr.us-west-2.amazonaws.com
Flag --email has been deprecated, will be removed in 1.14.
Login Succeeded

또한 AWS CLI에서 취득한 docker login 명령에는 유효 기간이 있다. 일정 시간이 서면 레지스트리에 액세스할 수 없게 되므로, 그 때는 레지스트리 다시 인증을 해야 한다.

리포지토리 만들기

이미지를 push한 후에는 대상으로 저장소를 제공한다.

브라우저에서 저장소를 만들려면 다음 단계를 수행한다.

  • https://console.aws.amazon.com/ecs/에 접속해서 AWS ECS(EC2 Container Service)의 관리 콘솔을 연다. (주의: ECR은 ECS에 통합되어 있어 이미지 관리도 ECS 관리 콘솔에서 수행한다.)
  • “저장소 설정 화면"에서 저장소 이름으로 “myfirstapp"를 입력하고 “다음 단계"를 클릭한다.
  • 저장소 URI가 표시되므로 이후의 작업에 대한 기록해 두길 바란다. URI의 형식은 계정 번호.dkr.ecr.지역 이름.amazonaws.com/저장소 이름이다.

또한 CLI에서 다음 명령을 만들 수 있다.

# aws ecr create-repository --repository-name myfirstapp
{
    "repository": {
        "registryId": "xxx",
        "repositoryName": "myfirstapp",
        "repositoryArn": "arn:aws:ecr:us-west-2:xxx:repository/myfirstapp2",
        "createdAt": 1490510283.0,
        "repositoryUri": "xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp2"
    }
}

저장소에 이미지를 push한다

저장소에 이미지를 push하려면 docker tag 명령으로 저장소 이름을 명시하는 이미지 이름의 별명을 준비해야 한다. 별칭은 관리 콘솔 또는 CLI의 응답에 표시된 저장소의 URI를 지정한다.

% docker tag myfirstapp xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp

docker push하면 이미지를 push 할수 있다.

% docker push xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp
The push refers to a repository [xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp]
17c42ed7fd27: Pushed
213ceaccd73e: Pushed
ac71ddba259e: Pushed
f8a68ba3c32d: Pushed
509e95f0d599: Pushed
3369321ad418: Pushed
23b9c7b43573: Pushed
latest: digest: sha256:7844dcb21756932f0cc93399519159f02f6c7b68f86af516d30c50b18b85d2ea size: 1783

이미지를 pull 할 때도 저장소를 명시하여 이미지 이름을 지정한다.

% docker pull xxx.dkr.ecr.us-west-2.amazonaws.com/myfirstapp

개인 저장소를 팀과 공유하려면?

DockerHub와 동일하게 팀 구성원의 IAM 사용자 그룹에 대해 IAM 정책을 설정하여 이미지 관리자 모두에게 push를 허용하고 이미지 이용자 전원에게 pull을 허용 할 수 있다.

또한, ECR의 경우 기본적으로 저장소는 비공개이므로 허용한 상대에 대해 특정 작업을 허용해 나가는 방법을 해야 한다.

구체적인 권한 설정 방법은 다음 두 가지가 있다. 모두 궁극적으로는 IAM 정책이 IAM 사용자에게 적용된다는 점에서 동일하지만, 후자의 관리 콘솔을 사용하는 방법을 초보자도 알기 쉽기에 추천한다.

  • (ECR 이외의 서비스 공통) 직접 IAM 정책을 만들고 사용자에게 연결한다.
    • 저장소에 대한 적절한 사용 권한을 설정 한 IAM 정책을 만들고 허용 할 IAM 사용자 또는 사용자 그룹에 연결한다.
    • 자세한 내용은 AWS의 문서를 참조한다.
    • 장점
      • CLI에서 실행할 수 있기 때문에 자동 설정하고 싶은 경우에 유효하다.
    • 단점
      • IAM 자체가 복잡하기 때문에 IAM 정책을 쓰고 잘못 적절한 권한을 설정할 수없는 위험이있다. 실시시 확인이 필요하다.
  • ECR (한정) ECR 관리 콘솔에서 설정
    • 실시 방법
      • ECR 관리 콘솔에서 저장소의 “액세스 권한"페이지를 열고 저장소 관리 정책을 만들 수 있다.
      • 자세한 내용은 AWS의 문서 를 참조한다.
    • 장점
      • 관리 콘솔 GUI에서 작업 할 수있다. CUI에 익숙하지 않은 사람은 알기 쉽다.
      • 사용자를 선택하고 “pull 만」· 「push와 pull”· “모든 3 개의 ‘에서 허용 할 작업을 선택할 뿐이므로, 누구에게 무엇을 허용하고 있는지 알기 쉽다.
    • 단점
      • GUI 기반이므로 자동화 어렵다.

결론

여기서는 빌드한 이미지를 공유하는 방법으로 레지스트리 서비스를 소개하였다. 또한 구체적인 레지스트리 서비스로 Docker Hub와 Amazon ECR을 소재로 저장소를 관리하고 이미지를 push하는 방법에 대해 소개하였다. 이번에는 팀 내에서 공유 할 때 액세스 권한 관리 방법은 개요만 설명했지만, 실제 프로젝트에 적용 할 때 문제를 방지하기 위해서는 적절한 저장소의 권한 정책을 수립하는 것이 중요하다. 본문에서 소개한 Docker와 AWS의 문서를 참고하고 사전에 검증한 후에 도입하기를 추천한다.