티스토리 뷰

Docker/Docker 기초

Docker의 구성

로또_ 2019. 9. 14. 21:57

레이어 저장방식

 

Docker Layer

도커 이미지는 컨테이너를 실행하기 위한 모든 정보를 가지고 있기 때문에 보통 용량이 수백메가에 이릅니다. 처음 이미지를 다운받을 땐 크게 부담이 안되지만 기존 이미지에 파일 하나 추가했다고 수백메가를 다시 다운받는다면 매우 비효율적일 수 밖에 없습니다.

 

도커는 이런 문제를 해결하기 위해 레이어layer라는 개념을 사용하고 유니온 파일 시스템을 이용하여 여러개의 레이어를 하나의 파일시스템으로 사용할 수 있게 해줍니다. 이미지는 여러개의 읽기 전용read only 레이어로 구성되고 파일이 추가되거나 수정되면 새로운 레이어가 생성됩니다. ubuntu 이미지가 A + B + C의 집합이라면, ubuntu 이미지를 베이스로 만든 nginx 이미지는 A + B + C + nginx가 됩니다. webapp 이미지를 nginx 이미지 기반으로 만들었다면 예상대로 A + B + C + nginx+ source 레이어로 구성됩니다. webapp 소스를 수정하면 A, B, C, nginx 레이어를 제외한 새로운 source(v2) 레이어만 다운받으면 되기 때문에 굉장히 효율적으로 이미지를 관리할 수 있습니다.

 

컨테이너를 생성할 때도 레이어 방식을 사용하는데 기존의 이미지 레이어 위에 읽기/쓰기read-write 레이어를 추가합니다. 이미지 레이어를 그대로 사용하면서 컨테이너가 실행중에 생성하는 파일이나 변경된 내용은 읽기/쓰기 레이어에 저장되므로 여러개의 컨테이너를 생성해도 최소한의 용량만 사용합니다.

가상화의 특성상 이미지 용량이 크고 여러대의 서버에 배포하는걸 감안하면 단순하지만 엄청나게 영리한 설계입니다.

 

Docker 이미지 의존 관계

위 그림은 Docker 이미지 간의 의존 관계를 보여줍니다. Docker 이미지는 16진수로 된 ID로 구분하고, 각각의 이미지는 독립적입니다. 위의 루트노드처럼 보이는 곳에서 시작하여 리프노드까지 일렬로 서로 연결되어 있습니다. 즉 Docker는 이미지를 통째로 생성하지 않고, 바뀐 부분만 생성한 뒤 부모 이미지를 계속 참조하는 방식으로 동작합니다. 위에서도 설명하였지만 다시 말하자면, Docker에서는 이를 레이어라고 합니다.

 

참고 : Union mount, Union File System

생성된 Docker 이미지는 읽기 전용 상태입니다. 여기서 내용이 바뀌면 이미지를 수정하지 않고, 쓰기 이미지를 생성한 뒤 내용을 기록합니다. 이러한 방식을 Union mount라고 하며 Union mount를 지원하는 파일시스템을 Union File System이라 합니다.


 

 

이미지 경로

Docker image url

이미지는 url 방식으로 관리하며 태그를 붙일 수 있습니다. ubuntu 14.04 이미지는 docker.io/library/ubuntu:14.04 또는 docker.io/library/ubuntu:trusty 이고 docker.io/library는 생략가능하여 ubuntu:14.04 로 사용할 수 있습니다. 이러한 방식은 이해하기 쉽고 편리하게 사용할 수 있으며 태그 기능을 잘 이용하면 테스트나 롤백도 쉽게 할 수 있습니다

 

 

더 자세히 알아보고 가겠습니다. 먼저 베이스 이미지가 있는데, 리눅스 배포판의 유저랜드만 설치된 파일을 뜻합니다. 유저랜드에 대해 설명하자면,  OS는 메모리 사용을 기준으로 커널 공간과 유저 공간으로 나눌 수 있습니다. 여기서 유저 공간에서 실행되는 파일과 라이브러리를 유저랜드(userland)라고 합니다. 리눅스 커널만으로 부팅할 수 없으므로 부팅에 필요한 최소 실행 파일과 라이브러리 조합을 뜻하기도 합니다. 보통 리눅스 배포판에서 유저랜드는 부팅에 필요한 실행 파일과 라이브러리 그리고 고유의 패키징 스스템을 포함합니다. 

 

 


 

 

Docker file

도커는 이미지를 만들기 위해 Dockerfile이라는 파일에 자체 DSL(Domain-specific language)언어를 이용하여 이미지 생성 과정을 적습니다.  이것은 굉장히 간단하지만 유용한 아이디어인데, 서버에 어떤 프로그램을 설치하려고 이것저것 의존성 패키지를 설치하고 설정파일을 만들었던 경험이 있다면 더 이상 그 과정을 블로깅 하거나 메모장에 적지 말고 Dockerfile로 관리하면 됩니다. 이 파일은 소스와 함께 버전 관리 되고 원한다면 누구나 이미지 생성과정을 보고 수정할 수 있습니다.

 

 


 

 

Docker Hub

Docker Hub

 큰 용량의 이미지를 서버에 저장하고 관리하는 것은 쉽지 않은데 도커는 Docker hub를 통해 공개 이미지를 무료로 관리해 줍니다. 

 

 

위의 이미지는 GitHub 또는 Bitbucket 저장소와 연동하여 Dockerfile을 Push했을 때 이미지를 자동으로 빌드하는 기능을 나타내고 있습니다. 도커파일을 github이나 bitbucket에 커밋하면 도커허브에서 그 파일을 가져와서 자동으로 빌드를하여 이미지를 생성합니다.

 

 


 

 

Command와 API

도커 클라이언트의 커맨드 명령어는 정말 잘 만들어져 있습니다. 대부분의 명령어는 직관적이고 사용하기 쉬우며 컨테이너의 복잡한 시스템 구성을 이해하지 못하더라도 편하게 사용할 수 있습니다. 또한 http기반의 Rest API도 지원하여 확장성이 굉장히 좋고 훌륭한 3rd party 툴이 나오기 좋은 환경입니다.

 

 


 

chroot와 컨테이너

 

오래전부터 리눅스/유닉스 환경은 chroot라는 명령을 제공했습니다. chroot는 파일 시스템에서 루트 리렉터리(/)를 변경하는 명령입니다. chroot로 특정 디렉터리를 루트 디렉터리로 설정하면 chroot jail이라는 환경이 생성되는데, chroot jail안에서는 바깥의 파일과 디렉터리의 접근 할 수 없습니다. 이처럼 chroot는 디렉터리 경로를 격리하기 때문에 서버 정보 유출과 피해를 최소화 하는데 주로 사용되었습니다.

 

chroot는 chroot jail에 들어갈 실행 파일과 공유 라이브러리를 직접 준비해야하고 설정 방법이 복잡합니다. 또한, 완벽한 가상 환경이 아니기 때문에 각종 제약이 많습니다. 이후 리눅스는 LXC(LinuX Container)라는 시스템 레벨 가상화를 제공했습니다. LXC는 컴퓨터를 통째로 가상화하여 OS를 실행하는 것이 아닌 리눅스 커널 레벨에서 제공하는 일종의 격리된 가상 공간입니다. 이 가상 공간에는 OS가 설치되지 않기 때문에 가상 머신이라 하지 않고, 컨테이너라고 부릅니다.

 

리눅스 커널의 Control Groups(cgroups)는 CPU, 메모리, 디스크 네트워크 자원을 할당하여 완전한 형태의 가상 공간을 제공합니다. 또한, 프로세스 트리, 사용자 계정, 파일시스템, IPC등을 격리시켜 호스트와 별개의 공간을 만듭니다. 이것을 Namespace isolation(namespace)이라고 합니다. LXC는 리눅스의 커널의 cgroup과 namespace 기능을 활용하여 가상 공간을 제공합니다. LXC는 격리된 공간만 제공할 뿐 개발 및 서버 운영에 필요한 부가 기능이 부족했습니다. Docker는 리눅스 커널의 cgroups와 namesapce를 기반으로 하여 이미지, 컨테이너 생성 및 관리 기능과 다양한 부가 기능을 제공합니다.

 

Docker가 처음 개발될 당시에는 LXC를 기반으로 구현을 하였지만 버전 0.9 부터는 LXC를 대신하는 libcontainer를 개발하여 사용하고 있습니다. 내부적으로는 실행 드라이버(exec driver)라고 하는데 libcontainer는 native, LXC는 lxc로 표시됩니다. 실행 옵션에 따라 libcontainer를 사용하지 않고 LXC를 사용할 수 있습니다.

 

 

반응형