25/10/20 컨테이너 기술과 애플리케이션 가상화 1

344th·2025년 12월 11일

AWS AI

목록 보기
25/48

Process&Thread

네임스페이스

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

  • 리눅스 커널에서 제공하는 기능 중 하나
  • 하나의 시스템을 여러 개의 가상 시스템처럼 보이게 만들어주는 기술

⇒ 컴퓨터 시스템에서도 서로 다른 리소스를 구분하기 위한 식별 방법이 필요

⇒ 이때, 사용하는 기능이 바로 네임스페이스

네임스페이스의미역할
pidPID: Process ID리눅스 커널의 프로세스 ID를 분리
netNET: Networking네트워크 인터페이스(NET)를 관리
ipcIPC: Inter Process Communication프로세스 간 통신(IPC) 접근을 관리
mntMNT: Mount파일 시스템의 마운트를 관리
utsUTS: Unix Timesharing System커널과 버전 식별자를 관리

도커 기초 지식

도커의 정의

도커

: 컨테이너라고 부르는 운영체제 수준의 가상화 방식으로 소프트웨어를 배포하는 방식을 사용하는 PaaS 제품

  • on premises
  • IaaS
  • PaaS
  • SaaS

가상화의 개념

: 컴퓨터에서 활용하는 리소스를 추상화하는 개념

: 여러 개의 가상머신을 생성함으로써, 단일 컴퓨팅 자원을 여러 개의 논리적인 자원으로 나누어 동작시킬 수 있음

구분VM (Virtual Machine)Container
실행 단위OS 단위 (Guest OS 포함)프로세스 단위
커널각각의 Guest OS가 자체 커널을 가짐호스트 커널을 공유
격리 수준하드웨어 수준 (완전 독립)OS 수준 (커널 공유)

도커 구성 요소

image.png

  • docker-cli : 도커 클라이언트
    • 사용자의 입력을 도커 데몬이 이해할 수 있도록 api 요청 형태로 변환해서 전달 → 유닉스 소켓을 통해 이루어짐 → tcp 를 이용해서도 가능 ⇒ 즉, 물리적으로 다른 컴퓨터에 있어도 ok
    • shell 과 비슷한 역할
  • dockerd : 도커 데몬
    • 도커 API 요청을 수신하고, 도커 이미지, 컨테이너 등과 같은 도커와 관련된 객체를 관리

    • SPoF(단일 장애 지점) 문제

      : 이 부분이 죽으면 시스템 전체가 죽음

      → containerd 를 분리

  • containerd : 컨테이너 관리자 : 컨테이너 실행과 관리에 필요한 기능을 수행하는 오픈소스 컨테이너 런타임
    • 컨테이너의 생명주기를 모두 관리
      • 도커 이미지 전송
      • 컨테이너 실행
      • 스토리지
      • 네트워크
    • 마지막에 runc 호출
    • CNCF에 기증
      • 오픈소스 프로젝트
      • CNCF?

        CNCF (Cloud Native Computing Foundation)

        = “클라우드 네이티브 기술 생태계를 발전시키기 위한 오픈소스 재단”

        • 설립: 2015년
        • 소속: 리눅스 재단(Linux Foundation) 산하 단체
        • 목적:
          • 클라우드 환경에서 애플리케이션을 확장성 있고, 회복력 있게, 효율적으로 운영할 수 있게 돕는 기술을 표준화하고 관리
        즉, CNCF는 클라우드 네이티브 기술의 중심 허브예요. (쿠버네티스, Prometheus, Envoy 같은 프로젝트들이 여기 소속되어 있습니다.)
  • runc : 컨테이너 실행과 관련된 작업을 수행하는 저수준 컨테이너 런타임
    • containerd 는 실행 이외에도 컨테이너 관리를 위한 다양한 역할을 하지만, runc 는 실제 컨테이너 실행만 담당
    • OCI 규격에 따라 만들어짐
      • OCI?

        OCI란?

        OCI (Open Container Initiative)

        = “컨테이너 기술의 표준 규격을 만드는 오픈소스 프로젝트”

        • 설립: 2015년
        • 주관: 리눅스 재단(Linux Foundation)
        • 참여 기업: Docker, Red Hat, Google, IBM, Microsoft, AWS 등
        • 목적:
          > 컨테이너 생태계가 “특정 회사 기술에 종속되지 않도록”
          > 
          > 
          > **표준 컨테이너 포맷과 런타임 명세를 정의**하는 것
          > 

        배경: 왜 OCI가 만들어졌을까?

        2013~2015년 사이에는 Docker가 컨테이너 시장을 독점했어요. 하지만 각 기업들이 “Docker 전용 포맷에 종속되는 건 위험하다”고 느끼기 시작했죠. 그래서 2015년에 Docker가 중심이 되어 리눅스 재단 아래 OCI를 설립, 자신들의 기술을 표준으로 공개했습니다.

        💡 즉, “Docker만의 기술” → “모든 컨테이너가 따를 수 있는 표준”으로 바꾼 거예요.


        OCI의 주요 표준 3가지

        표준명설명예시
        1️⃣ OCI Runtime Specification컨테이너를 “어떻게 실행할 것인가” 정의runc, crun
        2️⃣ OCI Image Specification컨테이너 이미지를 “어떻게 패키징·저장할 것인가” 정의Docker image, Podman image
        3️⃣ OCI Distribution Specification컨테이너 이미지를 “어떻게 Registry로 주고받을 것인가” 정의Docker Hub, Harbor, GitHub Container Registry
        즉,

        OCI는 “컨테이너를 만들고 → 저장하고 → 실행하는” 전 과정을 표준화합니다.


        OCI 아키텍처 구조

        [컨테이너 생태계]
         ├─ OCI Image Spec      ← 이미지 구조 (.tar, layers, manifest)
         ├─ OCI Runtime Spec    ← 컨테이너 실행 규칙 (namespace, cgroups 등)
         └─ OCI Distribution Spec ← 이미지 전송 프로토콜 (push/pull)
        
        이 표준을 구현한 대표적인 기술들이 아래와 같습니다 👇
        역할구현체 예시
        Runtime Specrunc, crun, gVisor, Kata Containers
        Image SpecDocker, Buildah, Kaniko
        Distribution SpecDocker Registry, Harbor, GHCR

        OCI와 Docker, Kubernetes의 관계

        기술역할
        Docker컨테이너 빌드 + 배포 + 실행 툴 (OCI 기반으로 동작)
        OCI컨테이너의 이미지·런타임 표준 정의
        containerd / CRI-O쿠버네티스가 사용하는 컨테이너 런타임 (OCI 호환)
        Kubernetes여러 컨테이너를 자동 관리하는 오케스트레이션 시스템

        💡 즉, OCI는 표준,

        Docker와 containerd는 그 표준을 구현한 실제 툴,

        Kubernetes는 그 툴을 이용하는 상위 플랫폼이에요.


        정리 요약

        항목설명
        이름Open Container Initiative
        소속Linux Foundation
        역할컨테이너 실행·이미지·전송 규격의 표준 정의
        대표 규격Runtime Spec, Image Spec, Distribution Spec
        대표 구현체runc, Docker, containerd, CRI-O
        목적벤더 종속 없는 컨테이너 생태계 표준화

        한 줄 요약

        ✅ OCI는 컨테이너의 “표준 언어”를 만드는 재단입니다.

        Docker는 OCI 규격을 구현한 도구,

        Kubernetes는 OCI 규격을 활용하는 플랫폼,

        그리고 CNCF는 OCI를 포함한 클라우드 네이티브 생태계 전체를 관리하는 조직이에요.


  • containerd-shim : containerd와 runc 사이에서 작동하는 중간 프로세스 : 컨테이너 실행을 조정하는 역할
    • 컨테이너의 표준입출력 스트림을 관리

도커 설치

가상머신 생성

mkdir docker
vagrant init
ii Vagrantfile

vagrant up

https://docs.docker.com/engine/install/centos/

Install using the rpm repository

Set up the repository

sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

Install Docker Engine

sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Start Docker Engine

**$ sudo systemctl enable --now docker**
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
  • 심볼릭 링크가 생성된 이유

    🧩 1️⃣ systemctl enable이 하는 일

    systemctl enable docker 는 “Docker 서비스를 부팅 시 자동 시작하도록 등록”하는 명령입니다. 이때 systemd는 내부적으로 서비스 단위 파일(.service) 을 읽어들여, 그걸 해당 타겟(target) (즉, 실행 레벨에 해당하는 group)에 심볼릭 링크로 연결합니다. 즉 👇
    /usr/lib/systemd/system/docker.service   ← 서비스 정의 파일 (원본)
    /etc/systemd/system/multi-user.target.wants/docker.service → 심볼릭 링크 (자동 시작 등록)
    

    ⚙️ 2️⃣ 왜 심볼릭 링크를 쓰나?

    systemd는 서비스 자동 시작 여부를 “심볼릭 링크 존재 여부”로 판단하기 때문이에요.
    디렉터리역할
    /usr/lib/systemd/system/시스템에서 제공하는 기본 서비스 정의 파일들 (Docker, sshd, crond 등)
    /etc/systemd/system/사용자가 수정/활성화한 서비스 설정들이 저장되는 곳
    /etc/systemd/system/<target>.wants/부팅 시 함께 실행할 서비스들의 링크 목록
    즉,
    • Docker의 원본 서비스 파일은 /usr/lib/systemd/system/docker.service

    • enable 명령은 “이 서비스를 부팅 시 자동으로 실행해야 한다”고 systemd에 알려주기 위해

      **심볼릭 링크를 `/etc/systemd/system/multi-user.target.wants/` 아래에 추가**합니다.

      💡 “심볼릭 링크가 있으면 자동 실행, 없으면 비활성화”

      이게 systemd의 enable/disable 내부 로직이에요.


      🧱 3️⃣ 심볼릭 링크의 역할을 예시로 보면

      $ sudo systemctl enable docker
      Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
      

      → 이 말은 “부팅 시 multi-user.target(즉, 텍스트 로그인 단계)에서 Docker 서비스를 자동으로 시작하라”는 의미입니다.

      즉, systemd는 링크를 보고 어떤 서비스가 자동시작 대상인지 알게 됩니다.


      🔄 4️⃣ -now 옵션은?

    • -now는 “지금 즉시(start) 서비스도 시작하라”는 의미입니다.

      즉, 아래 두 명령을 합친 것과 같습니다 👇

      sudo systemctl enable docker     # 부팅 시 자동 실행 등록
      sudo systemctl start docker      # 지금 즉시 실행
      

      🧭 5️⃣ 정리 요약

      항목설명
      심볼릭 링크 생성 이유systemd가 “부팅 시 자동 실행 대상 서비스”를 구분하기 위해
      원본 파일 위치/usr/lib/systemd/system/docker.service
      링크 생성 위치/etc/systemd/system/multi-user.target.wants/docker.service
      enable 의미서비스 자동시작 등록
      --now 의미즉시 실행도 함께 수행
      disable 시 동작심볼릭 링크를 삭제함 (원본 파일은 그대로 남음)

      ✅ 한 줄 요약:

      systemctl enable은 “서비스를 부팅 시 자동 실행 목록에 등록하기 위해”

      해당 타겟 디렉토리에 심볼릭 링크를 생성하는 명령이에요.

      systemd는 이 링크 존재 여부로 서비스 활성화 상태를 관리합니다.

설치 및 버전 확인

**$ docker --version**
Docker version 28.5.1, build e180ab8
**$ docker -v**
Docker version 28.5.1, build e180ab8
**$ docker version**
Client: Docker Engine - Community
 Version:           28.5.1
 API version:       1.51
 Go version:        go1.24.8
 Git commit:        e180ab8
 Built:             Wed Oct  8 12:20:03 2025
 OS/Arch:           linux/amd64
 Context:           default
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.51/version": dial unix /var/run/docker.sock: connect: permission denied

permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.51/version": dial unix /var/run/docker.sock: connect: permission denied

→ 유닉스 소켓은 루트 사용자만 권한이 있음

**$ getent group docker**
docker:x:987:

도커 그룹 엔트리 확인

**$ sudo usermod -aG docker $USER**

현재 사용자 보조 그룹에 도커 그룹 추가

**$ id vagrant**
uid=1000(vagrant) gid=1000(vagrant) groups=1000(vagrant),987(docker)
**$ docker version**
Client: Docker Engine - Community
 Version:           28.5.1
 API version:       1.51
 Go version:        go1.24.8
 Git commit:        e180ab8
 Built:             Wed Oct  8 12:20:03 2025
 OS/Arch:           linux/amd64
 Context:           default
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.51/version": dial unix /var/run/docker.sock: connect: permission denied

아직도 permission denied 남

→ 새로운 로그인 세션부터 변경사항이 적용되므로

다시 로그인하면

**$ docker version**
Client: Docker Engine - Community
 Version:           28.5.1
 API version:       1.51
 Go version:        go1.24.8
 Git commit:        e180ab8
 Built:             Wed Oct  8 12:20:03 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          28.5.1
  API version:      1.51 (minimum version 1.24)
  Go version:       go1.24.8
  Git commit:       f8215cc
  Built:            Wed Oct  8 12:17:02 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.7.28
  GitCommit:        b98a3aace656320842a23f4a392a33f46af97866
 runc:
  Version:          1.3.0
  GitCommit:        v1.3.0-0-g4ca628d1
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

permission denied 나던 서버 부분도 정상적으로 출력되는 것을 확인 가능

클라이언트 부분 정보는 정상 출력되는데 서버 부분은 권한 제한 걸리는 이유

: 서버 버전 정보를 가져올 때 도커 데몬에 유닉스 소켓으로 요청을 보내기 때문

  • docker version은 내부적으로 다음 두 단계를 수행
① 클라이언트 버전 출력

- 이건 CLI 실행 파일 자체의 메타데이터이므로
    
    로컬에서 바로 읽어서 출력
    
    → 즉, 데몬과 통신 불필요.
    

② 서버(Daemon) 버전 요청

- CLI가 Docker Daemon에게 `/version` REST API 요청을 전송
    - 경로: `unix:///var/run/docker.sock`
    - 요청 URL: `GET /v1.51/version`
- Daemon이 응답을 반환하면 “Server:” 섹션이 출력

> `docker version` 명령은 서버 버전 확인 시 Docker 데몬에 REST API를 전송하기 때문에,
> 
> 
> `/var/run/docker.sock` 유닉스 소켓에 접근할 권한이 없으면 **Server 부분만 permission denied** 가 발생
> 

Verify that the installation is successful by running the hello-world image:

**$ sudo docker run hello-world**
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
17eec7bbc9d7: Pull complete
Digest: sha256:6dc565aa630927052111f823c303948cf83670a3903ffa3849f1488ab517f891
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

도커 기초

도커 기초 개념

도커 작동 방식

도커 클라이언트 -> 도커 호스트 -> 도커 레지스트리
							 <-             <-
  • 도커 클라이언트 : 도커에 명령을 내릴 수 있는 CLI 도구 : 도커 컨테이너를 이용해 컨테이너, 이미지, 볼륨 등을 관리
  • 도커 호스트 : 도커를 설치한 서버 혹은 가상머신 : 물리 서버가 될 수도 있고 가상 서버가 될 수도 있음
  • 도커 레지스트리 : 도커 이미지를 저장하거나 배포하는 시스템
    • Public(공개) 레지스트리 ex) 도커 허브
    • Private(개인) 레지스트리

도커 이미지

: 붕어빵 틀

: 컨테이너 형태로 소프트웨어를 배포하기 위해 필요한 모든 요소(코드, 라이브러리, 설정 등)를 실행할 수 있는 포맷으로 컴파일 및 빌드한 패키지

  • 독립적 → 의존성 고려할 필요 x
  • 경량화된 패키지
    • 비교적 작은 용량으로도 제 역할을 수행 가능
  • 특정 시점의 도커 컨테이너 형태를 담은 스냅샷
  • 도커 이미지를 통해 동일한 환경을 가진 여러 개의 컨테이너를 손쉽게 생성 가능
  • 여러 개의 레이어로 구성
  • 도커 허브와 같은 중앙 저장소에 저장되어 관리됨 → 도커 이미지를 도커 허브에 업로드 or 다운로드 가능

도커 컨테이너

: 붕어빵 틀로 찍어서 나온 붕어빵

: 도커 이미지를 실행할 수 있는 인스턴스(instance)

  • 도커 이미지로부터 생성됨
  • 실행, 중지, 재실행, 삭제 등의 명령을 내릴 수 있음
  • 컨테이너는 자체적으로 파일 시스템을 가짐
  • 각 컨테이너는 독립적으로 실행됨
  • 컨테이너 내부에는 자체적으로 운영체제 전부를 포함하지 않음
    • 가상머신과 같은 개념 x

    • 도커 엔진과 운영체제를 공유

      ⇒ 컨테이너는 도커 엔진이 설치되어 있는 호스트 운영체제를 이용

  • 프로그램을 실행시키기 위해 최소한으로 필요한 바이너리, 라이브러리와 같은 구성 요소로 이루어져 있음

hello world 실행 과정

**$ sudo docker run hello-world
#1**
Unable to find image 'hello-world:latest' locally
#2
latest: Pulling from library/hello-world
#3
17eec7bbc9d7: Pull complete
#4
Digest: sha256:6dc565aa630927052111f823c303948cf83670a3903ffa3849f1488ab517f891
#5
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
  • docker run hello-world : hello-world 라는 이름의 컨테이너를 실행
  • #1 : 로컬에서 hello-world:latest 라는 이미지를 찾을 수 없다
  • #2 : 해당 이미지가 없으므로 library/hello-world에서 pull을 받겠다
    • pull? : 도커 이미지를 원격 저장소에서 로컬로 다운로드 : 도커 허브에서 hello-world 이미지를 다운로드
  • #3 : pull 이 완료됨
  • #4

    Digest = Docker 이미지의 고유한 식별자(ID) 이자,

    이미지 내용 전체를 해싱(SHA256) 해서 얻은 무결성 검증값(fingerprint)

    • Docker 이미지는 여러 레이어(layer) 로 구성됨
    • 각 레이어의 바이너리 데이터(파일 시스템 스냅샷)를 모두 해싱해서
      최종적으로 합쳐진 이미지 전체의 **SHA256 해시**를 계산함
      
    • 이 해시값이 바로 Digest (예: sha256:6dc565a...)

      Digest는 Docker 이미지의 내용을 SHA256으로 해싱한 고유 지문이며,

      Docker는 이 값을 이용해 이미지 무결성 검증을 수행함

    • Digest

      Digest 의 역할

      역할설명
      고유 식별자같은 이름과 태그(hello-world:latest)라도 실제 내용이 다르면 Digest가 다름
      무결성 검증Docker가 이미지를 받을 때 서버의 Digest와 클라이언트가 계산한 Digest를 비교해 “내용이 변조되지 않았는지” 확인
      캐시 판단 기준docker pull 시 Digest가 동일하면 “이미 최신 버전”으로 인식
      보안 측면Digest를 직접 지정해 이미지 버전을 고정할 수 있음 (태그보다 안전함)

      Digest와 Tag의 차이

      구분TagDigest
      형식:latest, :v1.0.0@sha256:6dc565aa...
      의미사람이 관리하는 버전 이름이미지 내용에 기반한 고유 해시값
      변경 가능성태그는 다른 이미지로 덮어쓸 수 있음Digest는 절대 불변
      사용 예시hello-world:latesthello-world@sha256:6dc565aa630927...

      💡 태그(tag) 는 “이름표”,

      Digest 는 “지문”

      Digest는 해시 함수인가?

      • Digest 자체는 해시 함수가 아니라, 해시 결과값(hash output) 입니다.

      • 실제로 사용하는 해시 함수는 SHA256 (Secure Hash Algorithm 256-bit).

      • SHA256은 단방향 함수(one-way function) 로,

        입력(이미지 데이터)이 조금이라도 바뀌면 전혀 다른 해시가 나오므로
        
        **무결성 검사에 이상적**입니다.

        👉 따라서 “Digest가 무결성 검사를 시행한다”기보다는,

        Digest는 무결성 검사를 위한 해시값으로 사용된다

        가 정확한 표현이에요.

        Docker가 Digest를 검증하는 과정

      1. docker pull 시,

        Docker Hub(Registry)는 이미지의 메타데이터와 Digest를 응답합니다.

      2. 클라이언트는 다운로드한 실제 데이터의 SHA256을 계산합니다.

      3. 서버에서 받은 Digest와 일치하는지 비교합니다.

      4. 불일치하면 다운로드 실패 (변조 방지)

        이 과정을 통해 이미지의 무결성(integrity) 과 신뢰성(trust) 을 확보합니다.

        정리 요약

        항목설명
        Digest 정의이미지 전체의 해시값(SHA256)
        형식sha256:<64자리 해시>
        기능이미지 무결성 확인, 고유 식별자 역할
        태그와 차이태그는 이름표, Digest는 고유 지문
        사용 예시docker pull hello-world@sha256:6dc565aa...
        무결성 검사 여부Docker는 Digest 비교로 무결성 검사 수행 ✅
  • #5 : 도커 이미지 ‘hello-world:latest’의 다운로드가 완료

도커 기초 명령어

도커 이미지 다운로드

docker image pull {이미지 이름:태그 이름}

**$ docker image pull ubuntu**
#1
Using default tag: latest
#2
latest: Pulling from library/ubuntu
#3
4b3ffd8ccb52: Pull complete
#4
Digest: sha256:66460d557b25769b102175144d538d88219c077c678a49af4afca6fbfc1b5252
#5
Status: Downloaded newer image for ubuntu:latest
#6
docker.io/library/ubuntu:latest
  • #1 : 태그 이름을 입력받지 않으면 자동으로 latest 태그가 적용됨
  • #2 : 우분투 이미지의 latest 태그의 우분투 이미지를 다운로드한다는 메시지가 표시됨
    • 도커 허브에서 다양한 이미지 태그 확인 가능
  • #3 : 이미지 레이어 다운로드가 완료되었다는 Pull complete 메세지가 나타남
    • 이 메세지는 이미지 레이어의 개수만큼 나타남
    • 여기서는 한 개의 메세지가 나타나는 것을 보아 우분투 이미지는 한 개의 레이어로 구성되어 있음을 알 수 있다
    • 이때 해시값은 도커 이미지가 빌드될 때 생성된 ID
  • #4 : 다운로드한 모든 레이어의 정보와 메타정보를 포함하는 이미지의 해시값
  • #5 : latest 태그를 통해 우분투 이미지를 다운로드했다는 상태 메시지를 확인 가능
  • #6 : 끝으로 다운로드한 이미지의 URL이 나타남
**$ docker image pull python:3.11.6**
3.11.6: Pulling from library/python
90e5e7d8b87a: Pull complete
27e1a8ca91d3: Pull complete
d3a767d1d12e: Pull complete
711be5dc5044: Pull complete
48b2d58a56e9: Pull complete
f4b2d251d97d: Pull complete
289cc84fca99: Pull complete
d2774833febd: Pull complete
Digest: sha256:2a725c9721f737a2944244c98c714d24f8bcfaddd9f5c15083cbaa024f7fce54
Status: Downloaded newer image for python:3.11.6
docker.io/library/python:3.11.6

docker image pull python:3.11.6

: 앞선 실습과 다르게 이미지 태그 이름을 명시해 3.11.6 태그의 파이썬 이미지 다운로드

  • 이미지를 구성하는 각 레이어의 해시값 확인 가능
  • 위 레이어를 모두 포함하는 이미지 DIGEST 값을 확인 가능

도커 이미지 상세 구조

[Image Index]  ← 여러 플랫폼용 매니페스트의 목록
   ├── [Manifest #1]  ← ex. amd64
   │      ├── config.json
   │      └── layers[]
   ├── [Manifest #2]  ← ex. arm64
   │      ├── config.json
   │      └── layers[]
   └── ...
  • Image Index(이미지 인덱스) : digest : 매니페스트 리스트 : 이미지 인덱스는 다수의 이미지 매니페스트로 구성됨
  • Image Manifest(이미지 매니페스트) : 다양한 운영체제 및 아키텍처에서 해당 이미지를 활용할 수 있도록 설정값과 다양한 레이어들을 제공함
  • Layer(레이어)
  • 도커 이미지 상세 구조 “이미지 인덱스 → 매니페스트 → config → layers” 이 3단계 구조가 Docker 이미지의 핵심 계층이에요.

    🧩 1️⃣ 큰 틀 구조

    Docker(또는 OCI) 이미지는 이렇게 계층화되어 있습니다 👇
    [Image Index]  ← 여러 플랫폼용 매니페스트의 목록
       ├── [Manifest #1]  ← ex. amd64
       │      ├── config.json
       │      └── layers[]
       ├── [Manifest #2]  ← ex. arm64
       │      ├── config.json
       │      └── layers[]
       └── ...
    
    즉,
    • 이미지 인덱스(Image Index, manifest list)

      → 여러 플랫폼(예: amd64, arm64)별 매니페스트의 “목차”

    • 매니페스트(Manifest)

      → 하나의 플랫폼 이미지의 “설계도”

    • Config + Layers

      → 그 설계도를 실제 파일과 실행 정보로 구현한 “내용물”

      🧱 2️⃣ 각 구성 요소 설명

      구성 요소파일 형태역할
      Image Index (Manifest List)index.json여러 아키텍처용 매니페스트를 나열 (예: x86_64, arm64 등)
      Manifestmanifest.json특정 플랫폼용 이미지의 레이어 목록과 config 참조
      Configconfig.json환경변수, 명령어, Entrypoint, 사용자 등 실행 정보
      Layerslayer.tar실제 파일시스템(각 명령의 변경사항)

      ⚙️ 3️⃣ 각 파일의 실제 예시 구조

      🧾 ① Image Index (Manifest List)

      index.json (또는 “manifest list”)

      {
        "schemaVersion": 2,
        "manifests": [
          {
            "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
            "digest": "sha256:aabbcc...",      // 특정 매니페스트의 식별자
            "platform": {
              "architecture": "amd64",
              "os": "linux"
            }
          },
          {
            "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
            "digest": "sha256:dd1122...",      // ARM64 버전
            "platform": {
              "architecture": "arm64",
              "os": "linux"
            }
          }
        ]
      }
      

      → 즉, 하나의 이미지 이름(hello-world:latest) 에

      여러 플랫폼용 이미지(= 매니페스트) 버전이 들어있을 수 있습니다.


      🧾 ② Manifest (단일 플랫폼용)

      {
        "schemaVersion": 2,
        "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
        "config": {
          "mediaType": "application/vnd.docker.container.image.v1+json",
          "digest": "sha256:ccddeeff...",
          "size": 7023
        },
        "layers": [
          {
            "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
            "digest": "sha256:17eec7bbc9d7...",
            "size": 12345
          },
          {
            "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
            "digest": "sha256:998877aaccff...",
            "size": 45678
          }
        ]
      }
      
    • config.digest → 실행 정보(config.json)

    • layers[].digest → 각 파일시스템 스냅샷(layer.tar)의 해시


      🧾 ③ Config (실행 설정)

      {
        "architecture": "amd64",
        "os": "linux",
        "config": {
          "Env": ["PATH=/usr/local/bin"],
          "Cmd": ["/hello"],
          "Entrypoint": null,
          "WorkingDir": "/"
        },
        "rootfs": {
          "type": "layers",
          "diff_ids": [
            "sha256:17eec7bbc9d7...",
            "sha256:998877aaccff..."
          ]
        }
      }
      

      📦 ④ Layers (파일 시스템 델타)

    • 각 레이어는 압축된 .tar.gz 파일 (layer.tar)

    • 예: apt-get install, COPY, RUN 등의 결과로 변경된 파일만 포함

    • OverlayFS로 합쳐져 하나의 루트 파일시스템으로 제공됨


      🧠 4️⃣ 요약 정리

      단계이름역할파일 예시
      1️⃣Image Index여러 아키텍처별 매니페스트의 목록index.json
      2️⃣Manifest하나의 플랫폼 이미지 정의서 (config + layers 참조)manifest.json
      3️⃣Config이미지 실행 설정, 환경변수, 명령 등config.json
      4️⃣Layers실제 파일시스템 데이터 (rootfs)layer.tar

      🧭 5️⃣ 전체 구조 다이어그램

      graph TD
          A[Image Index (Manifest List)]
          A --> B1[Manifest - amd64]
          A --> B2[Manifest - arm64]
      
          B1 --> C1[Config.json]
          B1 --> D1[Layer 1 (tar)]
          B1 --> D2[Layer 2 (tar)]
      
          B2 --> C2[Config.json]
          B2 --> D3[Layer 1 (tar)]
          B2 --> D4[Layer 2 (tar)]
      

      ✅ 정리 한 줄

      Docker 이미지는

      Image Index(=Manifest List) → Manifest → Config + Layers

      로 구성된 계층 구조를 가지며,

      인덱스는 여러 플랫폼 버전의 매니페스트를,

      매니페스트는 해당 플랫폼의 파일시스템(Layers) 과 실행 설정(Config) 을 정의합니다.

도커 이미지 목록 확인

docker image ls

**$ docker image ls**
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
ubuntu        latest    97bed23a3497   2 weeks ago     78.1MB
hello-world   latest    1b44b5a3e06a   2 months ago    10.1kB
python        3.11.6    0dba5a08d425   24 months ago   1.01GB
  • REPOSITORY : 이미지 이름
  • TAG : 이미지 태그
  • IMAGE ID : 다운로드한 이미지의 ID
    • 다운로드할 때의 DIGEST 값과 다름
      • 다운로드할 때의 DIGEST 값 : 도커 레지스트리에 존재하는 이미지의 DIGEST 값
      • IMAGE ID : 다운로드한 후에 로컬에서 할당받은 IMAGE ID 값
  • CREATED : 이미지가 만들어진 시간
  • SIZE : 이미지 크기

도커 컨테이너 실행

docker container run [이미지명]

**$ docker container run ubuntu**

아웃풋이 따로 출력되지 않음

아무일도 일어나지 않음

할일을 지정해주지 않았기에 할일이 없어서 바로 off 됨

도커 컨테이너 목록 확인

docker container ls

**$ docker container ls**
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

어떤 컨테이너도 실행되고 있지 않음

docker container ls -a

**$ docker container ls -a**
CONTAINER ID   IMAGE         COMMAND       CREATED         STATUS                     PORTS     NAMES
4a19f0dc5751   ubuntu        "/bin/bash"   3 minutes ago   Exited (0) 3 minutes ago             naughty_borg
816cb7c5cd4c   hello-world   "/hello"      2 hours ago     Exited (0) 2 hours ago               goofy_chatelet

실행 중인 컨테이너와 정지 상태인 컨테이너 모두 확인

  • CONTAINER ID : 해당 컨테이너에 대한 고유한 ID
    • IMAGE ID 와는 별개
  • STATUS
    • Up
    • Exited (0) : 컨테이너가 종료되었음을 의미함
      • 0 : 정상적으로 종료되었음을 의미함

컨테이너 내부 접속

docker container run -it [이미지 이름]

**$ docker container run -it ubuntu**
root@6fedab338d1a:/#
  • -it
    • i

      : interactive

      : 표준 입력(STDIN)을 열어놓는다는 의미

      • -i 옵션만 주면 표준 입력만 열림
    • t

      : tty
      
      : 가상 터미널
      
      - `-t` 옵션만 주면 터미널에 진입하지만 어떤 입력도 먹지 않음

      ⇒ 가상 터미널을 통해 키보드 입력을 표준 입력으로 컨테이너에 전달

  • root@6fedab338d1a : 사용자 이름과 호스트 이름이 변경된 것을 확인 가능
    • 사용자 이름 : root
    • 호스트 이름 : 컨테이너 id
  • run ubuntu : 실행 후 바로 종료
  • run -i ubuntu : 출력되는데 프롬프트가 안보임
  • run -t ubuntu : 프롬프트는 보이지만 입력 불가
root@6fedab338d1a:/# **ls**
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr

다른 터미널 창에서 컨테이너 목록 다시 확인

**$ docker container ls**
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
6fedab338d1a   ubuntu    "/bin/bash"   34 minutes ago   Up 34 minutes             gracious_sanderson

STATUS 가 Up 인 컨테이너가 보임

run -t ubuntu 를 해도 위에 뜸

→ 종료 시그널을 전달할 수 없기에 Ctrl+C 로 빠져나와도 Up 상태로 남아있게 됨

컨테이너 종료

  • 컨테이너 내부에 접속해 있는 터미널에서 exit 입력
  • docker container stop [컨테이너 id] : 약 10초 후에 컨테이너가 종료됨
  • docker container kill [컨테이너 id] : 즉시 종료됨 : 그러나 위험
  • stop vs. kill docker stop 과 docker kill 은 모두 컨테이너를 종료하는 명령이지만, “어떻게 종료하느냐(시그널 처리)”가 다릅니다. 하나씩 단계적으로 살펴볼게요 👇

    🧩 1️⃣ 공통점

    항목설명
    공통 목적컨테이너 내부 프로세스를 종료하기 위함
    결과컨테이너가 “exited” 상태로 바뀜
    대상컨테이너 내 PID 1 프로세스 (일반적으로 애플리케이션 프로세스)
    즉, 둘 다 컨테이너를 멈춘다는 점에서는 같습니다. 차이는 “종료 절차의 정도(순한 종료 vs 즉시 종료)”에 있습니다.

    ⚙️ 2️⃣ docker stop

    “정상 종료 요청” (Graceful shutdown)

    동작 순서

    1️⃣ 컨테이너의 PID 1 프로세스 에게 SIGTERM 신호를 보냄 2️⃣ 애플리케이션이 종료 작업을 수행할 시간을 줌 3️⃣ 기본 대기시간(10초, --time 옵션으로 변경 가능) 동안 기다림 4️⃣ 아직 종료되지 않으면 SIGKILL 신호를 보냄 (강제 종료)
    docker stop <container>
    # 또는
    docker stop --time=5 <container>   # 5초 후 강제 종료
    

    특징

    항목설명
    종료 신호SIGTERM → (지연 후) SIGKILL
    종료 절차정상적인 shutdown (cleanup, flush 등 가능)
    안전성안전함
    속도느림 (기본 10초 기다림)
    💡 즉:

    stop은 “문 닫기 전에 정리 좀 하고 나가세요” 라고 요청하는 명령이에요.


    ⚔️ 3️⃣ docker kill

    “즉시 강제 종료” (Forceful shutdown)

    동작 순서

    1️⃣ 컨테이너의 PID 1 프로세스에 SIGKILL 신호를 바로 보냄 2️⃣ 커널이 프로세스를 즉시 종료 (cleanup 수행 기회 없음)
    docker kill <container>
    
    또는 특정 신호로도 종료할 수 있음:
    docker kill --signal SIGINT <container>
    

    특징

    항목설명
    종료 신호SIGKILL (또는 지정한 신호)
    종료 절차비정상적인 즉시 중단
    안전성낮음 (데이터 유실 위험)
    속도빠름
    💡 즉:

    kill은 “지금 당장 꺼!” 하는 명령이에요 — 애플리케이션에게 정리할 기회를 주지 않습니다.


    🧱 4️⃣ 비교 요약

    구분docker stopdocker kill
    보내는 신호SIGTERM → (대기 후) SIGKILLSIGKILL (또는 지정 신호)
    종료 방식정상 종료 (graceful)즉시 종료 (force)
    cleanup 수행 기회있음없음
    기본 대기 시간10초 (--time 옵션 변경 가능)없음
    안전성안전함위험함 (데이터 손상 가능)
    속도느림빠름
    사용 예시웹서버나 DB 등 정상 종료 필요한 서비스멈추지 않는 컨테이너 강제 종료

    🧠 5️⃣ 실제 예시로 보기

    예를 들어 Nginx 컨테이너가 실행 중일 때:
    $ docker stop nginx
    # -> nginx 프로세스가 SIGTERM 수신 후 로그 flush, 연결 종료 후 정상 종료
    
    $ docker kill nginx
    # -> nginx 프로세스가 SIGKILL 수신 후 바로 종료 (세션, 로그 flush 안 됨)
    

    🧭 6️⃣ 요약 한 줄

    ✅ docker stop 은 정상 종료(SIGTERM → SIGKILL)

    ✅ docker kill 은 즉시 강제 종료(SIGKILL)

    → stop = polite (정상적), kill = brutal (즉시 강제)


    원하신다면 두 명령이 내부적으로 커널 수준에서 어떤 system call(kill(), waitpid())을 사용하는지까지 리눅스 시그널 플로우 형태로 그려드릴까요?
root@6fedab338d1a:/# exit
exit

종료한 컨테이너에 다시 접속하고 싶다면

docker container start [컨테이너 ID]

**$ docker container start 6fedab338d1a**
6fedab338d1a
**$ docker container ls**
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS              PORTS     NAMES
6fedab338d1a   ubuntu    "/bin/bash"   44 minutes ago   Up About a minute             gracious_sanderson

docker container attach [컨테이너 ID]

: 컨테이너 내부에 접속

**$ docker container attach 6fedab338d1a**
root@6fedab338d1a:/# history
    1  ls
    2  exit
    3  history

종료됐다가 재시작된 것이지, 삭제됐다가 재생성된 것이 아니므로 히스토리 확인 가능

# Ctrl+P
root@6fedab338d1a:/# **history**
    1  ls
    2  exit
    3  history
    4  exit
    5  history
# Ctrl+P+Q: 종료하지 않고 터미널만 빠져나옴
root@6fedab338d1a:/# **read escape sequence**

컨테이너 삭제

# 컨테이너 목록 확인
**$ docker container ls -a**
CONTAINER ID   IMAGE         COMMAND       CREATED             STATUS                         PORTS     NAMES
6fedab338d1a   ubuntu        "/bin/bash"   51 minutes ago      Exited (137) 18 seconds ago              gracious_sanderson
4a19f0dc5751   ubuntu        "/bin/bash"   About an hour ago   Exited (0) About an hour ago             naughty_borg
816cb7c5cd4c   hello-world   "/hello"      3 hours ago         Exited (0) 3 hours ago                   goofy_chatelet

# hello-world 컨테이너 삭제
**$ docker container rm 816cb7c5cd4c**
816cb7c5cd4c

# 삭제된 거 확인 가능
**$ docker container ls -a**
CONTAINER ID   IMAGE     COMMAND       CREATED             STATUS                            PORTS     NAMES
6fedab338d1a   ubuntu    "/bin/bash"   52 minutes ago      Exited (137) About a minute ago             gracious_sanderson
4a19f0dc5751   ubuntu    "/bin/bash"   About an hour ago   Exited (0) About an hour ago                naughty_borg

Up 상태인(동작 중인) 컨테이너는 삭제 불가

이미지 삭제

**$ docker image ls**
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
ubuntu        latest    97bed23a3497   2 weeks ago     78.1MB
hello-world   latest    1b44b5a3e06a   2 months ago    10.1kB
python        3.11.6    0dba5a08d425   24 months ago   1.01GB

# hello-world 이미지 삭제
**$ docker image rm hello-world**
Untagged: hello-world:latest
Untagged: hello-world@sha256:6dc565aa630927052111f823c303948cf83670a3903ffa3849f1488ab517f891
Deleted: sha256:1b44b5a3e06a9aae883e7bf25e45c100be0bb81a0e01b32de604f3ac44711634
Deleted: sha256:53d204b3dc5ddbc129df4ce71996b8168711e211274c785de5e0d4eb68ec3851

**$ docker image ls**
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
ubuntu       latest    97bed23a3497   2 weeks ago     78.1MB
python       3.11.6    0dba5a08d425   24 months ago   1.01GB

docker container ls -a 에서 컨테이너가 하나라도 존재하는 이미지는 삭제 불가

**$ docker container prune

$ docker container ls -a**
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

stop 된 모든 컨테이너 삭제

docker ps

== docker container ls

$ docker rm -f $(docker ps -aq)

== docker rm -f $(docker container ls -aq)

모든 컨테이너를 삭제

$(docker ps -aq)

  • docker ps : 컨테이너 목록
  • -aq
    • a

      : 실행 중이지 않은 컨테이너까지 모두 출력

    • q

      : 컨테이너의 ID 만 출력

      ⇒ 모든 컨테이너의 ID 출력

도커 이미지 변경

ubuntu 이미지를 public.ecr.aws/docker/library/ubuntu 해당 이미지로 변경

**$ docker image pull public.ecr.aws/docker/library/ubuntu**

**$ docker tag public.ecr.aws/docker/library/ubuntu ubuntu**

**$ docker image ls**
REPOSITORY                             TAG       IMAGE ID       CREATED              SIZE
my-ubuntu                              0.1       e416ca5d44c4   About a minute ago   135MB
ubuntu                                 latest    97bed23a3497   2 weeks ago          78.1MB
public.ecr.aws/docker/library/ubuntu   latest    97bed23a3497   2 weeks ago          78.1MB
python                                 3.11.6    0dba5a08d425   24 months ago        1.01GB

**$ docker image rm public.ecr.aws/docker/library/ubuntu**
Untagged: public.ecr.aws/docker/library/ubuntu:latest
Untagged: public.ecr.aws/docker/library/ubuntu@sha256:66460d557b25769b102175144d538d88219c077c678a49af4afca6fbfc1b5252

**$ docker image ls**
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
my-ubuntu    0.1       e416ca5d44c4   About a minute ago   135MB
ubuntu       latest    97bed23a3497   2 weeks ago          78.1MB
python       3.11.6    0dba5a08d425   24 months ago        1.01GB

터미널1

**$ docker image ls**
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
ubuntu       latest    97bed23a3497   2 weeks ago     78.1MB
python       3.11.6    0dba5a08d425   24 months ago   1.01GB

$ docker container run -it ubuntu
root@2995f8506568:/# **ifconfig**
bash: ifconfig: command not found

컨테이너 내부 IP 를 확인하려고 ifconfig 명령어를 입력한다고 해서 ifconfig 명령어를 사용할 수는 없음

→ net-tools 를 설치해야 가능

# net-tools 설치
$ docker container attach 2995f8506568
root@2995f8506568:/# **apt update && apt install net-tools**
# 이제 됨
root@2995f8506568:/# **ifconfig**
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 2a:03:c4:36:c5:51  txqueuelen 0  (Ethernet)
        RX packets 4983  bytes 34526156 (34.5 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3534  bytes 195242 (195.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

터미널2

# 현재 컨테이너의 스냅샷 이미지 저장
**$ docker container commit 2995f8506568 my-ubuntu:0.1**
sha256:e416ca5d44c4dafdf64e32695deee256ad743e3bf134b4e71fce12beea401132

**$ docker image ls**
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
my-ubuntu    0.1       e416ca5d44c4   About a minute ago   135MB
ubuntu       latest    97bed23a3497   2 weeks ago          78.1MB
python       3.11.6    0dba5a08d425   24 months ago        1.01GB

기존 컨테이너 종료 후 새롭게 만든 my-ubuntu 이미지를 컨테이너로 실행

**root@2995f8506568:/# exit**
exit
**[vagrant@docker ~]$ docker container ls -a**
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS                     PORTS     NAMES
2995f8506568   ubuntu    "/bin/bash"   14 minutes ago   Exited (0) 7 seconds ago             kind_carson

**$ docker container rm 2995f8506568**
2995f8506568

**$ docker image ls**
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
my-ubuntu    0.1       e416ca5d44c4   6 minutes ago   135MB
ubuntu       latest    97bed23a3497   2 weeks ago     78.1MB
python       3.11.6    0dba5a08d425   24 months ago   1.01GB

**$ docker container run -it my-ubuntu:0.1**
root@6a700bd5fbb4:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether fe:b8:0e:ef:88:bb  txqueuelen 0  (Ethernet)
        RX packets 8  bytes 736 (736.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3  bytes 126 (126.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

**root@6a700bd5fbb4:/# exit**
exit

docker 유용한 명령어

docker search

: Docker Hub (공식 이미지 저장소) 에서 이미지를 검색하는 명령

**$ docker search centos**
NAME                           DESCRIPTION                                     STARS     OFFICIAL
centos                         DEPRECATED; The official build of CentOS.       7779      [OK]
corpusops/centos               centos corpusops baseimage                      0
dockette/centos                My Custom CentOS Dockerfiles                    1
eclipse/centos                 CentOS based minimal stack with only git and…   1
centos/postgresql-10-centos7   PostgreSQL is an advanced Object-Relational …   21
...

Official 이미지인지 확인 가능 등

docker inspect

: Docker 객체(컨테이너, 이미지, 볼륨, 네트워크 등)의 상세 JSON 메타데이터를 출력

  • 이 명령은 Docker Engine의 내부 상태를 직접 조회
**$ docker inspect ubuntu**
[
    {
        "Id": "sha256:97bed23a34971024aa8d254abbe67b7168772340d1f494034773bc464e8dd5b6",
        "RepoTags": [
            "ubuntu:latest"
        ],
        "RepoDigests": [
            "ubuntu@sha256:66460d557b25769b102175144d538d88219c077c678a49af4afca6fbfc1b5252"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2025-10-01T13:01:37.838375075Z",
        "DockerVersion": "26.1.3",
...

즉, docker search 는 원격 API를, inspect 는 로컬 Docker Daemon API를 사용

구분docker searchdocker inspect
목적Docker Hub 등 원격 저장소에서 이미지 검색로컬 Docker 엔진의 객체 상세 정보 조회
대상이미지 이름(검색어)컨테이너, 이미지, 네트워크, 볼륨 등
출력 형식표 형태 (요약)JSON 형태 (상세)
정보 수준개요 수준매우 세부 수준
사용 위치원격 (인터넷 연결 필요)로컬 (Docker Daemon 필요)
예시docker search ubuntudocker inspect nginx

docker save -o

: Docker 이미지의 내보내기(export)

docker load -i

: Docker 이미지의 가져오기(import)

⇒ Docker Hub를 거치지 않고 이미지 파일을 직접 주고받고 싶을 때 사용하는 명령

**$ docker save -o my_image.tar ubuntu:latest

$ ls**
my_image.tar

**$ docker image ls**
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
my-ubuntu    0.1       e416ca5d44c4   13 minutes ago   135MB
ubuntu       latest    97bed23a3497   2 weeks ago      78.1MB
python       3.11.6    0dba5a08d425   24 months ago    1.01GB

**$ docker image rm ubuntu:latest**
Untagged: ubuntu:latest
Untagged: ubuntu@sha256:66460d557b25769b102175144d538d88219c077c678a49af4afca6fbfc1b5252

**$ docker load -i my_image.tar**
Loaded image: ubuntu:latest

**$ docker image ls**
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
my-ubuntu    0.1       e416ca5d44c4   15 minutes ago   135MB
ubuntu       latest    97bed23a3497   2 weeks ago      78.1MB
python       3.11.6    0dba5a08d425   24 months ago    1.01GB
명령어동작방향
docker save이미지를 tar 파일로 내보냄 (Export)로컬 → 파일
docker loadtar 파일에서 이미지를 불러옴 (Import)파일 → 로컬

docker save 는 이미지를 파일로 백업,

docker load 는 그 파일을 다시 Docker에 복원하는 명령

둘 다 Docker Hub 없이 이미지 전달이 가능하다는 게 핵심

docker export / docker import 와의 차이점

명령어대상포함 정보목적
docker save/load이미지모든 레이어 + 메타데이터 (완전한 이미지 구조)이미지 백업/복원용
docker export/import컨테이너파일시스템 스냅샷 (실행 상태 기반)컨테이너 상태 복제용

docker create

: docker 컨테이너 생성

**$ docker create --name os2 ubuntu:latest**

**$ docker ps -a**
CONTAINER ID   IMAGE           COMMAND       CREATED          STATUS                      PORTS     NAMES
f4c22e2d5688   ubuntu:latest   "/bin/bash"   25 seconds ago   Created                               os1
6a700bd5fbb4   my-ubuntu:0.1   "/bin/bash"   15 minutes ago   Exited (0) 15 minutes ago             elegant_gauss

os1 이라는 name 을 가진 컨테이너 생성됨

→ STATUS: Created

**$ docker create -it --name os1 ubuntu:latest**
  • name : os1 이라는 name 을 가진 컨테이너를 생성함
  • -it : 컨테이너가 나중에 실행될 때 표준 입력 및 tty 가 할당되도록 설정

docker run

== create + start

profile
새싹 개발자

0개의 댓글