Docker Architecture and Image — 도커 아키텍처와 이미지 명령어

도커가 어떤 구조로 동작하는지 이해하면 명령어를 외우지 않아도 흐름이 보인다. 도커는 클라이언트-서버 아키텍처를 기반으로 동작하며, 이미지를 관리하는 다양한 명령어를 제공한다.

도커 아키텍처

도커는 클라이언트-서버 아키텍처를 사용한다.

Docker 아키텍처

아키텍처는 크게 세 가지 구성요소로 나뉜다.

도커 데몬(docker daemon)

사용자 모르게 백그라운드에서 실행되며 특정 작업을 수행하는 프로그램이다. 도커 API 요청(request)을 수신하고 이미지, 컨테이너, 네트워크, 볼륨과 같은 도커 객체를 관리한다. 데몬은 다른 데몬과 통신하여 도커 서비스를 관리할 수도 있다 (예: Kubernetes).

도커 클라이언트(docker client)

많은 도커 사용자와 도커가 상호 작용하는 기본 방법이다. docker run과 같은 명령을 사용하면, 클라이언트는 이러한 명령을 수행하도록 데몬(dockerd)에게 전송한다. 도커 명령은 도커 API를 사용하며, 둘 이상의 데몬과 통신이 가능하다.

도커 레지스트리(docker registry)

도커 이미지를 저장하는 저장소이다. Docker Hub는 누구나 사용할 수 있는 공개 레지스트리이며, 도커는 기본적으로 Docker Hub에서 이미지를 찾는다. 개인 레지스트리를 실행할 수도 있다.

도커 객체(docker object)

도커를 사용하면 이미지, 컨테이너, 네트워크, 볼륨, 플러그인 및 기타 객체를 만들고 사용하게 된다.

  • 이미지: 특정 프로그램을 실행하는 데 필요한 모든 것을 담고 있는 Read-Only 템플릿이다. 도커 컨테이너의 생성 지침이 포함된 읽기 전용 템플릿으로, 이미지를 생성하려면 도커 파일(Dockerfile)을 작성해야 한다. 도커 파일의 각 명령어는 이미지에 레이어(layer)를 만든다. 도커 파일을 수정하고 이미지를 다시 빌드(build)하면, 변경된 레이어만 다시 빌드된다.
  • 컨테이너: 이미지의 실행 가능한 인스턴스이다. 도커 API 또는 CLI를 사용하여 컨테이너를 생성, 시작, 중지, 이동, 삭제할 수 있다. 컨테이너가 제거되면 영구 저장소(볼륨)에 저장되지 않은 상태 변경사항이 모두 사라진다.

도커 엔진의 기술 변화

도커 엔진 기술 변화

초기 도커 엔진은 리눅스 컨테이너(LinuX Container, LXC)를 기반으로 작동했다. chroot, 네임스페이스, cgroup을 조합하여 프로세스 가상화를 구현했다.

하지만 Docker 이후로 많은 컨테이너 런타임이 생겨났고, 당시 컨테이너 런타임에 대한 표준 인터페이스가 존재하지 않아 런타임별 서로 다른 인터페이스를 갖는 경우가 빈번하여 많은 혼란과 불편함이 발생했다.

이러한 문제를 해결하기 위해, 2015년 6월 IBM, Docker, CoreOS, Google, MS 등 주요 회사들이 컨테이너 형식 및 런타임에 대한 개방형 산업 표준인 OCI(Open Container Initiative)를 구성했다.

이후 0.9.0 버전부터는 libcontainer OCI를 이용하여 도커 엔진을 구성하였고, 1.11.0 이후 버전부터 도커 엔진은 도커 데몬(dockerd), 컨테이너 데몬(containerd), runC OCI를 이용하여 컨테이너들을 관리하는 구조로 발전했다.

  • 도커 데몬(dockerd): 도커 CLI로부터 명령어를 수신하여 처리
  • 컨테이너 데몬(containerd): 컨테이너 런타임 툴. 네트워크, 볼륨 등은 도커 데몬에 맡기고 컨테이너 관리 기능만 담당
  • runC: 컨테이너를 실제 생성하고 종료시키는 역할 수행. 호스트 OS에 대한 의존성을 제거하여 리눅스에 의존적인 문제를 해결

도커 실행 원리

도커는 클라이언트와 서버로 구성된다.

  • 클라이언트: 도커 명령을 입력받는 명령줄을 제공하며, 입력된 도커 명령은 서버의 도커 데몬에게 전달
  • 서버: 도커 엔진의 도커 데몬을 이용하여 컨테이너를 시작, 운영, 정지 등을 담당. 도커 데몬이 실행되는 환경에 존재

실행 흐름:

  1. 클라이언트는 도커 명령을 입력받는 명령줄을 제공하며, 입력된 도커 명령은 서버의 도커 데몬에게 전달한다
  2. 도커 데몬은 docker.socket이 보유한 도커 API를 이용하여 컨테이너 생성 및 명령을 수행한다
  3. 컨테이너에서 수행된 서비스 결과를 클라이언트에게 전달 및 실행 결과를 출력한다

도커 이미지 명령어

로컬 서버 및 데스크톱에 도커 이미지를 저장하는 방법은 두 가지이다:

  1. Dockerfile을 통해 새로운 이미지를 생성(docker build)하는 방법
  2. 도커 허브로부터 이미지를 내려받는(docker pull) 방법

이미지를 실행(docker run)하면 서비스하려는 애플리케이션 컨테이너가 된다.

도커 이미지 명령어 흐름도

이미지 관련 명령어

사용법: docker image COMMAND

명령 설명
build Dockerfile에서 이미지 빌드
history 이미지의 기록 표시
import tarball에서 내용을 가져와서 파일 시스템 이미지 생성
inspect 하나 이상의 이미지에 대한 세부 정보 표시
load tar 아카이브 또는 STDIN에서 이미지 로드
ls 이미지 목록 나열
prune 사용하지 않는 이미지 제거
pull 레지스트리(기본: Docker Hub)에서 이미지 다운로드
push 이미지를 레지스트리에 업로드
rm 하나 이상의 이미지 제거
save 하나 이상의 이미지를 tar 아카이브에 저장
tag SOURCE_IMAGE를 참조하는 TARGET_IMAGE 태그를 생성

pull 명령 — 이미지 다운로드

$ docker [image] pull [OPTIONS] NAME[:TAG|@DIGEST]
  • NAME: 이미지 이름 (예: debian)
  • TAG: 이미지 버전. 태그를 입력하지 않으면 자동으로 latest로 지정된다
  • @IMAGE_DIGEST: 다이제스트(원격 도커 레지스트리에서 관리하는 이미지 고유 식별 값)
$ docker pull debian                  # latest 태그 자동 지정
$ docker pull debian:10.3             # 특정 태그 명시
$ docker image ls                     # 다운로드된 이미지 목록 확인

pull 명령의 상세 출력에서 확인할 수 있는 항목:

  1. 이미지 태그 값 출력 (태그를 입력하지 않으면 자동으로 최신버전 지정)
  2. 이미지 버전: 라이브러리는 도커 허브가 이미지를 저장하고 있는 네임스페이스로 제공된다
  3. 도커 허브에서 제공되는 이미지의 분산해시(distribution hash) 값
  4. 다이제스트: 도커 허브(또는 원격 도커 레지스트리)에서 관리하는 이미지 고유 식별 값
  5. 상태: 다운로드한 이미지의 상태 정보
  6. docker.io는 도커 허브의 이미지 저장소 주소를 나타낸다

이미지 및 컨테이너 구조

이미지는 레이어 구조로 되어 있다. 예를 들어 Web App 이미지는 아래와 같은 레이어를 가질 수 있다:

  1. Layer 1: Debian Linux (베이스 이미지)
  2. Layer 2: Apache httpd
  3. Layer 3: Web App 소스코드

각 레이어는 읽기 전용(Read-Only)이며, 컨테이너를 실행하면 이미지 레이어 위에 읽기/쓰기 가능한 레이어가 추가된다. 하나의 이미지로 여러 컨테이너를 생성할 수 있으며, 각 컨테이너는 자신만의 읽기/쓰기 레이어를 갖는다.