이번장에서는 좀 더 나아가 도커 이미지의 구성 방식에 대해 좀 더 자세히 살펴보도록 하자.
유니온 파일 시스템
이미지는 컨테이너 실행에 필요한 파일과 설정값등을 포함하고 있는 것으로
상태값을 가지지 않고 변하지 않는다. (Immutable).
이는 도커 시스템이 기본적으로 유니온 파일 시스템을 사용하기 때문이다.
유니온 마운트 는 병합 마운트라고 알려진 기술로
동일한 디렉토리에 여러 파일시스템을 마운트하는 기술이다.
핵심은 "먼저 마운트된 것을 살려둔 상태로 추가적으로 마운트하는 것"
으로 겹치는 것(폴더, 파일)이 있으면 나중 것을 덮어쓴다.
간단히 아래와 같이 /mnt 폴더를 유니온 마운트 하였다고 가정해 보자.
$ mount /dev/sdb /mnt
$ mount --union /dev/sdc /mnt
|
각각의 폴더에는 아래와 같이 파일을 추가하면 sdb 추가후 sdc 와 같이 추가하였다면
그 결과는 아래와 같다.
도커 이미지에서 위의 sdb 를 상위 레이어 , sdc 폴더를 하위 레이어라고 한다.
COW ( Copy-On-Write )
하지만 위와 같이 유니온 파일 시스템만 사용한다면 file-b1 이나 link1 같은 경우에
기존 데이터를 찾을 수 없을 것이다.
따라서 도커 이미지는 COW (Copy-On-Write) 기능을 사용한 하며 이는 간단히
하위 레이어에서 상위 레이어에 위치한 파일을 수정해야 할 때 기존 파일을 복사후 수정 하는 전략이다.
이렇게 하면 변경된 파일만 저장되므로
하위 레이어에 저장되는 파일은 새로 추가된 파일 및 기존 레이어에 있으나 수정된 파일들 뿐일 것이다.
그렇기 때문에 최초에 상위 레이어를 포함하는 이미지를 받을 때는 시간이 걸리지만 이후 상위 버전의
이미지를 받을 때는 변경 및 추가된 파일들만 받게 되므로 시간이 오래 걸리지 않게 된다.
도커 레이어
도커의 이미지는 여러개의 읽기 전용 read only 레이어로 구성되고
파일이 추가되거나 수정되면 새로운 레이어가 생성된다.
(하위 레이어를 추가해도 COW 를 사용하기 때문에
기존 상위 레이어에 파일에 대한 변경은 일어나지 않고
복사후 수정되기 때문에 상위 레이어가 Read Only 가 된다.)
예로 ubuntu 이미지가 A + B + C의 집합이라면,
ubuntu 이미지를 베이스로 만든 nginx 이미지는 A + B + C + nginx가 된다.
webapp 이미지를 nginx 이미지 기반으로 만들었다면
예상대로 A + B + C + nginx + source 레이어로 구성된다.
webapp 소스를 수정하면 A, B, C, nginx 레이어를 제외한 새로운 source(v2) 레이어만 다운받으면 되기 때문에
굉장히 효율적으로 이미지를 관리할 수 있다.
컨테이너를 생성할 때도 레이어 방식을 사용하는데
기존의 이미지 레이어 위에 읽기/쓰기 read-write 레이어를 추가한다.
이미지 레이어를 그대로 사용하면서 컨테이너가 실행중에 생성하는 파일이나 변경된 내용은
읽기/쓰기 레이어에 저장되므로 여러개의 컨테이너를 생성해도 최소한의 용량만 사용한다.
가상화의 특성상 이미지 용량이 크고 여러대의 서버에 배포하는걸 감안하면
단순하지만 엄청나게 영리한 설계이다.
docker history
docker history 명령을 입력하면 이미지를 구성하는 Layer 를 확인할 수 있다.
최초 55.3 MB 데이터에 해당하는 레이어가 OS 에 해당하는 레이어이며
apt-get 을 사용해서 nginx 를 설치하는 53.7 MB 짜리 레이어도 있고
nignx 를 구성하기 위한 환경을 설정하는 ENV 레이어 들도 보인다.
그리고 nginx 를 docker pull 명령으로 다운 받으면 해당 레이어들은 로컬 캐시에 저장되며
다른 이미지를 다운시 이 이미지가 동일한 레이어를 사용한다면 로컬 캐싱된 레이어를 가져다 쓰며
(아래 화면에서 nginx 및 mysql 의 OS 이미지가 동일한 것을 확인할 수 있다)
nginx 이미지를 컨테이너 1, 컨테이너 2, 컨테이너 3 이렇게 실행하는 경우
각 컨테이너는 각각의 레이어를 가지며 COW 를 사용해서 기존 이미지에서 수정되는 부분이 Copy-On-Write 된다.
docker image inspect
이미지에 대한 환경 구성을 확인하고자 하는 경우에는 docker image inspect 명령을 사용한다.
JSON 포멧으로 이미지 구성 정보를 확인할 수 있다.
$ docker image inspect nginx
[
{
"Id": "sha256:ae513a47849c895a155ddfb868d6ba247f60240ec8495482eca74c4a2c13a881",
"RepoTags": [
"nginx:latest"
],
"RepoDigests": [
"nginx@sha256:0fb320e2a1b1620b4905facb3447e3d84ad36da0b2c8aa8fe3a5a81d1187b884"
],
"Parent": "",
"Comment": "",
"Created": "2018-04-30T13:55:45.019400581Z",
"Container": "0ef39071559eb65fbe2a265267bde365d9c1abd07e073f4c5ba8e597eaf4b67b",
"ContainerConfig": {
"Hostname": "0ef39071559e",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": { => 어떤 포트를 열어야 하는지 확인할 수 있다.
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [ => nginx 의 버전 정보와 PATH 설정 정보를 얻을 수 있다.
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.13.12-1~stretch",
"NJS_VERSION=1.13.12.0.2.0-1~stretch"
],
"Cmd": [ => 디폴트로 시작할 때의 커맨드를 확인할 수 있다.
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"nginx\" \"-g\" \"daemon off;\"]"
],
"ArgsEscaped": true,
"Image": "sha256:c8f4442c599dff3a115ef8d89402c826d90541769c2b31bb2f5473c94e5db945",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": [],
"Labels": {
},
"StopSignal": "SIGTERM"
},
"DockerVersion": "17.06.2-ce",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.13.12-1~stretch",
"NJS_VERSION=1.13.12.0.2.0-1~stretch"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"ArgsEscaped": true,
"Image": "sha256:c8f4442c599dff3a115ef8d89402c826d90541769c2b31bb2f5473c94e5db945",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": [],
"Labels": {
},
"StopSignal": "SIGTERM"
},
"Architecture": "amd64", => 기반이 되는 OS 정보를 확인할 수 있다.
"Os": "linux",
"Size": 108958610,
"VirtualSize": 108958610,
"GraphDriver": {
"Data": null,
"Name": "aufs"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:d626a8ad97a1f9c1f2c4db3814751ada64f60aed927764a3f994fcd88363b659",
"sha256:82b81d779f8352b20e52295afc6d0eab7e61c0ec7af96d85b8cda7800285d97d",
"sha256:7ab428981537aa7d0c79bc1acbf208c71e57d9678f7deca4267cc03fba26b9c8"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
|
'Container > Docker' 카테고리의 다른 글
10. Docker Image 생성 (도커파일) (0) | 2020.01.14 |
---|---|
09. Docker Image 생성 (기존이미지 사용) (0) | 2020.01.14 |
07. Docker Image (0) | 2020.01.14 |
06. Docker Run (0) | 2020.01.14 |
04. Docker CE 설치하기 (0) | 2020.01.14 |