Connecting

불좀 꺼줄래? 내 Docker좀 보게 PART 2 - 컨테이너와 Docker 설치방법 본문

Container

불좀 꺼줄래? 내 Docker좀 보게 PART 2 - 컨테이너와 Docker 설치방법

팬도라 2020. 11. 12. 10:59
반응형

컨테이너

우리가 일반적으로 생각하는 컨테이너는 무엇인가?

선박 운영에 있어서 사용되는 컨테이너는 일종의 표준 규격을 가지고 안에 화물을 넣어서 쉽게 이동할 수 있는 인류의 물품 수송에 일대 혁명을 가져온 발명품이다. 컨테이너가 없던 시절 크레인과 인력을 동원하여 화물을 적양하 하는 것이 일반적이었다. 여기서 발생하는 인력과 시간 및 사고와 물자 분실은 필수 불가결한 존재였다. 하지만 컨테이너가 등장하면서 규격화된 크레인과 수송체계만 있으면 과정이 매우 단순화되며 비용도 크게 줄었다.

우리가 학습할 컨테이너도 운송용 컨테이너와 다르지 않다. 만약 본인이 Go로 작성된 어떠한 애플리케이션을 만들고 있다고 가정한다. 당연히 본인 컴퓨터에서는 관련 환경설정이 되어 있기 때문에 개발하고 운영하는데 아무런 지장이 없겠지만 다른 이가 내가 만든 애플리케이션을 이어서 개발하거나 실행하고자 한다면 본인과 다른 컴퓨팅 한경 때문에 정상적으로 실행이 되지 않을 것이고 이를 실행하기 위한 별도의 세팅 과정이 필요할 것이다. 만약 이렇게 만들어진 애플리케이션이 다양한 라이브러리와 의존성을 가지고 있다면, 서로 다른 개발자 컴퓨터 사이의 개발환경 세팅에 따라 오류가 발생할 수 있고 이를 해결하기 위한 엄청난 노력이 필요할 것이다. 이를 효과적으로 해결할 수 있는 방법이 바로 컨테이너이다.

컨테이너는 위의 부록에서 반시 언급한 operating-system-level virtualization의 종류이다.

운영체제 수준에서 가상화하는 방식을 채택하기 때문에 별도의 하드웨어가 필요하지 않고 본인이 실행하고 있는 운영체제 커널을 공유해서 컨테이너를 실행하게 되며 하이퍼바이저를 사용하는 가상화 기술 대비 매우 빠른 속도로 실행되는 특징을 가지고 있다. 물론 프로세스를 격리하기 때문에 약간의 오버헤드를 가질 수 있지만 하이퍼바이저에서 발생하는 오버헤드에 비하면 미미한 수준이며, 하나의 운영체제에서 다수의 프로세스가 실행되고 있는 것과 같이 다수의 컨테이너를 실행하는 것도 가능하다.

이렇게 격리된 컨테이너는 호스트의 환경이 아닌 독자적인 실행환경을 가지고 있기 때문에 다른 운영체제 혹은 다른 개발 환경에서도 독립적으로 실행이 가능하고, 상태를 가지지 않는 특성 때문에 다른 컨테이너에게 영향을 주지 않으면서 파일 혹은 이미지 형식으로 쉽게 공유할 수 있다. 이러한 컨테이너의 기능을 잘 이해하기 위해서는 리눅스 컨테이너의 동작을 이해할 필요가 있다.

리눅스 컨테이너 LXC

리눅스 컨테이너 LXC는 리눅스에서 컨테이너 기능을 제공하기 위한 인터페이스다. 기본적으로 API를 제공하기 때문에 리눅스 사용자가 쉽게 시스템 또는 애플리케이션 컨테이너를 생성하고 관리할 수 있게 도와주는 역할을 수행한다. 리눅스 컨테이너 LXC가 운영체제 수준 가상화이기 때문에 namespce, Apparmor와 SELinux, Seccomp, chroot, CGroups과 같은 커널 기능을 사용한다. 여기서 가장 중요하게 살펴봐야 할 것이 namespace와 CGroups이다.

  • namespace

    • 하이퍼바이저에서는 게스트 머신이 독립적인 공간을 제공하고 서로 충돌이 나지 않도록 관리하는 기능을 가지고 있는데, 리눅스 커널에는 namespace가 동일한 역할을 담당한다. 리눅스 커널에는 8가지의 namespace가 제공되고 있는데 살펴보면 다음과 같다.

      • mnt (파일 시스템 마운트): 호스트 파일 시스템에 구애받지 않고 독립적으로 파일 시스템을 마운트 하거나 언마운트 가능
      • pid (프로세스): 독립적인 프로세스 공간을 할당
      • net (네트워크): namespace 간에 network 충돌 방지 (중복 포트 바인딩 등)
      • ipc (SystemV IPC): 프로세스 간의 독립적인 통신 통로 할당
      • uts (hostname): 독립적인 hostname 할당
      • user (UID): 독립적인 사용자 할당
      • Time Namespace : 독립적인 시스템 시간 할당
      • Control group (cgroup) Namespace : 자신이 속한 cgroup의 그룹의 상대적인 경로 제공

![](https://camo.githubusercontent.com/5a17e1529afffcd02d251093ff5d116ee687bcff/68747470733a2f2f74686570726163746963616c6465762e73332e616d617a6f6e6177732e636f6d2f692f62706e396673326c766d67696779767961376f742e706e67)
  • CGroups

    • 커널에서 사용되는 자원 (resources)에 대한 제어를 가능하게 하는 기능을 말한다. 이 기능 없이는 각각의 컨테이너에서 별도의 자원을 사용할 수 없기 때문에 실행 자체가 불가능하다. CGroups에서는 다음과 같은 자원을 제어한다.

![](https://i.stack.imgur.com/uLPjc.png)

-   CPU
-   메모리
-   I/O (입출력)
-   네트워크
-   device 노드

이렇게 정의한 콘셉트를 그림으로 표현하면 다음과 같다.

우리가 리눅스 운영체제에 커널에 대한 모든 내용을 전부 숙지할 수는 없겠지만 최소한 Docker 컨테이너를 제대로 이해해야 Docker에서 발생하는 여러 제약사항이나 문제점을 쉽게 이해하고 찾을 수 있는 해결력을 가질 수 있다. 더불어서 LXD라는 것도 존재하는데 이는 LXC를 사용하는 컨테이너 시스템이다. Docker를 사용하던 LXD를 사용하던지 상관없이 우리는 리눅스 커널의 LXC의 기능을 사용한다.

부록 - 컨테이너는 만능일까?

리눅스 컨테이너는 당연히 리눅스 커널에서 관리하기 때문에 리눅스 이외에는 동작하지 않고, 컨테이너 환경에서 다른 OS를 설치할 수 없다. 실습을 진행하면서 다른 운영체제를 다운로드하여서 설치하는 경우를 보면서 헷갈릴 수가 있지만 엄밀하게 말하면 실행 중인 커널은 하나이기 때문에 다른 운영체제 컨테이너를 다운로드하더라도 호스트 OS의 커널을 사용하면서 동작한다. 따라서 컨테이너별 별도의 커널 구성이 불가하기 때문에 컨테이너마다 다른 커널을 설치하고 운영하는 것조차 불가능하다.

그렇다면 윈도우는 컨테이너 사용이 불가능할까? 원칙적으로는 불가능하지만 가상화 기술을 이용해 이를 보안한다. 기존 윈도우에서 컨테이너 즉 Docker를 사용하기 위해서는 윈도에서 제공하는 별도의 하이퍼바이저를 사용해서 리눅스를 설치하고 이 기반위에서 동작하게 구현을 해두었다. 하지만 WSL (Windows Subsystem for Linux)이 포함되면서 윈도우 커널 안에도 리눅스 호환 커널 인터페이스를 제공하기 시작했고, WSL2를 통해 윈도우에서도 Docker 사용이 원활해졌다.

Docker

Docker는 솔로몬 하익스 (Solomon Hykes)가 설립한 프랑스 PaaS기업인 dotCloud에서 내부 프로젝트로 진행되었던 컨테이너 시스템을 오픈소스로 공개하고 회사 이름을 Docker로 변경하게 되었다. 기존 리눅스 컨테이너의 기능을 상당 부분 사용했으며, 사실상 업계 표준으로 사용되면서, Docker로 작성된 패키지 / 이미지가 많기 때문에 접근성과 사용하기 좋다는 장점을 가지고 있다.

Docker Installation

본격적으로 Docker를 사용하기 이전에 각 운영체제별로 Docker를 설치하는 방법을 기술하도록 하겠다.

Windows 10

윈도우 2004 WSL2 기반으로 설치하는 방법을 기술하도록 하겠다.

  1. 제어판 -> windows 기능 켜기 / 끄기 에서 Linux용 windows 하위 시스템을 체크하고 재부팅한다.

  2. powershell를 관리자 권한으로 실행하고 다음 명령어를 입력한다.

    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
  3. WSL 2를 설치하기 위해 Virtual Machine 플랫폼 옵션 기능을 사용하도록 설정한다.

    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
  4. Linux 커널 업데이트 패키지를 다운로드하고 실행한다.

  5. WSL 2를 기본 버전으로 사용하도록 설정한다.

    wsl --set-default-version 2
  6. 스토에서 리눅스 배포판이 정상적으로 설치가 진행되는지 확인한다.

  7. 선택적으로 윈도우 터미널을 설치하여 사용할 수 있다.

  8. 다음 링크를 접속해서 Docker Desktop for Windows를 다운로드한다. Stable 버전을 다운받는것을 권장한다.

Linux

리눅스에서는 Ubuntu 20.04 LTS 버전을 기준으로 기술한다.

  1. 먼저 패키지를 업데이트하고 필요 프로그램을 다운로드한다.

    $ sudo apt-get update
    
    $ sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg-agent \
        software-properties-common
  2. Docker 공식 GPG키를 추가한다.

    $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    
    $ sudo apt-key fingerprint 0EBFCD88
    
    pub   rsa4096 2017-02-22 [SCEA]
          9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
    uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
    sub   rsa4096 2017-02-22 [S]
    
  3. 각 아키텍처 별로 레파지토리를 추가한다. 일반적으로 우리가 사용하는 컴퓨터의 경우 x86_64 / amd64를 사용한다.

    • x86_64 / amd64

      $ sudo add-apt-repository \
         "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
         $(lsb_release -cs) \
         stable"
    • armhf

      $ sudo add-apt-repository \
         "deb [arch=armhf] https://download.docker.com/linux/ubuntu \
         $(lsb_release -cs) \
         stable"
    • arm64

      $ sudo add-apt-repository \
         "deb [arch=arm64] https://download.docker.com/linux/ubuntu \
         $(lsb_release -cs) \
         stable"
  4. Docker 설치를 진행한다.

     $ sudo apt-get update
     $ sudo apt-get install docker-ce docker-ce-cli containerd.io

Mac OS

macOS Catalina에서 brew를 사용하여 설치하는 방법으로 기술한다.

  1. brew를 사용해서 설치할 것이기 때문에 brew가 설치되어있지 않다면 다음 링크에서 brew를 먼저 설치하는 것을 권장한다.

  2. 설치를 진행한다.

    $ brew search docker
    $ brew cask install docker

    모든 설치가 완료되었다. 다음부터 본격적으로 Docker 기본 사용법에 대해서 알아보도록 하겠다.

Comments