현재 저는 청년취업사관학교에서 클라우드 관련 과정을 수강하고 있습니다.
클라우드에 대한 학습을 시작하기에 앞서 개발, 배포 환경이라는 분야에 있어 빠지지 않는 플랫폼인 Docker에 대한 기초적인 지식을 습득하게 되었습니다.
이번 글에서는 Docker를 학습하고 난 뒤에 정리된 여러 생각들을 작성해보며 나름대로 정리를 해볼까 합니다.
Docker는 어떤 플랫폼일까요?
제가 읽은 관련 도서에서는 Docker를 애플리케이션을 컨테이너화하여 격리된 환경에서 실행할 수 있게 해주는 플랫폼으로 소개하고 있습니다.
그렇다면 '격리'라는 것은 무엇이고 애플리케이션을 격리시켰을 때의 장점은 무엇인지가 중요할 것입니다. 하나씩 정리해봅시다.
격리란 말 그대로 어떤 요소를 다른 요소에 영향을 받지 않도록 분리시키는 것을 의미합니다.
모든 기술은 어떤 문제를 해결하기 위해서 등장합니다. 격리 기능이 필요한 이유는 '자원 공유 및 의존성 문제'를 해결하기 위해서입니다.
예를 들어 하나의 호스트 운영체제가 있다고 생각해봅시다. 그리고 그 위에는 여러 개의 애플리케이션이 실행되고 있다고 가정해봅시다. 어떤 문제가 발생할 수 있을까요?
먼저 하나의 프로세스(실행 중인 애플리케이션)에 부하가 걸리게 될 때 문제가 생길 수 있습니다. 그렇게 되면 그 프로세스에만 문제가 발생하는 것이 아니라 같은 자원(CPU, RAM 등)을 공유하는 다른 프로세스에도 영향이 가기 마련입니다. 이것이 첫 번째 문제입니다.
또한 프로세스 간 의존성이 있을 때를 생각해봅시다. 하나의 프로세스에 대해 업데이트와 같은 특정 작업을 수행한다고 가정해보면, 해당 작업이 다른 프로세스에 영향을 주지 않는다고 보장할 수 없습니다.
이 외에도 여러 가지 문제점들이 존재하지만, 이 두 가지 예시만으로도 애플리케이션을 격리시켜 실행할 필요성을 충분히 느낄 수 있습니다.
그렇다면 Docker에서는 컨테이너라는 독립된 환경을 어떻게 생성할 수 있을까요?
컨테이너는 그 자체로 생성할 수 없습니다. '이미지'가 있어야 컨테이너를 생성할 수 있습니다.
이미지란, 간단하게 특정한 애플리케이션이 실행될 수 있도록 하는 일련의 지침과 필요한 파일들을 포함하는 패키지라고 이해할 수 있습니다.
그렇다면 이미지를 어떻게 만들 수 있을까요?
이미지는 여러 가지 방법으로 생성할 수 있습니다. 이미 존재하는 컨테이너를 사용하여 이미지를 생성할 수도 있습니다.
하지만 일반적으로 Dockerfile이라는 파일에 앞서 얘기한 일련의 지침을 특정한 문법에 따라 작성하고, 이 Dockerfile을 빌드함으로써 이미지를 생성합니다.
추가적으로 이미 공식적인 서비스들에 대한 이미지는 DockerHub라고 하는 저장소에 존재합니다. DockerHub를 통해 공식 이미지뿐만 아니라 커뮤니티에서 제작한 다양한 이미지들을 쉽게 사용할 수 있습니다.
좋습니다. 이미지가 있다고 가정하고, 컨테이너가 생성되었습니다. 여기서 궁금한 점이 하나 생깁니다.
일반적으로 하나의 컨테이너 위에는 하나의 애플리케이션이 배포됩니다. 하지만 웹 애플리케이션의 일반적인 3계층 구조(프레젠테이션 계층, 비즈니스 로직 계층, 데이터 계층)만 생각해도 컨테이너 간 통신은 필수적인 요소입니다.
그렇다면 컨테이너 간 통신을 어떻게 지원하는지 알아봅시다.
Docker에서는 Network라고 하는 기능을 사용하여 컨테이너 간 통신을 지원합니다. 통신이 필요한 컨테이너를 같은 Network 내부에 위치시키고, 도메인의 경우에는 컨테이너 이름을 사용할 수 있게 해줍니다. 어떤 컨테이너에 요청을 보내고 싶다면 컨테이너 이름을 사용하면 됩니다. 그러면 Docker의 내장 DNS가 해당 요청을 적절한 컨테이너에게 전달해줍니다.
컨테이너를 생성했고, 네트워크 기능을 사용하여 컨테이너 간 통신을 가능하게 만들었습니다. 하지만 여전히 하나 의문점이 남습니다. 컨테이너는 일반적으로 '일회용'입니다. 쉽게 삭제하고, 쉽게 생성할 수 있다는 것이 컨테이너의 장점입니다. 그렇다면 내부적인 데이터는 어떨까요? 영속적일까요?
특정한 설정 없이 컨테이너를 삭제하면 내부적인 데이터는 함께 삭제됩니다. 그렇다면 데이터의 영속성을 보장하는 방법은 무엇일까요?
Docker에서는 Volume이라는 기능을 통해 데이터의 영속성을 보장합니다.
Volume은 컨테이너의 특정 디렉토리를 호스트 시스템의 디렉토리에 연결(마운트)하는 방식으로 작동합니다. 이렇게 하면 컨테이너가 삭제되어도 데이터는 호스트 시스템에 남아있게 되어 영속성을 유지할 수 있습니다. 또한 여러 컨테이너가 같은 Volume을 공유할 수 있어, 데이터 공유에도 유용합니다.
지금까지 Docker의 기본적인 요소들에 대해 알아보았습니다. 하지만 실제 애플리케이션은 여러 개의 컨테이너로 구성되는 경우가 많습니다. 이런 경우 각 컨테이너를 개별적으로 관리하는 것은 번거로울 수 있습니다. 이를 해결하기 위해 Docker Compose라는 도구가 있습니다.
Docker Compose는 여러 컨테이너로 구성된 애플리케이션을 정의하고 실행할 수 있게 해주는 도구입니다. YAML 파일을 사용하여 서비스, 네트워크, 볼륨 등을 정의하고, 단일 명령으로 모든 서비스를 시작할 수 있어 매우 편리합니다.
Docker에 대한 기본적인 개념들을 학습하며 몇 가지 요소들에 대한 생각들을 정리해봤습니다. 아직 배울 것이 많이 남아있지만, 이 정도의 이해만으로도 Docker를 활용해볼 수 있었습니다.
Docker는 그 자체로도 완성된 플랫폼이지만, 현실에서는 Docker만으로는 부족한 경우가 있다고 합니다. 여력이 생기면 다음 글에서는 Docker의 몇 가지 한계점들을 해소해주는 서비스인 K8S에 대한 생각을 정리해보도록 하겠습니다.