42서울/Inception

도커와 가상머신 그리고 컨테이너 [42 inception 과제 개념 1]

뜨거운 개발자 2023. 6. 24. 17:56

도커란 무엇인가?

도커에 대한 쉽게 비유적으로 설명한 영상 2가지 먼저 첨부하겠습니다.

  1. 짧은 영상
  2. 긴 영상

공식 사이트

Docker는 애플리케이션 개발, 배송 및 실행을 위한 개방형 플랫폼입니다.
Docker를 사용하면 애플리케이션을 인프라에서 분리하여 소프트웨어를 신속하게 제공할 수 있습니다. 
Docker를 사용하면 애플리케이션을 관리하는 것과 동일한 방식으로 인프라를 관리할 수 있습니다.

Docker docs 사이트에 있는 docker의 설명입니다.

이것만 보면 무슨말인지 이해하기 어렵습니다. 당연합니다. 배경지식부터 차근차근 쌓아갑시다.

일단 도커에 대해서 말하려면 필요한 가상화 기술에 대해서 먼저 이야기하고, 가상화 기술인 가상머신과 컨테이너에 대해서 이야기해보겠습니다.

가상화 기술의 등장배경

우리가 어떤 프로그램을 개발했다고 예시를 들어보겠습니다. 설명의 편의를 위해 프로그램과 어플리케이션은 같은 의미로 사용하겠습니다.

개발자가 개발한 프로그램을 실행 시키려면, 사용자 컴퓨터에 프로그램의 실행 환경을 설정해줘야 합니다.

그래서 과거에는 개발자는 어떤 프로그램을 만들면 그 환경까지 하나하나 사용자에게 설정을 해주도록 설정파일들과 설치 스크립트를 만들어서 설치를 진행했습니다.

이 방법은 오늘날에도 많이 사용되긴 하지만 이러한 방법은 상당히 번거롭고 문제가 생길 수 있는 방법입니다.

문제점을 크게 2개의 내용으로 설명을 진행하겠습니다.

첫번째 문제. 버전 충돌.

한가지 예시를 들어보겠습니다. 예를 들어 저는 게임을 배포하는 개발자라고 생각해보겠습니다.

제가 만든 게임을 실행 하려면 유니티 3.7 버전 이 있어야만 실행이 됩니다.

그런데 사용자 컴퓨터에 유니티가 있기는 있는데 버전이 7.0입니다. 슬프게도 유니티 7.0으로는 제가 만든 게임을 실행할 수 없습니다..

이런 상황이라면 개발자에게 2가지 선택지가 있습니다.

  1. 첫번째 방법은 사용자 컴퓨터에 있는 유니티 7.0버전을 삭제하고 유니티 3.7버전을 다운로드 받는 방법을 선택할 수 있습니다. 이 방법은 저희가 개발한 프로그램은 아주 잘 돌아갈 것 입니다.

 다만, 사용자가 유니티 7.0 버전 이 필요한 게임을 하고 싶으면, 또 삭제하고 다시 설치해야 합니다.

 그리고 만약 두개의 게임을 동시에 돌려야 하는 경우는 어떨까요?

 🚨 이 방법은 아에 동시에 두개의 게임을 실행하는 것이 아에 불가능합니다.

  따라서 단순하게 생각하던 개발자는 이 방법은 별로 좋지 않다.. 라는 결론을 내리고 다른 방법을 생각합니다.

  1. 두 번째 방법은 사용자 컴퓨터에 이전에 있던 버전인 유니티 7.0을 삭제하지 않고 유니티 3.7을 다운로드 받는 것입니다. 얼핏 생각하기에는 아무런 문제가 없어보이고 상당히 이상적입니다.

 그러나 이 경우는 더 골치가 아픕니다. 왜냐하면 한 프로그램의 두가지 버전을 모두 가지고 있으면 환경 설정이 상당히 까다롭기 때문입니다.

 개발자가 열심히 설정 파일을 만들어서 7.0버전과 충돌이 나지 않게 잘 3.7 버전을 설치하고 실행 환경을 세팅했다고 하겠습니다. 하지만 또 다른 새로운 버전의 유니티가 필요하게 되면 또 다시 설정을 해야하고 여러가지 게임이 설치했을 경우 문제가 생길 가능성이 큽니다.

 🚨 최악의 경우 저희가 개발한 3.7버전 게임도 안되고, 사용자가 이전에 7.0을 사용하던 다른 게임도 안 될 가능성이 생깁니다. 이렇게 되면 아주 큰 문제겠죠 역시 이것도 좋지 않은 방법인 것 같습니다.

이렇게 두 가지 선택지 모두 별로인 것 같지만, 그래도 두번째 방법을 잘 활용해서 버전 충돌이 나지 않게 업데이트를 하고 이전 버전과 호환성을 유지하는 방향으로 겨우 문제를 해결 할 수 있습니다.

하지만 그것보다 더 큰 문제가 일어날 수 있습니다.

두번째 문제. 운영체제 차이

그래도 첫번째 문제는 심각한 문제가 있지만, 설정을 잘해주고 충돌만 없다면 어떻게 실행은 가능했습니다. 그런데 두번째는 문제가 더 심각합니다.

또 상황을 예시로 들어보겠습니다. 맥북을 사용하는 개발자가 있고 윈도우를 사용하는 개발자가 있었습니다.

맥북을 사용하는 개발자는 윈도우를 사용하는 개발자에게 본인의 맥북에서 만든 프로그램을 공유합니다. 그런데, 윈도우 개발자는 실행이 안됩니다. 그래서 맥북 개발자는 필요한 프로그램을 전부 설치해줍니다.

🚨 그런데 맥북 개발자가 아무리 필요한 모든 세팅을 해도 프로그램이 돌아가지가 않습니다. 왜냐하면 컴퓨터를 실행하는 환경인 운영체제가 다르기 때문이죠.

이런 문제 때문에 실제로 윈도우에서만 사용 가능한 프로그램이 있고 맥북에서만 사용가능한 프로그램도 실제로 존재합니다. 총체적 난국입니다. 큰 회사라면 두 운영체제에 맞는 개발자를 둘 다 고용하면 되겠지만, 비효율적이고, 여전히 큰 문제입니다.

개발자들의 고민

이제 이런 문제에 대해서 개발자들은 고민하기 시작합니다. 근본적으로 모든 문제는 환경설정을 해주는데 그 환경이 컴퓨터마다 다르기 때문에 발생한다는 것을 깨닫습니다. 그래서 질문을 던집니다.

❓ 컴퓨터가 운영체제가 다르던, 내부에 어떤 프로그램이 있더라도, 상관없이 독립된 환경을 만들 수는 없을까?

그래서 프로그램을 실행하는 모든 환경을 한번에 해둔 공간을 하나 만들면 좋겠다고 생각을 합니다.

그런 고민 들을 해결하기 위해서 가상화라는 개념이 등장합니다. 가상화의 대표적인 기술 두 가지가 가상머신과 컨테이너 기술입니다.

그래서 도커가 뭔데요

사실 많은 사람들이 컨테이너와 도커를 많이들 같은 맥락에서 사용합니다. 사실 도커는 컨테이너를 더 편하게 다룰 수 있도록 도와주는 도구입니다.

뒤쪽에서 컨테이너에 대해서 더 자세하게 다루겠지만, 간단하게 컨테이너를 설명하면 컨테이너는 하나의 공간입니다.

🧑🏻‍💻 컨테이너 안에 설정, 설치, 버전 등 프로그램을 실행하기 위한 환경설정, 그리고 프로그램 자체가 모두 들어있습니다. 그래서 어떤 컴퓨터에서 실행을 하더라도 같은 컨테이너면 같은 실행환경을 보장해줍니다.

자, 그러면 가상화 기술과 가상머신, 그리고 컨테이너에 대해서 알아보겠습니다.

가상화 기술

가상화란 무엇인가

설명을 시작하기 전에..

널널한 개발자님 강의 링크

이 영상을 꼭 보시는 것을 추천합니다. 글의 많은 부분이 이 강의를 참고하였음을 알립니다.

가상화? 그 전에 운영체제

도커가 어떻게 작동하는지 알기 위해서는 운영체제의 구성에 대해서 먼저 알아야합니다.

여러분은 운영체제가 어떤 구조인지 알고 계신가요?

저는 OSI 7 layer를 좋아하지 않습니다. 너무 복잡하기 때문이죠. 그래서 컴퓨터를 간단하게 3개로 쪼개보겠습니다.

컴퓨터의 운영체제를 간략하게 위 그림과 같이 나타낼 수 있습니다.

위 그림을 기반으로 설명을 진행하겠습니다.

👨🏻‍💻 컴퓨터는 크게 하드웨어와 소프트웨어로 나눌 수 있고, 그 소프트웨어를 또, 커널계층과 어플리케이션 계층으로 나눌 수 있습니다.

하드웨어

하드웨어는 CPU, RAM, HDD(하드디스크),NIC(네트워크 인터페이스 카드) 등등 컴퓨터의 기계적인 부품을 의미합니다.

소프트웨어는 크게 두가지로 나눌 수 있습니다.

  1. 첫 번째는 어플리케이션 계층입니다.

 이곳은 저희가 사용하는 프로그램들이 돌아가는 계층입니다. 일반적인 사용자와 심지어 개발자들도 대부분 이곳에서 활동을 합니다. 어플리케이션 계층에서 크게 알아둬야 하는 것은 프로세스와 소켓이 있습니다.

프로세스 : 프로그램이 돌아가는 상태

소켓 : 운영체제 커널 계층의 구성요소와 입력과 출력을 하기 위해서 존재하는 파일

  1. 두 번째는 운영체제 커널 계층입니다.

 커널 계층은 Driver 구성 요소로 이뤄져 있습니다.

 저희가 흔히 알고 있는 윈도우, MacOs, Linux등의 운영체제도 사실 프로그램입니다. 일반적으로 사용자에게 접근 권한이 없는 경우도 많고 많이 감춰 놨기 때문에 접할 일도 많지 않습니다.

 대부분 커널 계층에 있는 구성요소들은 운영체제가 직접 통제하고 사용자는 수정 권한조차 없습니다.

커널: CPU 및 메모리 등과 같은 하드웨어 구성요소와 통신하는 부분이며, 응용 프로그램은 커널을 기반으로 실행이 됩니다.

Driver : 운영체제는 Driver라는 프로그램을 만들어서 하드웨어를 제어합니다.

구성요소: TCP/IP 등, 통신에 필요하거나, 그 외의 운영체제에서 통제하는 요소들 (커널을 주로 구성요소라고도 부릅니다.)

지금까지는 설명을 위한 배경 지식이었고, 다음으로 이러한 시점으로 컴퓨터를 바라볼 때, 가상머신은 어떻게 동작하는지 알아보도록 하겠습니다.

가상 머신의 등장

특정 운영체제에서만 사용 가능한 프로그램이 있습니다.(윈도우 또는 맥 또는 리눅스에서만)

각 운영체제는 모두 위에서 설명한대로는 같은 계층을 가지지만, 운영체제마다 GUI 또는 file System이 다를 수 있고 각각 구현되는 방식이 다릅니다. 그렇기 때문에 어떤 프로그램을 배포할 때 운영체제 마다 다른 설치파일을 만들어야만 했습니다.

이것에 신물이 난 개발자는 다음과 같은 질문을 던집니다.

👨🏻‍💻 새 PC를 사는 대신, PC 안에 새로운 가상의 PC를 만들어서 PC안에서 가상의 PC를 사용할 수는 없을까?

조금 더 고급적으로 표현하면 컴퓨터를 소프트웨어로 만들고자 하는 생각이 나온 것 입니다.

🖥️ 운영체제 위에 직접 설치를 하는 것이 아니라 가상 환경을 만들어서 그 위에 설치를 하는 가상화라는 개념이 등장합니다.

그리고 가상화의 구현으로 아래 그림처럼 어플리케이션, 운영체제의 커널과 그 구성요소 그리고 하드웨어까지 전부 소프트웨어로 만들어 버립니다. 그것이 바로 가상머신입니다.

저희는 저희 컴퓨터 즉 호스트의 운영체제는 Host OS, 가상머신의 운영체제를 Guest OS라고 부릅니다.

하나의 Host OS 위에 여러개의 Guest OS가 올 수 있습니다.

가상머신의 등장 이후(문제해결!!)

이제 가상머신을 사용해서 맥에서 사용하는 프로그램도, 리눅스에서 사용하는 프로그램도 윈도우에서 사용하는 프로그램도 전부 사용이 가능합니다.

비용을 많이 절감했고, 그 덕분에 사용 불가능한 프로그램도 다 구동이 가능하게 됐습니다.

그리고 개발자들은 하나의 컴퓨터를 이용해 환경이 분리된 여러개의 컴퓨터를 가진 것과 같아졌습니다.

환경 설정들을 가상머신에 저장하고, 다른 컴퓨터에 가서 그 가상머신을 그대로 사용이 가능했습니다.

👨🏻‍💻 그래서 가상머신 파일만 주면, 어떤 컴퓨터에서도 같은 실행을 할 수가 있었고 이것은 그동안의 고민들을 해결해주었습니다.

다만, 그동안 불가능한 것들을 해결해준 가상머신도 문제가 몇가지 있었습니다.

독립된 환경을 유지를 해줬지만, 성능 측면에서 너무나도 아쉬운 부분이 있었기 때문입니다.

가상머신의 문제점

만능인 것 같던 가상머신도 큰 문제가 있었는데 용량이 너무 컸습니다.

하나의 컴퓨터에 설치하고자 했던 운영체제를 설치하고, 하드웨어까지 소프트웨어로 구현을 하고 유저의 프로그램까지 구현하기 때문에 당연하게도 용량이 매우 컸습니다.

그리고, 가상머신은 하나의 컴퓨터이기 때문에 구동을 하는데 실제 컴퓨터를 켜는 것 처럼 시간이 걸렸습니다.

이렇게 무거운 프로그램이 돌아가다 보니 여러개의 가상머신을 사용해서 컴퓨터를 돌리는 것은 상당히 컴퓨터에게 무리가 가는 작업이었습니다. 위에 있는 그림을 보면 실제 컴퓨터가 2개의 가상머신을 돌리는 경우를 보면, 1,2,4,5,6,7,8,9 컴퓨터는 총 8개의 프로세스를 돌리고 있는 것을 볼 수가 있습니다. 이것은 컴퓨터에게 상당한 무리를 주는 일 입니다.

👨🏻‍💻 또한 가상머신을 사용한 가상화 작업은 기술적으로 반드시 하이퍼바이저를 거쳐야하기 때문에 일반 호스트에 비해서 성능 손실이 발생할 수 밖에 없습니다.

그래서 가상머신은 완전한 운영체제를 직접 구현하기 때문에 성능이 떨어질 수 밖에 없었고, 크기가 너무 컸습니다. 역시 또 개발자들은 고민하기 시작합니다.

새로운 기술의 등장

그래서 또 한 가지 생각을 합니다. 위의 그림을 보시면 색깔이 같은 부분은 Host OS에도 있는 계층입니다.

그런데 운영체제가 달라서 실행 불가능 했던 프로그램은 뚝 떼어서 공간을 만들고 커널과 하드웨어는 Host OS에 있는 자원을 활용하면 되지 않을까 라는 생각이 들어 한 기술이 개발됩니다.

그것이 바로 컨테이너라는 기술입니다.

컨테이너? 그게 뭔데요?

컨테이너와 가상머신 비교

컨테이너 기술과 가상화 기술의 차이점

💡 컨테이너란 어플리케이션과 바이너리파일(설치파일),라이브러리 를 묶어서 만든 하나의 독립적인 실행공간입니다.

그동안 가상머신은 운영체제를 설치하고 하드웨어까지 구현을 해야했지만 컨테이너는 필요한 어플리케이션과 설치파일, 라이브러리만 묶어서 하나의 공간으로 만들었습니다.

그리고 그동안 가상머신의 운영체제가 필요했던 것을 도커 엔진을 사용해서 처리해줍니다.

👨🏻‍💻 즉 새로운 것을 설치하는 방법이 아닌 기존에 있는 자원을 활용하는 방식으로 작동하게 됩니다.

실제로 도커는 실제로 새로 커널을 구성하는 것이 아니라 운영체제의 커널을 사용합니다. 따라서 호스트 운영체제에서 지원하지 않는 기능이 존재할 수 있습니다.

💡 그렇기 때문에 도커는 도커 엔진을 사용해서 이 문제를 해결합니다.

 (도커 엔진에 대해서는 다른 게시물에서 더 자세히 다루겠습니다.)

과거에는 Docker toolbox 기술로 이것을 해결하였고 현재는 toolbox는 더이상 사용되지 않고, 대신에 Docker Desktop기술을 사용해서 이 문제를 해결합니다.

 도커(컨테이너)를 사용하게 되면, 가상머신보다 훨씬 크기도 작고 실행하는 프로세스도 적어져서 부하도 적습니다.

컨테이너의 특징

Docker가 무엇인지 설명하기 위해서는 컨테이너에 대한 이해가 우선입니다.

💡 컨테이너란 종속성 및 필요한 모든 구성을 포함하여 패키지 내부에 필요한 모든 것을 포함하여, 애플리케이션을 패키징 한 것입니다.

컨테이너에 대해서 쉽게 설명하자면 어떤 물체를 격리하는 공간이라고 보면 되고, 각각의 컨테이너는 격리된 상태로 다른 컨테이너들과 분리된다는 특징이 있습니다. 쉽게 생각하면 정말 저희가 알고 있는 컨테이너 박스와 같은 느낌으로 정해진 용어입니다.

컨테이너는 리눅스 상에서 사용하는 기술입니다. chroot, namespace, cgroup  Linux 자체 기능만으로 구현되어 있고, 프로세스 단위로 독립적인 공간을 만드는 기술입니다.

Docker의 Container는 Linux의 Container를 이용한 것이고, Linux의 Container에 여러 기능을 추가하여 어플리케이션을 Container로 조금 더 이용하기 쉽게 만들어 둔 것입니다.

💡 컨테이너의 핵심은 어디서나 같은 환경에서 실행 가능한 격리된 환경으로 프로세스의 생명주기를 관리합니다.

컨테이너 기술은 도커만의 기술이 아니라 리눅스 자체 기능이라는 것을 한번 더 강조하고 다음으로 넘어가겠습니다.

이식성

💡 지금부터 쉽게 생각해서 컨테이너란 실행 환경을 가진 하나의 분리된 공간이라고 생각하겠습니다. 컨테이너는 다른 곳으로 이식이 가능하다는 특징이 있습니다.

어떤 프로그램을 실행할 때 필요한 모든 것을 딱 떼어내서 컨테이너라는 것을 만들었습니다. 그 안에 설정, 설치, 버전 등 프로그램을 실행하기 위한 환경설정과 프로그램 자체가 들어있습니다.

이제부터는 하나하나 직접 설치하고 설정하는게 아니라 이 패키지만 실행하면 바로 원하는 프로그램을 실행할 수 있도록 해줍니다. 컨테이너가 어디서나 같은 환경으로 실행 가능한 환경을 만들어줍니다. 이러한 특징을 이식 가능(portable)하다고 부릅니다.

이러한 컨테이너의 특징 덕분에 어플리케이션을 사용자에게 배포를 할 때 뿐 아니라 회사에서도 서로 환경이 다른 다양한 팀과 쉽게 프로그램을 공유와 이동 할 수가 있습니다.

따라서 컨테이너의 이식성과 하나의 격리된 환경에 패키징 하는 기술은 개발과 배포에 훨씬 더 효율성을 부여합니다.

마치며..

이 게시글에서 모든 컨테이너의 기능을 다루지는 않았습니다.

컨테이너의 기술적 개념인 layer형식은 이미지에 대해서 알아야만, 다룰 수 있기 때문에 이미지를 먼저 이야기하고 다루도록 하겠습니다.

여기서 나오는 개념에 대해서는 꼭 숙지를 하고 다음 단계로 가시길 권장합니다.

728x90