요 며칠 간 docker-compose 로 redis 나 mysql container 생성하는 방법을 공유했습니다.
https://kimdubi.github.io/categories/docker/
이 과정에서 Docker Image 의 중요성에 대해 새삼 다시 느끼게 되어 정리하는 시간을 가지고자…
이번 글에서는 docker의 image 에 대해 소개하겠습니다.

Docker Image

Docker 에서 가장 중요한 두 축은 Container 와 Image 라고 생각합니다.
Docker Image는 container를 띄우는데 필요한 모든 파일이나 설정값들을 포함하고 있습니다.
잘하시는 분들께 “Docker가 왜 좋아요?” 라고 물으면 종종 “dependency 꼬일 일 없이 서비스 띄울 수 있으니까”
라는 굉장히 전문가 느낌의 이해하기 어려운 답변이 돌아올 때가 있는데

Container의 독립성 + Container를 띄우는데 필요한 모든 정보를 갖고 있는 Image

두가지가 합쳐지면 위의 답변과 같은 장점이 발휘되는 것이죠
이미 Docker Image에 모든 필요한 정보가 다 있으니 추가로 설치하고 컴파일할 것이 없고
추가로 한다쳐도 Container는 독립적이니 다른 Container에 영향을 끼칠 게 없다
=> “dependency 꼬일 일 없이 서비스를 띄울 수 있다”

kimdubi:~ kimdubi$ docker search centos
NAME                               DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
centos                             The official build of CentOS.                   5763                [OK]
ansible/centos7-ansible            Ansible on Centos7                              126                                     [OK]
jdeathe/centos-ssh                 OpenSSH / Supervisor / EPEL/IUS/SCL Repos - …   114                                     [OK]
consol/centos-xfce-vnc             Centos container with "headless" VNC session…   107                                     [OK]
centos/mysql-57-centos7            MySQL 5.7 SQL database server                   67
imagine10255/centos6-lnmp-php56    centos6-lnmp-php56                              57                                      [OK]
tutum/centos                       Simple CentOS docker image with SSH access      44

docker image는 docker hub 라는 곳에서 받아옵니다 (pull)
centos, mysql, nginx 등등 정말 다양한 image 가 있으니 필요한 것을 골라 쓰면 됩니다.
그런데 의문이 하나 생깁니다.

  • 이렇게 image 가 많다면.. docker hub 는 그 수천만개의 image 를 어떻게 갖고 있는 것일까?
  • DB 하나 띄울 때마다 Image를 새로 받아온다면 그 용량은 어떻게 감당하지?

여기에서 Docker 의 장점인 “레이어 저장방식” 이 등장합니다.

어떻게 저장 되는가

위 그림에서 각각의 이미지들은 아래와 같이 정리할 수 있습니다.

  • ubuntu image = A + B + C
  • nginx image = ubuntu image + nginx
  • web_app image = nginx image + web app source

하나의 이미지 (ubuntu)는 여러개의 레이어로 구성 되고 (A+B+C)
무언가 파일이 추가되거나 수정되면 새로운 레이어(nginx) 가 생성되어 새로운 이미지 (nginx image)가 됩니다.
만약 기존에 web app image 를 사용하던 사람이 app source 부분만 수정된 wep_app 을 올려야한다면
A+B+C+ nginx + web app source_v2 모든 레이어를 다시 받아오는 게 아니라 web app source_v2 라는 새로운 레이어만 받아오면 되기 때문에 굉장히 효율적입니다.

Docker image layer 확인

기본 centos image로 centos, centos2, centos3 image 를 만들어 정말 layer 구성으로 되는지 확인해보겠습니다.

* centos image
* centos2 image = centos + a
* centos3 image = centos2 + b
  • centos image 준비
kimdubi:~ kimdubi$ docker images | grep centos
centos                    latest              67fa590cfc1c        4 months ago        202MB
  • centos container 생성
kimdubi:~ kimdubi$ docker run -d -it --name centos centos:latest
908a06abf004551684c784bf83579d93293cfc4f94e1c9978554621afd362b3d

kimdubi:~ kimdubi$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
908a06abf004        centos:latest       "/bin/bash"         14 seconds ago      Up 14 seconds                           centos
  • 파일 추가 ( 새로운 layer 추가 )
kimdubi:~ kimdubi$ de 908 /bin/bash
[root@908a06abf004 /]# fallocate -l 2G layertest
[root@908a06abf004 /]# ls -ltr layertest
-rw-r--r-- 1 root root 2147483648 Jan 10 16:17 layertest
  • 변경된 내용 commit 하여 새로운 centos2 image 생성
kimdubi:~ kimdubi$ docker commit centos centos2
sha256:505f52d32377641f5eccdce9ce28db8c00cbd623065420b250b4d418d4a1597c


kimdubi:~ kimdubi$ docker run -d -it --name centos2 centos2
f6895c211f404735b7ba5b1e2e32f44fc18e96d8ae6babe98e0f21785aa5461a

kimdubi:~ kimdubi$ de f689 /bin/bash

[root@f6895c211f40 /]# fallocate -l 2G layertest2
[root@f6895c211f40 /]# ls -ltr layertest2
-rw-r--r-- 1 root root 2147483648 Jan 10 16:19 layertest2
  • centos3 Image 도 동일하게 생성
kimdubi:~ kimdubi$ docker commit centos2 centos3
sha256:9d82b922d5e7053aee3bed1628feb87dfaa020e552932bf11ca68de9d76b518c

kimdubi:~ kimdubi$ docker run -d -it --name centos3 centos3
10fd843d74e87444503e39d53fa6eb03585e0d83eee44a095c628dfffa4072f0
  • 생성된 image 확인
kimdubi:~ kimdubi$ docker images | grep centos
centos3                   latest              9d82b922d5e7        8 minutes ago       4.5GB
centos2                   latest              505f52d32377        11 minutes ago      2.35GB
centos                    latest              67fa590cfc1c        4 months ago        202MB
  • layer 확인
kimdubi:~ kimdubi$ docker inspect 9d82b922d5e7 | grep Parent
        "Parent": "sha256:505f52d32377641f5eccdce9ce28db8c00cbd623065420b250b4d418d4a1597c",
kimdubi:~ kimdubi$ docker inspect 505f52d32377 | grep Parent
        "Parent": "sha256:67fa590cfc1c207c30b837528373f819f6262c884b7e69118d060a0c04d70ab8",

=> centos3 의 parent 는 centos2, centos2의 parent는 centos 확인

kimdubi:~ kimdubi$ docker ps -s | grep centos
10fd843d74e8        centos3             "/bin/bash"         13 seconds ago      Up 10 seconds                           centos3             0B (virtual 4.5GB)
f6895c211f40        centos2             "/bin/bash"         3 minutes ago       Up 3 minutes                            centos2             2.15GB (virtual 4.5GB)
908a06abf004        centos:latest       "/bin/bash"         5 minutes ago       Up 5 minutes                            centos              2.15GB (virtual 2.35GB)
  • centos 컨테이너의 경우 image 크기는 200MB + 생성한 파일 2.15GB
  • centos2 컨테이너의 경우 centos container + 생성한 파일 2.15GB
  • centos3 컨테이너의 경우 centos2 container + 생성한 파일 0 => size : 해당 컨테이너가 실제로 사용중인 크기
    virtual size : size + 상위 부모 이미지의 크기 => 컨테이너를 띄울 때 부모 이미지의 사이즈는 가상으로만 잡히고 실제 디스크를 차지하는 사이즈는 해당 컨테이너의 사용분 만큼임 => 용량도 image layer와 같은 개념으로 사용됨