[Infra] 가상머신과 컨테이너 그리고 Docker
가상머신과 컨테이너라는 기술이 무엇이고 서로 어떤 차이가 있는지 확인합니다. 또한 가장 대표적인 컨테이너 기술 Docker를 간단히 살펴봅니다.
개요
안녕하세요.
이번 글에서는 물리적인 자원을 가상화하는 가상머신(Virtual Machine)과 리눅스 운영체제에서 시작된 컨테이너(Container) 개념을 살펴보고 서로 비교해보겠습니다. 또한 가장 대표적인 컨테이너 기술인 Docker를 간단히 알아보겠습니다.
OS와 가상머신과 컨테이너
OS: 컴퓨터를 움직이도록 돕는 기반 소프트웨어
위키백과에서는 운영체제(Operating System, 이하 OS)를 “사용자의 하드웨어, 시스템 리소스를 제어하고 프로그램에 대한 일반적 서비스를 지원하는 시스템 소프트웨어”로 정의합니다. OS는 사용자에게 프로그램을 쉽고 효율적으로 실행할 수 있는 환경을 제공하고 하드웨어 및 소프트웨어 자원을 할당, 관리, 보호하며 잘못된 자원 사용의 감시나 입출력 장치의 제어 등을 수행합니다.
만약 OS가 없다면 우리는 1+1이라는 작업을 위해 사용할 메모리를 지정하고 메모리에 값을 저장하며 그 값을 어떤 CPU에서 연산하고 연산의 결과를 어디에 저장하며 그 결과를 어떻게 출력할지 등 모든 작업을 전달해야 합니다. 말 그대로 아무 것도 할 수 없는 상태가 되버리죠!
가상머신: 마치 CPU와 메모리가 있는 것처럼!
가상머신(Virtual Machine, 이하 VM)은 CPU나 메모리 등의 하드웨어를 가상화하여 구현한 소프트웨어입니다. 이렇게 가상으로 만든 컴퓨팅 환경에는 OS나 응용 프로그램을 설치할 수 있습니다. VM은 크게 실행을 지원하는 시스템 가상머신과 단일 프로세스를 지원하는 프로세스 가상머신으로 나눈다고 하는데요. 우리가 이 글에서 주로 다루는 VM은 전자입니다. 후자의 예시로는 JVM(Java Virtual Machine)이나 PVM(Python Virtual Machine) 등을 꼽을 수 있겠네요.
이 VM을 생성하고 관리하는 논리적인 플랫폼을 하이퍼바이저(Hypervisor)라고 합니다. 하이퍼바이저는 가상 OS와 호스트 OS 간의 명령어 차이를 해소하며 가상머신 모니터 또는 가상머신 매니저(VMM: Virtual Machine Monitor, Virtual Machine Manager)라고도 부릅니다.
하이퍼바이저는 보통 타입1과 타입2로 나뉘는데요. 타입1(native 또는 bare-metal)은 OS가 프로그램을 제어하듯 하이퍼바이저가 해당 하드웨어에서 직접 실행되며 게스트 OS는 하드웨어 위에서 2번째 수준으로 실행됩니다. 리눅스의 KVM과 Microsoft의 Hyper-V 등이 대표적입니다. 타입2(hosted)는 일반 프로그램과 같이 호스트 OS에서 실행되며 VM 내부에서 동작하는 게스트 OS는 하드웨어에서 3번째 수준으로 실행됩니다. VMware의 VMware Workstation나 Oracle의 VirtualBox 등이 타입2에 속합니다.
컨테이너: 보다 가벼운 가상화
컨테이너(Container)는 애플리케이션과 그 실행에 필요한 모든 라이브러리 및 종속성을 패키징하여 격리된 환경에서 실행할 수 있도록 합니다. 이는 VM과 달리 전체 OS를 포함하지 않고, 호스트 OS의 커널을 공유하여 더 가볍고 빠른 성능을 제공합니다.
컨테이너는 애플리케이션의 이식성을 높이고, 개발과 배포의 일관성을 유지하는 데 큰 장점을 가지고 있습니다. 예를 들어, Docker와 같은 컨테이너 플랫폼을 사용하면 개발자는 로컬 환경에서 애플리케이션을 컨테이너화하여 테스트한 후, 동일한 컨테이너 이미지를 프로덕션 환경에 배포할 수 있습니다. 이로 인해 “제 컴퓨터에서는 잘 되는데요”라는 문제를 최소화할 수 있습니다. 또한, 컨테이너는 자원을 효율적으로 사용할 수 있도록 설계되어 있어, 여러 개의 컨테이너를 단일 호스트에서 동시에 실행할 수 있습니다. 이는 클라우드 환경에서의 스케일링과 관리에 유리하며, 마이크로서비스 아키텍처와 같은 현대적인 소프트웨어 개발 방식에 적합합니다.
가상머신과 컨테이너는 취향차이?
곧 소개할 Docker의 홈페이지는 아래의 그림을 통해 설명합니다.
컨테이너는 애플리케이션 수준의 추상화로 여러 컨테이너가 동일한 하드웨어에서 동작하고 각각의 프로세스로 분리되어 OS 커널을 공유합니다. 이에 반해 VM은 하드웨어의 추상화로 각 VM은 전체 OS와 애플리케이션, 기타 필요한 파일을 모두 복사하므로 상대적으로 크고 무겁습니다. 표로 정리하면 아래와 같아요!
가상 머신 | 컨테이너 | |
---|---|---|
가상화 | OS, 애플리케이션 | 애플리케이션 |
커널 공유 | X (격리된 커널) | O (호스트 커널 공유, 보안 취약점 가능성 존재) |
용량 | 비교적 큼 | 비교적 작음 |
속도 | 느림 | 빠름 |
Docker
그렇다면 Docker는 정확히 무엇일까요? Docker는 가장 널리 쓰이는 컨테이너 기술 중 하나입니다. 사실 Docker 개발 이전의 LXC나 개발 이후의 Kubernetes, Podman와 같이 다양한 기술을 통해 컨테이너를 접할 수 있는데요. 현재는 컨테이너 시장의 업계 표준에 해당하는 위상으로 다양한 레퍼런스와 강력한 생태계를 자랑합니다.
Docker의 구조
다음의 그림과 함께 Docker의 구조를 간단히 알아보겠습니다.
가장 먼저 Docker daemon을 살펴볼텐데요. Docker의 가장 핵심이 되는 daemon 프로세스로 Docker API의 요청을 확인합니다. 이미지, 컨테이너, 네트워크, 볼륨 등 Docker 오브젝트를 관리하며 Docker 서비스 운영을 위해 다른 daemon과 통신합니다. 다음으로 살펴볼 개념인 Docker Client(`docker`)는 다수의 유저가 Docker와 상호작용하는 방법입니다. docker run
을 입력하면 client가 이 명령어를 dockerd
로 전송합니다. docker
는 Docker API를 사용하며 client는 다수의 daemon과 통신할 수 있습니다.
Docker Registry는 Docker 이미지를 저장합니다. 쉽게 접할 수 있는 registry로는 Docker Hub을 꼽을 수 있습니다. Docker Hub은 누구나 접근할 수 있는 registry로 Docker가 기본적으로 참조하는 registry입니다. 물론 개인적인 registry를 운용할 수도 있어요! docker pull
이나 docker run
명령어를 사용할 때 설정한 registry로부터 필요한 이미지르 가져옵니다. 반대로 docker push
명령어를 사용하면 이미지를 업로드합니다. 마치 git pull
과 git push
와 같은 구성이죠?
Docker Desktop은 Mac, Windows, Linux 환경에서 컨테이너화된 애플리케이션과 마이크로서비스를 생성하거나 공유할 수 있는 간편한 애플리케이션입니다. 내부적으로 앞서 설명드린 Docker daemon, client을 비롯해 compose, content trust, kubernetes 등을 포함합니다.
마지막으로 Docker의 기본 단위인 오브젝트를 살펴보겠습니다. Docker 이미지(Image)는 Docker container 생성을 위한 명령어의 읽기 전용 템플릿입니다. 이미지는 다른 이미지를 기반으로 수정 후 생성할 수도 있어요! 예를 들어 ubuntu 이미지를 기반으로 Apache web server를 설치하는 식으로 말이죠! 이와 같이 이미지를 생성하기 위해서는 Dockerfile이 필요합니다. 이미지 생성 및 실행을 위한 절차를 정의한 파일인데요. 각 명령어는 이미지의 계층을 생성하며 Dockerfile을 수정 후 이미지를 다시 생성한다면 변화된 계층부터 재생성합니다. 이미지가 다른 기술에 비해 가볍고 용량이 적으며 빠른 이유입니다.
Docker 컨테이너(Container)는 이미지의 실행 가능한 인스턴스입니다. Docker API나 CLI를 이용해 생성, 시작, 정지, 이동, 삭제 등의 작업이 가능합니다. 1개의 컨테이너에 다수의 네트워크, 저장소, 새로운 이미지를 연결할 수 있습니다. 기본적으로 컨테이너는 다른 컨테이너나 호스트 머신과 분리된 상태로, 이를 연결하기 위해서는 Docker 네트워크 혹은 자체적인 통신의 구축이 필요합니다. 이런 컨테이너를 제거한다면 영구 저장소에 저장하지 않은 모든 변경 사항도 함께 사라지므로 주의가 필요합니다.
그래서 어떻게 구성된다는 이야기인가요??
이 단락은 Docker에 익숙하지 않으신 분들에게 해당합니다!! 여기서는 Docker의 구조에서 설명한 개념을 빵집에 비유해서 설명합니다.
개념 | 예시 |
---|---|
Client | 가게 주인 |
Docker host | 빵집 |
Registry | 빵 레시피 상점 |
Images | 빵 레시피 |
Container | 빵 |
Dockerfile | 나만의 제빵 비법 |
docker pull | 레시피 상점에서 레시피 사오기 |
docker build | 기본 레시피에 나만의 제빵 비법을 더해 나만의 레시피 만들기 |
docker run | 기본 레시피나 나만의 레시피를 보고 빵 만들기 |
docker push | 레시피 상점에 레시피 공유하기 |
가게 주인이 빵집을 열고 레시피 상점에서 사온 레시피로 빵을 만듭니다. 이 과정은 유저가 레지스트리에서 이미지를 받아와 컨테이너를 생성하는 과정과 유사하죠?? 시간이 흘러 가게 주인이 자신만의 비법을 완성했고 원래 레시피에 비법을 더한 새로운 레시피를 바탕으로 빵을 만듭니다. 이는 기존 이미지를 가져와서 Dockerfile을 통해 수정한 커스텀 이미지를 만들고 이를 통해 컨테이너를 생성했음을 의미합니다. 이렇게 만든 나만의 레시피가 너무 유명해져서 가게 주인은 이를 레시피 상점에 공유하기에 이릅니다. 이는 레지스트리에 커스텀 이미지를 업로드하는 프로세스라고 할 수 있습니다.
물론 비유이니만큼 실제 개념과 분명히 차이가 있습니다만… 조금이라도 이해에 도움이 되었으면 좋겠네요!
마무리하며
이번 글에서는 VM, 컨테이너 그리고 Docker에 대해 간단히 알아봤습니다. 정리해보자면 아래와 같아요!
- VM: 하드웨어 가상화로 완전한 격리 필요 시 적합 (예: 다른 OS 실행).
- 컨테이너: 경량성과 빠른 배포가 중요할 때 유리 (예: 마이크로서비스).
- Docker: 컨테이너 생태계의 표준으로, 개발부터 배포까지 일관된 환경 제공.
이 개념을 처음 접했을 때 꽤나 헤맸던 기억이 새록새록하네요. 모쪼록 이 글이 조금이라도 도움이 되었기를 바랍니다!
감사합니다. 😀
참고 문헌
- Operating system, https://en.wikipedia.org/wiki/Operating_system
- Virtual Machine, https://en.wikipedia.org/wiki/Virtual_machine
- Docker 공식 문서 https://docs.docker.com
- Microsoft, “Hyper-V 기술 개요”, https://learn.microsoft.com/ko-kr/virtualization/hyper-v-on-windows/about/
- Red Hat, “컨테이너 vs. 가상 머신”, https://www.redhat.com/ko/topics/containers/containers-vs-vms