가상화, 도커 의미(이미지와 컨테이너)
도커가 필요한 이유는 무엇인가?
내가 만든 파워포인트 문서를 다른 컴퓨터에서 열었을 때, 글꼴이 다르게 나오거나 한글파일의 버전이 달라서 글꼴이 깨져서 나온 경험을 해봤을 것이다. 이처럼 다른 하드웨어나 운영체제에서도 내가 만든 파일이나 프로그램을 제대로 실행시키려면 내 컴퓨터와 동일한 환경을 갖추어야 한다. 가상화 기술인 도커를 사용하면 내 컴퓨터의 작업 환경과 버전 정보 전체를 다른 컴퓨터 환경에 복제하여 어떤 컴퓨터 환경에서도 애플리케이션을 안정적으로 실행할 수 있다.
가상화
가상화는 물리적인 하드웨어(HW) 장치를 논리적인 객체로 추상화하는 것을 의미한다. 즉, 하나의 하드웨어를 여러 대처럼 동작시키거나 반대로 여러 대의 장치를 묶어 하나의 장치인 것처럼 사용자에게 공유자원으로 제공하는 기술이다.
서버 가상화
한 대의 물리적 서버 자원을 여러 대의 가상 서버(머신)로 나눠 쓰는 것을 말하는데, Virtual Machine(VM)을 통해 가상화를 구현할 수 있다. 가상머신은 컴퓨팅 환경(하드웨어)을 소프트웨어로 구현, 즉 컴퓨터(하드웨어)를 에뮬레이션하는 소프트웨어라고 표현한다.
하이퍼바이저
공유 컴퓨팅 자원을 관리하고 가상 머신의 생성/삭제를 관할하며, 가상 머신에서 동작할 게스트(Guest) 운영체제를 활성화시켜주는 소프트웨어이다.
컨테이너(Container)의 의미
컨테이너라고 하면 흔히 화물 운송용 컨테이너를 생각해볼 수 있다. 안에 어떤 것이 들어 있는지에 상관없이 컨테이너라는 규격화된 단위로 포장하여 화물은 어디로든 운송할 수 있다. 컴퓨터 세계에서도 컨테이너란 애플리케이션과 그 실행에 필요한 라이브러리와 종속성 등을 패키지 단위로 묶은 것을 의미한다.
즉, 화물 운송에서 사용하는 컨테이너와 같이 컴퓨터 세계에서 컨테이너란 데스크톱이든 노트북이든 어떤 환경에서든 실행할 수 있는 소프트웨어의 실행 단위(프로세스)라고 할 수 있다.
가상머신(VM)과 컨테이너(Container)
둘 다 하나의 하드웨어에서 애플리케이션 구동을 위한 격리 환경을 마련해 주지만 큰 차이점이 있다.
가상화 방식이 다르다. 가상머신은 운영체제 위에 하드웨어를 에뮬레이션하고 그 위에 운영체제를 올리고 프로세스를 실행하는 반면에, 도커 컨테이너는 하드웨어 에뮬레이션 없이 리눅스 커널을 공유해서 바로 프로세스를 실행한다.
가상 머신의 경우 하드웨어를 가상화하기 때문에, 하드웨어를 논리적으로 공유해서 쓰는 것이다. 즉 하드웨어를 에뮬레이션하게 된다. 하나의 하드웨어에서 여러 대의 컴퓨터가 구동되는 것처럼 에뮬레이션(흉내 내기)하는 것이다. VMware, VirtualBox 등이 이에 해당한다. 그래서 각각의 가상 머신은 자체 운영체제(OS)를 실행해야 하며 일반적으로 용량이 GB 단위를 가지게 된다.
컨테이너의 경우 운영체제 수준의 가상화를 하기 때문에, 이미 설치되어 있는 호스트 리눅스의 커널을 공유해서 쓰는 것이다. 애플리케이션이 실행되는데 필요한 요소들만 패키징되어 있어서 MB 단위로 가상 머신에 비해 매우 가볍다는 차이점을 가지고 있다.
리눅스 컨테이너란?
리눅스 컨테이너는 운영체제 수준의 가상화 기술로 리눅스 커널을 공유하면서 프로세스를 격리된 환경에서 실행하는 기술이다. 하드웨어를 가상화하는 가상 머신과 달리 커널을 공유하는 방식이기 때문에 실행 속도가 빠르고, 성능 상의 손실이 거의 없다. 컨테이너로 실행된 프로세스는 커널을 공유하지만, 리눅스 네임스페이스(Linux namespaces), 컨트롤 그룹(Cgroup), 루트 디렉터리 격리 등의 커널 기능을 활용해 격리되어 실행된다. 이러한 격리 기술 덕분에 호스트 머신에게는 프로세스로 인식되지만, 컨테이너 관점에서는 마치 독립적인 환경을 가진 가상 머신처럼 보인다.
도커(Docker)
LXC(리눅스 컨테이너)로부터 파생된 도커는 가상머신과 같이 하드웨어를 가상화하는 것이 아니라, 리눅스 운영체제에서 지원하는 다양한 기능을 사용해 컨테이너(하나의 프로세스)를 실행하기 위한 별도의 격리 환경(파일 시스템)을 준비하고 리눅스 네임스페이스와 다양한 커널 기능을 조합해 프로세스를 특별하게 실행시켜준다. 이는 가상머신과 같이 하드웨어를 가상화하는 것이 아니라, 리눅스 운영체제의 커널을 공유하면서 하나의 프로세스(컨테이너)를 실행하기 위한 별도의 환경을 구축하고 도커는 바로 프로세스를 격리시켜 실행해주는 도구라고 할 수 있다.
컨테이너 이미지(Image)와 컨테이너
이미지란 컨테이너 실행에 필요한 모든 파일과 설정 값 등을 포함하고 있는 것을 의미한다. 즉, 이미지는 컨테이너를 생성하는 클래스 같은 역할을 하고 컨테이너는 이미지를 실행한 프로그램(프로세스)라고 볼 수 있다. 흔히 클래스(Class)를 붕어빵틀, 인스턴스(Instance)를 붕어빵에 비교하듯이 이미지가 붕어빵틀, 컨테이너가 붕어빵이라고 할 수 있다. 예를 들어 Ubuntu이미지는 Ubuntu를 실행하기 위한 모든 파일을 가지고 있으며, mysql 이미지는 mysql을 실행하는데 필요한 파일과 사용자 이름, password, port정보 등을 모두 가지고 있다.
따라서 도커 이미지의 용량은 보통 수백MB가 넘는데, 가상머신의 이미지에 비해 매우 적은 용량이다. 도커 프로그램에서 이미지는 Dockerfile이라는 파일로 만든다. Dockerfile에는 설치할 이미지 패키지, 명령어, 환경 변수, 포트정보 등이 작성된다.
ex. Dockerfile
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y vim apache2
COPY index.html /var/www/html/
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
보통 도커 허브(hub.docker.com)에서 제공하는 공식 이미지를 다운로드 받아 이미지를 설치하게 된다.
이미지의 경우 변하지 않는다는 특징이 있기 때문에 같은 이미지로 여러 개의 컨테이너(프로세스)를 생성하는 것이 가능하고, 컨테이너의 상태가 바뀌거나 삭제되어도 이미지는 그대로 남아있는다.