들어가며
해당 글은 실전 Docker 사용법보다는, Docker가 무엇인지 소개하는 것을 목표로 하고 있습니다. 자세한 Docker 명령어와 사용법을 알고 싶다면 Docker Doc를 참고해주세요!
Docker 개념 잡기
Docker란 무엇일까요? 개발자라면 꼭 알아야 한다고 하는 이야기도 들리고 도커가 뭔지 어떻게 감을 잡을지 모르겠다고 하는 도커 입문자에게는 Docker의 개념을 잡기가 참 어렵습니다. 도커에 대해 검색하고 공부할 때 컨테이너, 패키징, 이미지 등등 낯선 단어의 등장에 머리부터 아파지기 쉽습니다. 이 글은 Docker가 뭔지 감을 못 잡고 계신 분들, "그래서 Docker 왜 써야 하는데?"라는 의문을 가지고 계신 분들을 대상으로 하고 있습니다.
저는 새로운 개념을 공부할 때는 우선 공식 문서를 보는 습관을 가지고 있습니다. 유명한 오픈 소스나 기술은 공식 문서의 퀄리티가 높고 깊은 내용까지 알 수 있기 때문입니다. 마찬가지로 Docker 또한 공식 문서가 꽤 잘 구성되어 있습니다. 영어로 적혀있긴 하지만 크롬에서 제공하는 자동 번역을 사용해도 읽는데 큰 지장이 없으니 꼭 한번 읽어보시기를 권장드립니다.
Docker는 무엇이고 어떤 컨셉을 가지고 있을까요? Docker 공식 문서에서는 docker를 다음과 같이 정의하고 있습니다. 영어를 싫어하시는 분들을 위해 간단한 해석본도 같이 첨부해 두었습니다.
Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code quickly, you can significantly reduce the delay between writing code and running it in production. Docker는 응용 프로그램 개발, 배포, 실행을 위한 개방형 플랫폼입니다. Docker를 사용하면 애플리케이션과 인프라를 분리하여 소프트웨어를 신속하게 제공할 수 있습니다. Docker를 사용하면 애플리케이션 관리와 같은 방식으로 인프라 관리가 가능합니다. Dockeer의 방법론인 빠른 배포, 테스트, 배치를 통해 코드 작성과 운영 사이의 지연 시간을 현저하게 줄일 수 있습니다. |
이 내용이 무슨 말을 하는 건지 잘 이해가 되지 않아도 괜찮습니다. 우선 위 내용과 같은 일을 하기 위해서 Docker가 탄생했구나~ 정도만 이해하시면 됩니다. Docker를 관통하는 가장 큰 개념은 Immutable Infrastructure 입니다. 이 개념은 여러분이 사용하는 윈도우, 리눅스, 우분투, 맥 등과 같은 OS와 서비스를 제공하는 환경을 분리한다는 개념을 뜻합니다. 그렇다면 환경을 왜 분리해야 할까요?
제 컴퓨터에선 잘 되는데요?
Docker를 사용하지 않은 환경에서는 자신의 컴퓨터에서 돌려 본 후, 상용 서버로 애플리케이션을 배포했을 때 고려해야 할 사항이 정말 많습니다. 각종 환경 변수, OS 호환성, 하드웨어 차이에 따른 이슈 등등 많은 것들을 관리해야 했습니다. 이 때문에 로컬에서 잘 돌아가던 애플리케이션이 서버만 가면 시작조차 되지 않는 경우도 드문 일은 아니였습니다. 윈도우 환경에서 개발한 애플리케이션이 리눅스 OS를 사용하는 서버에서 작동이 될지 안 될지 알 수 조차 없었죠.
또 자신의 컴퓨터에 설정해 놓거나, 설치해 둔 프로그램은 사람마다 모두 다릅니다. 그렇기 때문에 제 컴퓨터에서 돌아가는 소스코드가 다른 사람의 컴퓨터에서도 멀쩡히 돌아간다는 보장을 받을 수 없었죠. 이에 관한 유명한 대사가 있습니다. 다른 사람의 소스코드를 병합한 후 애플리케이션에 오류가 발생하여 문의하면, 자신의 컴퓨터에선 잘 되는데 왜 거기서만 오류가 나냐는 대사인 "제 컴퓨터에선 잘 되는데요?"라는 대사입니다. 특정 컴퓨터의 환경을 맞춰야만 돌아가는 애플리케이션은 설치하기도, 배포하기도 까다롭고 어려웠죠.
그래서 개발자들은 운영 환경과 어플리케이션을 모두 묶어서 한꺼번에 배포할 수 없을까?라는 고민을 하게 되었고, 이는 곧 Docker의 개발로 이어졌습니다. 환경에 관계없는 애플리케이션 구동은 Docker의 가장 큰 관심사였고 이는 Immutable Infrastructure라는 개념을 만들었습니다.
OS 분리
애플리케이션의 실행 환경을 OS단부터 모두 저장하는 것은 더 간편한 방법이지만 무거운 방법입니다. 가벼운 프로그램 하나를 돌리려고 해도 OS, 하드웨어까지 모두 묶어버리기 때문에 용량도 크고, OS위에 OS를 올리기 때문에 무겁고 느립니다. Docker에서는 이러한 단점을 개선하기 위해 반가상화 기법을 사용합니다. Docker 엔진은 호스트 OS위에서 바로 돌아가고, 호스트와 커널을 공유하기 때문에 IO가 빠르다는 장점이 있습니다.
하지만 Docker가 하는 반가상화 기법도 단점이 있습니다. Host OS와의 완전한 분리 환경이 아니기 때문에 멀티 OS가 불가능합니다. 즉 윈도우에서 리눅스 OS를 베이스로 만들어진 Docker를 실행하기는 어렵다는 이야기입니다.
윈도우에서 Docker 이미지를 실행할 수 없다니, 윈도우도 Docker가 있잖아요? |
윈도우에서는 Docker를 실행하기 위해 여러 우회 방법을 사용합니다. 간단하게 말하자면 윈도우에서는 리눅스 가상 머신을 올리고, 그 위에 도커를 올립니다. 그렇기 때문에 사실상 윈도우의 도커는 효율이 그리 좋지 못합니다.
Docker Image, Container
개발자의 컴퓨터에서 잘 돌아가는 환경이 있다면, 이를 모두 묶어버려서 하나의 파일로 만들어버리고 이를 서버에 올리면 잘 돌아가지 않을까? 라는 고민에서 생긴 것이 바로 Docker Image입니다.
Docker에서는 기본적으로 제공하는 Base Image가 있습니다. 리눅스 배포판에 유저랜드만 설치된 파일을 베이스 이미지로 제공하고 있고 여기에 애플리케이션에 필요한 라이브러리, 소스 등을 설치한 후 다시 이미지를 만들 수 있습니다. 일반적으로 이미지를 제작한다고 하면 이러한 베이스 이미지를 기초로 만든 이미지를 뜻합니다. Docker에서는 이 모든 환경을 하나의 이미지 파일로 묶어버립니다.
이렇게 모든 환경을 묶어버린 이미지는 실행 환경에 영향을 받지 않습니다. Docker 엔진 위에서 실행하기만 한다면 개발자가 설계한 환경 위에서 정해진 라이브러리와 소스를 실행합니다. 제작된 이미지는 파일이기 때문에 이를 실행하기 위해서는 파일을 프로세스로 만들어야 합니다. 이를 위해 Docker에서는 이미지를 사용하여 Container를 제작하여 운영체제에서 돌아가는 프로세스를 만듭니다.
Docker의 장점, Immutable Infrastructure
프로그램의 실행 환경과 어플래케이션을 같이 묶어서 Docker 엔진 위에만 올리면 OS, 환경과 상관없이 작동되도록 만드는 추상화 기법입니다. 그리고 이는 곧 어느 환경에서나 작동하는 애플리케이션이 됩니다. Immutable Infrastruecure는 다음과 같은 장점을 가지고 있습니다.
편리한 관리
서비스 운영 환경을 이미지로 생성하여 이 이미지만 관리하면 됩니다. 이미지는 버전관리 시스템을 활용할 수 있습니다.
확장
이미지 하나로 서버를 손쉽게 확장할 수 있습니다. 클라우드의 Auto Scaling기능과 연동하면 수평 확장이 가능합니다.
테스트
어느 PC나 환경에서든 이미지를 실행하면 서비스 운영 환경과 같은 환경이 구성됩니다. 서버에 올린 다음 테스트하지 않아도 서버 환경과 유사하게 테스타가 가능합니다.
가벼움
Docker는 OS를 분리하여 이미지로 제작합니다. 그렇기 때문에 가볍고 어디서든 실행 가능한 환경을 제공합니다.
Docker가 격리된 환경을 제공하는 방법
Docker가 격리된 컨테이너 환경을 제공하는 방법을 알기 위해서는, 리눅스에서 격리된 환경을 만드는 방법을 먼저 이해해야 합니다. 리눅스에서는 chroot라는 명령어를 통해 루트 디렉터리를 변경할 수 있습니다. 루트 디렉터리가 /home/eric/ 으로 변경되었다면 해당 파일 시스템에서는 /home/eric/ 을 루트 디렉터리로 인식하고, 루트 디렉터리보다 상위의 디렉터리를 인식할 수 없게 됩니다.
즉 밖에서는 안을 볼 수 있지만 격리된 디렉터리에서는 바깥쪽 파일, 디렉터리를 볼 수 없게 되는 것입니다. 이를 chroot jail이라고 부릅니다. 하지만 이렇게 만들어진 격리 공간은 여러 제약 사항이 있습니다. 그렇기 때문에 리눅스는 이 환경에 시스템 레벨 가상화 LXC (LinuX Container)를 추가로 제공합니다.
OS를 공유하지 않는 격리 공간을 컨테이너라고 부르고, LXC를 사용하면 CPU, Memory, Disk 등을 할당할 수 있습니다. 이를 통해 호스트와 격리된 공간을 만들 수 있습니다.
Docker는 이러한 리눅스 시스템을 활용하여 명령어 몇 번 만으로 격리된 공간과 프로세스를 제공합니다. 물론 OS를 공유하기 때문에 호스트 입장에서는 docker가 실행하는 프로세스는 자신이 실행하는 하나의 프로세스와 같고, 파일 시스템 또한 내부에서 외부를 볼 수 없지만 호스트는 도커 파일 시스템 내부를 볼 수 있기 때문에 완벽한 격리 상태가 되지는 않습니다.
Docker는 기본적으로 LXC를 기반으로 구현하였지만 0.9버전부터 libcontainer를 사용하여 개발하고 있습니다. LXC를 사용할지, libcontainer를 사용할지는 옵션으로 변경할 수 있습니다.
Docker를 활용하여 할 수 있는 것들
다른 개발자가 만들어 놓은 이미지 사용
개발자가 제작해 놓은 애플리케이션을 설치하고 세팅하기는 어려운 일입니다. 하지만 이러한 세팅을 모두 완료한 상태로 만든 docker image를 받는다면 더 이상 자신의 개발 환경에 따라 설정을 다시 할 필요가 없습니다. docker에서는 개발자들이 제작한 이미지를 공유하는 docker hub를 운영하고있습니다. 필요한 애플리케이션이 있다면 여기에서 애플리케이션을 받아온 다음, 그냥 실행시키면 돌아갑니다. 환경에 독립적이기 때문에 자신에 환경에 맞는 세팅을 어느 정도 생략할 수 있습니다. 예를 들어, MySQL과 같은 DB도 이미지를 받아온 다음 그냥 실행시키기만 하면 손쉽게 DB를 사용할 수 있습니다.
제작한 어플리케이션을 대규모 서버에 배포
자신이 구축한 애플리케이션을 서버 한대에 배포하는 것은 귀찮지만 어려운 일은 아닙니다. 환경을 맞춰주고, 여러 가지 세팅을 해주면 되니까요. 하지만 세팅해야 할 서버가 수백대라면 어떨까요? 하나하나 모든 환경을 맞추기는 쉽지 않을 것이고, 애플리케이션에 변경 사항이 있다면 정말 끔찍할 것입니다. docker를 사용한다면 이러한 환경 세팅 없이 그저 이미지를 배포하기만 하면 됩니다. 하나하나 도커 애플리케이션을 받는 것은 귀찮겠지만 환경 세팅을 하지 않아도 되니 시간도 절약할 수 있겠네요.
여담
물론 이러한 대규모 서버에 배포할 때 하나하나 도커 이미지를 설치하는게 귀찮아서 나온 컨테이너를 관리하는 애플리케이션도 있습니다. 다음 소개는 이것을 주제로 진행할 것 같은데요, 최근 공부하는 쿠버네티스입니다. 도커와는 다르게 공식 문서가 한글로 되어있고 대화형 터미널도 제공하기 때문에 튜토리얼 자체는 하기 쉬운 편입니다. 다음 소개를 기대해주세요!
References
'Web > Infra' 카테고리의 다른 글
[Tech 면접] 시스템을 설계해보라는 질문을 받는다면? (2) | 2020.06.12 |
---|---|
Kubernetes(쿠버네티스)를 소개합니다 (4) | 2020.05.31 |
동기/비동기와 블로킹/논블로킹 (7) | 2020.05.08 |
브라우저에 URL을 입력했을 때 발생하는 일들 (9) | 2020.04.25 |
로드밸런서의 종류와 동작방식 (14) | 2020.03.23 |
댓글