1. Docker
Docker는 컨테이너 기반의 가상화 플랫폼이다. 기존 host OS위에 가상 OS를 띄워 OS 기반으로 어플리케이션을 서비스 하는 방식에서 좀 더 가벼운 컨테이너 기반으로 프로세스 격리를 통해 가상화를 가능하게 해주어 자원 낭비를 최소화 하였다.
그림에서 보다시피 기존 VM방식은 호스트위 가상 OS를 띄워 해당 OS위에서 서비스를 제공해주는 방식이였다면, Docker의 경우 Docker 미들웨어를 두고 컨테이너를 통해 서비스를 제공해준다.
이러한 방식의 장점으로는 빠르게 컨테이너 단위로 실행 및 파괴가 가능하기 때문에 더욱 쉽게 자원 관리를 할 수 있게 된다. 또한 하나의 서비스를 제공하기 위해 필요한 단위가 작아지므로 같은 자원 대비 더욱 많은 서비스 제공이 가능해지게 된다.
2. Docker engine
Docker에대해 어느정도 알아봤으니 이제 Docker를 구성하는 요소들에 대해 알아보자.
우리가 흔히말하는 Docker는 Docker engine을 의미한다.
Docker를 설치, 실행하면 dockerd라는 데몬 프로그램이 서버로서 실행되며
rest api, cli(docker) 도구들이 클라이언트가 되어 작업을 지시한다
3. Docker Architecture
Docker에 대해 알아보려면 우선 Docker의 구조에 대해 알아보자.
- Docker는 server - client 구조를 사용한다 위에서 말한 Docker client는 server 역할을 하는 Docker daemon(dockerd)와 데이터를 주고 받는다.
- Docker client와 daemon은 동일한 시스템이 있을 수도 있고 client가 원격으로 daemon에 연결할 수 있다.
- client와 daemon은 unix소켓 또는 네트워크 인터페이스를 통해 rest api를 사용하여 통신한다.
3.1 Docker daemon
docker daemon은 client로부터 api요청을 수신하고, 이미지, 컨테이너, 네트워크, 볼륨과 같은 객체들을 관리하는 가장 중요한 역할이다.
데몬은 또한 서비스를 관리하기 위해 다른 데몬과 통신할 수도 있다.
3.2 Docker client
우리가 흔히 cli에서 사용하는 docker 명령어는 우리가 가장 많이 Docker와 상호 작용하는 방법이다.
예를들어 docker run이라는 명령을 실행하면 docker client가 dockerd에게 api로 전달을 하게되고 dockerd가 이 명령을 수행 결과를 docker client 에게 가져다 주면 유저들은 그 결과를 보게된다.
또한 docker client 는 둘 이상의 daemon과 통신할 수 있다.
4. Docker registry
registry는 docker image를 저장한다. docker hub는 누구나 사용할 수 있는 public registry이며 docker 는 기본적으로 docker hub에서 이미지를 찾도록 구성되어 있다.
registry vs repository
- registry : 이미지를 저장하는 서비스 물리적 저장소의 개념ex) docker hub, 개인 registry
- repository : 이름이 같지만 TAG가 다른 이미지의 논리적 모음
5. Image
Docker에서 가장 중요한 개념중 하나인 Image는 컨테이너가 실행되는데 필요한 파일 , 설정값등을 포함하고있는것이다. (Immutable) 컨테이너는 이미지를 실행한 상태로 볼 수 있고, 추가되거나 변화된 값들은 컨테이너에 저장되고, 한 이미지로 여러가지 컨테이너를 생성할 수 있다. 마치 Java의 class와 instance의 관계라고 생각하면 쉽다. Docker의 Image는 Docker hub에서 제공해주는 이미지 말고도 직접 Dockerfile를 통해 이미지를 만들 수 있다. 이러한 이미지들은 docker hub를 통해 관리할 수 있다.
6. Container
지금까지 위에서 본 Image는 결국 Container를 실행하기 위한 파일이다. 마치 자바의 클래스와 인스턴스의 관계와 같다. 컨테이너는 격리되어있는 프로세스로 마치 VM으로 실행된 호스트처럼 사용이 가능하다. 다음은 ubuntu 컨테이너를 실행한 모습이다.
docker run -it ubuntu bash
- -it : 표준 입출력 터미널로 접근하기 위해
- bash : 컨테이너가 실행될때 bash쉘을 실행시킨다는 의미
ubuntu:latest 버전이 지금 로컬에 존재하지 않으므로 hub에서 받아오는 모습이다.
받아온 후 -it, bash 명령어 덕분에 컨테이너의 쉘에 접속한 모습이다.
컨테이너의 쉘에 접속한다는 의미는 현재 동작하고 있는 ubuntu 컨테이너 내에서 shell을 실행 후 해당 shell에 터미널을 통해 표준 입출력을 진행한다는 의미다.
또한 컨테이너는 실행시킬 명령이 없으면 종료하게 된다.
즉 할일이 없다면 종료하게 된다.
그래서 아무일도 하지않는 컨테이너를 만들게 되면, 만들자 마자(run) 바로 종료되는 모습을 볼 수 있다.
ex) docker run ubuntu 는 컨테이너가 바로 죽는걸 볼 수 있다
하지만 위에서 설명한 -it, bash처럼 무언가 할 일을 만들어 준다면 컨테이너는 종료하지 않는다.
(bash가 표준 입력을 기다리며 실행중이므로 종료하지 않는다.)
7. Layer
Docker 이미지는 컨테이너에 대한 모든 정보를 가지고 있기 때문에 보통 용량이 굉장히 크다.
이런 이미지를 수정할때마다 다운받는다 하면 매우 비효율 적일수밖에 없다.
이렇기 때문에 Layer라는 개념이 나왔다.
Union File System으로 여러개의 레이어를 마치 하나의 파일 시스템처럼 이용할 수 있게 해준다.
실제로 실행해 보면 이 layer라는 개념을 쉽게 이해할 수 있다.
이 사진은 새로운 python이미지를 pull하는 사진이다. 보면 모든 레이어를 다운로드 받은걸 알 수 있다.
이 사진은 새로운 python을 기반으로 하는 다른이미지를 pull하는 사진이다. 보면 Already exists라는 부분이 보일 것이다. 이부분은 이미 로컬 호스트에 존재하는 layer로 굳이 받을 필요가 없어 새로 추가되어야 할 layer만 pull받는 모습이다.