본문 바로가기
DevOps/Docker

5. Docker Image

by 비어원 2022. 5. 14.
728x90

모든 도커 컨테이너는 도커 이미지로부터 생성된다. 그래서 도커를 사용하고 관리하기 위해서는 이미지를 다룰 줄 알아야 한다. 이번 장에서는 도커 이미지를 생성하고 관리하는 방법에 대하여 알아보자.

 

이미지 저장소

도커 이미지는 기본적으로 도커 허브라는 중앙 이미지 저장소에서 이미지를 내려받는다. 도커 허브는 도커가 공식적으로 제공하는 이미지 저장소로, 도커 계정을 가지고 있다면 누구든지 해당 저장소에 있는 이미지를 내려받을 수 있다. 또한, 이미지를 도커 허브로 업로드를 할 수도 있다. 도커 허브로 올린 이미지는 깃허브 오픈소스처럼 모든 사람에게 공개가 된다.

물론 도커 허브에는 개인 저장소를 제공하여 이미지를 비공개로 올릴 수 있지만 요금을 지불해야 한다. 도커 이미지 저장소를 직접 구축하여 요금을 지불하지 않고 도커 이미지를 비공개로 저장할 수도 있다. 도커 이미지 저장소는 Nexus나 Harbor 등으로 구축할 수 있다.

 

이미지 검색

도커 허브에서 자신이 원하는 도커 이미지를 검색하여 내려받을 수 있다. 도커 허브 사이트에서 원하는 도커 이미지를 검색할 수도 있지만 docker search 명령어를 통해 도커 이미지를 찾을 수도 있다.

docker search ubuntu
NAME                             DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                           Ubuntu is a Debian-based Linux operating sys…   14240     [OK]
...

 

이미지 생성

도커 이미지를 생성하는 방법은 여러가지가 있지만, 구동 중인 컨테이너의 현재 상태를 이미지로 생성하여 저장할 수 있다. 일단 다음 명령어를 통해 실습할 컨테이너를 생성한다. 그 다음, 컨테이너 내부에 아무 파일을 생성하여 기존 이미지로부터 변경사항을 만든다.

$ docker run -it \
--name commit_test \
ubuntu:14.04
root@6986b6d01b91:/# echo "seo the beer 1" >> first-message.txt

 

그 다음 컨테이너에서 빠져나와 docker commit 명령어를 입력해 현재 상태의 컨테이너를 이미지로 만든다.

# docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
$ docker commit -a "beer1" \
-m "first commit" \
commit_test \
commit_test:1.0

sha256:67994ca9da6d3e02a42f5b8798b3b2d114f7357a016486f5d5e612b3cb3b69e1
  • -a: author로 이미지의 작성자를 나타낸다.
  • -m 은 커밋 메시지를 남긴다. 깃과 유사하다.

 

docker commit 명령어 마지막에는 도커 이미지 이름이 들어간다. 참고로 도커 이미지 이름 구조에는 몇 가지 의미가 있다.

  1. {repository}/{name}:{tag} (레포지토리 이름 명시)
  2. {name}:{tag} (레포지토리 이름 X -> 도커 허브 공식 이미지 or 로컬 이미지)

 

1.0 버전으로 이미지가 커밋되었다. 이제 docker images 명령어를 통해 이미지 생성이 완료되었는지 확인해보자.

$ docker images
REPOSITORY                           TAG       IMAGE ID       CREATED              SIZE
commit_test                          1.0       67994ca9da6d   About a minute ago   197MB
ubuntu                               14.04     13b66b487594   12 months ago        197MB
...

 

그 다음 변경사항이 이미지에 잘 담겼는지 확인하기 위해 새로 생성된 이미지를 통해 컨테이너를 생성해보자.

$ docker run -it \
--name commit_test2 \
commit_test:1.0

root@c0c6f1534b9f:/# ls
bin  boot  dev  etc  first-message.txt ...

여기서 새로운 파일을 하나 더 생성하여 변경사항을 또 만들어보자. 변경사항을 만든 후 커밋을 하자.

root@c0c6f1534b9f:/# echo "seo the beer 2" >> second-message.txt
root@c0c6f1534b9f:/# exit

$ docker commit -a "beer1" \
-m "second commit" \
commit_test2 \
commit_test:1.1

sha256:a28cd0955d1dda35cc55687e0cc2588314f353703ce194c0a3ff07b32e81bc1a

 

커밋 후 도커 이미지 조회를 하면 1.1버전의 이미지도 추가된 것을 확인할 수 있다.

$ docker images
REPOSITORY                           TAG       IMAGE ID       CREATED         SIZE
commit_test                          1.1       a28cd0955d1d   8 seconds ago   197MB
commit_test                          1.0       67994ca9da6d   5 minutes ago   197MB
ubuntu                               14.04     13b66b487594   12 months ago   197MB
...

 

이미지 구조

컨테이너로 이미지를 만들 때 commit 명령어를 사용하여 만든다. 여기서 컨테이너가 어떻게 이미지로 생성되며 이미지의 구조는 어떻게 되어있는지 알아보자.

일단 다음 명령어를 통해 이미지의 세부정보를 확인해보자. 그 중 Layers 부분을 확인해보자.

$ docker inspect ubuntu:14.04 | grep Layers -C 6
...
    "Layers": [
      "sha256:f2fa9f4cf8fd0a521d40e34492b522cee3f35004047e617c75fadeb8bfd1e6b7",
      "sha256:30d3c4334a2379748937816c01f5c972a8291a5ccc958d6b33d735457a16196e",
      "sha256:83109fa660b2ed9307948505abd3c1f24c27c64009691067edb765bd3714b98d"
    ]
...
$ docker inspect commit_test:1.0 | grep Layers -C 6
...
        "Layers": [
      "sha256:f2fa9f4cf8fd0a521d40e34492b522cee3f35004047e617c75fadeb8bfd1e6b7",
      "sha256:30d3c4334a2379748937816c01f5c972a8291a5ccc958d6b33d735457a16196e",
      "sha256:83109fa660b2ed9307948505abd3c1f24c27c64009691067edb765bd3714b98d",
      "sha256:385f0684b0433d7caa70fd3fffec0b1b0633df228921da539a8164f7206dc275"
    ]
...
$ docker inspect commit_test:1.1 | grep Layers -C 6
...
        "Layers": [
      "sha256:f2fa9f4cf8fd0a521d40e34492b522cee3f35004047e617c75fadeb8bfd1e6b7",
      "sha256:30d3c4334a2379748937816c01f5c972a8291a5ccc958d6b33d735457a16196e",
      "sha256:83109fa660b2ed9307948505abd3c1f24c27c64009691067edb765bd3714b98d",
      "sha256:385f0684b0433d7caa70fd3fffec0b1b0633df228921da539a8164f7206dc275",
      "sha256:90721c7a23c054c822ab073bf2477b5fa809fb0ee52058805a79f27f345e6eab"
    ]
...

 

자세히 보면 도커 이미지는 Layer로 관리되며 기본 이미지인 ubuntu:14.04는 3개의 레이어이며 , commit_test:1.0ubuntu:14.04 에서 하나가 추가된 레이어로 구성되어있고, commit_test:1.1commit_test:1.0 에서 하나가 더 추가된 레이어로 구성되어있다. 변경사항이 하나의 레이어로 구성된다고 보면 된다.

그림으로 나타내면 다음과 같다.

 

이미지 삭제

docker rmi 명령어를 통해 생성된 이미지를 삭제할 수 있다.

$ docker rmi commit_test:1.0
Error response from daemon: conflict: unable to remove repository reference "commit_test:1.0" (must force) - container c0c6f1534b9f is using its referenced image 67994ca9da6d

 

하지만 이미지를 사용 중인 컨테이너가 존재하는 이미지는 삭제할 수 없다는 에러가 발생한다. 여기서 -f 옵션을 추가하여 이미지를 강제로 삭제할 수는 있지만 이는 이미지 레이어 파일을 실제로 삭제하지 않고 이미지 이름만 삭제하기 때문에 의미가 없다.

따라서 이미지를 완전히 삭제하려면 사용 중인 컨테이너를 삭제한 후 이미지를 삭제해야 한다.

$ docker stop commit_test2 && docker rm commit_test2
$ docker rmi commit_test:1.0

Untagged: commit_test:1.0
  • Untagged: ~~ 메시지는 이미지에 부여된 이름만 삭제한다는 것을 의미한다.

 

여기서 commit_test:1.0 이미지를 삭제를 했는데 실제로는 해당 이미지의 레이어 파일이 삭제되지는 않는다. commit_test:1.0을 base image로 둔 commit_test:1.1 이미지가 있기 때문이다. 그래서 레이어를 실제로 삭제하지는 않고 레이어에 부여된 이름을 삭제한다.

 

이번에는 commit_test:1.1 이미지를 삭제해보자.

$ docker rmi commit_test:1.1
Untagged: commit_test:1.1
Deleted: sha256:a28cd0955d1dda35cc55687e0cc2588314f353703ce194c0a3ff07b32e81bc1a
Deleted: sha256:ba71bc1f39c96905bcf09649e33156f9e68b827170ec4a635e8ae6befe9970a7
Deleted: sha256:67994ca9da6d3e02a42f5b8798b3b2d114f7357a016486f5d5e612b3cb3b69e1
Deleted: sha256:13415c99537774d6fa414dfd5c6c3f20a8e915f6b6c086abf464a5f626c96ef2

이번에는 Deleted: 라는 출력 결과가 나오는데 이는 이미지 레이어가 실제로 삭제되었음을 의미한다. 이미지의 이름을 가리키는 ID와 실제 레이어를 가리키는 ID가 삭제되었는데 실제 레이어 파일은 sha256:ba71bc1f... 라는 ID에 의해 참조된다. 즉, 삭제되는 이미지의 부모 이미지가 존재하지 않아야 해당 이미지의 파일이 실제로 삭제된다.

 

dangling

컨테이너가 사용 중인 이미지를 -f 옵션으로 강제로 삭제한다면 이미지의 이름은 <none> 으로 변경된다 이러한 이미지를 댕글링(dangling) 이미지라고 하는데, 댕글링 이미지는 docker images -f dangling=true 명령어를 사용하여 별도로 확인할 수 있다.

$ docker images -f dangling=true
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
<none>       <none>    5d5225958bcd   3 weeks ago   964MB

사용 중이지 않은 댕글링 이미지는 docker image prune 명령어를 통해 한꺼번에 정리할 수 있다.

 

이미지 추출

docker save 명령어를 통해 컨테이너의 커맨드, 이미지 이름, 태그 등 이미지의 메타데이터를 포함한 모든 정보를 하나의 파일로 추출할 수 있다.

$ docker save -o ubuntu_14_04.tar ubuntu:14.04
  • -o 옵션에는 추출될 파일 이름을 입력한다.

 

추출된 이미지는 docker load 명령어로 다시 로드할 수 있다.

$ docker load -i ubuntu_14_04.tar

 

save, load와 비슷하게 구동 중인 컨테이너의 파일시스템을 추출하고 추출된 파일을 다시 이미지로 돌려놓는 방법도 있다.

# 컨테이너의 파일시스템을 추출
$ docker export -o rootFS.tar mycontainer 

# 추출된 파일을 이미지로 저장
$ docker import rootFS.tar myimage:0.0

 

하지만 이미지를 단일 파일로 저장하는 것은 효율적이지 않는다. 추출된 이미지는 레이어 구조의 파일이 아닌 단일 파일이기 때문에 여러 버전의 이미지를 추출하게 되면 이미지 용량은 추출된 이미지 용량 그대로 차지하게 된다.

 

이미지 배포

save나 export 처럼 이미지를 파일로 추출해서 로컬에 저장할 수도 있지만 로컬이 아닌 도커 허브처럼 외부 저장소에 배포를 할 수도 있다.

도커 저장소는 (1) 도커 허브에서 제공하는 공개 저장소(2) 직접 구축하는 도커 사설 레지스트리 가 있다. 만약 도커 이미지를 비공개로 배포하고 싶다면 도커 사설 레지스트리를 구축하거나 도커 허브에서 유료로 제공하는 개인 저장소를 이용하면 된다.

먼저 도커 허브 저장소를 이용하는 방법을 알아보자.

 

  1. Create a Repository 클릭

  1. 레포지토리 정보 입력 > Create

 

저장소에 이미지 올리기

생성한 레포지토리에 이미지를 올리기 위해 테스트용 이미지를 하나 생성하자.

$ docker run -it --name pull_test ubuntu:14.04
$ docker commit pull_test docker-study:0.0

 

이미지를 커밋했다면 접두어를 하나 추가하여 이미지가 저장되는 저장소 이름을 설정하자. docker tag 명령어로 설정할 수 있다.

  • 도커 이미지 이름은 {레포지토리 이름}/{이미지 이름}:{tag} 로 구성된다.
$ docker tag docker-study:0.0 beer1/docker-study:0.0

$ docker images 
REPOSITORY                           TAG       IMAGE ID       CREATED         SIZE
beer1/docker-study                   0.0       e16d5c8d7469   3 minutes ago   197MB
docker-study                         0.0       e16d5c8d7469   3 minutes ago   197MB
...

 

그 다음은 도커 이미지를 올릴 차례인데, 공개된 도커 이미지를 받아오는 것은 누구든지 가능하지만 레포지토리에 도커 이미지를 올리기 위해서는 로그인을 하여 권한을 얻어야 한다. docker login 명령어로 로그인을 하자.

$ docker login -u {user-name}
  • 이 명령어를 입력한 후 비밀번호를 치면 로그인이 된다.

 

로그인에 성공했다면 push를 하자.

$ docker push beer1/docker-study:0.0

 

실제로 이미지가 올라갔는지 확인하려면 Tags 탭을 클릭하면 된다.

 

저장소에 있는 이미지 내려받기

docker pull 명령어로 도커 허브에 있는 공개된 이미지를 내려받을 수 있다. 이는 로그인을 하지 않아도 누구든지 가능하다.

$ docker pull beer1/docker-study:0.0

 

728x90

'DevOps > Docker' 카테고리의 다른 글

7. 도커 컨테이너 로그와 자원 할당 제한  (0) 2022.05.17
6. Dockerfile  (0) 2022.05.14
4. Docker Network  (0) 2022.05.14
3. Docker Volume  (0) 2022.04.24
2. Docker Container  (0) 2022.04.24

댓글