Docker 101 - 1장: 기본적인 개념

okkkkkky·2023년 8월 6일
0

FE 주니어 개발자가 회사에서 생존하기 위해 정리 겸, Docker 101을 작성해보았습니다. 참고 자료 이외에도 원티드 백엔드 챌린지 2023년 8월 강의의 내용을 반영하였습니다.

도커이미지

Docker를 조금 더 이해하기 위해선 이 용어들에 대해서 꼭 짚고 넘어가야 합니다.

가상화 기술

가상화란 물리적인 컴퓨터 하드웨어를 보다 효율적으로 활용할 수 있도록 해주는 프로세스입니다. 가상화 기술은 단일 컴퓨터가 가지고 있는 요소들을 가상머신(Virtual Machine, 줄여서 VM), 즉 가상의 컴퓨터로 분할할 수 있도록 해줍니다. 실제로 이 VM은 각각 자체 운영체제를 가지고 있으며, 독립적인 컴퓨터처럼 작동할 수 있습니다.

간단한 예를 들면, 가상화 기술은 아래의 상황에서 사용될 수 있습니다.

  • 더 많은 스토리지 공간과 또 다른 운영 체제를 필요로 하는 경우
  • 많은 트래픽을 처리하기 위해 처리 능력이 월등해야 하는 경우
  • 단일 컴퓨터로는 처리가 어렵고, 더 많은 내부 메모리가 필요한 경우

이러한 경우들에서는 물리적인 컴퓨터가 여러대 있는 것보단 여러개의 VM이 있는 것이 오히려 효율적으로 어플리케이션을 운영할 수 있게 되는 것이죠. 여기서 하드웨어와 가상머신을 이어주는, 중간관리자의 역할을 해주는 것이 필요한데, 그것이 바로 하이퍼바이저(Hypervisor)입니다. 즉, 가상머신들이 존재하는 가상화 계층을 구성해주는 소프트웨어입니다. 아래의 이미지가 앞서 말한 내용들을 모두 함축적으로 담고 있습니다.

하이버바이저

컨테이너

Docker는 리눅스 운영체제에 내장되어있는 컨테이너 기술을 이용해서 위의 작업들을 쉽게 해주는 소프트웨어입니다. 그럼 컨테이너 기술은 어떤 것을 의미하고, 컨테이너는 무엇일까요?
컨테이너 기술 역시, 위에서 언급한 가상화 기술입니다. 호스트 운영체제, 즉 어플리케이션을 구동하려고 하는 디바이스의 운영체제 (Mac OS, Windows, Linux등이 될 수 있겠죠)에 여러 개의 프로세스 단위의 격리된 환경을 구성해주고, 그 각각의 환경을 컨테이너라고 할 수 있죠. 그렇다면, 컨테이너와 가상머신은 어떻게 다를까요 ?

가상머신 vs 컨테이너

이 두 이미지의 차이점이 뭘까요 ? 바로, 각 VM, Container안에 Guest OS가 있느냐 없느냐의 차이입니다. 기본적으로 운영체제의 전체 번들을 가지고 있느냐의 차이는 공간차지의 면에 있어서 굉장한 차이를 보입니다. 또한, 가상머신의 경우, 시스템을 동작시킨 후 어플리케이션이 동작할 수 있는 반면, 컨테이너는 이미 호스트 운영체제 위에서 어플리케이션만 동작시키면 되기 때문에 실행속도에 있어서도 많은 차이를 보입니다.

리눅스 커널

리눅스의 컨테이너 기술을 활용하였다고 위에서 언급했는데, 그럼 이 기술은 어떻게 가능한 것일까요 ? 이 리눅스 컨테이너를 가능하게 했던 것은 리눅스 커널에서 제공하는 기능들이 있었기 때문입니다. 여기서 커널이란, 운영체제의 핵심적인 역할을 하는 것으로, 하드웨어와 응용프로그램 사이에서 인터페이스를 제공하고, 컴퓨터 자원을 관리해줍니다. 이 리눅스 커널에서 컨테이너 기술을 가능하게 했던 주요 3가지 기능에 대해서 간단히 알고 가는 것도 조금 더 Docker를 이해하는데 좋겠죠 ?

chroot

chroot란 change root의 약자입니다. 말그대로 루트를 변경한다는 뜻입니다. 루트 폴더의 위치를 변경하는 기능을 수행합니다. 이로써, 가상의 root를 설정하여 프로세스를 격리할 수 있게 됩니다. 컨테이너가 격리된 환경에서 관리될 수 있는 토대를 만들어줄 수 있습니다.

namespace

namespace는 프로세스, 즉 실행되고 있는 프로그램의 리소스를 격리하는 기술입니다. 여러 프로세스들이 각각 독립적인 리소스 공간을 가지게 되는 것입니다. 각자의 소속들이 생기게 되는 것이고, 이로 인해 프로세스들은 격리될 수 있습니다. (여기서 "격리"라는 표현이 중요한 포인트입니다!)

cgroups

namespace와 조금은 비슷한 느낌입니다. 하지만, cgroups의 경우, 프로세스들의 자원을 격리하고 사용을 제어합니다. 루트에서 각 프로세스 별로 자원을 어떻게 사용할 것인지 제한하고 분배하는 역할에 조금 더 가깝습니다. namespace는 조금 더 작은 단위, cgroups는 조금 더 큰 단위로 이해하면 좋겠죠 ?

Docker가 그래서 뭔데요?

자, 한 개의 어플리케이션을 개발할 때 필요한 것들에 대해서 생각해봅시다.

1) 어플리케이션의 앞단을 담당하는 클라이언트,
2) 클라이언트와 통신을 하는 서버 및 database,
3) 그리고 이외에 필요한 환경변수나 dependency 등이 있을 수 있겠네요.

만약 내 컴퓨터에서 만들어진 어플리케이션을 다른 사람의 컴퓨터에서 구동을 시키고 싶다면,앞서 말한 것들을 설치하는 등의 과정이 필요할 것이고, 환경변수를 직접 설정해야 하는 번거로움이 있을 수 있습니다. 혹은 직접 수동으로 설치했다 하더라도, 안되는 경우들이 한번쯤은 나타날 수도 있겠죠.
그래서 "이 모든 것들을 위에서 언급한 컨테이너 기술을 사용하여, 각각의 다른 운영체제에서 쉽게 배포하고 구동할 수 있게끔 도와주고 관리해주는 툴"이라고 간단하게 정의내릴 수 있을 것입니다.
Docker를 사용함으로써, 개발자들은 인프라와 관련된 것들은 Docker에 맡기고 어플리케이션에 조금 더 집중할 수 있겠죠 !

Docker architecture

자, 이제 Docker가 무슨 일을 하는지도 알겠고, 컨테이너 기술이 뭔지도 알겠으니 Docker가 어떻게 구성되어있고, 어떻게 실행되는지 확인해 볼 차례입니다.

Docker의 구성

Docker client

Docker client는 Docker daemon과 상호작용을 합니다. docker run, docker build, docker pull과 같이 docker와 관련된 명령어를 사용하여 Docker daemon에 작업을 요청합니다. 위의 이미지에서 맨 왼쪽 영역에 해당합니다.

Docker daemon

Docker 엔진에서 핵심적인 역할을 합니다. Docker client에서 보내는 Docker API를 수신받고, Docker 객체(이미지, 컨테이너 등)를 관리합니다. 혹은 다른 daemon과 통신하여 Docker 서비스 역시 관리할 수 있습니다.

Docker registries

Docker registry에는 Docker 이미지를 저장합니다. Docker Hub는 공개 저장소로 다른 사용자들도 언제든 사용할 수 있고, 이외에도 private 저장소도 있습니다. 만약 client에서 docker pull 혹은 docker run이라는 명령어를 실행하면, 지정된 저장소에서 image를 내려받는 것이고, docker push를 실행하게 되면, 이 저장소로 이미지를 push하는 행위를 하는 것입니다.

Docker object

자, 그렇다면, Docker daemon이 관리하고 있다는 Docker object가 무엇인지 살펴볼 필요가 있겠죠 ! 여러가지들이 있지만 아래의 구성사항에 대해 조금 더 면밀히 알아봅시다.

image

: 이미지는 Docker 컨테이너를 만들기 위한 템플릿이라고 생각하면 간단합니다. 이 이미지를 기반으로 컨테이너를 만들 수 있는 것입니다. 직접 우리가 이미지를 만들 수도 있고, 남들이 만들어 놓은 이미지를 기반으로 컨테이너를 생성하고 어플리케이션을 빌드할 수 있습니다. 예를 들면, 우분투 이미지를 기반으로 하지만, Apache 웹 서버와 어플리케이션을 설치하고 이를 실행하는데 필요한 구성 세부 정보를 포함하는 이미지를 만들 수 있는 것이죠 !

container

자, 위에서 계속 언급했던 컨테이너가 이제 등장합니다. 컨테이너는 실행 가능한 이미지 인스턴스입니다. 프로그램이 실행되고 있는 것을 프로세스라고 하듯, 이미지가 실행되면 컨테이너가 됩니다. 이 컨테이너는 계속 언급했듯, 다른 컨테이너들이나 호스트로부터 "격리"되어있습니다. Docker client에 의해 컨테이너의 상태를 관리할 수 있고, 컨테이너가 만약 사라지게 되면 스토리지에 별개로 저장되지 않는 변경 사항들은 모두 휘발됩니다.

Docker storage

만약 컨테이너 별로 데이터를 공유해야 하거나, 이미 실행이 중단된 컨테이너의 데이터를 참조해야 하는 경우에는 어떻게 해야 할까요 ? 이런 경우, Docker storage 기능을 사용할 수 있습니다. 여기에는 두 가지 옵션이 있는데, 바로 bind mounts와 volume입니다. 이 두 개의 차이점은 데이터가 Docker 호스트의 어디에 존재하느냐에 있습니다.

bind mounts

bind mounts가 있는 곳
초창기 Docker부터 사용되었던 바인드 마운트는 host 시스템 그 어느곳에서든 존재할 수 있습니다. Docker 호스트에 존재하는 Docker 프로세스가 아닌 프로세스 혹은 Docker 컨테이너는 이곳에 언제든 접근할 수 있습니다. 다만, volume에 비해 기능이 제한적입니다. 호스트 머신의 파일 또는 디렉토리의 절대 경로가 참조되어 컨테이너에 마운트(연결이라고 생각합시다)됩니다. 꼭 이 파일이나 디렉토리가 호스트 머신에 미리 있을 필요는 없고 없는 경우엔 필요에 따라 생성되기도 합니다. 바인드 마운트는 호스트 머신의 디렉토리 구조 혹은 OS가 바뀌면 같이 바뀌게 됩니다.

volume

volume이 있는 곳
볼륨은 바인드 마운트와는 달리 Docker에 의해 관리되는 호스트 파일시스템에 존재합니다. 마찬가지로, 비 Docker 프로세스 혹은 Docker 컨테이너가 접근할 수 있습니다. 볼륨을 컨테이너에 마운트하면 이 디렉토리가 컨테이너에 마운트됩니다. 물론 여러 컨테이너에 동시에 마운트할 수 있죠. docker volume prune 이라는 명령어를 통해 volume을 삭제할 수 있습니다. volume에는 이름을 지정할 수도 있고, 임의로 지정되는 경우도 있습니다. 물론 임의로 지정되는 경우에는 고유의 이름으로 생성됩니다.
볼륨은 바인드 마운트에 비해 조금 더 효율적으로 사용될 수 있기때문에 더 선호되고 있는데요, Docker 문서에서도 상황에 따라 어떤 storage를 사용할지 달라질 수 있다고 하였으나 볼륨 사용을 조금 더 권장하는 것 같습니다. 아래는 공식문서에서 설명하는 볼륨이 바인드 마운트에 비해 가지고 있는 장점들을 나열한 것입니다. 결론적으로는 볼륨은 Docker가 관리하니까 더 좋다 -! 입니다.

  • 볼륨은 바인드 마운트보다 백업 또는 마이그레이션이 더 쉽습니다.
  • 볼륨은 바인드 마운트보다 백업이나 마이그레이션이 더 쉽습니다.
  • 볼륨은 Linux와 Windows 컨테이너 모두에서 작동합니다.
  • 볼륨은 여러 컨테이너 간에 보다 안전하게 공유할 수 있습니다.
  • 볼륨 드라이버를 사용하면 원격 호스트 또는 클라우드 공급자에 볼륨을 저장하고, 볼륨의 콘텐츠를 암호화하거나, 다른 기능을 추가할 수 있습니다.
  • 새 볼륨은 컨테이너에 의해 콘텐츠가 미리 채워질 수 있습니다.
  • Docker 데스크톱의 볼륨은 Mac 및 Windows 호스트의 바인드 마운트보다 훨씬 더 높은 성능을 제공합니다.
  • 볼륨은 볼륨을 사용하는 컨테이너의 크기를 늘리지 않고 볼륨의 콘텐츠가 특정 컨테이너의 수명 주기 외부에 존재하기 때문에 컨테이너의 쓰기 가능한 레이어에 데이터를 지속하는 것보다 볼륨이 더 나은 선택인 경우가 많습니다.

자, 이 정도면 제가 이해하고 싶었던 Docker의 기본적인 개념들에 대해서는 알아본 것 같습니다. Docker compose나 다른 개념들에 대해서는 이후 글에서 차근차근 알아보는 것으로 하겠습니다 !

참고
https://www.ibm.com/kr-ko/topics/virtualization
https://aws.amazon.com/ko/what-is/virtualization/
https://www.redhat.com/ko/topics/linux/what-is-the-linux-kernel
https://www.nginx.com/blog/what-are-namespaces-cgroups-how-do-they-work/
https://www.baeldung.com/linux/cgroups-and-namespaces
https://docs.docker.com/get-started/overview/
https://docs.docker.com/storage/

0개의 댓글