최고의 도커가 되기 위한 지침서(A guide to becoming the best docker) — 01. Introduction

한지승
HASHBOX
Published in
9 min readMay 30, 2019

--

Docker 로고

혹시 도커에 대해 들어본 적이 있나요? 필자는 도커를 이용한 간단한 프로토타입 개발이나 외주 작업을 진행할 때 도커를 이용한 개발을 매우 익숙합니다. 이제는 도커가 없이 환경을 구축하고 작업을 하는 것은 있을 수 없는 일이라고 생각이 듭니다.

하지만 이런 편의성에도 아직까지 도커에 대해서만 들어보았지 사용하지는 않는 개발자 분들이 많았고, 같이 협업을 해야하는 상황에서 개발하기에 앞서 도커에 대한 기본 설명을 해야하는 번거로움을 많이 느끼고 있었습니다. 이에 도커에 대해서 가볍게 정리하고 실무적으로 사용하면서 얻었던 정수들을 모아 도커에 처음 입문하는 개발자가 쉽게 이해할 수 있는 글을 써보게 되었습니다. 이 글을 통해 많은 개발자 분들이 쉽게 도커에 입문하는데 도움이 되었으면 좋겠습니다.

서비스를 개발하는데 있어 필요한 요소 중에서 인프라를 어떻게 구성하냐는 중요한 요소 입니다. 초기 도커라는게 존재하지 않던 태초 시절에는 서비스를 제공하기 위해서 여러가지 단계가 존재했습니다.

간단하게 이를 정리하면,

  1. 서비스를 제공하기 위한 서버 OS 설치
  2. 서비스 제공을 위한 애플리케이션 설치 (웹서버, 데이터베이스, 웹어플리케이션 등)
  3. 각 애플리케이션의 Configuration 설정
  4. 서비스 데몬 실행

위와 같은 대표적인 행위들이 일어날 것입니다. 하지만, 대표적인 행위들이 그렇치 위에 나열한 순서 사이에 수많은 중간 단계들이 필요합니다. 그러다가 무언가 알 수 없는 이유에 의해 꼬이면 서버를 다시 설치하고 다시 구현하는 그런 불상사태가.. 생각만 해도 싫습니다. 나아가서 서비스가 커져서 이 인프라를 분산하고 다중화해야한다면? 죄송합니다.

또한 서비스를 위한 인프라 구성 뿐만아니라 어떠한 특정 환경을 반복해서 다시 구현해야하는 경우도 예를 들 수 있습니다. 예를들어 bash쉘 내에서 스크립트가 돌고 어떠한 수많은 관련 파일들과 상태가 생성되고 이를 다시 초기 상태로 돌려 스크립트를 다시 돌려야하는 경우를 설명할 수 있습니다.

위와 같은 경우 말고도 수없이 많은 곳에서 docker가 있다면 무섭지 않습니다. 안 무섭다 못해 환영스러울 것입니다. (이런 경우가 없으면 도커에 이점이 확 부각 되지 않기 때문에..) 인제 도커가 무엇인지 빨리 알고 싶지 않으신가요?

도커의 기반이 되는 기술

도커에서 사용하는 컨테이너 기술은 사실 도커로 인해 생긴 기술이 아니랍니다. 컨테이너 기술을 구현하기 위해 근간이 되는 대표적인 기능은 namespace , cgroup 입니다. 두 기능은 리눅스 커널에 기본 내장되어있는 기능으로 개별적으로 사용이 가능합니다.

namespace

namespace 는 리눅스 커널에서 파일시스템, 프로세스, 네트워크, ipc 통신, user id 등을 격리시키는 기능입니다. 즉, 리눅스 내에서 독립된 가상 공간을 할당해 주는 것이라 생각하시면 쉽습니다. 이를 통해 컨테이너 간 서로를 인식 못하고 마치 독립적인 VM을 올린 효과를 줍니다.

cgroup

cgroup 은 Control Group의 약어로 호스트의 자원을 직접 제어가 가능하게 해주는 기능입니다. 이를 통해서 CPU, 메모리, 네트워크, 디바이스 등과 같은 하드웨어 자원들을 제한할 수 있습니다. 이를 통해 각 컨테이너 마다 각기 다른 하드웨어 리소스를 할당하여 관리할 수 있게 해줍니다.

이처럼 기존에 있던 namespace , cgroup 과 같은 기술을 잘 조합하고 사용하기 쉽도록 만들어 프로세스를 완벽하게 격리하고 관리하여 사용할 수 있도록 만든 것이 도커입니다.

도커는 2013년 3월 경 Pycon 컨퍼런스에서 Solomon Hykes가 The future of Linux Containers라는 발표를 통해 세상에 처음 나오게 되었습니다. 이후 수많은 사람들이 도커를 이용하고 입소문이 타면서 지금은 큰 서비스를 운영하는데 있어서 de facto(사실상 표준)로 받아 들여지고 있습니다.

컨테이너 vs 가상머신(VM)?

처음 컨테이너 기술이랑 가상머신이랑 무슨 차이가 있는지 헷갈려 하시는 분들이 많습니다.

가상 머신(좌)과 컨테이너(우)의 차이 (출처: https://blog.netapp.com/blogs/containers-vs-vms/)

위에서 설명했듯이 namespacecgroup 의 설명을 이해하셨다면 컨테이너 기술이 하나의 커널 내에서 환경을 격리시키고 host의 하드웨어 자원을 공유해서 사용한다는 것을 아실 수 있습니다. 하지만 가상머신에서는 가상화 레이어 위에 각각의 OS가 설치가 되고 해당 위해서 할당된 가상화 하드웨어를 사용하는 것을 그림에서 확인하실 수 있습니다. 즉, 가상머신은 가상화 레이어에 의해 에뮬레이션된 하드웨어 자원을 사용하는 것이고 컨테이너는 호스트의 자원을 격리된 환경에서 그대로 활용하기 때문에 오버헤드가 적다는 것을 의미하며 실제로 컨테이너를 사용했을 때의 성능은 호스트에서 사용하는 성능과 거의 비슷한 성능을 냅니다. 끝내주죠?

도커의 구현 원리

위에서 설명 드렸던 내용은 도커를 직접 쓰지 않으셔도 넘어가는 얘기로 수도 없이 많이 들은 내용이실 수도 있습니다. 이제는 직접 도커가 어떻게 구현이 되어있고 어떠한 용어가 있는지에 대해서 알아보겠습니다.

도커의 기본적인 철학은 하나의 컨테이너를 하나의 프로세스처럼 사용을하고 각 컨테이너는 stateless하도록 사용하자라 말할 수 있습니다. 이 말에 대해 차근차근히 설명드리도록 하겠습니다.

이미지와 레이어 그리고 도커 허브

도커는 컨테이너 내의 환경을 마치 snapshot처럼 immutable한 이미지로 만들고 이를 레이어 방식을 이용하여 구현하여 관리합니다. 쉽게 설명을 드리면 대표적인 이미지들이 ubuntu, centos와 같은 것으로 예를 들을 수 있습니다.

으잉? 가상머신이 아니라면서 왜 OS들이 나오는 거죠?

위와 같은 의문이 드실 수도 있습니다. 컨테이너는 하나의 격리된 공간이기 때문에 격리된 공간 안에 특정 OS에서 사용하는 bin , lib 들을 넣고 환경변수를 세팅한다면 마치 해당 OS를 사용하듯이 사용할 수 있습니다. 각 OS에 맞는 bin , lib , 환경 변수들을 세팅해 놓은 상태를 이미지로 저장을 해서 관리를 하는 것입니다. 또한 이렇게 누군가가 만들어 놓은 이미지를 공개하고 누구나 사용할 수 있도록 Docker hub라는 서비스를 운영하고 있습니다. 마치 Github와 같은 것이죠. 또한 이러한 오피셜한 이미지들은 Ubuntu, CentOS 단체에서 직접 최적화한 이미지를 제공하기 까지 합니다!

하지만 이러한 이미지들을 기반으로 새로운 부분을 추가하고 커스터마이즈할 수 없다면 직접 이미지를 만들 때마다 특정 OS의 bin , lib 들을 직접 만들어야 하는걸까요? 정답은 아닙니다. 도커는 이러한 이미지를 레이어 방식으로 관리하고 특정 이미지를 기반으로 레이어를 차곡차곡 쌓아서 새로운 이미지를 만들 수 있도록 구현하였습니다. 그렇기 때문에 중복적으로 사용되는 부분은 공간을 중복으로 사용하지 않을 뿐더러 특정 이미지를 기반으로 추가적인 커스터마이즈가 가능토록 하였습니다.

Immutable한 이미지? Stateless?

위에서 잠깐 Immutable한 이미지를 만든다는 말을 했었습니다. 도커는 컨테이너를 생성하면서 특정 이미지로 환경을 만들 수 있는데, 말그대로 immutable한 이미지이기 때문에 컨테이너 내에서 어떠한 추가적인 쓰기를 할 때 R/W Layer라는 레이어를 쌓아놓고 이 레이어에 변경된 내용들을 기록하는 방식으로 구현되어있습니다. 또한 stateless한 상태를 지양하기 때문에 컨테이너를 내리고 재생성할 때 R/W Layer에 기록된 내용은 전혀 저장을 하지 않고 사라지며 처음 이미지 상태 그대로 환경으로 재생성됩니다.

으잉? 그러면 persistent한 데이터가 필요한 경우에는 사용을 못하나요?

결론부터 말씀드리자면 사용하실 수 있습니다. 하지만 명시적으로 어떠한 폴더는 persistent한 데이터라고 알려주어야 한답니다. 이는 다음 편에서 설명 드리도록 하겠습니다.

도커 이미지를 어떻게 만들지?

이미지를 만드는데 어렵거나 다른 이미지 만드는 툴이 있는 것 아닌가요?

지금까지 계속 이미지라는 용어를 많이 사용을 했었는데 이미지를 만드는 방법에 대해서 설명 드리겠습니다. 도커에서 사용할 수 있는 이미지를 만드는 것은 텍스트 파일을 통해서 쉽게 만들 수 있습니다. 다음 간단한 nginx 웹서버를 만들기 위한 스크립트의 예입니다.

FROM nginx:1.15.12ADD ./static_web /var/www/htmlWORKDIR /etc/nginx
CMD ["nginx"]
EXPOSE 80
EXPOSE 443

간단하게 설명을 드리자면 도커 허브에서 nginx 이미지 중에서 1.15.12 버전으로 가져와서 베이스로 이미지를 만들 것이고, 현재 static_web 폴더에 있는 내용을 컨테이너 내에서 /var/www/html 위치에 추가를 하고 /etc/nginx 디렉토리에서 앞으로의 명령어들을 실행할 것이고 nginx 를 실행할 것이다. 마지막으로 이 컨테이너는 80, 443포트를 열어놓고 있을 것이다라는 의미입니다. 참 쉽죠? 이렇게 이미지로 만들어 놓았을 때 도커를 실행할 수 있는 환경 어디에서든 똑같은 환경으로 웹서버를 올릴 수 있습니다. 단 한줄에 명령어로 말이죠!

간단하게 도커에 대해서 알아보고 어떠한 원리로 구현이 되어있는지에 대해 알아 보았습니다. 우선적으로 도커가 어떠할 때 쓰이고 어떻게 구현 되어있는지를 알면 앞으로의 편부터는 쉽게 따라오실 수 있으실 겁니다. 다음 포스트부터는 이러한 내용을 기반으로 도커를 직접 어떻게 사용하고 어떻게 활용이 되는지 알아보도록 하겠습니다.

궁금하거나 설명이 이해가 안되는 부분이 있다면 언제나 질문은 환영입니다.

--

--

한지승
HASHBOX

딥러닝 분야에 모험가 — Machine Learning Engineer @ Clova, Naver Corp. — CV (https://hashbox.github.io)