본문 바로가기
DevOps/Docker

Docker란 무엇인가? 왜 사용할까?

by 🌻♚ 2021. 10. 6.

Docker 개요

어느 순간부터 Docker가 마치 업계 표준이된 것 처럼… 많은 서비스에서 사용되고 있는 기술이 되었습니다. 특히 MSA(Micro Service Architecture) 가 대세로 떠오르면서 MSA의 단점인 관리의 복잡성을 해결해주기 위해 서비스의 컨테이너화가 이루어지고, 이 과정에서 Docker와 Kubernetes가 많이 도입되었습니다.

MSA(Micro Service Architecture)

※ MSA는 서비스간의 의존성을 없애고 기능을 쪼개는 것을 중점적으로 설계한 아키텍처입니다.
예를 들어, 은행 시스템을 하나의 통합된 프로그램으로 개발하지 않고… 입/출금 서비스, 조회 서비스, 대출 서비스 등 기능별로 작게 쪼개서 MSA 형태로 되어 있다고 가정하겠습니다. 이 때 새로운 대출 유형이 생겨 개발이 필요하면, 은행 시스템 전체를 수정할 필요 없이 대출 서비스의 수정만으로 작업을 경량화 할 수 있습니다.

위의 예시처럼 MSA는 아래와 같은 장점을 갖을 수 있습니다.

  • 서비스 단위의 개발 가능
  • 지속적인 통합과 배포(CI/CD)를 효율적으로 할 수 있음
    • 패치가 필요한 서비스만 배포하거나 Hotfix(정기 패치 이외 급하게 수정이 필요한 패치)를 빠르게 처리할 수 있음
  • 전체가 아닌 필요한 서비스에만 이중화를 할 수 있다.

전체적인 그림에서 서비스간 결합도(Coupling)를 줄이고 응집도(Cohesion)를 높이는 효과를 볼 수 있습니다.

MSA에 이런 장점들이 있는 반면에… 서비스들을 관리하기 복잡하다는 단점이 있습니다. Docker를 사용하면 이런 문제를 쉽게 해결할 수 있습니다.

Why Docker?

IaC(Infrastructure as Code)

우선 위의 글의 내용에서는 시스템을 신속하게 구축하고 관리하는 관점 에서 MSA에 중점적인 이유를 작성했는데… Docker가 꼭 MSA를 위한 기술은 아닙니다. 테스트, 스테이징, 배포 등 여러 용도로도 사용할 수 있습니다.

단, 중요하게 봐야할 관점은 Docker를 사용하면 IaC(Infrastructure as Code)가 가능 하다는 점이라고 생각합니다.

이제 앞으로 여러 실습들을 진행하면서 Docker로 컨테이너를 만들어서 사용해 보면… 그냥 애플리케이션을 담은 가상화된 공간? 분리된 공간? 혹은 운영체제 위에 운영체제? 그냥 이정도로 보일 수 있습니다.

그런데 Docker의 진짜 큰 힘은 인프라를 코드화해서 관리할 수 있다는 점 입니다. 앞으로 확인해볼 Dockerfile이나 docker-compose를 만져보면 이전에는 직접 시스템을 세팅해줘야 하는 부분들을 코드로 편리하게 관리할 수 있는 것을 볼 수 있습니다.

Docker와 Container, 가상화

Docker를 이해하기 위해서는 Container와 가상화에 대한 이해가 선행되어야합니다. Docker이외에도 containerd, CRI-O 등 컨테이너 런타임이 많이 존재합니다. 실제 예를 들어, Container를 Orchestrating하는 플랫폼인 Kubernetes의 최신 버전에서는 더 이상 컨테이너 런타임으로 Docker를 더 이상 지원하지 않는다고 공고했습니다. 그래서 Container를 다루는 기술을 알아야합니다.

해당 글에서는 Container, 가상화 와 Docker에 대해 다룹니다.

Container란?

Docker를 이해하는데 있어서 Container에 대한 이해가 필요 합니다.

컨테이너는 Host OS 상에서 리소스를 논리적으로 구분하여 마치 별도의 서버인 것 처럼 사용할 수 있게 하는 기술 입니다. 이게 논리적으로 구분한다는게 중요한데… 물리적으로 구분하지 않기 때문에 쉽게 없애고 다시 생성하고 할 수 있는 것 입니다. 이런 면에서 가볍다고 표현할 수 있습니다.

예시가 정확하지는 않지만… 쉽게 비유를해서 생각해보면 건물(물리적 리소스)에서 벽을 치고 공간을 구분해서 음식점, 술집, 부동산, PC방, 사우나 등 용도에 따라 전기세, 수도세, 자리세(논리적 리소스)를 각각 사용한 만큼 내고 같은 이름의 직원을 고용해도 구분하기 쉬운 것 처럼 각 컨테이너들은 할당 받은 리소스를 이용하고 같은 포트를 사용해도 구분이 가능합니다.(건물을 분리하는 것은 어렵지만… 내부 공간은 인테리어를 통해 바꾸는 것은 쉽다는 가정)

컨테이너는 목적에 따라 논리적인 구분들 두고 사용한다.

이렇게 구분해서 컨테이너를 사용하는 이유는 아래와 같다.

  • 여러 애플리케이션에서 사용하고 있는 라이브러리나 미들웨어의 버전에 대한 충돌을 회피
  • 이식성과 확장성이 좋다
    • 컨테이너 이미지 그대로 의존성 없이 다른 환경에서 실행 가능
    • 컨테이너를 여러 개 실행해서 이중화 가능
  • 다양한 운영 환경을 지원할 수 있다
    • Windows 환경에서 Linux를 실행하거나 그 반대도 가능

컨테이너에 대해 알아봤는데… 기존에 VMWare나 Virtualbox를 이용해서 가상환경을 만들어 사용해본 개발자로서 한 가지 의문이 생길 수 밖에 없습니다.

"가상화 기술과는 어떤 차이가 있을까?"

가상화 기술과 컨테이너 기술의 차이

Legacy

  • 하나의 물리 서버에 애플리케이션 배포
  • 애플리케이션간 라이브러리나 미들웨어 버전의 충돌이 발생할 수 있음

Hosted Hypervisor(가상화 소프트웨어)

  • Virtual Box, VMWare, Parallels 와같은 소프트웨어
  • 호스트 OS 위에 가상화 소프트웨어를 설치해서 가상환경 구축
  • 간편하게 사용할 수 있어 클라이언트 PC에서 개발환경을 구축하거나 테스트를 위해 주로 사용
  • 컨테이너와는 다르게 Guest OS가 존재하여 오버헤드가 비교적 크다.
    • OS 위에 OS를 실행하는 것이므로 리소스(CPU, 메모리 등)을 할당하는데 작업이 필요

Bare Metal Hypervisor

  • Hyper-v, XenServer, ESXI Server, 등이 있다.
  • Host OS 없이 하드웨어에 직접 하이퍼바이저를 설치
  • Host OS가 없어 자원을 효율적으로 사용할 수 있다.
    • 하드웨어가 제어
    • 오버헤드가 비교적 적다.
  • 가상 머신들을 관리하기 위한 콘솔이 필요

Container

  • Docker, containerd, CRI-O 등이 컨테이너 런타임으로 있음
  • Guest OS가 없고 Host OS의 커널을 공유하여 오버헤드가 적고 가벼워 빠르다
    • OS 실행 없이 별도의 환경에서 애플리케이션 실행이 가능
  • 이식성과 확장성이 높다.

가상화 기술과 컨테이너 기술은 비슷하면서도 다르다. 어느 하나가 더 좋다 나쁘다라고 정의하기보다는 각각 목적에 맞게 다르게 사용되고 있다.

Docker란?

Docker는 컨테이너 기술을 사용하여 애플리케이션에 필요한 환경을 신속하게 구축하고 테스트 및 배포를 할 수 있게 해주는 플랫폼 입니다.

무료로 제공해주는 CE(Community Edition)과 EE(Enterprise Edition)으로 나뉘고 아래와 같은 플랫폼들에서 작동 가능하다.

  • Linux
    • Ubuntu
    • CentOS
    • Debian
  • Cloud
    • Azure
    • AWS
  • Windows10
  • MacOS
  • ETC

널리 사용되고 있는 대부분의 환경에서 모두 구동 가능하다.

※ Docker가 컨테이너 기술을 만든 것이라고 헷갈려할 수 있을 것 같습니다. 컨테이너 기술을 이미 존재하는 기술이고 Docker는 이 컨테이너 기술을 사용하기 쉽게 만든 프로그램입니다.

Docker 이미지

컨테이너를 생성하는 Base가 되는 것이 이미지 입니다. 이미지는 컨테이너를 실행하는데 필요한 모든 것을 포함하고 재사용이 가능하다. 약간 클래스와 인스턴스의 개념이나, 붕어빵 틀과 붕어빵으로 생각하면 쉽게 접근할 수 있다.

단순히 개발하고 있는 애플리케이션만 이미지형태로 만들어서 배포하는 것이 아니라… Database나 WEB/WAS 처럼 미들웨어로 사용되는 프로그램들 혹은 다른 OS 환경을 실행하기 위한 이미지가 Docker 이미지 Repository(Ex. Docker Hub)에 배포되어 있어 받아서 사용하면 된다.

  • Oracle 이미지를 받아서 컨테이너를 생성하고 DB로 활용
  • Java, Apache/Tomcat이 설치되어 있는 이미지를 받아서 그 위에 애플리케이션을 올리고 재배포
  • Windows OS에서 CentOS 운영체제를 사용하기 위해 CentOS 이미지를 받아서 사용

개발과 배포의 흐름

Docker가 컨테이너 기술을 사용하는 소프트웨어라는 것은 알겠는데… 아직 왜 사용하고 사용하면 어떤 장점이 있는지 감이 안올 수 있습니다. 그래서 한 가지 예시로, 아래 개발과 배포에 대한 흐름을 비교해서 확인해보겠습니다.

Legacy

실제로 이렇게 개발환경을 구성하는 곳은 없겠지만… 쉽게 설명하기 위해 조금 극단적인 예시를 들었습니다. 아래는 Legacy 환경에서 개발 부터 배포의 흐름입니다.

  1. 개발자가 개인 PC에서 애플리케이션을 개발하고 Repository에 배포합니다.
  2. Repositorty에서 애플리케이션을 받아 테스트환경에서 테스트합니다.
  3. Repository에서 애플리케이션을 받아 스테이징환경에서 서비스를 구동하기 위한 모든 애플리케이션을 테스트합니다.
    1. 스테이징 환경은 실환경과 똑같지만 규모가 작은 환경으로 생각하시면 됩니다.
  4. 실환경에 애플리케이션을 배포합니다.

위의 흐름을 봤을 때… 발생할 수 있는 가장 큰 문제가 하나 보일겁니다. 애플리케이션은 모든 환경에서 같지만… 각 환경의 서버의 운영체제나 그위에 올라가 있는 미들웨어 프로그램들은 동일하지 않다. 의존성 문제나 제품 자체가 달라 생기는 문제 등, 개발자 개인 PC에서는 애플리케이션이 정상작동하는데 테스트환경에서는 오류가 발생하는 문제가 발생할 수 있습니다. 그래서 최대한 프로덕션 환경을 기준으로 다른 환경도 똑같이 맞추려고 가상환경을 이용해서 환경을 구축하면 어느정도 커버는 가능하지만… 완벽하게 의존성을 제거할수는 없고 여전히 아래와 같은 문제들이 있다.

  • 무겁다.
  • 이식과 확장에 불리하다.
  • 관리가 복잡하다. 등

Containerized Applications(Docker)

Docker를 사용해서 서비스를 운영하다는 것은 애플리케이션들을 컨테이너화(Containerizing)했다는 뜻입니다.

  1. 개발자가 개인 PC에서 Docker 이미지를 빌드해서 Repository에 배포한다.
  2. 테스트, 스테이징, 프로덕션 환경에 Docker 프로그램만 설치하고 배포된 애플리케이션 이미지를 받아 실행 후 테스트한다.
    1. 애플리케이션에 필요한 미들웨어도 컨테이너로 받아서 사용한다.
    2. 애플리케이션에 필요한 모든 요소들을 컨테이너로 받고 Docker-compose, Docker Swarm, Kubernetes 등을 이용해서 관리할 수 있다.

애플리케이션을 컨테이너화 했을 때 개발과 배포의 흐름이 매우 간단해져서 빠르게 진행될 수 있는 것을 확인할 수 있습니다. 서버의 운영체제나 미들웨어의 의존성에 대해 걱정할 필요없이 Docker만 설치되어 있다면 모든 것이 해결됩니다.

더불어 컨테이너에 대한 관리를 Dockerfile, docker-compose나 더 나아가 kubernetes를 사용하면 인프라가 코드화되어 편리하게 관리할 수 있다.

이렇게 편한데 Docker가 인기 없을 이유가 없다.

Docker 작동 원리

지금까지의 Docker에 대한 내용을 봤을 때…

  • 의존성을 제거하고 논리적인 공간으로 분리가 된다.
  • 이식성과 확장성이 좋다.
  • 개발과 배포가 빠르다. 와 같은 장점들을 보여드렸습니다. 그렇다면 이게 어떻게 가능할까요?

Docker는 리눅스 커널의 기술이 기반되고 있다.

Container Namespace

Docker를 사용하다보면 컨테이너별로 논리적인 공간을 갖게된다는 것을 확인할 수 있다. 이는 Linux 커널의 namespace를 사용하고 있기 때문에 가능한 것이다. namespace는 변수의 개념과 비슷합니다. 논리적으로 이름을 붙여 참조할 수 있도록하여 충돌을 피하는 방식입니다. Linux는 아래의 오브젝트에 namespace를 붙일 수 있습니다.

  • PID(Process ID)
  • UID(User ID)
  • Network
  • mount(file system mount)
  • UTS(hostname)
  • IPC(프로세스간의 통신)

이렇게 namespace를 사용하면 Host OS나 다른 컨테이너와 같은 PID를 갖는 프로세스를 띄우거나 같은 포트에 서비스를 띄우는 작업들을 할 수 있습니다.

그럼 Windows 10 환경에서는 어떨까요?

Docker는 namespace 처럼 리눅스 커널의 기술을 기반으로하고 있는데 어떻게 Windows에서 Docker를 사용할 수 있는 것 일까요?

  • Windows에서 Docker는 Hyper-V를 이용한 Linux VM에 Docker를 실행하는 방법을 이용하고 있습니다. 그래서 결국은 Linux에서 실행되고 있는 것 입니다.
  • Hyper-V를 사용하면 VMWare, Virtualbox와 같은 가상화 툴을 사용할 수 없다.

리소스 관리

Docker에서 컨테이너를 실행하면 논리적인 namespace를 갖지만… 결국 Host OS의 물리적인 리소스는 공유해야합니다.

리눅스 커널의 cgroups를 활용하면 아래 리소스들을 제어할 수 있다.

  • CPU
  • Memory
  • Network
  • I/O

cgroups는 프로세스와 쓰레드를 그룹화해서 관리하기 위한 기능이다. 이런 제어는 꼭 필요한 부분이다. 예를 들어 특정 컨테이너가 모든 자원을 사용해버려 다른 프로세스에 문제를 발생시키면 안되기 때문에 제한을 둘 수 있다.

태그

,

댓글0