이 문서를 통해 네임스페이스, C그룹, Rootfs의 세 가지 핵심 기능을 포함하여 Docker 컨테이너의 핵심 구현 원칙에 대해 배울 수 있습니다.
다음 글에서 간단한 Docker를 처음부터 구현하는 방법을 보여드릴 예정이므로 여기서는 Docker의 핵심 원칙을 간략히 살펴보겠습니다.
먼저 컨테이너가 프로세스와 어떻게 다른지 생각해 보세요.
- 프로세스: 프로그램이 실행된 후 컴퓨터 실행 환경의 합계입니다.
즉, 컴퓨터 메모리의 데이터, 레지스터의 값, 스택의 명령어, 열린 파일 및 다양한 장치에 대한 상태 정보의 모음입니다.
- 컨테이너: 컨테이너의핵심은 프로세스의 동적 동작을 제한하고 수정하여 프로세스의 '경계'를 만드는 것입니다.
Docker와 같은 대부분의 Linux 컨테이너에서 Cgroups 기법은 제약 조건을 만드는 데 사용되는 기본 수단이며, 네임스페이스 기법은 프로세스 보기를 수정하는 데 사용되는 기본 방법입니다.
네임스페이스 기반 보기 격리
docker run -it으로 컨테이너를 시작하고 들어가면 다음과 같이 프로세스, 네트워크 및 파일 시스템이 격리되어 있는 것을 볼 수 있습니다:
[root@docker cpu]# docker run -it busybox
/ #
/ # ps
PID USER TIME COMMAND
1 root 0:00 NY
7 root 0:00 ps
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet .1/8 scope host lo
valid_lft forever preferred_lft forever
120: eth0@if121: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet .2/16 brd 5.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ls
bin dev etc home lib lib64 proc root sys tmp usr var
- ps 명령에 호스트 컴퓨터의 프로세스가 표시되지 않습니다.
- IP 명령은 컨테이너 내부의 네트워크 카드만 볼 수도 있습니다.
- 또한 ls 명령은 호스트와 다른 파일을 표시하는 것 같습니다.
이는 Linux 네임스페이스 기술을 통해 보기 격리를 가능하게 하는 Docker의 핵심 기능 중 하나입니다.
컨테이너가 호스트에서 격리된 것처럼 보입니다.
Linux에서는 격리의 속성에 따라 네임스페이스가 다릅니다:
- )PID Namespace
- 2) 네임스페이스 마운트
- )UTS Namespace
- )IPC Namespace
- 5) 네트워크 네임스페이스
- 6) 사용자 네임스페이스
다른 리소스의 격리는 다른 유형의 네임스페이스를 통해 달성할 수 있습니다. 예를 들어, 이전 IP a는 컨테이너의 네트워크 카드 정보만 볼 수 있으며, 이는 네트워크 네임스페이스를 통해 격리됩니다.
그러나 Linux 네임스페이스 기술은 실제로 전체 컴퓨터에 대한 애플리케이션 프로세스의 보기를 수정합니다. 즉, 운영 체제에 의해 특정 지정된 콘텐츠만 '보기' 위해 보기가 제한됩니다. "특정 지정된 콘텐츠만.
다음과 같이 해당 네임스페이스로 이동하기만 하면 이러한 고립에서 벗어날 수 있습니다:
먼저 바쁨 상자를 시작한 다음, ip a를 사용하여 네트워크 카드 정보를 확인합니다.
[root@docker ~]# docker run --rm -it busybox /bin/sh
/ #
/ # ip a show eth0
116: eth0@if117: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet .2/16 brd 5.255 scope global eth0
valid_lft forever preferred_lft forever
컨테이너의 IP는 172.17.0.2입니다.
그런 다음 새 터미널:: nsenter를 통해 컨테이너 네트워크 네임스페이스를 입력해 보세요.
먼저 도커 검사 명령을 사용하여 컨테이너의 PID를 찾습니다.
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
75e821d24261 busybox "/bin/sh" 32 seconds ago Up 31 seconds great_heisenberg
[root@docker ~]# docker inspect -f '{{.State.Pid}}' 75e821d24261
3533
그런 다음 nsenter --net 명령을 사용하여 PID에 해당하는 프로세스의 네트워크 네임스페이스를 입력합니다.
[root@docker ~]# nsenter --target 3533 --net
[root@docker ~]# ip a show eth0
116: eth0@if117: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet .2/16 brd 5.255 scope global eth0
valid_lft forever preferred_lft forever
보시다시피, 이 시점에서 ip a를 실행하여 얻은 정보는 컨테이너에서 실행하는 것과 완전히 동일합니다.
즉, Docker는 격리를 위해 네임스페이스를 사용합니다.
참고로 네임스페이스의 가장 큰 문제점은 완전히 격리되어 있지 않다는 점입니다.
- 우선, 컨테이너는 호스트에서 실행되는 특수한 종류의 프로세스일 뿐이므로 여러 컨테이너 간에 사용되는 호스트 운영 체제 커널은 여전히 동일합니다.
따라서 보안을 강화하기 위해 공유 커널을 사용하지 않는 Firecracker, gVisor, Kata 등과 같은 샌드박스 컨테이너도 있습니다.
- 둘째, Linux 커널에는 네임스페이스를 사용할 수 없는 리소스와 객체가 많이 있는데, 가장 대표적인 예가 시간입니다.
호스트의 시간을 실제로 수정하는 컨테이너의 시간 수정은 공유되므로 모든 컨테이너 시간을 수정하게 됩니다.
C그룹 기반 리소스 제약 조건
도커 실행이 컨테이너를 시작할 때 --cpus 또는 --memory 플래그를 추가하여 CPU 및 메모리 제한을 지정할 수 있습니다.
다음과 같이 --cpus=0.5를 사용하여 0.5 코어로 제한한 다음 잠시 데드 루프를 실행하여 CPU가 어떻게 사용되고 있는지 확인합니다.
[root@docker ~]# docker run -d --cpus 0.5 busybox NY -c "while true; do :; done"
d281fb2dc96cff371e9607197502c6ea3e04f4d0f3fd2ad38991c2321271736b
CPU 사용량 확인
[root@docker ~]# top
top - 15:38:20 up 286 days, 4:02, 3 users, load average: 0.72, 0.46, 0.36
Tasks: 96 total, 2 running, 48 sleeping, 0 stopped, 0 zombie
%Cpu(s): 52.0 us, 0.0 sy, 0.0 ni, 47.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.3 st
KiB Mem : 1006956 total, 157876 free, 201008 used, 648072 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 538972 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3763 root 20 0 4392 400 336 R 50.0 0.0 0:49.43 NY
3790 root 20 0 162112 4416 3724 R 0.3 0.4 0:00.01 top
1 root 20 0 43884 4280 2552 S 0.0 0.4 1:56.18 systemd
보시다시피 CPU 제한이 0.5이기 때문에 0.5개의 코어만 사용되며, 이는 위 명령어에서 볼 수 있는 50개입니다.
이것은 Docker의 또 다른 핵심 기능인 Linux Cgroups 기술 구현에 기반한 리소스 제한입니다.
Linux Cgroups는 프로세스에 대한 리소스 제한을 설정하는 데 사용되는 Linux 커널의 중요한 기능입니다.
Linux Cgroups의 전체 이름은 Linux 제어 그룹입니다.
주요 기능은 CPU, 메모리, 디스크, 네트워크 대역폭 등 프로세스 그룹이 사용할 수 있는 리소스를 제한하는 것입니다.
Linux에서 Cgroups가 사용자에게 노출하는 인터페이스는 파일 시스템, 즉 운영 체제의 /sys/fs/cgroup 경로 아래에 파일 및 디렉터리로 구성되며 다음을 사용하여 액세스할 수 있습니다.
이를 보기 위한 마운트 -t cgroup 명령은 다음과 같습니다:
[root@docker ~]# mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
보시다시피 /sys/fs/cgroup 아래에는 하위 시스템이라고도 하는 cpuset, cpu, 메모리와 같은 많은 하위 디렉터리가 있습니다.
즉, 현재 이 컴퓨터에서 C그룹이 제한할 수 있는 리소스 유형입니다.
예를 들어 CPU 하위 시스템의 경우 다음과 같은 프로필을 볼 수 있습니다:
[root@docker ~]# ls /sys/fs/cgroup/cpu
cgroup.clone_children cgroup.sane_behavior cpuacct.stat cpuacct.usage_all cpuacct.usage_percpu_sys cpuacct.usage_sys cpu.cfs_period_us cpu.rt_period_us cpu.shares docker release_agent tasks
cgroup.procs cpuacct.usage cpuacct.usage_percpu cpuacct.usage_percpu_user cpuacct.usage_user cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat notify_on_release system.slice user.slice
이러한 구성 파일은 CPU를 제한하는 방법과 제한해야 하는 프로세스를 정의합니다.
그렇다면 구성 파일은 어떻게 작동할까요? 다음은 정확히 어떻게 사용되는지 보여주는 데모입니다.
예: CPU 사용량 제한
해당 하위 시스템 아래에 디렉터리를 만들어야 합니다(예: 이제 /sys/fs/cgroup/cpu 디렉터리로 이동하여 컨테이너라는 디렉터리를 만듭니다):
[root@docker ~]# cd /sys/fs/cgroup/cpu
[root@docker cpu]# mkdir container
이 디렉터리는 "제어 그룹"입니다.
운영 체제에서 새로 생성한 컨테이너 디렉토리에 해당 하위 시스템에 해당하는 리소스 제한 파일을 자동으로 생성하는 것을 확인할 수 있습니다.
[root@docker cpu]# ls container
cgroup.clone_children cpuacct.stat cpuacct.usage_all cpuacct.usage_percpu_sys cpuacct.usage_sys cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
cgroup.procs cpuacct.usage cpuacct.usage_percpu cpuacct.usage_percpu_user cpuacct.usage_user cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks
다음 단계는 구성 파일을 수정하여 CPU를 제한하는 것입니다. 이 경우 앞서 만든 컨테이너 "제어 그룹"을 사용합니다.
이는 주로 다음 세 가지 파일을 통해 이루어집니다.
- cpu.cfs_quota_us: 각 제어 주기에서 프로세스가 사용할 수 있는 CPU 시간, 기본값은 -1, 즉 제한이 없습니다.
- cpu.cfs_period_us: 제어 주기, 기본값은 100ms입니다.
- 작업: 제한된 프로세스의 PID 목록입니다.
예를 들어 100ms는 20ms, 즉 최대 0.2코어로 제한될 수 있습니다.
먼저 백그라운드에서 이 스크립트를 실행합니다.
[root@docker cpu]# while : ; do : ; done &
[1] 3892
분명히 이 스크립트는 컴퓨터의 CPU를 100%까지 소모할 수 있는 데드 루프를 실행합니다. 출력에 따르면 이 스크립트가 프로세스 번호 3892로 백그라운드에서 실행되고 있음을 알 수 있습니다.
Top을 실행하여 CPU 사용량을 확인하면 이 3892 프로세스가 CPU의 거의 100%를 차지하며 코어를 꽉 채우고 있음을 알 수 있습니다.
[root@docker cpu]# top
top - 16:07:06 up 286 days, 4:31, 3 users, load average: 0.59, 0.50, 0.50
Tasks: 97 total, 2 running, 48 sleeping, 0 stopped, 0 zombie
%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1006956 total, 166520 free, 190840 used, 649596 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 549216 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3892 root 20 0 115684 532 0 R 92.0 0.1 0:48.64 bash
이 시점에서 프로세스의 CPU 사용량을 제한하도록 cgroups를 구성할 수 있습니다.
기본적으로 컨테이너 제어 그룹의 CPU 할당량은 아직 어떤 방식으로도 제한되어 있지 않으며, CPU 주기는 기본적으로 100ms이므로 위의 프로세스가 전체 CPU를 차지할 수 있습니다.
[root@docker cpu]# cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us
-1
[root@docker cpu]# cat /sys/fs/cgroup/cpu/container/cpu.cfs_period_us
100000
다음으로 이 구성 파일을 수정하여 CPU 제한을 설정할 수 있습니다. 예를 들어 컨테이너 그룹의 cfs_quota 파일에 20ms를 작성합니다.
[root@docker cpu]# echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us
[root@docker cpu]# cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us
20000
마지막으로 프로세스 PID가 작업 파일에 기록되어 구성이 적용됩니다.
[root@docker cpu]# echo 3892 > /sys/fs/cgroup/cpu/container/tasks
[root@docker cpu]# cat /sys/fs/cgroup/cpu/container/tasks
3892
그런 다음 적용 여부를 확인합니다:
[root@docker cpu]# top
top - 16:13:56 up 286 days, 4:38, 3 users, load average: 0.20, 0.61, 0.59
Tasks: 94 total, 2 running, 48 sleeping, 0 stopped, 0 zombie
%Cpu(s): 21.6 us, 0.0 sy, 0.0 ni, 78.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.3 st
KiB Mem : 1006956 total, 166552 free, 190808 used, 649596 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 549248 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3892 root 20 0 115684 532 0 R 19.9 0.1 5:56.94 bash
보시다시피 3892 CPU는 20%로 제한되어 있습니다.
CPU 하위 시스템 외에도 Cgroups의 각 하위 시스템에는 다음과 같은 고유한 리소스 제한 기능이 있습니다:
- blkio는 일반적으로 디스크와 같은 디바이스에 사용되는 블록 디바이스에 대한 I/O 제한을 설정합니다;
- cpuset을 사용하여 프로세스에 별도의 CPU 코어와 해당 메모리 노드를 할당합니다;
- 메모리를 사용하여 프로세스의 메모리 사용량 제한을 설정합니다.
Linux C그룹은 사용하기 쉽도록 설계되었습니다. 간단히 말해, 하위 시스템 디렉터리와 리소스 제한 파일 집합의 조합입니다.
Docker와 같은 Linux 컨테이너 프로젝트의 경우, 각 하위 시스템 아래에 각 컨테이너에 대한 제어 그룹을 생성한 다음 컨테이너 프로세스를 시작한 후 해당 제어 그룹의 작업 파일에 이 프로세스의 PID를 입력하기만 하면 됩니다.
그리고 이와 같은 파라미터를 사용하여 도커 실행을 실행하여 이러한 제어 그룹 아래의 리소스 파일에 어떤 값을 넣을지 지정하는 것은 사용자의 몫입니다:
docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
컨테이너를 시작한 후, 제어 그룹 "docker"의 Cgroups 파일 시스템 아래 CPU 하위 시스템에서 리소스 제한 파일의 내용을 확인하면 이를 확인할 수 있습니다:
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us
100000
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us
20000
컨테이너 이미지의 비밀
이 섹션에서는 다음 세 가지 주요 문제에 대해 설명합니다.
- 1) 컨테이너에서 파일을 수정해도 호스트가 영향을 받지 않는 이유는 무엇인가요?
- 2) 컨테이너의 파일 시스템의 출처는 어디인가요?
- 3) 도커 이미지는 어떻게 구현되나요?
컨테이너 이미지는 런타임 환경을 이미지로 패키징하여 애플리케이션 실행을 방해할 수 있는 환경 문제를 방지하는 Docker의 세 번째 핵심 기능입니다.
파일 시스템
컨테이너에서 파일 시스템은 어떤 모습인가요?
컨테이너의 파일시스템은 마운트 네임스페이스에 의해 격리되므로 독립적이어야 합니다.
마운트 네임스페이스는 파일 시스템의 "마운트 지점"에 대한 컨테이너 프로세스의 보기를 수정합니다. 프로세스의 보기는 "마운트" 작업 후에만 변경됩니다. 이 경우 새로 생성된 컨테이너는 호스트의 마운트 지점을 직접 상속합니다.
컨테이너 프로세스가 시작될 때 컨테이너 프로세스의 전체 루트 디렉터리 "/"를 다시 마운트하는 방법을 생각하는 것은 어렵지 않습니다. 그리고 마운트 네임스페이스 덕분에 이 마운트는 호스트에 보이지 않으므로 컨테이너 프로세스가 원하는 대로 할 수 있습니다.
Linux의 chroot 명령을 사용하면 이 작업을 쉽게 수행할 수 있습니다.
마운트 네임스페이스는 루트 네임스페이스의 개선 사항을 기반으로 개발되었으며, Linux 운영 체제에서 최초의 네임스페이스입니다.
그렇다면 첫 번째 질문은 왜 호스트는 컨테이너의 파일 수정에 영향을 받지 않을까요? 마운트 네임스페이스를 사용하여 격리되어 있기 때문입니다.
rootfs
위에서 언급했듯이 마운트 네임스페이스는 파일 시스템 마운트 지점에 대한 컨테이너 프로세스의 인식을 수정하며, 컨테이너의 루트 디렉터리에 마운트되고 컨테이너 프로세스의 격리 후 실행 환경을 제공하는 데 사용되는 이 파일 시스템을 "컨테이너 이미지" 라고 합니다. 보다 기술적인 이름은 rootfs입니다.
rootfs는 운영 체제에 포함된 파일, 구성 및 디렉터리일 뿐이며 운영 체제 커널은 포함되지 않습니다. Linux 운영 체제에서는 이 두 부분이 별도로 저장되며, 운영 체제는 부팅 시에만 지정된 버전의 커널 이미지를 로드합니다.
따라서 rootfs는 운영 체제의 "몸체"만 포함하며, 운영 체제의 "영혼"은 포함하지 않습니다. 실제로 동일한 머신의 모든 컨테이너는 호스트 운영 체제의 커널을 공유합니다.
결국 컨테이너는 샌드박스 역할을 하는 에뮬레이트된 하드웨어 머신이 있을 뿐만 아니라 각 샌드박스에서 전체 게스트 OS를 실행하여 애플리케이션이 돌아다닐 수 있도록 합니다.
그러나 컨테이너가 반복해서 강조되는 중요한 기능인 일관성을 갖게 된 것은 rootfs 덕분입니다. rootfs는 애플리케이션뿐만 아니라 전체 운영 체제의 파일과 디렉터리를 패키징하므로 애플리케이션과 애플리케이션을 실행하는 데 필요한 모든 종속성이 캡슐화됩니다.
두 번째 질문: 컨테이너의 파일시스템은 어디에서 가져오나요? 실제로는 이미지가 빌드될 때 패키징된 다음 컨테이너가 시작될 때 루트 디렉터리에 마운트됩니다.
Image
Docker는 이미지 디자인에 레이어 개념을 도입했습니다. 즉, 사용자가 이미지를 만드는 각 작업 단계는 증분 루트프인 레이어를 생성합니다.
rootfs의 재사용은 레이어 개념을 도입함으로써 이루어 집니다. 매번 rootfs를 새로 만들 필요 없이 레이어를 기반으로 수정하기만 하면 됩니다.
Docker 이미지 레이어는 UnionFS라고도 하는 Union 파일 시스템이라는 기능을 사용하는데, 이 기능은 서로 다른 위치의 여러 디렉터리를 단일 디렉터리로 통합하는 것을 주요 기능으로 합니다.
예를 들어 디렉터리 A와 디렉터리 B를 디렉터리 C 아래에 마운트하는 경우 디렉터리 C에는 디렉터리 A와 디렉터리 B의 모든 파일이 포함됩니다.
디렉터리 A와 대상 B가 보이지 않으므로 디렉터리 C에 그만큼 많은 파일이 들어 있는 것처럼 보입니다.
Docker 이미지는 여러 레이어로 나뉘며, 이 레이어는 UFS를 사용하여 단일 디렉터리에 마운트되므로 이 디렉터리에 전체 파일이 포함됩니다.
UnionFS는 시스템마다 자체 구현이 다르므로 Docker 배포판마다 다른 것을 사용하며, 이는 docker 정보를 통해 확인할 수 있습니다. 가장 일반적인 것은 aufs, overlay2
다음 그림과 같이 유니온 마운트는 최상위 레벨에 있어 통합된 보기를 제공합니다. 사용자는 전체 시스템에 하나의 레이어만 있는 것처럼 보이지만 실제로는 그 아래에 많은 레이어가 있습니다.
이미지에는 정적 파일만 포함되어 있지만 컨테이너는 실시간 데이터를 생성하므로 컨테이너의 rootfs는 이미지 위에 읽기/쓰기 레이어와 초기화 레이어를 추가합니다.
컨테이너 rootfs는 읽기 전용 레이어 + 초기화 레이어 + 읽기-쓰기 레이어로 구성됩니다.
읽기 전용(컴퓨팅)
이 컨테이너의 루트fs의 하위 레이어, 즉 읽기 전용으로 마운트된 이미지의 모든 레이어의 합계입니다.
읽기-쓰기 레이어
이 디렉터리는 이 컨테이너에 대한 rootfs의 최상위 계층이며 읽기 쓰기를 의미하는 rw로 마운트됩니다. 이 디렉터리는 파일이 쓰여질 때까지 비어 있습니다.
컨테이너에서 쓰기 작업을 수행하면 수정에 의해 생성된 콘텐츠가 이 계층에 증분 방식으로 나타나며, 삭제 작업은 보다 구체적으로 구현됩니다.
AUFS 화이트아웃은 쓰기 가능한 상위 디렉터리에 화이트아웃 숨김 파일을 생성하여 구현됩니다.
이를 위해 aufs는 읽기-쓰기 레이어에 화이트아웃 파일을 생성하여 읽기 전용 레이어의 파일을 '마스킹'합니다.
예를 들어 읽기 전용 레이어에서 foo라는 파일을 삭제하려는 경우, 이 삭제는 실제로 읽기-쓰기 레이어에 .wh.foo라는 파일을 생성합니다. 따라서 두 레이어가 함께 마운트되면 foo 파일은 .wh.foo 파일에 의해 "가려져" "사라지게" 됩니다.
초기화 레이어
이 레이어는 "-init"으로 끝나는 레이어로 읽기 전용 레이어와 읽기-쓰기 레이어 사이에 끼어 있습니다. init 레이어는 Docker 프로젝트에서 /etc/hosts, /etc/resolv.conf 등의 정보를 저장하기 위해 생성하는 별도의 내부 레이어입니다.
초기화 레이어가 필요한 이유는 무엇인가요?
예를 들어 호스트 이름은 이미지 계층의 일부이며 읽기/쓰기 계층에서만 변경할 수 있지만 이 정보를 도커 커밋에서 커밋하고 싶지 않으므로 초기화 계층을 사용하여 변경 사항을 저장합니다.
코드를 커밋할 때 일반적으로 모든 종류의 구성 정보도 함께 제출하지 않는다는 것은 이해할 수 있습니다.
도커 커밋은 읽기 전용 및 읽기-쓰기 레이어만 커밋합니다.
마지막 질문: 도커 이미지는 어떻게 구현되나요? 레이어링을 위한 레이어 개념을 도입하고 페더레이션 파일 시스템의 도움으로 레이어를 오버레이하면 최종적으로 완전한 이미지가 형성됩니다.
이것은 이미지의 주요 내용일 뿐이며, 이미지 형식으로 패키징하는 방법은 OCI 사양입니다.
요약
이 시점에서 일반적으로 Docker 컨테이너 구현이 다음 3가지 주요 기능을 사용한다는 것은 분명합니다:
- 1) Linux 네임스페이스의 격리 기능
- )Linux Cgroups Docker의 제한 기능
- 3) 루트프 기반 파일 시스템





