Docker 한줄 요약
도커는 리눅스 컨테이너에 여러 기능을 추가함으로써 애플리케이션을 컨테이너 단위로 사용할 수 있게 Golang으로 만들어진 오픈소스 프로젝트이다.
리눅스 컨테이너?
리눅스 컨테이너는 리눅스 운영체제 수준의 가상화 기술로,
컨테이너화 된 애플리케이션은 운영체제 커널과 격리된 공간에서 실행된다.
이것을 가능케 해주는 것은 리눅스에 있는 namespace와 cgroup(컨트롤 그룹)이다.
리눅스 네임스페이스
리눅스에서 프로세스를 관리하는 방법으로는, 커널이 PID 1을 가지는 init 프로세스를 실행시키고 해당 프로세스의 자식으로 프로세스를 생성한다.
이때 자식들은 별도의 네임스페이스를 지정해주지 않으면, init 프로세스의 네임스페이스 속하게 되고 이는 리눅스 시스템 기본 네임스페이스가 된다.
하지만 기본 네임스페이스 이외의 네임스페이스를 지정하게 되면 리소스를 다른 네임스페이스와 분리한다.
리소스를 기준으로 여러 네임스페이스가 있는데,
- PID 네임스페이스 : PID를 분리하여 각 네임스페이스 내에서 독립적으로 프로세스를 관리할 수 있게 해줌
즉, 프로세스의 PID는 자신이 속해있는 네임스페이스 안에서만 유효하다는 뜻이다. - 네트워크 네임스페이스 : 네트워크 인터페이스, ip 주소, 포트 등의 네트워크 리소스를 분리해준다.
- 마운트 네임스페이스 : FS 마운트 포인트를 격리하여 각 네임스페이스에서 독립적으로 파일 시스템을 사용할 수 있게 해준다.
- 호스트 네임스페이스 : 호스트 이름과 도메인 이름을 격리하여 여러 컨테이너가 각자 다른 호스트 이름을 가지고 동작할 수 있게 해준다.
이러한 리눅스 네임스페이스를 사용해 컨테이너가 독립적인 환경을 가지도록 한다.
리눅스 cgroup
리눅스 cgroup은, 물리적인 리소스(CPU, Memory, Disk) 등의 사용을 그룹 별로 제한하거나 구분할 수 있게 해준다.
그룹 별로 우선순위를 다르게 둘 수도 있으며 사용량을 모니터링 할 수 있다.
커널과 완벽히 격리되는가?
위에서 리눅스 컨테이너는 운영체제 커널과 격리된 공간에서 실행된다고 했는데, 호스트 운영체제의 커널을 아예 배제하지는 않는다.
컨테이너 내 애플리케이션을 실행시키기 위해 필요한 커널은 도커 엔진이 설치된 호스트 운영체제의 커널을 사용한다.
호스트 운영체제의 커널로 부터 자원을 할당받고, 네트워크 환경을 제공받는다.
컨테이너가 독자적으로 가지는것은 프로세스를 실행시키기 위한 코드, 환경, 라이브러리등이 있다.
VM 과 도커 컨테이너
도커 컨테이너에 대해 설명할 때 VM과 항상 비교되곤 한다.
VM도 가상화 기술의 일종으로, 호스트 운영체제 위에 독자적인 OS를 가지는 격리된 공간을 제공해준다.
OS라는 말이 굉장히 중요한데, 아래 그림을 보자.
VM과 호스트 운영체제 사이에는 Hypervisor가 존재하고, Container와 호스트 운영체제에는 Docker Engine이 존재한다.
Hypervisor는 호스트 운영체제로부터, VM 머신이 필요한 리소스와 네트워크 환경을 제공해준다.
VM에는 Guest OS라는 영역이 있는데, 이 OS를 사용하기 위해서는 라이브러리, 커널 같은것들을 전부 VM 이미지에 포함시켜야 한다.
따라서 배포시에 이미지의 크기도 커질뿐더러, 시스템 자원을 가상화 하고 독립된 공간을 생성하는 작업은 Hypervisor를 반드시 거치기 때문에 일반 호스트에 비해 성능의 손실이 발생한다.
반면에 Docker Container는 Guest OS라는 개념이 없어 이미지의 크기가 많이 줄고, Docker Engine을 통해 컨테이너에 필요한 커널은 호스트의 커널을 공유해 사용한다.
즉, 각각의 Docker Container들은 OS단위로 격리되는것이 아닌 프로세스 단위로 격리된다.
Docker는 왜 사용해야 하는가?
VM에 비해 크기가 가볍고, 빠르다는것도 알겠다. 근데 굳이 왜 써야하는지는 크게 와닿지 않는다.
개발과 배포가 쉽다
예를들어 Python 프로그램을 만들어서 배포해야 된다고 생각해보자.
그런데 Python도 여러 버전과 라이브러리가 있고, 심지어 Python 말고도 다른 환경도 우리 애플리케이션을 구동하는데 필요하다.
맨 처음으로 떠오르는 배포 방법은 README에 구동에 필요한 환경을 적어놓는것이다.
1. Python 3.6 버전 설치
2. pip install ~~~
3. 다음 SDK를 다운받아주세요
4. ...
만약 애플리케이션을 사용하는 사람이 Python 3.7버전이 이미 있다면?
라이브러리의 버전이 맞지 않다면?
SDK 버전이 수시로 바뀐다면?
모든 유저들에게 동일한 구동 환경을 보장할 수 없게된다.
아예 VM 이미지로 싹다 포함시켜서 배포시킨다면 해결되겠지만 너무 무겁다
Docker는 이를 image로 해결한다.
Docker image에 라이브러리를 포함시킬 수 있어 VM의 장점과,
Docker image만의 Layer 구조로 README의 장점을 둘 다 가져오게 된다.
버전 관리가 쉽다
위에서 만든 애플리케이션을 10대의 서버에서 구동하고 있다고 가정해보자.
이때 Python 3.6버전에 치명적인 결함이 발생해 급하게 3.7버전으로 모든 서버를 업데이트 하였다.
그러다 실수로 하나의 서버에는 3.7 버전이 아닌 3.8버전으로 업데이트를 하게 되었는데,
자꾸 3.8버전으로 업데이트한 서버만 장애를 일으키고 뻗어버린다.
파이썬 버전이 하나만 다르다는걸 발견하기 쉬울까?
만약 실수한 부분이 하나가 아니라 여러 개라면?
Docker는 image를 통해 동일한 개발 및 운영환경을 보장하고, Layer 구조로 변경 이력, 버전 정보 등을 쉽게 확인할 수 있다.
다시 Docker 한줄 요약
Docker는 독립적인 개발 및 운영환경을 보장하고, 호스트 OS 커널만을 공유해 프로세스 단위로 격리되는 가상화 기술이다.
Docker Image, Layer들에 관해서는 다음 포스트에서 다루겠다.
'Infra > Docker' 카테고리의 다른 글
[Docker] Docker Daemon (0) | 2023.06.27 |
---|---|
[Docker] Dockerfile (1) | 2023.05.20 |
[Docker] 도커 볼륨과 네트워크 (0) | 2023.05.19 |
[Docker] 도커 이미지와 컨테이너 (0) | 2023.05.18 |
[Docker] 도커 시작하기 (2) | 2023.04.05 |