컨테이너 기술을 지원하는 다양한 프로젝트 중 하나로, 어플리케이션에 국한되지 않고 의존성 및 파일 시스템까지 패키징하여 빌드, 배포, 실행을 단순화한다.

✏️ namespace?
프로세스를 실행할 때 시스템의 리소스를 분리해서 실행할 수 있도록 도와주는 기능
컨테이너에 할당하는 자원을 조정하는 데 사용하며, 프로세스 및 스레드를 그룹화하여 관리하는 기능이다. Host OS의 CPU, 메모리와 같은 리소스를 그룹별로 제한 가능하며, 계층 구조로 프로세스를 그룹화하여 관리가 가능하여 하위 cgroup은 상위 cgroup의 제한 설정이 그대로 적용된다.
✏️ 컨테이너 내 프로세스 자원 초과 시 처리 과정
컨테이너에서 CPU, Memory, Disk I/O 등을 초과하는 경우, 커널이 자원 초과 상황을 감지하고 제어를 실행한다.
컨테이너가 cgroup으로 memory limit: 512MiB로 설정하였으나 init process가 700MiB를 사용하여 limit이 초과된 경우, Linux 커널의 OOM Killer가 동작하여 프로세스가 강제 종료된다. shim이 PID 1 종료를 감지하면, 컨테이너의 종료 상태를 containerd에 알려 containerd가 container의 상태를 갱신한다.
✏️ OverlayFS 기반 계층 파일 시스템 구성 요소
읽기 전용 이미지 (lowerdir): 컨테이너 이미지 레이어로, 불변이며 rootf에 unpack된다. 여러 개의 레이어가 아래쪽에서부터 순차적으로 쌓인다.
upperdir: 쓰기 가능한 단일 디렉토리로, 컨테이너 런타임 시 변경된 파일은 모두 upperdir에 저장된다. Copy-on-Write 방식으로 원래 lowerdir에 있던 파일을 수정할 경우 upperdir로 복사된 후 변경된다.
rootfs: 해당 컨테이너의 독립된 루트 파일 시스템으로, 여러 레이어 (읽기 전용 이미지 레이어 + 쓰기 레이어)를 OverlayFS로 병합하여 구성한 디렉토리다.
workdir (임시 공간): OverlayFS 내부에서 upperdir과 lowerdir을 병합할 때 필요한 작업 디렉토리로, 디렉토리 생성/삭제 작업 등에 필요한 임시 작업 공간이다.
namespace 생성 및 cgroup 설정, rootfs 마운트 및 교체, UID/GID 매핑, Capability, seccomp, AppArmor 적용, init 프로세스 실행 기준을 담당한다. 현재는 경량화된 runC로 교체되었다.
✏️ dockerd (Docker Engine), containerd, runc
dockerd: Docker의 진입점으로, Docker의 전체 운영을 관리한다. Docker 엔진에 이미지 실행을 요청하면, containerd 데몬에 책임을 위임한다.
containerd (=cri-o): 이미지 pull/unpack을 통해 임시 rootfs 디렉토리를 구성한다. runc 사용을 위한 OCI bundle 디렉토리를 생성한다.
containerd-shim (=podman/crio): runc 실행 및 init 프로세스를 관리한다. stdout/stderr 연결, docker exec/log, exit code 감시, pid 추적 등을 한다.
runc: 표준 OCI 런타임으로, libcontainer의 리팩토링 구현체이다.

Docker 컨테이너는 서버의 물리 NIC와 별도로 각 컨테이너마다 가상 NIC를 할당한다. Default gateway로 Linux bridge인 docker0를 만들어, 외부 네트워크와 교환하는 패킷에 NAT 작업을 수행하고 컨테이너 간 네트워크를 연결한다.
각 컨테이너에 격리된 네트워크 공간을 만들고 컨테이너의 eth0에 static IP를 할당한다.
컨테이너 내부의 eth0와 docker0로 연결된 veth인터페이스를 연결하여 컨테이너 외부와 통신한다.
✏️ docker0?
container 내부 IP와 Port를 기반으로 vethxxx를 라우팅하는 역할을 수행한다. 실제 NAPT (Network Address and Port Translation)는 iptable에서 수행한다.
Docker 컨테이너 간 통신은 링크 기능을 사용하여 이루어지며, Docker 컨테이너와 외부 네트워크 통신은 가상 bridge docker0와 Host OS의 물리 NIC에서 패킷을 전송한다.
프로세스가 가지는 권한을 세분화하여 관리하는 기능이다. Root 사용자에게 모든 권한을 부여하지 않고 최소 권한만 할당하는 등 세밀한 접근 제어가 가능하다.
리눅스에서 프로세스와 파일의 상호작용을 제한하는 역할을 하며, 컨테이너와 호스트 간의 보안 경계를 강화한다.
Ubuntu 및 Debian에서 주로 사용되는 보안 모듈로, 프로세스의 권한을 제한하는 프로필 기반 보안 시스템이다. SELinux보다 설정이 단순하고 사용하기 쉽다. 특정 실행 명령과 프로세스의 실행을 제한한다.