도커의 개념과 구조에 대해 학습한다.
가상화 기술이 발전하기 전까지는 하나의 서버에 하나의 애플리케이션만 구동할 수 있었다. 안정적이었지만 그만큼 남는 서버 자원이 방치되어 비효율적이었다. 이를 개선하기 위해 등장한 것이 가상화 기술이다.
가상화 기술은 물리적 하드웨어 자원을 논리적 자원으로 제공하여 각 프로세스에 할당한다. 가상화 기술 중에서도 하이퍼바이저 기반 가상화가 가장 많이 이용되었다. 하이퍼바이저는 논리적으로 분할된 공간에 VM이라는 독립된 가상 환경을 만들고 호스트 시스템에서 VM에 설치된 게스트 OS를 구동 및 모니터링하는 역할을 한다.
이 기술을 사용하면 이전보다 서버 자원을 효율적으로 사용할 수 있지만 각 프로세스를 구동하기 위한 OS들에 대해 매번 자원을 할당하고 부팅해줘야 하기 때문에 시간 및 자원 소모가 컸다.
VM은 some level of hardware와 kernel virtualization을 통해 게스트 OS를 실행하고, 게스트 kernel을 통해 virtual hw에 접근할 수 있다. 하지만 이 방법을 사용하려면 하드웨어 가상화까지 필요해 비용이 너무 높아진다.
하이퍼바이저(가상 머신 모니터)는 하이퍼바이저 OS와 가상 머신 리소스를 분리하여 가상 머신의 생성과 관리를 지원한다.
Native, Bare Metal, Microkernelized Hypervisor로 불린다. 호스트의 하드웨어에서 직접 구동되어 게스트 OS를 관리한다. VM 리소스는 호스트 OS 대신 하이퍼바이저에 의해 하드웨어가 직접 예약되기에 TYPE-2에 비해 오버헤드가 적다. 엔터프라이즈 데이터 센터와 서버 기반 환경에서 주로 사용된다.
Hosted, Monolithic Hypervisior로 불린다. 호스트 OS에서 Software Layer 또는 Application으로서 구동된다. 이 방식은 호스트 OS에서 게스트 OS를 추상화하는 방식으로 동작하기에 설치 및 구성이 편리하다. VM 리소스는 호스트 OS에 따라 예약된 후 하드웨어에 대해 실행되기에 오버헤드가 발생할 수 있다. 개인 컴퓨터에서 여러 OS를 구동하려는 개인 사용자에게 적절하다.
컨테이너 기술은 호스트 OS 위에서 프로세스 단위 격리를 제공한다. 프로세스가 다른 시스템과 격리되어 실행된다는 점에서 VM과 하이레벨이 유사하지만 로우 레벨에서는 게스트 OS 존재 유무의 차이가 있다.
도커는 리눅스 컨테이너 시스템 runC를 이용해 단일 OS 위에서 격리된 컴퓨팅 환경을 운영할 수 있도록 도와주는 애플리케이션 레벨 가상화 소프트웨어다.
ps 명령어를 통해 컨테이너 내부에서 실행중인 프로세스를 확인할 수 있다.
VM은 호스트 컴퓨터 위에 가상 운영체제를 실행하고, 각 운영체제는 자체 커널을 통해 독립적으로 동작한다. 각 VM은 완전히 격리되어 있어 영향을 주지 않지만 용량과 성능이 무겁고 오버헤드가 크다.
Docker Container는 호스트 운영체제 위에서 실행하고, 컨테이너 단위로 애플리케이션과 종속성을 패키징한다. 또한 호스트 OS의 커널을 공유하기 때문에 가볍고 빠르게 실행된다. 여러 컨테이너를 실행하는 경우 각 컨테이너는 격리되지만 공유 리소스를 사용하여 효율이 높다.
가상화의 목적에 따른 선택
완전한 격리와 다양한 운영체제의 실행 -> VM
애플리케이션의 패키징, 배포, 확장 -> Docker

도커 아키텍처는 크게 3가지 부분으로 구성된다.
Client
Docker Host (Docker Engine과 유사한 의미)
Docker Registry

위 그림은 Docker 컨테이너의 생성부터 종료까지의 다양한 단계와 상태를 보여준다.
컨테이너 라이프사이클 관련 명령어는 다음과 같다.
# 컨테이너 생성: 중지된 컨테이너 생성
# 로컬에 이미지가 없으면 자동으로 Docker Hub에서 다운로드
docker create --name <container-name> <image-name>
# 컨테이너 시작: 중지된(생성된) 컨테이너 시작
docker start <container-id/name>
# 컨테이너 실행: create + start. 컨테이너 생성 및 실행
# -it: 인터렉티브 모드(표준 입출력 사용). -d: 백그라운드 모드
docker run -it -d --name <container-name> <image-name> bash
# 컨테이너 일시정지
docker pause <container-id/name>
# 컨테이너 재개
docker unpause <container-id/name>
# 컨테이너 중지
docker stop <container-id/name>
# 컨테이너 재시작
docker restart <container-id/name>
# 컨테이너 종료
docker kill <container-id/name>
# 컨테이너 제거
docker rm <container-id/name>
자세한 설명은 여기를 참고하자
도커 파일은 도커 이미지를 만들고 빌드하기 위한 텍스트 파일이다. 도커 이미지를 구성하는 데 필요한 모든 단계와 명령을 정의할 수 있다. 이를 사용하면 반복적이고 일관적인 컨테이너 이미지 빌드 프로세스를 자동화할 수 있다.

1. 이미지 빌드 과정을 도커파일에 작성한다.
2. 도커엔진이 도커파일을 한 줄씩 읽어서 이미지를 빌드한다.
3. 빌드된 이미지를 실행하여 도커 컨테이너를 구성한다.
도커파일을 빌드하여 이미지를 생성할 때 명령어를 한 줄씩 읽어가며 이미지 레이어를 생성한다. 이후 각 레이어는 변경사항이 있는 경우에만 재빌드되도록 하여 빌드 속도를 향상시키고 중복 작업을 방지할 수 있다.(레이어 캐싱)
이미지 레이어의 캐싱 기준에 관한 자세한 내용은 여기를 참고하자.
여러 컨테이너를 관리할 때, 단일 명령어 파일을 통해 생성, 관리, 배포를 수행할 수 있다.
Dockerfile을 사용하면 단일 컨테이너의 빌드 프로세스는 자동화할 수 있지만 다중 컨테이너의 경우 번거로워진다. 이 때 도커 컴포즈를 사용하면 다중 컨테이너의 빌드 자동화를 구성할 수 있어 애플리케이션의 배포 및 관리가 매우 수월해진다.

Docker Compose는 Dockerfile을 대체하는 도구가 아니라 Dockerfile과 함께 사용하는 도구다. 각 서비스의 구성을 위해 Dockerfile을 사용한다면 Docker Compose는 서비스 전반의 구성을 위해 사용한다. 즉, Docker Compose는 여러 Dockerfile을 관리하는 도구라고 이해할 수 있다.
도커 컨테이너, 가상화, 내부구조 (feat. VM vs Container)
Docker가 Image Layer를 구성하는 방법
Docker run, start, create 차이
Docker 이해하기 -1 : 기초 이론(아키텍처, 흐름, 주요 용어)
Docker 이해하기 -2 : 컨테이너 라이프 사이클 & CLI 이해하기
Docker 이해하기 -3 : Dockfile 이해하고 Nginx 구성 및 실행방법
Docker 이해하기 -4 : Docker Compose 이해하고 구성하기