[Docker & K8s] (1) - 도커란?

도커란?

 

도커(Docker)는 리눅스 컨테이너에 여러 기능을 추가함으로써 애플리케이션을 컨테이너로서 좀 더 쉽게 사용할 수 있게 만들어진 오픈소스 프로젝트입니다. 도커는 Go 언어로 작성돼 있으며, 2013년 3월에 첫 번째 릴리스가 발표된 이후 지금까지 꾸준히 개발되고 있습니다. 기존에 쓰이던 가상화 방법인 가상 머신과는 달리 도커 컨테이너는 성능의 손실이 거의 없어서 차세대 클라우드 인프라 솔루션으로서 많은 개발자들에게 주목받고 있습니다.

 

도커와 관련된 프로젝트는 도커 컴포즈(Docker Compose), 레지스트리(Private Registry), 도커 허브(Docker Hub), Docker for Desktop 등 여러 가지가 있지만 일반적으로 도커라고 하면 도커 엔진(Docker Engine) 혹은 도커에 관련된 모든 프로젝트를 의미합니다. 보통 도커 엔진이라는 의미로 더 많이 쓰이는데 도커 엔진은 컨테이너를 생성하고 관리하는 주체로서 이 자체로도 컨테이너를 제어할 수 있고 다양한 기능을 제공하는 도커의 주 프로젝트이기 때문입니다.

 

가상 머신과 도커 컨테이너

 

기존의 가상화 기술은 하이퍼바이저를 이용해 여러 개의 운영체제를 하나의 호스트에서 생성해 사용하는 방식이었습니다. 이러한 여러 개의 운영체제는 가상 머신이라는 단위로 구별되고, 각 가상 머신에는 우분투(Ubuntu), CentOS 등의 운영체제가 설치되어 사용됩니다. 하이퍼바이저에 의해 생성되고 관리되는 운영체제는 게스트 운영체제(Guest OS)라고 하며, 각 게스트 운영체제는 다른 게스트 운영체제와는 완전히 독립된 공간과 시스템 자원을 할당받아 사용합니다. 이러한 가상화 방식을 사용할 수 있는 대표적인 가상화 툴로 VirtualBox, VMware 등이 있습니다.

가상 머신과 도커 컨테이너의 구조

 

그러나 각종 시스템 자원을 가상화하고 독립된 공간을 생성하는 작업은 하이퍼바이저를 반드시 거치기 때문에 일반 호스트에 비해 성능의 손실이 발생합니다. 그뿐만 아니라 가상 머신은 게스트 운영체제를 사용하기 위한 라이브러리, 커널 등을 전부 포함하기 때문에 가상 머신을 배포하기 위한 이미지로 만들었을 때 이미지의 크기 또한 커집니다. 즉, 가상 머신은 완벽한 운영체제를 생성할 수 있지만 위와 같은 여러 단점들이 있습니다.

 

이에 비해 도커 컨테이너는 가상화된 공간을 생성하기 위해 리눅스의 자체 기능인 chroot, 네임스페이스(namespace), cgroup을 사용함으로써 프로세스 단위의 격리 환경을 만들기 때문에 성능 손실이 거의 없습니다. 컨테이너에 필요한 커널은 호스트의 커널을 공유해 사용하고, 컨테이너 안에는 애플리케이션을 구동하는 데 필요한 라이브러리 및 실행 파일만 존재하기 때문에 컨테이너를 이미지로 만들었을 때 이미지의 용량 또한 가상 머신에 비해 대폭 줄어듭니다. 

 

도커를 시작해야 하는 이유

 

컨테이너를 다루는 도구는 CRI-O, Podman 등 여러 가지가 존재하지만, 그 중에서도 도커는 컨테이너 생태계에서 가장 보편적으로 사용되어 온 도구입니다. 컨테이너를 사용하기 위해 반드시 도커를 사용해야 하는 것은 아니지만, 일반적으로 컨테이너하면 도커를 가장 많이 떠올리기 때문에 도커는 쿠버네티스를 비롯한 다양한 오픈소스 프로젝트에 많은 영향을 미쳤으며, 지금도 다양한 컨테이너 생태계에 영향을 주고 있습니다.

 

그렇다면 왜 그렇게 많은 회사와 프로젝트가 도커와 같은 컨테이너 기술을 선택했는지, 그리고 왜 도커를 시작해야 하는지 개발자 입장에서 먼저 이야기해 보도록 하겠습니다.

 

1. 애플리케이션의 개발과 배포가 편해집니다

 

서버를 부팅할 때 실행되는 운영체제를 일반적으로 '호스트 OS'라고 부르며, 도커 컨테이너는 호스트 OS 위에서 실행되는 격리된 공간입니다. 따라서 컨테이너 자체에 특별한 권한을 주지 않는 한, 컨테이너 내부에서 수많은 소프트웨어를 설치하고 설정 파일을 수정해도 호스트 OS에는 영향을 끼치지 않습니다. 즉, 독립된 개발 환경을 보장받을 수 있다는 것입니다.

 

컨테이너 내부에서 여러 작업을 마친 뒤 이를 운영 환경에 배포하려고 한다면, 해당 컨테이너를 '도커 이미지'라고 하는 일종의 패키지로 만들어 운영 서버에 전달하기만 하면 됩니다. 컨테이너에서 사용되던 패키지를 운영 서버에서 새롭게 설치할 필요도 없으며 각종 라이브러리 설치 등으로 인한 의존성을 걱정할 필요도 없습니다. 이로 인해 개발/운영 환경의 통합이 가능해집니다.

 

게다가 도커 이미지는 가상 머신의 이미지와 달리 커널을 포함하고 있지 않기 때문에 이미지 크기가 그다지 크지 않습니다. 또한 도커는 이미지 내용을 레이어 단위로 구성하며, 중복되는 레이어를 재사용할 수 있어서 애플리케이션의 배포 속도가 매우 빨라진다는 장점이 있습니다.

 

2. 여러 애플리케이션의 독립성과 확장성이 높아집니다

 

소프트웨어의 여러 모듈이 상호 작용하는 로직을 하나의 프로그램 내에서 구동시키는 방식을 모놀리스(Monolith) 애플리케이션이라고 합니다. 소규모 서비스에서는 이 방식이 어울릴지도 모르지만, 서비스의 기능이 복잡해지고 거대해질수록 소프트웨어 자체의 확상성과 유연성이 줄어든다는 단점이 있습니다. 이러한 모놀리스 방식을 대체하기 위해 새롭게 떠오른 개념이 바로 마이크로서비스(Microservices) 구조입니다.

 

마이크로서비스 구조는 여러 모듈을 독립된 형태로 구성하기 때문에 언어에 종속되지 않고 변화에 빠르게 대응할 수 있으며, 각 모듈의 관리가 쉬워진다는 장점이 있습니다. 컨테이너는 수 초 내로 생성, 시작이 가능할 뿐만 아니라 여러 모듈에게 독립된 환경을 동시에 제공할 수 있기 때문에 마이크로서비스 구조에서 가장 많이 사용되고 있는 가상화 기술입니다.

 

예를 들어 웹 서비스는 데이터베이스 컨테이너와 웹 서버 컨테이너로 분리할 수 있고, 웹 서비스에 부하가 발생할 시 마이크로서비스 구조의 웹 서버 컨테이너만 동적으로 늘려서 부하를 분산할 수 있습니다. 또한 웹 서버와 데이터베이스의 이미지 버전을 독립적으로 관리하기 때문에 유지 보수도 용이해집니다.

 

3. 도커를 통해 컨테이너 기술을 쉽게 학습할 수 있습니다

 

컨테이너라고 하면 일반적으로 도커 컨테이너를 떠올리지만, 사실 컨테이너를 사용하기 위해 반드시 도커를 사용해야 하는 것은 아닙니다. 컨테이너 환경 자체를 구축하는 것은 간단한 셸 스크립트로도 가능할 정도로 단순할 수도 있지만, 도커나 Podman 등과 같이 컨테이너 기술을 사용자 레벨에서 적절히 추상화한 도구들을 사용할 수도 있습니다. 따라서 도커는 컨테이너를 사용할 수 있도록 구현한 일종의 도구일 뿐 모든 컨테이너 기술이 도커에 종속되는 것은 절대로 아닙니다. 

 

하지만 그럼에도 도커를 시작해야 하는 첫 번째 이유는 도커는 2013년부터 오랜 기간 동안 개발되어 왔기 때문에 프로젝트 자체의 성숙도와 편의성의 뛰어납니다. 두 번째 이유는 도커가 컨테이너 생태계 전반을 보다 쉽게 이해할 수 있도록 도와준다는 점입니다. 현재는 도커 외에도 컨테이너 기술을 구현한 오픈소스가 많지만, 초창기에는 많은 회사와 프로젝트들이 도커를 사실상 표준으로 사용했기 때문에 도커를 먼저 공부하면 도커가 오픈소스 생태계에 남긴 족적을 쉽게 이해할 수 있다는 장점이 있습니다.

 

도커 엔진 설치

 

도커는 다양한 운영체제에서 사용할 수 있습니다. 도커는 리눅스 컨테이너를 제어하는 API를 Go 언어로 구현한 libcontainer를 사용하기 때문에 대부분의 리눅스 운영체제에서 사용할 수 있습니다.

 

도커 엔진의 종류 및 버전

 

앞으로 설명할 도커의 기능들은 오픈소스 버전의 도커에 해당하는 도커 CE(Community Edition)을 기준으로 하고 있습니다. CE라는 이름에서 알 수 있듯이 도커 CE는 무료로 제공되는 도커 엔진이며, 별도의 기술 지원 및 서비스를 제공하지는 않지만, 도커 엔진 자체의 핵심 기능을 무료로 사용할 수 있다는 장점이 있습니다. 만약 엔터프라이즈 수준의 서포트가 필요할 경우 미란티스 컨테이너 런타임(Mirantis Container Runtime) 등을 고려할 수 있으나, 대부분의 경우 도거 CE만으로도 원하는 기능을 충분히 사용할 수 있습니다.

 

리눅스 도커 엔진 설치

 

리눅스에서 도커를 설치할 때 확인해야 할 사항은 아래와 같습니다.

  1. 지원 기간 내에 있는 배포판인지 확인
  2. 64비트 리눅스인지 확인 (64비트에 최적화)
  3. sudo 명령어로 설치하거나 root 권한을 소유한 계정에서 설치

 

우분투 운영체제 설치 방법: Ubuntu | Docker Docs

 

Ubuntu

Jumpstart your client-side server applications with Docker Engine on Ubuntu. This guide details prerequisites and multiple methods to install Docker Engine on Ubuntu.

docs.docker.com

설치가 완료된 후 도커가 정상적으로 동작하는지 확인하려면 `docker info` 명령어를 입력합니다. 이 명령어는 설치된 도커 엔진의 각종 정보를 출력하는 명령어입니다.

 

최신 버전의 도커 엔진은 새로운 기능을 사용할 수 있다는 장점은 있지만, 안정화되지 않아 각종 버그가 발생할 수 있으므로 가능하면 출시되고 어느 정도 시간이 흐른 버전의 도커 엔진을 사용하는 것을 권장합니다.

 

윈도우, 맥 OS 도커 설치

 

도커의 기능을 완전하게 사용하려면 리눅스에서 사용하는 것이 가장 바람직하지만 윈도우와 맥 OS에서도 간단한 테스트나 개발 용도로 도커를 사용할 수 있습니다. 이렇게 윈도우와 맥 OS에서 설치하는 도커를 일반적으로 Docker Desktop이라고 부릅니다.

  • Docker Desktop on Window는 Hyper-V 또는 WSL 2 중 하나를 선택해 가상화 환경을 구축할 수 있으며,
    이 두 방식의 가상화 원리는 다르지만 최종적으로 도커 기능 자체에는 차이가 없습니다.
  • Docker Desktop on Mac은 가상 환경을 생성하기 위해 리눅스킷(Linuxkit)이라고 불리는 툴을 이용하는데,
    리눅스킷은 최소화된 리눅스 커널만을 탑재한 뒤 필요한 작업만 컨테이너 기반의 서비스로 정의해 사용합니다.

 

단, Docker Desktop은 개인 용도로는 무료이지만, 상업적 용도로 기업에서 사용할 경우 별도의 유료 구독이 필요하다는 점에 유의합니다. 또한, Docker Desktop에서는 도커에서 제공하는 네트워크, 볼륨 기능 등이 일부 지원되지 않을 수 있으며, 예상치 못한 버그가 발생할 가능성이 높습니다. 따라서 가능하다면 Docker Desktop보다는 완전한 리눅스 환경에서 도커를 사용하는 것이 좋습니다.

 

리눅스 환경 마련

 

도커는 원래 리눅스에서 작동하는 데 최적화돼 있으므로 윈도우, 맥 OS에서 도커를 사용하면 일부 기능이 제약될 수 있습니다. 아직까지는 여러 커뮤니티에서 리눅스로 도커를 실행하는 것을 권장하지만 도커로 개발하기 위해 리눅스 물리 서버를 직접 구하기는 쉽지 않습니다. 이를 위한 대안으로 버추얼박스, VMWare 같은 가상화 도구로 리눅스 환경을 생성할 수도 있고, AWS(Amazon Web Service)에서 클라우드에서 인스턴스를 제공받아 사용하는 EC2(Elastic Compute Cloud) 서비스를 사용할 수도 있습니다.