땡글이LAB

[도커/쿠버네티스] 도커 이미지 생성, 추출, 배포 본문

Devops/도커, 쿠버네티스

[도커/쿠버네티스] 도커 이미지 생성, 추출, 배포

땡글이B 2022. 7. 18. 20:55

 모든 컨테이너는 이미지를 기반으로 생성되며 이미지를 다루는 방법은 도커 관리에서 빼놓을 수 없는 부분이다. 이미지의 이름을 구성하는 저장소, 이미지 이름, 태그를 잘 관리하는 것 뿐만 아니라, 이미지가 어떻게 생성되고 삭제되는지 이미지의 구조는 어떻게 돼 있는지 등을 아는 것 또한 중요하다. 이번 장에서는 이미지를 관리하는 기본적인 방법을 알아본다.

 

 Debian 운영체제에서 apt-get install 을 실행하면 apt 리포지토리에서 패키지를 내려받고 RedHat 운영체제에서 yum install 을 실행하면 yum 리포지토리에서 패키지를 내려받듯이 도커는 기본적으로 도커 허브(Docker Hub)라는 중앙 이미지 저장소에서 이미지를 내려받는다. 도커 허브는 도커가 공식적으로 제공하고 있는 이미지 저장소로서, 도커 계정을 가지고 있다면 누구든지 이미지를 올리고 내려받을 수 있기 때문에 다른 사람들에게 이미지를 쉽게 공유할 수 있다.

 

docker create, docker run, docker pull의 명령어로 이미지를 내려받았을 때, 도커는 도커 허브에서 해당 이미지를 검색한 뒤 내려받는다. 필요한 대부분의 이미지는 도커 허브에서 공식적으로 제공하거나 다른 사람들이 도커 허브에 이미 올려놓은 경우가 대부분이라서 애플리케이션 이미지를 직접 만들지 않아도 손쉽게 사용할 수 있다는 장점이 있다.

  • 단, 도커 허브는 누구나 이미지를 올릴 수 있기에 공식(Official) 라벨이 없는 이미지는 사용법을 찾을 수 없거나 제대로 동작하지 않을 수 있다.

 

 도커 허브에 어떤 이미지가 있는지 확인하기 위해 도커 허브 사이트를 직접 접속해서 찾아볼 수도 있지만 도커 엔진에서 docker search 명령어를 사용할 수도 있다. 예를 들어, ubuntu 라는 키워드와 관련된 이미지는 어떤 것이 있는지 검색해본다.

 

도커 이미지 생성

 앞에서 docker search 를 통해 검색한 이미지를 pull 명령어로 내려받아 사용할 수도 있지만, 도커로 개발하는 경우에는 컨테이너에 애플리케이션을 위한 특정 개발 환경을 직접 구축한 뒤, 사용자만의 이미지를 직접 생성해야 할 것이다. 이를 위해 컨테이너 안에서 작업한 내용을 이미지로 만드는 방법을 먼저 설명하겠다. 

 

// 컨테이너 생성(추후 이미지로 만들 컨테이너임)
$ docker run -i -t --name commit_test ubuntu:14.04

$ echo test_first!! >> first
$ docker commit \
-a "bog" -m "my first commit" \
commit_test \
commit_test:first

 위의 명령어에서 이미지의 이름을 "commit_test"로, 태그를 "first"로 설정했다. -a는 author 을 뜻하며, 이미지의 작성자를 나타내는 메타데이터를 이미지에 포함시킨다. commit_test:first 이미지의 작성자 데이터는 "bog"로 설정될 것이다. -m 옵션은 커밋 메시지를 뜻하고 이미지에 포함될 부가 설명을 입력한다.

 

 docker commit 명령어의 형식은 다음과 같다.

$ docker commit [OPTIONS] CONTAINER [REPOSITORY:TAG]

// 즉, "docker commit [옵션들] [컨테이너명] [원하는 이미지명:태그]" 이다

 

 

 최상위 디렉터리에 first라는 파일이 있는 도커 이미지가 생성됐다. docker images 명령어로 확인해본다. 

 

 이번에는 commit_test:first 이미지로 새로운 이미지를 생성해본다. commit_test:first 이미지로 컨테이너를 생성한 뒤, second라는 파일을 추가해 commit_test:second 라는 이미지를 새롭게 생성한다. 이미지를 생성하는 과정은 commit_test:first 이미지를 생성할 때와 같다.

$ docker run -i -t --name commit_test2 commit_test:first
$ docker commit \
-a "bog" -m "my second commit" \
commit_test2 \
commit_test:second

 위의 명령어로 다시 한 번 commit을 해서 새로운 이미지를 만들어본다. 아까와 같이 docker images 명령어로 이미지를 확인해보면, 이미지가 잘 생성된 것을 확인할 수 있다.

 

도커 이미지 구조 이해

 위와 같이 컨테이너를 이미지로 만드는 작업은 commit 명령어로 쉽게 수행할 수 있다. 그러나 이미지를 좀 더 효율적으로 다루기 위해 컨테이너가 어떻게 이미지로 만들어지며, 이미지의 구조는 어떻게 돼 있는지 알 필요가 있다. 다음 명령어를 입력해 이미지의 좀 더 자세한 정보를 확인해본다.

$ docker inspect ubuntu:14.04

$ docker inspect commit_test:first

$ docker inspect commit_test:second

 위 명령어들을 실행해보면, "Layers" 항목만을 보면 이미지 layer들이 쌓이는 것을 확인할 수 있다. 그림으로 나타내면 아래와 같다.

 

 이제 컨테이너를 중단시키고 컨테이너 삭제하고, 마지막으로 이미지를 삭제해본다.

$ docker stop commit_test2 && docker rm commit_test2

$ docker rmi commit_test:first

$ docker rmi commit_test:second

 "Deleted:"라는 출력결과는 이미지 레이어가 실제로 삭제됐음을 뜻한다. 이미지의 이름인 commit_test:second 를 가리키는 ID와 실제 레이어를 가리키는 ID가 삭제됐는데 실제 레이어파일은 sha256:8d5b9a....라는 ID에 의해 참조된다. 즉, 삭제되는 이미지의 부모 이미지가 존재하지 않아야만 해당 이미지의 파일이 실제로 삭제된다.

 

 그렇지만 commit_test:second 이미지를 삭제했다고 해서 ubuntu:14.04 이미지도 함께 삭제되는 것은 아니다. 앞에서는 second, first 파일이 존재하는 레이어만 삭제됐는데, commit_test:first 이미지 태그는 이미 삭제되어 존재하지 않지만 우분투 이미지를 가리키는 ubuntu:14.04 이미지 태그는 아직 존재하기 때문이다. 

 따라서 ubuntu 이미지의 레이어는 commit_test:second 이미지를 삭제할 때 함께 삭제되는 레이어의 범위에 포함되지 않는다. 

 

 

도커 이미지 추출

 도커 이미지를 별도로 저장하거나 옮기는 등 필요에 따라 이미지를 단일 바이너리 파일로 저장해야할 때가 있다. docker save 명령어를 사용하면 컨테이너의 커맨드, 이미지 이름과 태그 등 이미지의 모든 메타데이터를 포함해 하나의 파일로 추출할 수 있다. -o 옵션에는 추출될 파일명을 입력한다.

  • 메타데이터는 시간이 지남에 따라 많은 양의 데이터를 수집, 저장 및 분석할 수 있도록 일관된 방식으로 구조화된, 다른 데이터를 설명하는 데이터이다. 

 

$ docker save -o ubuntu_14_04.tar ubuntu:14.04

 

  추출된 이미지는 load 명령어로 도커에 다시 로드할 수 있다. save 명령어로 추출된 이미지는 이미지의 모든 메타데이터를 포함하기 때문에 load 명령어로 이미지를 로드하면 이전의 이미지와 완전히 동일한 이미지가 도커 엔진에 생성된다.

 

 save, load 명령어와 유사하게 사용할 수 있는 명령어로 export, import가 있다. docker commit 명령어로 컨테이너를 이미지로 만들면 컨테이너에서 변경된 사항뿐만 아니라 컨테이너가 생성될 때 detached 모드, 컨테이너 커맨드와 같은 컨테이너의 설정 등도 이미지에 함께 저장된다. 그러나 export 명령어는 컨테이너의 파일 시스템을 tar 파일로 추출하며 컨테이너 및 이미지에 대한 설정 정보를 저장하지 않는다.

 

 

도커 이미지 배포

 이미지를 생성했다면, 이를 다른 도커 엔진에 배포할 방법이 필요하다. save나 export와 같은 방법으로 이미지를 단일 파일로 추출해서 배포할 수 있지만 이미지의 파일 크기가 너무 크거나 도커 엔진의 수가 많다면 이미지를 파일로 배포하기 어렵다. 또한 도커의 이미지 구조인 레이어 형태를 이용하지 않으므로 매우 비효율적이다.

 

 이를 해결하는 첫 번째 방법은 도커에서 제공하는 도커 허브(Docker Hub) 이미지 저장소를 이용하는 것이다. 도커 허브는 도커 이미지를 저장하기 위한 클라우드 서비스라고 생각하면 이해하기 쉽다. 사용자는 단지 이미지를 올리고, 내려받기만 하면 되므로 매우 간단하게 사용할 수 있다. 

 

 두 번째 방법은 도커 사설 레지스트리(Docker Private Registry)를 사용하는 것으로서 사용자가 직접 이미지 저장소를 만들 수 있다. 그러나 사용자가 직접 이미지 저장소 및 사용되는 서버, 저장 공간 등을 관리해야 하므로 도커 허브보다는 사용법이 까다롭다. 그러나 회사의 내부망과 같은 곳에서 도커 이미지를 배포해야 한다면 도커 사설 레지스트리가 더 좋은 방안이 될 수 있다. 

 

 

도커 허브 저장소 (Docker Hub)

 도커 허브에 이미지를 올리기 위해 내 저장소를 생성해본다. 로그인한 뒤, 오른쪽 상단의 "Create Repository" 버튼을 클릭한다. 

 도커 허브 저장소 생성 성공!

 

저장소에 이미지 올리기

 방금 생성한 저장소에 이미지를 올려보도록 한다. 도커에서 다음 명령어를 입력해 저장소에 올릴 이미지를 생성한다. 

$ docker run -i -t --name commit_container1 ubuntu:14.04

$ docker commit commit_container1 my-image-name:0.0

 그러나 이 이름으로는 이미지를 저장소에 올릴 수 없다. 이미지 이름의 접두어는 이미지가 저장되는 저장소 이름으로 설정한다. 즉, 특정 이름의 이미지를 올리려면, 저장소 이름(사용자의 이름)을 이미지 앞에 접두어로 추가해주어야 한다. 

$ docker tag my-image-name:0.0 bohub12/my-image-name:0.0

 

 이미지 이름을 변경하고 나면 다음 명령어를 입력해 도커 허브 서버에 로그인한다. 로그인하지 않으면 생성한 저장소에 이미지를 올릴 수 있는 권한을 가질 수 없다. 회원 가입을 할 때 사용한 아이디와 비밀번호를 입력한다.

 

 도커 허브 서버에 로그인할 때는 "docker login" 명령어를 통해 한다. 로그아웃을 원하면 "docker logout"을 입력하면 된다.

 

 로그인 한 뒤에는, docker push [도커허브ID]/[이미지이름]:[태그] 형식으로 이미지를 저장소에 올린다.

$ docker push bohub12/my-image-name:0.0

 

이제 도커 허버의 저장소에 실제로 이미지가 올려졌는지 확인한다. Tags 항목에서 확인 가능하다.

 

 도커에서 이 이미지를 내려받으려면 별도로 로그인하지 않고 다음 명령어를 입력하면 된다.

$ docker pull bohub12/my-image-name:0.0

 

저장소 웹 훅(Webhook) 추가

 저장소에 이미지가 push 됐을 때 특정 URL로 http 요청을 전송하도록 설정할 수 있는데, 이 기능을 웹훅(Webhook)이라고 한다. 도커 허브의 웹훅 기능은 저장소에 새로운 이미지가 생성됐을 때 지정된 URL로 해당 이미지의 정보와 함께 http 요청을 전송한다.

 

 이 기능은 저장소에 추가된 새로운 이미지를 각 서버에 배포하는 애플리케이션을 작성할 때 유용하게 활용될 수 있다. 

 

 

도커 사설 레지스트리(Docker Private Registry)

 도커 사설 레지스트리를 사용하면 개인 서버에 이미지를 저장할 수 있는 저장소를 만들 수 있다. 이 레지스트리는 컨테이너로서 구현되므로 이에 해당하는 도커 이미지가 존재한다. 이 이미지는 도커에서 공식적으로 제공하고 있기 때문에 아래의 run 명령어로 간단히 사용할 수 있다.

 

$ docker run -d --name myregistry \
-p 5000:5000 \
--restart=always \
registry:2.6
  • --restart 옵션은 컨테이너가 종료됐을 때 재시작에 대한 정책을 설정하는 옵션이다. always는 컨테이너가 정지될 때마다 다시 시작하도록 설정하기 때문에 도커 호스트나 도커 엔진을 재시작하면 컨테이너도 함께 재시작된다.

 

레지스트리 컨테이너는 기본적으로 5000번 포트를 사용하므로 -p 옵션으로 컨테이너의 5000번 포트를 호스트의 5000번 포트와 연결했으며, 이 포트로 레지스트리 컨테이너의 RESTful API를 사용할 수 있다. 다음 명령어를 입력해 레지스트리 컨테이너가 정상적으로 작동하는지 확인한다. curl 은 HTTP 요청을 보내는 도구 중 하나이며, 어느 도구를 사용해도 상관없다. 

 

Private Registry에 이미지 Push하기

$ docker tag my-image-name:0.0 ${DOCKER_HOST_IP}:5000/my-image-name:0.0

$ docker push 192.168.99.101:5000/my-image-name:0.0
  • 위와 같이 push하게 되면, 오류가 난다. "vi /etc/default/docker"를 통해 DOCKER_OPTS="--insecure-registry=192.168.99.101:5000" 이라고 입력해서 테스트 용도로 HTTPS를 사용하지 않아도 이미지를 push, pull할 수 있게 해준다. 

 

추후에 Private Registry에 대해서 자세히 다루겠습니다 :)

 

 

References

 

시작하세요! 도커/쿠버네티스 - 교보문고

친절한 설명으로 쉽게 이해하는 컨테이너 관리 | ★ 이 책의 구성 ★◎ 도커의 기본 사용 방법을 익힘으로써 컨테이너의 기본 개념을 학습합니다. (1부 1장, 1부 2장)◎ 도커 스웜 모드를 통해 서

www.kyobobook.co.kr

 

도커 이미지 빌드와 Dockerfile 기초

도커(Docker)에서 이미지 빌드는 컨테이너와 함께 가장 중요한 개념입니다. 이미지는 컨테이너의 기반이 되는 파일들의 집합입니다. 사용자는 리눅스 배포판 이미지를 기반으로 자유롭게 프로비

www.44bits.io

Comments