👉 이 게시글은 도커 / 쿠버네티스 온라인 부트캠프 with 카카오엔터프라이즈 강의를 바탕으로 작성되었습니다.
이전 포스트에서 다루었던 내용들은 dockerfile을 통해 이미지를 build하고, 해당 이미지를 바탕으로 container를 실행하는 방법에 관한 것이었다. 이번에는 dockerfile을 통해 생성된 이미지를 도커 레지스트리에 ship(공개)하는 방법에 대해 다뤄보도록 하자.
도커 레지스트리는 도커 이미지를 관리하는 일종의 저장소이다. 위의 이미지에서 빨간 테두리로 표시된 부분이 도커 레지스트리에 해당된다. 대표적으로 dockerhub가 있으며, AWS, GCP와 같은 메이저 클라우드 사업자 또한 컨테이너 레지스트리로 불리는 이미지를 보관할 수 있는 저장소를 제공하고 있다. AWS에는 Amazon Elastic Container Registry (Amazon ECR), GCP에는Artifact Registry가 있으며, Azure와 Oracle도 동일한 서비스를 제공한다.
그런데 왜 dockerhub라는 대규모 레지스트리 플랫폼이 존재하는데, 굳이 클라우드 사업자가 제공하는 레지스트리를 사용하는 것일까?
첫 번째 이유는 보안이다. 서비스되고 있는 이미지에 보안상 중요한 내용이 담겨있는 경우, 기업 입장에서는 이를 철저히 관리할 방안을 찾을 수밖에 없다. 클라우드 사업자는 IAM (Identity and Access Management)을 통해 서비스 계정에 대한 접근 권한을 관리한다. 또한 토큰 인증, 이미지 암호화같은 보안에 관련된 전반적인 서비스를 클라우드 사업자가 담당하기 때문에 클라우드 사업자의 플랫폼을 이용하는 경우가 많다.
두 번째 이유는 CI/CD이다.
CI는 Continuous Integration의 약자로, 지속적 통합을 의미한다. 빌드와 테스트가 자동으로 수행되고 난 후 개발자가 수정 사항을 저장소에 정기적으로 merge하는 과정을 뜻하며, 이러한 자동화 서비스와 개발 문화를 포괄한 개념이다. 신속한 디버깅과 버그의 조기 탐지, 사용자에게 더 나은 서비스 경험을 제공하는 것을 목적으로 한다.
CD는 Continuous Delivery의 약자로, 지속적 전달을 의미한다. 운영 환경에 배포할 소스코드가 자동으로 세팅되며, 빌드 이후 변경 사항을 테스트 및 운영 서버에 배포하는 과정을 의미한다. 이를 통해 테스트 환경을 동적으로 생성할 수 있고, 배포 자동화를 통한 효율성 증대를 도모할 수 있다.
요약하면, 클라우드 사업자는 이 모든 환경을 한꺼번에 관리해주는 배포 파이프라인을 제공한다. 즉, 소스 코드를 작성하고, 소스 코드로부터 이미지를 빌드하고, 이미지를 각각 테스트 환경, 운영 환경에 배포하는 일련의 과정이 자동화되는 것이다. 따라서 개발자는 클라우드 사업자의 레지스트리를 사용함으로써 효율적으로 서비스를 운영할 수 있다.
먼저 dockerhub 공식 사이트에 접속하여 계정을 생성한 후 로그인을 완료하면 다음과 같은 화면이 나올 것이다.
해당 페이지에서 Create Repository를 눌러 이미지를 저장할 수 있는 저장소를 생성한다.
Name 란에 저장소명을 입력하고, Visibility 옵션 통해 업로드한 이미지를 검색 엔진에 노출시킬지 아닐지를 결정한다. 무료 계정의 경우 private repository를 한 개만 이용할 수 있다.
repository name을 입력하고 Create 버튼을 누르면 위와 같은 페이지가 나온다. 여기까지 dockerhub의 개인 계정에 이미지 저장소를 생성하는 방법에 대해 알아보았다.
저장소를 생성하였으니, 이제 해당 저장소에 도커 이미지를 push해보도록 하자.
먼저, 다음 명령어를 통해 터미널에서 dockerhub에 본인의 계정을 연동한다.
$ docker login
dockerfile이 존재하는 디렉토리에서 build 명령어를 통해 이미지를 빌드한다. 자신의 레파지토리에 이미지를 올리기 위해서는 꼭 다음과 같은 양식에 맞춰 빌드를 실행하여야 한다.
$ docker build -t <dockerhub username>/<레파지토리명:태그명> .
이제, 생성된 이미지를 push 명령어를 통해 레파지토리에 업로드한다.
$ docker push <dockerhub username>/<레파지토리명:태그명>
push가 완료되면 레지스트리에서 부여한 고유 문자열인 digest가 출력된다. 즉, 도커 레파지토리에 이미지가 정상적으로 올라갔다는 것을 의미한다. 다시 dockerhub로 돌아가서, 저장소 페이지를 들어가보자.
Tags and Scans 항목에 하나의 태그가 생성된 것을 확인할 수 있다. 해당 태그를 클릭해보면,
좌측에 dockerfile 빌드 과정에서 생성된 이미지 layer가 출력되며, layer별로 각각 어떤 명령어를 수행하였는지 확인이 가능하다.
지금까지는 dockerhub와 같은 외부 환경에서 레지스트리를 생성하고 이미지를 업로드 하였다. 하지만 로컬 환경에 도커 레지스트리를 구축하는 방법 또한 존재한다. 도커 레지스트리의 역할을 하는 컨테이너를 별도로 실행하고, 해당 컨테이너에서 이미지에 대한 push, pull 작업을 실행할 수 있다.
dockerhub에서 registry를 검색하면, 위와 같은 Official Image가 나온다. 해당 이미지를 기반으로 컨테이너를 실행하여 로컬 환경에서 도커 레지스트리를 구축해보도록 하자.
공식 문서에 따르면, 해당 이미지를 통해 로컬 레지스트리를 구축하는 명령어는 다음과 같다.
$ docker run -d -p 5000:5000 --restart always --name registry registry:2
위 명령어를 실행 후 docker ps 명령어를 통해 실행중인 컨테이너를 확인해보도록 하자.
registry:2 이미지를 기반으로 registry라는 이름의 컨테이너가 5000번 포트에 할당되어 실행중인 것을 확인할 수 있다.
즉, 해당 컨테이너가 로컬 환경에서 도커 레지스트리 역할을 하는 것이다.
해당 레지스트리에 이미지를 push하기 위해서는 tag 명령어를 통해 dockerhub에 이미지를 push할 때와 마찬가지로 양식에 맞게 변경해주어야 한다.
$ docker tag <레파지토리명:태그명> localhost:5000/<레파지토리명:태그명>
위 양식에 맞춰 이미지명을 다음과 같이 변경해서 로컬 레지스트리가 해당 이미지를 인식할 수 있도록 만들어준다.
apache2:1.1 → localhost:5000/apache2:1.1
jkseo/apache2:1.1 → localhost:5000/apache2:1.1
jkseo/web/apache2:1.1 → localhost:5000/apache2:1.1
이미지명을 변경한 뒤에 push 명령어로 로컬 레지스트리에 push하는 작업을 수행한다.
digest가 출력되었으면 정상적으로 로컬 레지스트리에 이미지가 push된 것이다.
추가적으로, 로컬 레지스트리에 저장된 이미지를 pull하기 위해서는 어떻게 해야 할까?
$ docker image pull localhost:5000/<레파지토리명:태그명>
매우 간단하다. 기존에 로컬 레지스트리에 저장한 이미지명을 pull 명령어로 받아오기만 하면 된다.
이미지가 정상적으로 다운로드된 것을 확인할 수 있다.
very나이스한 글이네요 도커 어렵다고 생각했는데, 정리 잘 하셨네요...!