[Docker] Docker 개요

김선형·2025년 8월 22일

Docker

목록 보기
1/6

Docker

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

Docker Structure
Docker Architecture

사용 기술

컨테이너 내 프로세스 격리: namespaces

  • PID: 컨테이너마다 별도의 프로세스 테이블을 관리한다. 특정 컨테이너의 프로세스에서 다른 컨테이너의 프로세스로 접근할 수 없다.
  • Network: 네트워크 디바이스, IP Address, 포트 번호, 라우팅 테이블, 필터링 테이블 등 네트워크 리소스를 namespace별로 할당할 수 있다.
  • UID/GID: 독립적인 사용자를 할당한다. User ID와 Group ID 공간을 격리하여, namespace 외부에 있는 user나 group이 내부의 공간을 보거나 건드릴 수 없다.
  • Mount: 마운트를 조작하여 namespace 내에 파일 시스템 트리를 구성하여, 컨테이너마다 특정 디렉토리를 루트 파일 시스템으로 보이게 한다.
  • UTS: namespace별로 호스트명과 도메인명을 독자적으로 가질 수 있다.
  • IPC: 공유 메모리, 큐, 세마포어 등 프로세스 간의 통신 자원을 분리할 수 있다.

✏️ namespace?
프로세스를 실행할 때 시스템의 리소스를 분리해서 실행할 수 있도록 도와주는 기능

프로세스에 할당된 리소스 제한: cgroup

컨테이너에 할당하는 자원을 조정하는 데 사용하며, 프로세스 및 스레드를 그룹화하여 관리하는 기능이다. Host OS의 CPU, 메모리와 같은 리소스를 그룹별로 제한 가능하며, 계층 구조로 프로세스를 그룹화하여 관리가 가능하여 하위 cgroup은 상위 cgroup의 제한 설정이 그대로 적용된다.

  • cpu: CPU 사용량 제한
  • cpuacct: CPU 사용량 통계 정보 제공
  • cpuset: CPU와 메모리 배치 제어
  • memory: 메모리와 swap 사용량 제한
  • devices: 디바이스 엑세스 허가 및 제한
  • freezer: 그룹에 속한 프로세스 정지 및 재개
  • net_cls: 네트워크 제어 태그 추가
  • blkio: 블록 디바이스 입출력 양 제어

✏️ 컨테이너 내 프로세스 자원 초과 시 처리 과정
컨테이너에서 CPU, Memory, Disk I/O 등을 초과하는 경우, 커널이 자원 초과 상황을 감지하고 제어를 실행한다.
컨테이너가 cgroup으로 memory limit: 512MiB로 설정하였으나 init process가 700MiB를 사용하여 limit이 초과된 경우, Linux 커널의 OOM Killer가 동작하여 프로세스가 강제 종료된다. shim이 PID 1 종료를 감지하면, 컨테이너의 종료 상태를 containerd에 알려 containerd가 container의 상태를 갱신한다.

이미지 관리 기술: OverlayFS 기반 계층 파일 시스템

  • Layering: 여러 디렉토리를 레이어로 취급하여, 읽기 전용 (lowerdir)과 읽기-쓰기 가능 (upperdir) 디렉토리를 하나의 통합된 파일 시스템처럼 사용한다. 사용자가 파일을 수정하면, 변경 사항은 upperdir에 기록되며 lowerdir의 원본은 변경되지 않는다.
  • Copy-on-Write: 파일 수정 시 원본을 그대로 두고 upperdir에 복사하여 변경함으로써, 원본 불변성을 보장한다.
  • 디렉토리 병합 및 우선순위: 여러 디렉토리 (lowerdir, upperdir, workdir)를 container rootfs로 병합하여 마운트한다. 동일한 파일이 존재하는 경우, upperdir 파일이 우선적이다.
  • 파일 시스템 투명성: 사용자에게는 하나의 디렉토리처럼 보이지만, 실제로는 여러 레이어를 OverlayFS가 조합하여 동작한다.

✏️ OverlayFS 기반 계층 파일 시스템 구성 요소
읽기 전용 이미지 (lowerdir): 컨테이너 이미지 레이어로, 불변이며 rootf에 unpack된다. 여러 개의 레이어가 아래쪽에서부터 순차적으로 쌓인다.
upperdir: 쓰기 가능한 단일 디렉토리로, 컨테이너 런타임 시 변경된 파일은 모두 upperdir에 저장된다. Copy-on-Write 방식으로 원래 lowerdir에 있던 파일을 수정할 경우 upperdir로 복사된 후 변경된다.
rootfs: 해당 컨테이너의 독립된 루트 파일 시스템으로, 여러 레이어 (읽기 전용 이미지 레이어 + 쓰기 레이어)를 OverlayFS로 병합하여 구성한 디렉토리다.
workdir (임시 공간): OverlayFS 내부에서 upperdir과 lowerdir을 병합할 때 필요한 작업 디렉토리로, 디렉토리 생성/삭제 작업 등에 필요한 임시 작업 공간이다.

LinuX Container (LXC)

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 Networking: 가상 bridge 및 가상 NIC

Docker Networking
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에서 패킷을 전송한다.

Docker Security

Capability

프로세스가 가지는 권한을 세분화하여 관리하는 기능이다. Root 사용자에게 모든 권한을 부여하지 않고 최소 권한만 할당하는 등 세밀한 접근 제어가 가능하다.

SELinux (Security-Enhanced Linux)

리눅스에서 프로세스와 파일의 상호작용을 제한하는 역할을 하며, 컨테이너와 호스트 간의 보안 경계를 강화한다.

AppArmor (Application Armor)

Ubuntu 및 Debian에서 주로 사용되는 보안 모듈로, 프로세스의 권한을 제한하는 프로필 기반 보안 시스템이다. SELinux보다 설정이 단순하고 사용하기 쉽다. 특정 실행 명령과 프로세스의 실행을 제한한다.

profile
선형의 비선형적 기록 🐜

0개의 댓글