도커의 Image layer
이 글을 작성하게 된 계기는 Container를 띄울 때 Container에 생성한 파일과 디렉토리들이 어디에 저장되고 관리되는지
궁금해서 찾다가 작성하게 되었습니다.
우리는 Docker를 사용할 때 아무생각 없이 Image를 pull받아서 Docker container를 실행합니다.
Docker Image를 받아오면 sha 256으로된 hash값들이 보이고 이를 pull하면서 받오게 됩니다.
저런 hash값들의 정체가 무엇인지, Container에서 파일과 디렉토리를 생성하면 어디에 저장되는지 등을 알아보려 합니다.
1. Docker image layer
Docker image는 layer로 이루어져 있으며, 각 layer 계층은 모두 Read only로 구성됩니다.
그 후 마지막 layer 위에 Container read/write 부분의 layer가 얹어지고 실행됩니다.
이 layer에 Container에서 write된 모든 데이터들이 저장됩니다.
각 Read only layer들은 모든 Container가 공유하게 됩니다.
따라서 같은 image를 사용해 run을 하면 모두 동일한 Container를 얻을 수 있게되는 것입니다.
또한 동일한 image를 run할 때 image를 새로 받아오지 않는 이유도 다 이 때문입니다.
그럼 write layer를 찾고 실제 그 값이 있는지 확인해보겠습니다.
- Docker 안에서 파일 생성
[root@ip-172-31-11-2 overlay2]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9b771db5bd22 mysql "docker-entrypoint.s…" 16 minutes ago Up 16 minutes 3306/tcp, 33060/tcp reverent_hypatia
[root@ip-172-31-11-2 overlay2]# docker exec -it 9b77 /bin/bash
bash-4.4# ls
bin boot dev docker-entrypoint-initdb.d entrypoint.sh etc home lib lib64 media mnt mysql_test opt proc root run sbin srv sys tmp usr var
bash-4.4# mkdir mysql_test
mkdir: cannot create directory 'mysql_test': File exists
bash-4.4#
mysql_test라는 것을 미리 만들었습니다.
- Docker diff확인
[root@ip-172-31-11-2 /]# cd /var/lib/docker/overlay2/
[root@ip-172-31-11-2 overlay2]# find . -name mysql_test
./cce3680e3378e4360ffb0191c7e58399e88f41eeba9526d247ca67e423fc743c/diff/mysql_test
./cce3680e3378e4360ffb0191c7e58399e88f41eeba9526d247ca67e423fc743c/merged/mysql_test
[root@ip-172-31-11-2 overlay2]# cd cce3680e3378e4360ffb0191c7e58399e88f41eeba9526d247ca67e423fc743c
[root@ip-172-31-11-2 cce3680e3378e4360ffb0191c7e58399e88f41eeba9526d247ca67e423fc743c]# cd diff
[root@ip-172-31-11-2 diff]# ls
mysql_test root run tmp
생성한 mysql_test라는 폴더가 있습니다. 그럼 여기서 파일을 하나 만들고 도커 안에서 확인해보겠습니다.
[root@ip-172-31-11-2 diff]# ls
mysql_test root run tmp
[root@ip-172-31-11-2 diff]# cd mysql_test/
[root@ip-172-31-11-2 mysql_test]# touch test.txt
[root@ip-172-31-11-2 mysql_test]# echo "hi hwan" >> test.txt
### docker
bash-4.4# cd mysql_test/
bash-4.4# ls
test.txt
bash-4.4# cat test.txt
hi hwan
이렇게 적용되는걸 확인할 수 있습니다.
2. OverlayFS
이러한 Docker image layer구조는 OverlayFS방식으로 만들어 집니다.
OverlayFS 는 Linux 용 유니온 마운트 파일 시스템 구현 입니다. 여러 기본 마운트 지점을 하나로 결합하여 모든 소스의 기본 파일과 하위 디렉토리를 포함하는 단일 디렉토리 구조를 만듭니다.
OverlayFS구조는 Docker의 GraphDriver의 구조와 같습니다.
[root@ip-172-31-11-2 overlay2]# docker inspect mysql --format='{{json .GraphDriver.Data}}' | jq
{
"LowerDir": "/var/lib/docker/overlay2/aebbcb0830285b9c9bd00a7dbc5745ea0b48d7895979715515b76ed02a6a8d63/diff:/var/lib/docker/overlay2/7201cbff4d6dc8978d334698ee233f321acc7b4d69b4634f018e42e9099261f1/diff:/docker/overlay2/b40d888c3f7a8c558beb73d5e5a9f4c4bce4e851bbc62b281357115017ce282c/diff:/var/lib/docker/overlay2/e724909d3ed46f213a3a78053b3fff56950c8c5b55154cdaa93c789445339d9e/diff:/var/lib/docker/overlay2/2b011ffc46cddd7f6dee1c7fc92c47ff222bcc023cff40dfdf3babf0/diff:/var/lib/docker/overlay2/5f6258f78fb8660ec71bccd9f9ceb4f2456d9479cce9cc5bcbec0dbcf4771ed2/diff:/var/lib/docker/overlay2/1cbe395e249ebc7c0e592913e50983bfdc067fde255b029075ca21fa/diff:/var/lib/docker/overlay2/8930ac15d0e2fb62a4fe424e1e0b0a7f4a4e3219eec024b337cfa4b2bc6154a3/diff:/var/lib/docker/overlay2/56ba0f5f1f018bf473ca4eec4873414517257dad28e02891a553948b/diff:/var/lib/docker/overlay2/5772c70728a464d170afa8e64c79f47c45cec05570e763d0392b39144491d0ab/diff",
"MergedDir": "/var/lib/docker/overlay2/a1327e15354615cd6dd21d4577caed5a0342968556237f51f302b0dcb98bc752/merged",
"UpperDir": "/var/lib/docker/overlay2/a1327e15354615cd6dd21d4577caed5a0342968556237f51f302b0dcb98bc752/diff",
"WorkDir": "/var/lib/docker/overlay2/a1327e15354615cd6dd21d4577caed5a0342968556237f51f302b0dcb98bc752/work"
}
각 dir은 목적을 가집니다.
- lower dir: 아래쪽에 위치한 디렉토리 레이어. 여기에 위치한 entry들은 read-only로 마운트되며, 만약 수정될 경우, upper dir에 COW로 적용되고 만약 삭제될 경우 특별히 삭제됨을 표시하는 whiteout이라는 특별한 파일을 통해서 삭제됨을 기록한다.
- upper dir: 최종적으로 write권한이 있는 맨 최상위 레이어로써, 모든 수정사항, 즉 삭제와 파일의 수정은 이 upper dir에 기록된다. upper dir에서 마스킹하는 디렉토리는 하위 디렉토리에 위치해 있더라도 무시된다.
- merge dir: 모든 upper dir + lower dir이 표시되는 환경
- work dir : 통합 뷰의 원자성을 보장하기 위해 존재하는 중간 계층. Overlay를 직접 사용할 때는 크게 중요하지 않다.
mount -t overlay overlay -o lowerdir=lower1/,upperdir=upper/,workdir=work/ merge/
이렇게 mount하게 되면 다음과 같은 디렉토리 구조를 확인할 수 있습니다.
[root@ip-172-31-11-2 overlay]# tree . -I work
.
├── lower1
├── merge
└── upper
[root@ip-172-31-11-2 overlay]# touch merge/a
[root@ip-172-31-11-2 overlay]# tree . -I work
.
├── lower1
├── merge
│ └── a
└── upper
└── a
overlay로 mount 후 merge에 a라는 파일을 생성하면 upper에도 생성이 됩니다.
Docker image도 이러한 방식으로 적용되며, docker diff, docker commit 명령어를 통해서 위와 같은 동작을 확인할 수 있습니다.
Docker image를 만들땐 이러한 방식으로 layer가 추가됩니다.
Reference
http://emal.iptime.org/noriwiki/index.php/Overlayfs
https://docs.docker.com/storage/storagedriver/