• [Docker] 컨테이너, 이미지란? 동작 방식은?

    2021. 6. 10.

    by. SDev

    728x90

    *** 본 정리는 2021 멋쟁이사자처럼 세렝게티올빼미 프로젝트 kubernetes 그룹에서 학습을 목적으로 정리한 글입니다.

    참고 자료: Docker and Kubernetes : The Complete Guide - udemy


     

    Docker를 Windows나 Mac에 설치한 후 터미널에서 '$ docker run hello-world'를 입력해보자.

     

     

    중간 부분에 "Hello from Docker!"가 출력되는데, 그 아래 Docker가 어떤 방식으로 동작했는지 설명이 출력되어 있다.

     

    Docker의 동작 구조 그림과 함께 보면 다음과 같다.

    1. Terminal에서 입력한 명령으로 Docker Client에게 명령이 전달된다. Docker Client는 다시 Server로 해당 명령을 전달한다.
    2. Docker Server는 hello-world라는 이미지를 찾기 위해 Image Cache를 확인해보지만 Image Cache는 비어있다.(혹은 hello-world라는 이미지를 갖고 있지 않다.)
    3. Docker Server는 해당 이미지를 찾기 위해 원격저장소인 Docker Hub를 방문해 hello-world 이미지를 요청한다.
    4. Docker Hub는 로컬의 Image Cache에 요청한 이미지를 내려준다.
    5. Docker Client는 받아온 이미지를 바탕으로 컨테이너를 생성해 프로그램을 실행한다.

     

    이후 다시 '$ docker run hello-world'을 입력해보면, 이전 응답에서 가장 첫 줄에 출력됐던 "Unable to find image 'hello-world:latest' locally"가 나타나지 않는다. 이미 Docker Hub로부터 hello-world 이미지를 내려받아 Image Cache에 해당 이미지를 갖고 있기 때문이다.

     

     

     

    • 이미지? 컨테이너?

     

    Image는 프로그램을 실행하기에 필요한 각종 의존성, 설정들을 모두 갖고 있는 Single File이다.

    Container는 Image를 바탕으로 실제로 프로그램을 실행시키는 인스턴스다.

     

     

     

    • 컨테이너는 어떻게 동작할까?

    OS의 작동 구조는 위 사진처럼 프로세스들이 하드웨어 자원을 요청하기 위해 Kernel로 System Call을 통해 자원을 요청하고, 할당 받는다.

    그런데, 만약 위 사진처럼 Python을 요청하지만 서로 다른 버전을 요청하는 경우가 있다면 어떻게 될까? 한 하드웨어 공간에서 Python에 대한 두 버전을 설치하는 것은 문제가 발생할 수 있기 때문에, 아래와 같이 Hard Disk를 나누게 된다.

     

     

    Hard Disk에서 각 프로세스에 대한 Segment를 나눠두고, 각 프로세스가 Hard Disk를 read하는 System Call을 커널로 전달하면, 커널에서는 어떤 프로세스가 시스템콜을 발생시켰는지 확인하고 Hard Disk 내 해당 프로세스의 segment에 접근해 원하는 리소스를 제공해주는 방식으로 작동된다. 이처럼 Hard Disk를 각 프로세스를 위한 segment로 나눠 저장하도록 하는 방식을 네임스페이싱(Namespacing)이라 한다.

     

     

     

    • Namespacing? Control Groups(cgroups)?

    네임스페이싱은 하나의 프로세스나 프로세스 그룹별로 자원(resource)를 분리(isolate)하는 방법이다. 네임스페이싱은 하드웨어에만 사용되는 것은 아니며 소프트웨어 요소에도 적용되는 개념이다. 네트워크 장치에도 적용할 수 있고, 다른 프로세스에 대한 소통, 조회 능력(the ability to talk to other processes or the ability to see other processes)에도 적용된다. 이처럼 프로세스가 이용할 필수적인 자원 제한을 위해 네임스페이스를 활용한다.

     

    그런데 스페이싱은 Control Group이라고 불리는 하나의 기능의 일종이다. cgourp은 특정한 프로세스가 사용할 수 있는 자원의 총 양을 제한(limit)하는데 사용한다.

    • Name spacing: hey, this area of the hard drive is for this process.
    • cgroup: Limit the amount of memory that a process can use, the amount of CPU

     

    +++ 네임스페이싱과 cgroup은 리눅스에서만 사용되며, Mac OS나 Windows에서 사용되지 않음

     

     

    컨테이너는 이처럼 프로세스와 OS 동작구조 내에서 수직적인 하나의 전체 running process를 일컫는 용어다.

     

    정리하자면, 컨테이너는 위와 같은 형태로 하나의 프로세스나 a set of processes의 자원들을 한데 모은 형태로 구성되어 있다.

     

     

     

    • Image(Single File)로 어떻게 이런 컨테이너를 생성할 수 있을까?

    예시 Image에는 크롬과 파이썬(FileSystem Snapshot), 구체적인 실행 커맨드가 포함되어 있다. 이를 바탕으로 오른쪽 그림처럼 컨테이너를 생성하려고 한다.

     

    1. 커널은 Hard Drive의 특정 섹션을 이 컨테이너를 위해 분리한다.
    2. Hard Drive의 segment(분리시킨 섹션)에 image의 파일스냅샷을 저장한다.
    3. 실행커맨드가 실행된다.

     

    결과적으로 이와 같은 형태로 이미지를 바탕으로 컨테이너가 생성되어, 이미지의 인스턴스로 실행된다.

     

     

     

    • 네임스페이싱과 cgroup은 리눅스에서 사용하는 개념인데 어떻게 Windows와 Mac에서 Docker를 사용할 수 있을까?

    Docker를 설치할 때 Linux 가상머신을 설치하게 된다. 이 안에서 각 컨테이너를 생성해 실행하는 방식으로 동작하는 것이다. Mac이나 Window 위에 Linux VM을 실행시키고, 그 Linux VM 위에 각 컨테이너를 실행시키는 것이다.

     

    이는 터미널에서 '$ docker version'을 입력했을 때 나오는 정보로 간단히 확인해볼 수 있다.

    Server의 engine/OS/Arch 항목을 보면 linux/amd64로 되어 있다. Mac 환경에서 Docker를 실행시키는데, Docker Server는 사실상 Linux 상에서 동작되고 있다.

    댓글