Docker ?
Docker의 기본에 대해서 알아보자
1. Docker를 쓰는 이유
-
일반적으로 도커 없이 프로그램 받을때 다운받고 실행하는 순서로는 아래와 같이

갖고 있는 서버, 패키지 버전, 운영체제 등에 따라 프로그램을 설치하는 과정중에 많은 에러들이 발생하게 되고, 설치 과정이 다소 복잡하다.
-
예를들어, Redis를 사용하기 위해 일반적으로는
- Redis 홈페이지 이동 -> redis.io 를 wget 명령어를 통하여 압축된 파일을 받고, install을 하여야 한다.
- 반면에 도커를 사용해서는 "docker run -it redis" 라는 명령어 한번으로 설치/실행이 가능하다.
-
이와 같이, 사용하려는 환경에 구애없이 편하게 응용프로그램들을 설치하고 사용할 수 있게 하는 장점이 있다.
2. Docker란 무엇인가?
- Docker는 컨테이너를 사용하여 응용프로그램을 더 쉽게 만들고 배포하고 실행할 수 있도록 설계된 도구이며 컨테이너 기반의 오픈소스 가상화 플랫폼이며 생태계이다.
- Container?
- MySQL, REDIS, WEB APP 등 프로그램을 손쉽게 배포/실행 하도록 컨테이너로 추상화 된 것
- 추상화를 통해 동일한 인터페이스를 제공하여 쉬운 관리가 가능하게 함
- 컨테이너는 코드와 모든 종속성을 패키지화하여 응용프로그램이 한 컴퓨팅 환경에서 다른 컴퓨팅 환경으로 빠르고 안정적으로 실행되도록 하는 소프트웨어의 표준단위
- Container Image?
- 컨테이너 이미지는 코드, 런타임, 시스템도구, 시스템 라이브러리 및 설정과 같은 응용프로그램을 실행하는데 필요한 모든것을 포함하는 가볍고 독립적이며 실행가능한 소프트웨어 패키지임
- 컨테이너 이미지는 런타임에 컨테이너가 되고, 도커 컨테이너의 경우 도커엔진에서 실행될 때 이미지가 컨테이너가 됨
- 컨테이너는 소프트웨어를 환경으로부터 격리시키고 개발과 스테이징의 차이에도 불구하고 균일하게 작동하도록 보장

3. Docker 사용의 흐름
- Docker를 사용할 때는
- 먼저 도커 CLI에 커맨드를 입력
- 도커 서버 (도커 Daemon) 가 그 커맨드를 받아서 그것에 따라 이미지를 생성 or 컨테이너를 실행하는 모든 작업을 하게됨

- Docker의 사용 흐름 예시

A) 도커 CLI에서 docker run hello-world (이미지name)을 치면
B) 도커 CLI에서 도커 서버로 요청을 보냄
C) 도커 서버는 로컬에 있는 Image Cache 보관 장소에서 hello-world 이미지를 찾아보고
D) 해당 이미지가 Cache 저장소에 없으면, Docker Hub에서 해당 이미지를 가져옴
Unable to find image 'hello-world:latest' locally # 로컬 Cache 저장소에는 hello-world 이미지가 없네요
latest: Pulling from library/hello-world # Docker Hub에서 hello-world 이미지를 Pulling 해옵니다.
b8dfde127a29: Pull complete # Pull 완료!! Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest
4. Docker 와 기존의 가상화 기술과의 차이를 통한 컨테이너 이해
* 가상화 기술이 나오기 전에
- 1대의 서버를 하나의 용도로만 사용
- 남는 서버 공간을 그대로 방치
- 하나의 서버에 하나의 OS, 하나의 프로그램만을 운영
- 안정적, but 비효율적
* 하이퍼 바이저 기반의 가상화 출현
- 논리적으로 공간을 분할하여 VM이라는 독립적인 가상환경의 서버 이용 가능
- 하이퍼바이저는 호스트 시스템에서 다수의 게스트OS를 구동할 수 있게 하는 소프트웨어, 하드웨어를 가상화하면서 하드웨어와 각각의 VM을 모니터링 하는 중간 관리자 역할을 함
* 네이티브 하이퍼 바이저 vs 호스트형 하이퍼 바이저
- 일반적으로는 호스트형 하이퍼 바이저를 많이 사용
- 네이티브 하이퍼 바이저 : 하드웨어 -> 하이퍼바이저 -> VM
- 하드웨어에 직접적으로 셋팅된 하이퍼 바이저가 VM을 관리하므로 안정적이고, 시스템 오버헤드가 적음
- 호스트형 하이퍼 바이저 : 하드웨어 -> OS -> 하이퍼바이저 -> VM
- 하이퍼 바이저가 일반적인 OS에 설치되고 VM을 관리한다. 하드웨어 자원을 VM 내부의 게스트 OS에 에뮬레이트 하는 방식으로 오버헤드가 큼
- 게스트 OS 종류에 대한 제약이 없고, 구현이 쉬움

- 하이퍼바이저에 의해 구동되는 VM은 각 VM마다 독립된 가상 하드웨어 자원을 할당 받음
- 논리적으로 분리되어 있어 한 VM에 오류가 발생하여도 다른 VM에는 오류 발생하지 않음
- 도커도 이 기술을 토대로 되어있음

- 도커는 기존 VM과 비교하여 하이퍼바이저와 게스트OS가 필요하지 않아 가벼움
- 도커의 경우, 호스트OS에서 image를 불러와 container를 실행시키면 되는데 반해, VM은 VM 실행 후 OS를 실행하고 그 위에서 APP을 실행하기에 무거움
- 공통점 : 도커 컨테이너와 VM은 기본 하드웨어에서 격리된 환경 내에 애플리케이션을 배치하는 방법임
- 차이점 : 격리된 환경을 얼마나 격리 시키는지의 차이가 존재
- 도커 컨테이너에서 돌아가는 애플리케이션은 컨테이너가 제공하는 격리 기능 내부에 샌드박스가 있지만, 여전히 같은 호스트의 다른 컨테이너와 동일한 커널을 공유한다.
- 결과적으로, 컨테이너 내부에서 실행되는 프로세스는 호스트 시스템(모든 프로세스를 나열할 수 있는 충분한 권한있음)에서 볼 수 있다.
EX) 도커로 몽고DB 컨테이너 시작하면, 호스트에서 ps -e grep 치면 몽고 프로세스가 표시된다.
그리고 컨테이너가 전체 OS를 내장할 필요가 없는 만큼, 훨씬 가볍고, 일반적으로 5-100MB 이다.
- 가상 머신과 함께 VM 내부에서 실행되는 모든 것은 호스트 운영체제 또는 하이퍼바이저와 독립되어 있다. 가상머신 플랫폼은 특정 VM에 대한 가상화 프로세스를 관리하기 위해 프로세스를 시작하고, 호스트 시스템은 그것의 하드웨어 자원 일부를 VM에 할당한다. 그러나 VM과 근본적으로 다른 것은 시작 시간에 이 VM 환경을 위해 새롭고 특정 VM 만을 위한 커널을 부팅하고 운영 체제 프로세스 세트를 시작한다.
- 이것은 응용 프로그램만 포함하는 일반적인 컨테이너보다 VM의 크기를 훨씬 크게 만든다. (OS까지 가상화를 하기 때문에)

- 커널은 공유, 컨테이너는 격리, 하드 디스크/CPU/메모리와 같은 자원들은 각 컨테이너별 격리
도커 컨테이너를 격리시킬 수 있는 이유?
- 도커는 리눅스/하이퍼바이저 등등 기존의 기술들을 기반으로 발전됨
- 리눅스에서 쓰이는 Cgroup (Control Groups)와 네임스페이스 (namespace) 를 사용
- Cgroup : CPU, 메모리, Network Bandwith, HD i/o등 프로세스 그룹의 시스템 리소스 사용량을 관리
- Namespace : 하나의 시스템에서 프로세스를 격리시킬 수 있는 가상화 기술, 별개의 독립된 공간을 사용하는 것처럼 격리된 환경을 제공하는 경량 프로세스 가상화 기술

Q) cgroup과 namespace 는 리눅스에서 사용가능한데, mac이나 windows 운영체제 PC를 사용하게 되면 어떻게 사용 가능한가?
A) 도커가 내부적으로 아래와 같이 구성

- 도커가 돌아가기 위해, 리눅스 VM이 설치되어 있고, 이를 이용하여 리눅스 커널을 사용하여 cgroup과 namespace를 통한 컨테이너 격리 가능
5. Docker 이미지 실행하기
이미지를 실행하기 위해 필요한 것
- 컨테이너가 시작될 때 실행되는 명령어 (ex. run kakaotalk)
- 파일 스냅샷 (ex. 컨테이너에서 카카오톡을 실행하고 싶다면 -> 카카오톡 파일의 스냅샷)

이미지로 컨테이너를 만드는 순서
- Docker 클라이언트에서 docker run <이미지네임> 입력
- 도커 이미지에 있는 파일 스냅샷을 컨테이너 하드디스크로 옮김

- 이미지에서 가지고 있는 명령어 (컨테이너가 실행될 때 사용될 명령어)를 이용해서 카카오톡을 실행
