Docker #1. 도커(Docker)란 무엇인가?
Prog. Langs & Tools/Docker

Docker #1. 도커(Docker)란 무엇인가?

이번 포스팅을 시작으로 도커를 처음 시작하는 사람이 알아야 할 내용 및 실습 방법에 대한 포스팅을 해 보려고 한다.

 

도커란 무엇인가?

도커는 컨테이너형 가상화 기술을 구현하기 위한 상주 어플리케이션과 이 어플리케이션을 조작하기 위한 명령행 도구로 구성되는 프로덕트이다. 어플리케이션 배포에 특화되어 있기 때문에 어플리케이션 개발 및 운영을 컨테이너 중심으로 할 수 있다.

웹 어플리케이션을 개발한다고 가정해 보자. 로컬에 Apache나 Nginx 같은 웹 서버를 구축한다고 생각해 보자. 가상 환경에 운영 환경과 같은 운영 체제를 설치하고 환경 구축 작업을 해야 한다. 이 때 로컬 환경에 도커만 설치하면 몇 줄짜리 구성 파일과 명령어 한 줄로 어플리케이션이나 미들웨어가 이미 갖추어진 테스트용 가상환경(도커 컨테이너)을 빠르게 구축할 수 있다. 가상화 소프트웨어와 비교해도 오버헤드가 적어진다는 장점이 있다.

가상머신과 컨테이너 비교

또한 도커의 큰 장점으로는 개발 후 운영 환경에 대한 배포나 어플리케이션 플랫폼으로 기능할 수 있다는 점에서 기존의 가상머신보다 더 뛰어나다. 그리고 도커는 이식성이 뛰어나서 로컬 머신의 도커 환경에서 실행하던 컨테이너를 다른 서버에 있는 도커 환경에 배포하거나 반대로 다른 서버의 도커 환경에서 동작하던 컨테이너를 로컬로 가져올 수 있다.

도커는 컨테이너형 가상화 기술을 사용한다. 컨테이너 가상화 기술은 도커 이전에도 존재했던 기술이었다.(ex. LSX, Linux Container) 컨테이너형 가상화를 사용하면 가상화 소프트웨어 없이도 운영 체제의 리소스를 격리해 가상 운영 체제로 만들 수 있다. 이러한 가상 운영 체제를 컨테이너라고 한다. 도커는 LSX가 가진 컨테이너의 이점을 잘 살리면서, 어플리케이션 배포에 초점을 맞췄다. 도커가 LSX에 비해 갖는 장점은 다음과 같다.

  • 호스트 운영 체제의 영향을 받지 않는 실행 환경(Docker Engine을 이용한 실행 환경 표준화)
  • Dockerfile을 이용한 컨테이너 구성 및 어플리케이션 배포 정의
  • 이미지 버전 관리
  • 레이어 구조를 갖는 이미지 포맷(차분 빌드가 가능함)
  • 도커 레지스트리(이미지 저장 서버 역할을 함)
  • 프로그램 가능한 다양한 기능의 API

도커는 컨테이너 정보를 Dockerfile로 관리한다. 이 코드를 기반으로 복제 및 배포가 이루어지기 때문에 재현성이 높은 것이 특징이다. 어플리케이션 배포 환경으로 도커가 널리 쓰이는 원인은 이렇듯 환경의 영향을 덜 받고 배포가 간편하기 때문이다.

컨테이너 하나에 모든 것이 포함되었다는 의미


도커를 사용하는 의의

기존의 방식으로 개발과 배포, 운영을 하는 사람들의 입장에서는 "굳이 익숙한 방법을 버리면서까지 도커를 도입해야 할 이유가 무엇일까?"라고 생각할 수도 있다. 도커를 사용하는 의의는 다음과 같이 생각해 볼 수 있다. 하나씩 살펴 보도록 하자.

  • 변화하지 않는 실행 환경으로 멱등성(Idempotency) 확보
  • 코드를 통한 실행 환경 구축 및 어플리케이션 구성
  • 실행 환경과 어플리케이션 일체화로 이식성 향상
  • 시스템을 구성하는 어플리케이션 및 미들웨어 관리의 용이성

도커 아키텍처

1. 환경 차이로 인한 문제 방지

여러 대의 서버에 같은 어플리케이션을 배포하는 상황을 생각해 볼 때, 같은 어플리케이션이더라도 서버마다 설정이 달라 다르게 동작할 수가 있다. 이 문제의 근본적인 원인은 인프라의 가변성(mutable infrastructure)을 허용하고 있기 때문이다.

어플리케이션은 항상 의존성을 갖는다. OS, CPU와 메모리 같은 리소스, 언어 런타임, 라이브러리 등등 말이다. 각 서버에 배포된 어플리케이션이 동일하다면 어플리케이션이 의존하는 환경의 차이를 가능한 배재하는 것이 이 문제를 해결하는 지름길이다.

이 문제를 해결하기 위해 코드로 관리하는 인프라(Infrastructure as Code)라는 개념이 등장하였다. 서버를 어떻게 구성할 것인지, 어떤 라이브러리와 도구를 설치할지를 코드로 정의하고 Chef나 Ansible 같은 프로비저닝 도구로 서버를 구축한다. 수작업이 개입할 여지를 줄이고 코드 중심으로 바꿈으로써 쉽게 같은 구성의 서버를 여러대 복제할 수 있다. 다만 이 경우도 잦은 업데이트 등으로 멱등성을 보장할 수 없는 경우가 발생할 수 있다.

그래서 이를 해결하기 위해 불변 인프라(Immutable Infrastructure) 개념이 등장했다. 불변 인프라는 어떤 시점의 서버 상태를 저장해 복제할 수 있게 하자는 개념이다. 제대로 설정된 상태의 서버를 항상 사용할 수 있다는 점이 가장 큰 장점이다. 서버에 변경을 가하고 싶을 때는 기존 인프라를 수정하는 대신 새로운 서버를 구축하고 그 상태를 이미지로 저장한 다음 그 이미지를 복제한다. 한 번 설정된 서버는 수정 없이 파기되므로 멱등성을 신경쓸 필요조차 없다.

도커는 컨테이너 가상화 기술을 사용한다. 호스트형 가상화에서 가상머신 OS를 재현하는 것과 달리, 컨테이너형 가상화는 운영체제 대부분을 호스트 운영체제와 공유한다. 따라서 실행에 걸리는 시간이 수 초 정도로 짧아진다. 도커는 도커 이미지(Dockerfile)로 서버 구성을 코드로 관리할 수 있다. 그러므로 기존 컨테이너를 빠르게 폐기하고 새로이 구축할 수 있다. 코드로 관리하는 인프라와 불변 인프라라는 두 개념을 모두 쉽게 실현할 수 있는 도구인 것이다.

2. 어플리케이션 구성 관리의 용이성

도커 컨테이너는 어플리케이션과 인프라를 함께 담은 상자다. 일정 규모가 넘어가게 되면 여러개의 컨테이너를 조합하여 서비스를 구성하게 되고, 시스템 전체에 대한 적절한 구성 관리가 필요해졌다. 도커는 필요한 컨테이너를 각각 구성하는 방법으로 이러한 시스템을 구성한다. 도커를 사용함으로써 배포 작업이 매우 쉬워지기는 했지만, 복잡한 시스템을 한 덩어리로 동작시키기는 쉽지 않다. 

도커에서는 이 문제를 도커 컴포즈(docker compose)를 통해 해결했다. 도커 컴포즈는 여러 컨테이너를 사용하는 어플리케이션을 쉽게 관리할 수 있는 도구이다. 도커 컴포즈를 사용하면 yaml 포맷으로 작성된 설정파일로 컨테이너를 정의하거나 컨테이너 간의 의존 관계를 정의해 시작 순서를 제어할 수 있다. 예를 들어 어떤 웹 어플리케이션에 Redis가 필요하다면 웹 어플리케이션과 Redis 컨테이너의 구성을 다음과 같이 정의해 실행하면 된다.

도커와 도커 컴포즈를 통해 여러 어플리케이션과 미들웨어의 의존관계를 간결한 코드로 관리할 수 있다. 반면, 대규모 트래픽 처리 같은 많은 작업을 해야 하는 시스템은 도커가 설치된 서버(도커 노드)를 여러 대 갖추고 이 노드 그룹에 필요한 만큼의 어플리케이션 컨테이너를 배포해야 한다. 여러 서버에 걸쳐 있는 컨테이너를 관리하는 기법을 컨테이너 오케스트레이션(container orchestration)이라고 한다. 컨테이너 오케스트레이션 분야에서 사실상 표준으로 자리잡은 건 쿠버네티스(Kubernetes, K8S)다. 도커 스웜보다 기능이 충실하며 확장성이 높다.


참고자료

  1. <도커/쿠버네티스를 활용한 컨테이너 개발 실전 입문> 야마다 아키노리 저
  2. <Docker Mastery: with Kubernetes and Swarm from a Docker Captain>(Udemy)