본문 바로가기
Infrastructure/Docker

[Docker] 그래서 도커(Docker)랑 컨테이너(Container)가 뭐냐구요

by 곰민 2023. 2. 26.

도커(Docker), 컨테이너(Container)는 무엇일까요?
도커(Docker) 등장 배경과 컨테이너(Container) 환경의 발달 과정 그리고 기존 가상화 방식과 컨테이너(Container) 기반 가상화 방식의 차이점과 운영방식등을 알아보도록 하겠습니다.

 

docker
도커 그 도커가요 도커가 도커죠뭐.. 이런 불상사를 막자

 

Docker의 배경


Docker는 2013년에 dotCloud의 Solomon Hykes와 그의 팀에 의해 그의 팀에 의해 2013년 PyCon에서 (The future of Linux Containers) 처음 데모 되었습니다.
출시 전 오클랜드 항구에 들어오는 모든 컨테이너 선박을 볼 수 있었고 “한 서버에서 다른 서버로 앱을 옮기는 것보다 지구 반대편에서 자동차를 배송하는 것이 더 쉽다” 는 사실이 해결해야 할 문제처럼 보였다고 합니다.

이 당시에는 클라우드 환경에서 애플리케이션을 배포하는 것이 어려운 문제가 있었습니다.

커져가는 클라우드 환경에서 서버가 10대라면 문제가 되지 않지만, 수천 대 이상의 서버를 관리하는 것은 매우 어려웠습니다.

기존 가상화 기술을 사용하면 리소스가 많이 소모되고 대규모 관리도 어려웠기 때문입니다.

 

dotCloud 팀은 가상화 자체가 문제가 아니라 가상화 사용 방식이 문제라는 것을 인식했습니다.

전체 운영 체제를 가상화하는 대신 애플리케이션과 해당 종속성만 가상화하는 것이 더 효율적이라는 것을 깨달았습니다.

이를 통해 Docker의 핵심인 컨테이너 개념을 개발하게 되었습니다.

팀이 처음 구현한 Docker는 컨테이너를 보다 쉽고 사용자 친화적으로 관리할 수 있는 방법을 제공하기 위해 LXC와 같은 기존 Linux 컨테이너 기술을 기반으로 구축되었습니다.

 

그렇다면 Docker는 컨테이너를 활용하여 기존 가상화 방식과는 어떤 점이 다르고 어떤 이점이 있는지 알아보도록 하겠습니다.

 

컨테이너(Container)란 무엇이며 기존 가상화와 컨테이너(Container) 기반의 가상화의 차이점


그렇다면 컨테이너는 무엇이며 컨테이너 기반 가상화가 기존 가상화와는 어떤 다른 점이 존재하는 것일까요?

 

Docker 래퍼런스 는 컨테이너를 이렇게 말합니다.

 

컨테이너는 애플리케이션이 한 컴퓨팅 환경에서 다른 컴퓨팅 환경으로 빠르고 안정적으로 실행될 수 있도록 코드와 모든 종속성을 패키징 하는 표준 소프트웨어 단위입니다. 
Docker 컨테이너 이미지는 코드, 런타임, 시스템 도구, 시스템 라이브러리 및 설정 등 애플리케이션을 실행하는 데 필요한 모든 것을 포함하는 경량의 독립 실행형 소프트웨어 패키지입니다.

 

Virtual Machines vs Containers

 

출처:https://www.atlassian.com/microservices/cloud-computing/containers-vs-vms

 

 

컨테이너화는 기본 운영 체제(OS) 커널을 동일한 시스템의 다른 컨테이너와 공유하는 격리된 환경에서 애플리케이션을 실행하는 방법입니다.
컨테이너는 종속성, 필요한 라이브러리 및 바이너리와 함께 애플리케이션을 컨테이너 이미지라고 하는 독립된 패키지로 패키지화하여 여러 컴퓨팅 환경에 쉽게 배포 및 배포할 수 있습니다.

즉 OS 레벨에서 어플리케이션 실행 환경을 격리함으로써 마치 다른 OS에서 동작하는 것과 같은 가상 실행 환경을 제공하는 기술입니다.

 

컨테이너 기반 가상화는 기존 가상화와 달리 하이퍼바이저 위에서 여러 개의 Guest OS를 실행하는 대신
호스트 OS 커널을 사용하여 격리된 여러 개의 컨테이너를 실행
합니다.

즉 컨테이너형 가상화는 Guest OS를 사용하지 않고 Host OS에 컨테이너형 가상화 소프트웨어를 설치합니다.


따라서 기존 가상화에 비해 컨테이너화가 더 가볍고 효율적입니다.

컨테이너 기반 가상화에서 각 컨테이너는 호스트 OS에서 프로세스로 실행되며 자체적으로 격리된 파일 시스템, 네트워크 인터페이스 및 리소스를 갖습니다.

설치 같은 번거로움을 크게 줄일 뿐만 아니라
가상 하드웨어나 Guest OS를 실행할 필요가 없는 만큼 성능도 좋아집니다.

 

 

Container내에 여러가지 애플리케이션 or Container 내 하나의 애플리케이션 🤔 🤔 ????

 

Container에는 여러 응용 프로그램을 도입할 수 있지만 원칙적으로 하나의 컨테이너에 하나의 애플리케이션(하나의 프로세스) 단위로 구축하고 여러 컨테이너를 결합하는 것이 좋습니다.
컨테이너를 만드는 비용이 매우 저렴하기 때문에 복잡한 컨테이너를 하나 만드는 것보다 단순한 컨테이너를 여러 개 만드는 것이 더욱 효율적이고 나중에 설계를 변경하기도 쉽습니다.

 

 

도커는 어떻게 이렇게 할 수 있을까요?(with 컨테이너의 역사)


컨테이너가 발전된 과정을 알아볼 필요가 있습니다.

 

Chroot and Chroot Jail

최신 컨테이너의 계보는 1979년, 루트 시스템 호출 및 명령줄 도구가 유닉스 버전 7의 일부로 제공되기 시작한 때로 거슬러 올라갈 수 있습니다. 

Chroot(Change Root)를 사용하면 프로세스의 Root 디렉터리를 변경하여 파일 시스템에서 특정 파일 및 디렉터리 집합으로 보기를 좁힐 수 있습니다.

 

출처:https://www.geeksforgeeks.org/chroot-command-in-linux-with-examples/


처음에 시스템 테스트를 실행하는 데 사용되던 chroot는 1982년 4.2 BSD를 통해 BSD 운영 체제 라인에 진입했습니다. 

컴퓨터 네트워킹과 인터넷이 확장되면서 1980년대 말과 1990년대 초, 잠재적 공격자를 시스템의 나머지 부분으로부터 "jail(감옥)"에 가두기 위해 네트워크 서비스를 분리하는 데 점점 더 많이 사용되었습니다.

따라서 'Chroot Jail' 또는 단순히 'Jail'이라는 용어가 만들어졌습니다.

하지만 chroot는 파일 시스템 사용을 제한하는 데만 사용할 수 있었습니다.

root가 다른 프로세스는 여전히 일반 IPC를 사용하거나 네트워크 인터페이스를 통해 서로 통신할 수 있지만, root user로 실행되는 프로세스를 제한하는 데는 사용할 수 없고 잘못 구성하기 쉬워 "Jail"에서 chrooted 된 프로세스가 쉽게 탈출할 수 있습니다.

이것이 바로 "JailBreak(탈옥)'이라는 용어가 등장한 이유입니다.

 

OS 수준의 가상화를 제공하기 위해 FreeBSD 4.0은 크게 확장된 jail 개념을 도입했습니다.

각 jail에는 고유한 IP 주소, 루트 디렉터리 및 CPU, 메모리 등의 리소스 제한이 있습니다.

FreeBSD 커널은 또한 서로 다른 jail에서 동일한 UID와 GID를 구별하기 시작했습니다.

예를 들어, 각 jail에는 고유한 root user(UID가 0)가 있지만 root jail의 root user만 제한 없는 기능을 사용할 수 있습니다.

root jail이 아닌 jail에서 실행 중인 프로세스는 다른 jail에서 실행 중인 다른 프로세스에 신호를 보낼 수 없습니다(UID가 일치하더라도).

파일 시스템의 마운트 및 마운트 해제, 장치 노드 생성 및 라우팅 테이블 수정도 금지됩니다.

FreeBSD jail은 chroot에서 먼 길을 왔지만, 보안 환경을 제공하면서 시스템 변경을 최소화하기 위해 몇 가지 엄격한 제한이 도입되었습니다. 예를 들어, jail은 통신을 위해 하나의 IPv4 주소만 가질 수 있고 통신에 UDP 또는 TCP만 사용할 수 있습니다(no raw sockets, IPv6 등 금지).

이로 인해 jail의 보안이 크게 향상되었지만, 일부 애플리케이션에서 추가 지원이 필요했습니다.

 

Solaris Container

2005년에 Solaris 10이 출시되면서 서로 다른 프로세스 그룹 간의 경계 관리 솔루션인 Solaris Zones에 대한 지원이 도입되었습니다.

나중에 Solaris 영역과 워크로드 리소스 관리의 조합이 Solaris 컨테이너로 알려지면서 "컨테이너"라는 용어가 활용되기 시작했습니다

 

LXC

출처:https://www.baeldung.com/linux/docker-containers-evolution

lxc의 등장(2008)

linux 환경에서 컨테이너를 구현하는 데 사용되는 두 가지 주요 Linux 커널 구성 요소는 "namespace"와 "cgroups"입니다.

 

cgroup(control group)

 

LXC는 cgroup을 사용하여 각 컨테이너에 대한 시스템 리소스(예: CPU, 메모리, 디스크 I/O)를 제한하고 우선순위를 지정합니다.

cgroup을 사용하면 LXC가 각 컨테이너에 리소스를 제어되고 효율적인 방식으로 할당하여 한 컨테이너가 너무 많은 리소스를 소비하여 다른 컨테이너의 성능에 영향을 미치는 것을 방지할 수 있습니다.

 

namespace

 

LXC는 Linux 커널 namespace를 사용하여 각 컨테이너에 대해 별도의 네임스페이스를 생성합니다.

namespace는 프로세스 ID, 네트워크 인터페이스, 파일 시스템 등 각 컨테이너에 대한 다양한 시스템 리소스를 격리합니다.

이러한 격리를 통해 한 컨테이너 내의 프로세스가 다른 컨테이너의 리소스를 간섭하거나 액세스 할 수 없습니다.

 

chroot

 

LXC는 chroot를 사용하여 각 컨테이너에 대한 파일 시스템 경계를 만듭니다.

새 컨테이너가 생성되면 LXC는 호스트 시스템의 root 파일 시스템과 격리된 새 root 파일 시스템을 생성합니다.

이러한 격리를 통해 각 컨테이너는 고유한 파일 시스템 계층 구조를 가질 수 있으며, 한 컨테이너 내의 프로세스가 다른 컨테이너의 파일에 액세스 하거나 수정할 수 없습니다.

 

LXC는 가상 머신과 유사하지만 오버헤드가 훨씬 낮은 격리된 컨테이너 환경을 만들 수 있습니다.

LXC 컨테이너는 호스트 시스템과 동일한 커널을 공유하므로 오버헤드를 최소화하면서 빠르게 시작하고 중지할 수 있습니다.

따라서 LXC는 각각 고립된 환경과 리소스 제한이 있는 단일 호스트 시스템에서 여러 애플리케이션을 실행할 수 있게 됩니다.

 

Docker가 처음 개발 됐을 당시에는 LXC를 기반으로 구현을 하였지만 최근부터는 Containerd(runC)를 개발하여 사용하고 있습니다.
Docker Engine과 cli 그리고 libContainer에 대해서는 추후 포스팅 하겠습니다.

 

Docker는 Namespace, cgroup와 rkxdms linux 커널의 기본 제공 컨테이너화 기능을 사용하여 애플리케이션을 실행하기 위한 격리된 환경을 만들기 때문에 linux가 아닌 다른 운영체제에서 Docker를 직접 띄울 수 없습니다.
VirtualBox, VMWare, WSl 등과 같은 가상 머신을 생성하고 Linux를 올리고 그 위에 Docker를 띄우는 방식으로 mac os나 window와 같이 linux base os 가 아닌 os 환경에서 docker를 활용할 수 있습니다.

 

Docker 이미지란?


그렇다면 도커에서 이미지란 무엇일까요?

이미지는 컨테이너를 실행하기 위한 일종의 Template입니다.

oop에서의 Class와 instance의 관계와 같이 컨테이너의 프로세스 실행 환경은 컨테이너 이미지에 의해 결정되지만 컨테이너 이미지 내에서 프로세스가 실행되지는 않습니다.

 

출처:https://www.geeksforgeeks.org/what-is-docker-images/

 

 

Docker와 Immutable Infrastructure


Immutable Infrastructure은 시스템이 점점 더 커지고 분산되면서 인프라 관리 및 유지보수가 어려워지고 시간이 많이 소요되는 문제를 해결하기 위해 2010년대 초에 등장한 새로운 인프라 관리 방식입니다.

 

Immutable Infrastructure는 소프트웨어 시스템을 구축하고 배포할 때, 변경되지 않는 불변 구성 요소를 사용하는 것을 강조합니다. 이를 위해 표준화된 Immutable 구성 요소를 사용하여 소프트웨어 시스템을 구축하고 배포합니다.

 

복잡성을 줄이고 안정성을 개선하기 위해 표준화된 Immutable 구성 요소를 사용하여 소프트웨어 시스템을 구축하고 배포하는 것을 강조했습니다.

출처:https://medium.com/@abhaydiwan/build-secure-immutable-infrastructure-in-the-cloud-devsecops-e8075d4c53d6

Immutable Infrastructure에서는 서버 및 기타 인프라 구성 요소를 일회용 구성 요소로 취급하여 필요에 따라 새 인스턴스를 생성하고 기존 인스턴스를 업데이트하거나 패치하지 않고 교체합니다. 이렇게 함으로써 시스템 구성 요소의 변화를 최소화하고, 이전 상태로 롤백할 수 있는 안정적인 인프라 환경을 구성할 수 있습니다.

 

Docker는 이미지와 컨테이너를 활용하여 Immutable Infrastructure 방식으로 안정적인 인프라 환경을 구성할 수 있도록 도와줍니다.

 

 

마지막으로 다시 보는 Docker


Docker는 컨테이너화 플랫폼으로, 애플리케이션별 가상화를 가능하게 하는 독립된 단위인 컨테이너를 생성합니다.
각 컨테이너에는 애플리케이션과 필요한 모든 종속성, 라이브러리, 구성 파일이 포함되어 있어 호스트 시스템과 독립적인 격리된 환경에서 실행될 수 있습니다.
이를 통해 개발자는 애플리케이션을 이식 가능하고 재현 가능한 단위로 패키징하여 다양한 환경에서 일관된 동작으로 배포할 수 있으며, 애플리케이션 버전이 변경되면 버리고 새로운 컨테이너를 시작하여 immutable infrastructure를 구현할 수 있습니다.
Docker는 초기에 lxc를 베이스로 컨테이너 생성 및 관리를 위한 가볍고 효율적인 방법을 제공하여 애플리케이션별 가상화를 구현합니다.
호스트 OS와 커널을 공유하기 때문에 게스트 OS가 필요하지 않아 성능상 이점을 가져올 수 있습니다.
또한 경계가 나뉜 파일 시스템과 쓰기 시 복사 기술을 사용하여 컨테이너의 스토리지 공간을 최소화하고 빠르고 효율적으로 컨테이너를 시작하고 관리할 수 있습니다.

 

 

참조


https://www.infoworld.com/article/3632142/how-docker-broke-in-half.html

https://blog.aquasec.com/a-brief-history-of-containers-from-1970s-chroot-to-docker-2016

https://medium.com/@abhaydiwan/build-secure-immutable-infrastructure-in-the-cloud-devsecops-e8075d4c53d6

https://www.atlassian.com/microservices/cloud-computing/containers-vs-vms

https://www.baeldung.com/linux/docker-containers-evolution

https://www.geeksforgeeks.org/chroot-command-in-linux-with-examples/

https://blogs.vmware.com/opensource/2018/02/27/the-story-of-containers/

반응형

댓글