도커에 대해 =)

이전 프로젝트들은 깃허브 action 이나 깃랩 runner 로 테스팅 / 자동 배포를 구축했었는데, 도커 환경 + 배포 소프트웨어를 이용한 배포를 구성해보려한다. 어떤게 더 나을지는 지켜봐야 알듯 ㅎ_ㅎ 한번 해보고 후기 남기는걸로..

도커를 사용하는 이유 ?

어떤 프로그램 / 프로젝트를 다운로드 혹은 셋업하는 과정을 간단하게 만들기 위해서!

예를 들어, 도커 없이 로컬에서 개발된 프로젝트를 서버에 배포한다고 생각해보자. 담당 개발자는 사용한 모든 패키지 버전 / pm2 나 supervisor 와 같은 프로세스 매니저 / DB / 인메모리 소프트웨어 등을 다시 셋업해야하고, 심지어는 프로그램간의 의존성으로 설치 과정 중 많은 에러가 발생할 수도 있다.

아래는 Redis를 설치하는 한가지의 예시이다.

[도커 없이 Redis 설치]

$ sudo apt install lsb-release curl gpg
$ curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg

$ echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
$ sudo apt-get update
$ sudo apt-get install redis

[도커로 Redis 설치]

$ docker run it redis

도커를 이용하여 프로그램을 설치하면 예상치 못한 에러도 덜 발생하며, 설치하는 과정도 훨씬 간단해진다.


그럼 도커란 무엇일까 ?

컨테이너를 사용하여 응용 프로그램을 더 쉽게 만들고 배포하고 실행할 수 있도록 설계된 도구이며 컨테이너 기반의 오픈소스 가상화 플랫폼이며 생태계이다.

여기서 컨테이너 라는 개념이 참 중요하다. 일반 컨테이너의 개념처럼 여러 물건을 한군데 모아 손쉽게 운송할 수 있도록 해주는 것처럼 프로그램을 손쉽게 이동 / 배포 관리를 할 수 있게 해준다. 또한 AWS, Azure, Google Cloud 등 어디에서든 실행 가능하게 해준다.

  • https://www.docker.com/resources/what-container/
  • https://www.docker.com/why-docker/

도커 이미지와 컨테이너의 정의

컨테이너는 코드와 모든 종속성을 패키지화하여 응용 프로그램이 한 컴퓨팅 환경에서 다른 컴퓨팅 환경으로 빠르고 안정적으로 실행되도록 하는 소프트웨어의 표준 단위이다.

컨테이너 이미지는 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정과 같은 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하는 가볍고 독립적이며 실행 가능한 소프트웨어 패키지이다.

도커 이미지를 이용해서 도커 컨테이너를 생성해서 사용한다.

즉, 도커 이미지는 프로그램을 실행하는데 필요한 설정이나 종속성을 갖고 있으며, 도커 이미지를 이용해서 컨테이너를 생성하며 도커 컨테이너를 이용ㅇ해서 프로그램을 실행한다 ! 요게 핵심이다.


도커를 사용할 때의 흐름

  1. 도커 CLI(Client)에 커맨드 입력
  2. 도커 서버(Daemon)이 커맨드를 받아서 그것에 따라 이미지를 생성하든 컨테이너를 실행하든 모든 작업을 하게 된다.

[ 테스트 ]

  1. 도커 CLI에 커맨드 입력

로컬에서 한번도 hello-world라는 이미지를 생성한 적이 없으므로, Docker hub로부터 hello-world 라는 이미지를 풀링하는 것을 볼 수 있다.

그 다음에는 도커가 해당 이미지를 로컬에 Cache 로 보관한다. 그 후 이제는 이미지가 있으니 그 이미지를 이용해서 컨테이너를 생성한다.

그 다음 다시 hello-world 이미지를 런 시켜보자.

Unable 문구가 뜨지 않고 바로 hello-world 이미지가 가져와졌음을 볼 수 있다. (최초 서버에서 가져올때 로컬에 cache로 저장했기 때문임)


도커와 가상화(VMware 등) 기술과의 차이

  • 가상화 기술이 나오기 이전
    • 한대의 서버를 하나의 용도로만 사용
    • 남는 서버 공간 그대로 방치
    • 하나의 서버에 하나의 운영체제, 하나의 프로그램만을 운영
    • 안정적이지만 비효율적임
  • 하이퍼 바이저 기반의 가상화 출현
    • 논리적으로 공간을 분할하여 VM 이라는 독립적인 가상 환경의 서버 이용 가능
    • 하이퍼 바이저는 호스트 시스템에서 다수의 게스트 OS를 구동할 수 있게 하는 소프트웨어, 그리고 가상화하면서 하드웨어와 각각의 VM을 모니터링 하는 중간 관리자이다.

하이퍼 바이저에는 두가지 형식이 있다.

  1. 네이티브 하이퍼 바이저
    • 하이퍼 바이저가 하드웨어를 직접 제어하기에 자원을 효율적으로 사용할 수 있으며, 별도의 호스트 OS가 없으므로 오버헤드가 적다.
    • 여러 하드웨어 드라이브를 세팅해야하므로 설치가 어렵다.
  2. 호스트형 하이퍼 바이저
    • 현재 가장 널리 사용됨
    • 일반적인 소프트웨어 처럼 호스트 OS 위에서 실행되며, 하드웨어 자원을 VM 내부의 게스트 OS에 에뮬레이트 하는 방식으로 오버헤드가 크다.
    • 게스트 OS 종류에 대한 제약이 없고 구현이 다소 쉽다.

하이퍼 바이저 기반의 VM 구조

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

이러한 가상화 기술에서 컨테이너 가상화 기술이 등장하였다.

  • 공통점
    • 도커 컨테이너와 가상머신은 기본 하드웨어에서 격리된 환경 내에 어플리케이션을 배치하는 방법이다.
  • 차이점
    • 가장 큰 차이점은 격리된 환경을 얼마나 격리시키는지의 차이
    • VM과 비교했을때 컨테이너는 하이퍼바이저와 게스트 OS가 필요하지 않으므로 더 가볍다
    • 어플리케이션을 실행할 때는 컨테이너 방식에서는 호스트 OS위에 어플리케이션의 실행 패키지인 이미지를 배포하기만 하면 되는데, VM은 어플리케이션을 실행하기 위해 VM을 띄우고 자원을 할당한 다음, 게스트 OS를 부팅하여 어플리케이션을 실행 해야 해서 훨씬 복잡하고 무겁다.

도커 컨테이너에서 돌아가는 애플리케이션은 컨테이너가 제공하는 격리 기능 내부에 샌드박스가 있지만, 여전히 같은 호스트의 다른 컨테이너와 동일한 커널을 공유한다. 결과적으로, 컨테이너 내부에서 실행되는 프로세스는 호스트 시스템(모든 프로세스를 나열할 수 있는 충분한 권한있음)에서 볼 수 있다.
예를 들어, 도커와 함께 몽고DB 컨테이너를 시작하면 호스트(도커가 아님)의 일반 쉘에 ps-e grep 몽고를 실행하면 프로세스가 표시됩니다.
또한, 컨테이너가 전체 OS를 내장할 필요가 없는 결과, 그것들은 매우 가볍고, 일반적으로 약 5-100 MB이다.

가상 머신과 함께 VM 내부에서 실행되는 모든 것은 호스트 운영 체제 또는 하이퍼바이저와 독립되어 있다. 가상 머신 플랫폼은 특정 VM에 대한 가상화 프로세스를 관리하기 위해 프로세스를 시작하고, 호스트 시스템은 그것의 하드웨어 자원의 일부를 VM에 할당한다. 그러나 VM과 근본적으로 다른 것은 시작 시간에 이 VM 환경을 위해 새롭고 이 특정 VM만을 위한 커널을 부팅하고 (흔히 다소 큰) 운영 체제 프로세스 세트를 시작한다는 것이다. 이것은 응용 프로그램만 포함하는 일반적인 컨테이너보다 VM의 크기를 훨씬 크게 만든다.
OS까지 가상화…  맥에서 윈도우를 깐다든지 리눅스에서 윈도우를 돌린다든지…
이러한 방법은 비교적 사용법이 간단할 수 있지만 굉장히 느리다.

컨테이너를 격리 시키는 방법

리눅스 OS 커널에서 각 프로세스들을 분리하는 것과 동일한 기술이 사용된다.

  • 네임 스페이스
    • 하나의 시스템에서 프로세스를 격리시킬 수 있는 가상화 기술 
      별개의 독립된 공간을 사용하는 것처럼 격리된 환경을 제공하는 경량 프로세스 가상화 기술 
  • C group
    • CPU, 메모리, Network Bandwith, HD i/o 등 프로세스 그룹의
      시스템 리소스 사용량을 관리 => 어떤 어플이 사용량이 너무 많다면 그 어플리케이션 같은 것을 C group에 집어넣어서 CPU와 메모리 사용 제한 가능

이 기술들을 이용하여 각 도커 컨테이너에 사용될 만큼의 자원을 할당한다.