본문 바로가기

CS

도커란 무엇일까?

먼저 과거부터 현재까지의 어떠한 어려움이 있었고 해당 어려움을 어떻게 극복했는 지를 보면 도커란 개념을 잡기에 수월할 것입니다

 

과거에는 하나의 서버에서 Java, Python 등 여러 런타임을 설치하고 운영하는 것이 매우 복잡했고 각 어플리케이션은 서로 다른 패키지와 종속성을 필요로 했으며 이로 인해 종속성 충돌이 발생할 가능성이 높았습니다

 

그렇다면 서버가 비정상적으로 동작하거나 멈추는 문제가 잦았으며 또한, 작은 업데이트 하나로도 큰 시스템 장애를 초래할 수 있었습니다. 인프라의 제약에 맞춰 개발을 하거나, 어플리케이션에 인프라를 맞추는 방식이 강요되었고, 이는 개발과 운영 모두에 큰 부담이 되었습니다.

 

 

이 문제를 해결하기 위해 "하이퍼바이저"를 통해 하나의 서버를 여러 가상 머신으로 분할하는 방식이 도입되었습니다. 이는 인프라 레벨에서 서버를 나누는 데 성공했지만, 여전히 패키지와 종속성 충돌 문제는 해결되지 않았고, 서버 식별 및 자원 관리의 어려움도 남아 있었습니다.

 

 

 

이러한 상황에서 등장한 것이 바로 도커입니다. 도커는 커널을 공유함으로써 CPU 아키텍처만 동일하면 패키지와 종속성이 서로 다른 어플리케이션들도 격리된 환경에서 효율적으로 동작할 수 있도록 했습니다. 각 어플리케이션은 이미지나 컨테이너로 격리되어 충돌을 미연에 방지할 수 있었으며, 개발 환경과 운영 환경을 동일하게 유지할 수 있어 운영상의 문제도 줄어들었습니다

 

 

 

운영체제가 아직 미흡한 사람으로써, 조금 어려운 말로 들렸었습니다 🤔

 

그래서 조금 더 천천히 설명을 해보자면, 우선 커널은 하드웨어와 소프트웨어 간의 중개자 역할을 하는 것으로 즉, cpu 메모리와 하드웨어 자원을 관리를 합니다. 여기서 커널은 어플리케이션이 요청한 작업을 하드웨어에서 실행할 수 있게 연결해주는 중요한 역할을 하며, 운영체제의 가장 기본적인 기능들을 수행합니다

 

그리고 cpu 아키텍처는 CPU의 기본적인 구조를 의미하며, CPU가 명령을 처리하고 계산하는 방식입니다. 즉, CPU의 설계 방식에 따라 명령어 세트가 달라지며, 이는 프로그램이 실행되는 방식을 결정합니다. 대표적인 CPU 아키텍처로는 x86(일반적으로 PC에서 사용)과 ARM(스마트폰, 태블릿 등에서 많이 사용)이 있습니다.


 

그렇다면 정리를 해봅시다

 

 

 

도커 컨테이너는 커널을 공유하는데, 이는 각 컨테이너가 독립된 프로세스로 실행되면서도 동일한 운영체제 커널을 통해 하드웨어 자원을 사용할 수 있음을 의미합니다. 즉, 각 컨테이너는 CPU, 메모리 등의 자원을 직접 관리하지 않고 커널을 통해 접근하게 됩니다.

 

 

CPU 아키텍처가 동일하다는 것은 컨테이너들이 동일한 명령어 세트로 CPU와 상호작용할 수 있다는 뜻입니다. 도커 컨테이너는 기본적으로 CPU 아키텍처가 동일할 경우, 패키지나 종속성이 서로 다르더라도 격리된 환경에서 실행될 수 있습니다. 예를 들어, x86 아키텍처에서 컴파일된 프로그램은 같은 x86 아키텍처의 다른 컴퓨터에서 실행할 수 있는 반면, x86과 다른 아키텍처인 ARM에서 실행할 수 없습니다.

 

 

출처: https://velog.io/@nikki/%EB%B0%B0%ED%8F%ACDocker

 

 

 

도커는 호스트 운영체제의 커널을 공유합니다. 여기서 호스트 운영체제는 서버 하드웨어 위에 설치된 기본적인 운영체제를 의미하죠  즉, 도커 컨테이너는 가상 머신처럼 별도의 OS를 실행하는 것이 아니라, 같은 운영체제 커널을 공유하면서도 각각의 어플리케이션은 자신만의 파일 시스템, 네트워크, 프로세스를 격리하여 사용하는 구조입니다. 이를 컨테이너화라고 하며, 각 컨테이너는 격리된 환경에서 독립적으로 동작하면서도 동일한 커널을 공유합니다.

 

패키지와 종속성 문제를 방지할 수 있는 이유는 컨테이너마다 독립된 파일 시스템과 라이브러리를 사용하기 때문입니다. 예를 들어, App A와 App B가 다른 라이브러리를 필요로 하더라도, 각각의 컨테이너는 자신의 환경에서 필요한 라이브러리만을 설치하여 사용할 수 있습니다. 격리된 환경 덕분에 종속성 충돌을 방지하면서도 커널을 공유하는 방식으로 효율성을 극대화할 수 있는 것입니다.

 

따라서, CPU 아키텍처가 동일하고 커널을 공유할 수 있으면, 격리된 환경에서 서로 다른 패키지와 종속성을 사용하면서도 하드웨어 자원을 효율적으로 나눠 쓸 수 있습니다.

 


덧붙혀서 알아야 할 개념 쿠버네티스

 

 

 

이러한 격리를 기반으로 충돌이 미연에 방지할 수 있었다. 하지만 이러한 도커 설치 환경이 무수히 많아지고 컨테이너가 비정상 동작하면? 등등 많은 문제들이 발생할 수 있었습니다

 

그래서 등장한 게 쿠버네티스인데 컨테이너의 생명주기, 여러 서버의 관리 등등 전부 관리를 해주는 툴로서, 쿠버네티스는 컨테이너를 관리하는 도구라고 생각하면 편합니다 조금만 더 간단히 더 알아보자면 

 

쿠버네티스는 컨테이너를 자동화하고 오케스트레이션하는 도구로, 다수의 컨테이너를 자동으로 배포, 스케일링, 복구하며 관리할 수 있도록 도와줍니다. 이를 통해 개발자는 더 이상 개별 컨테이너에 집중하지 않고, 시스템 전체의 안정성과 효율성을 유지할 수 있습니다.

 

 

쿠버네티스의 주요기능 4가지

컨테이너의 자동 배포 및 스케일링: 서비스 사용량에 따라 컨테이너를 자동으로 늘리거나 줄일 수 있음
컨테이너의 복구 및 재시작: 비정상적으로 종료된 컨테이너를 자동으로 재시작하거나, 교체해 서비스 가용성을 유지함
서비스 디스커버리와 로드 밸런싱: 컨테이너들이 서로 소통할 수 있도록 네트워크를 자동으로 설정하고, 로드 밸런싱을 제공
환경 간 일관성: 개발, 테스트, 운영 환경 간의 일치성을 유지하며, 각 환경에서 동일한 설정으로 배포할 수 있도록 지원

도커 용어 정리

 

 

도커가 왜 탄생했고 VM과 무엇이 다르며, 동일한 커널과 동일한 CPU 아키텍처로 인하여서 서로 격리된 환경을 통해 자신만의 환경을 구축하여서 버전 불일치 문제 등을 피해갈 수 있다는 것을 이해하였습니다

 

하지만 막상 이를 알고 도커를 접한다고 한들 어려워보이는 건 마찬가지입니다. 왜냐하면 너무 낯선 용어들이 많기 때문이죠 뭐 예를들면 이미지, 도커 허브, 이미지와 컨테이너와의 상관관계, 각 명령어 등등 아직 어려운 게 많습니다. 사실 저도 도커를 본격적으로 배우기 전에 새로운 것에 대한 괴리감과 두려움을 없애려고 정리하는 글입니다 😊

 

한 번 본격적으로 이를 정리해죠

 

 

 

도커 이미지란?

 

 

도커 이미지는 쉽게 말해서, 어플리케이션과 그 실행에 필요한 모든 요소들이 포함된 패키지입니다. 즉, 프로그램 실행에 필요한 모든 라이브러리, 파일 시스템, 설정 등이 담겨 있는 일종의 템플릿이라고 보면 됩니다.

 

즉 이미지는 단순히 어플리케이션 실행에 필요한 "정적 템플릿"이라는 것을 알 수 있습니다. 이미지 자체로는 실행되지 않으며 컨테이너를 실행하기 위한 템플릿 역할을 하는 것이라는 것이죠

 

그렇다면 컨테이너는 이미지를 기반으로 실행되는 실제 실행 환경이라는 것을 알 수 있습니다. 즉 이미지를 가지고 실행되는 프로세스 인 셈이죠. 이미지를 "설계도"라고 생각하고, 컨테이너는 그 설계도를 기반으로 만들어진 "객체"라고 생각하면 됩니다. 이미지는 바뀌지 않지만, 이미지를 바탕으로 여러 컨테이너를 만들어 실행할 수 있습니다.

 

 덧붙히자면 이미지가 편리한 이유가 만일 컨테이너라는 실행환경 구축을 위해 Mysql 이미지를 다운로드 받았다고 가정해봅시다. 그렇다면 해당 이미지에는 해당 애플리케이션의 실행에 필요한 모든 종속성이 포함이 되어있습니다. 즉 MySql 서버와 그에 필요한 모든 라이브러리가 포함된 환경이 생성이 되는 것입니다


 

그렇다면 우리가 왜 이미지를 이용하여야 할까요?

 

 

이미지를 사용하는 이유는 간단합니다. 일관된 환경을 보장하기 위함입니다. 개발, 테스트, 운영 환경에서 똑같이 실행될 수 있는 "설계도"가 있기 때문에, 어디서나 동일하게 동작할 수 있습니다. 이미지를 사용하면, 어플리케이션이 다른 환경에서도 충돌 없이 실행될 수 있습니다

 

말로 하면 잘 이해가 안 가니, 예시를 들어보죠 만약에 MySQL 서버를 직접 설치하면, 운영체제에 따라 설치 방식이 다르고, 버전이나 라이브러리 충돌 문제도 발생할 수 있습니다.

 

그러나 MySQL 이미지를 사용하면, 그 안에 이미 MySQL 서버와 필요한 모든 요소가 포함되어 있어, 어떤 환경에서도 동일하게 실행됩니다.

 

 

신기하지 않나요? 저희가 오라클이나 Mysql 등을 이용하려면 해당 웹사이트로 이동을 하여서 직접 툴킷을 다운로드 받고 빌드도구에 등록을 하였어야 했습니다. 그렇다면 해당 이미지는 어디서 가져오는 것일까요?


 

도커 레지스트리란?

 

 

레지스트리는 도커 이미지가 저장되어 있는 저장소입니다. 다양한 이미지들이 이곳에 저장되고 관리되며, 필요할 때마다 이미지를 레지스트리에서 다운로드하여 사용할 수 있습니다.

 

이와 자주 비교되는 것이 도커 공용 레지스트리인 도커 허브입니다, 도커 허브는 공용 도커 레지스트리입니다. 누구나 사용 가능한 이미지들이 저장되어 있고, 이를 다운로드해서 사용할 수 있습니다.

 

예를 들어, nginx나 mysql 같은 이미지를 쉽게 다운로드할 수 있습니다. 이는 이미 도커 허브에 저장되어 있고, 별도의 설치 과정 없이 바로 사용할 수 있습니다.

 

레지스트리는 더 넓은 개념으로, 이미지를 저장하고 관리하는 공간을 의미합니다. 도커 허브는 공용 레지스트리일 뿐이고, 그 외에도 프라이빗 레지스트리를 직접 설정할 수도 있습니다. 예를 들어, 회사 내부에서만 사용하는 이미지를 레지스트리에 저장하고 관리할 수 있습니다.


도커 운영체제

 

 

 

도커의 아키텍처는 크게 클라이언트, 도커 호스트, 그리고 레지스트리로 나뉩니다. 이를 레지스트리 같은 경우는 정리했으니 다른 것들을 정리해죠

 

 

도커 클라이언트

 

도커 클라이언트는 사용자가 도커를 사용하는 인터페이스입니다. 즉, 도커를 실행하는 명령을 보내는 도구입니다. 대표적인 명령으로는 다음과 같은 것들이 있습니다.

 

docker run: 이미지를 기반으로 컨테이너를 실행합니다. 만약 해당 이미지가 없다면,  레지스트리에서 이미지를 가져옵니다.
docker build: 도커파일을 기반으로 새로운 이미지를 생성하는 명령입니다.
docker pull: 레지스트리에서 이미지를 가져오는 명령으로 원하는 이미지를 도커 호스트에 다운로드할 수 있습니다.

 


 

도커 호스트

 

도커 호스트는 실제로 도커가 동작하는 환경으로 도커 데몬이 포함되어 있으며, 이미지 및 컨테이너가 관리합니다

 

도커 데몬: 도커 데몬은 도커 클라이언트의 요청을 받아서 처리하는 백그라운드 서비스로 도커 데몬은 클라이언트 명령을 실행하고, 컨테이너 및 이미지를 관리하며 또한 도커 데몬은 다른 데몬과 통신하여 여러 호스트에 걸쳐 도커 서비스를 관리할 수 있습니다

 


 

도커 명령어의 작동 원리

 

docker run: 클라이언트가 docker run 명령을 실행하면, 도커 데몬이 해당 이미지를 확인하고, 이미지가 없다면 레지스트리에서 이미지를 다운로드하여 컨테이너를 생성합니다. 이후 해당 컨테이너가 실행하는 것입니다

 

docker build: 도커파일을 기반으로 새로운 이미지를 생성하는 명령으로 도커파일은 이미지 생성을 위한 일종의 스크립트로, 어떤 OS를 사용할지, 어떤 애플리케이션을 설치할지 등을 정의합니다

 

docker pull: 도커 클라이언트가 레지스트리에서 이미지를 가져오는 명령으로 도커 허브나 프라이빗 레지스트리에서 이미지를 다운로드할 수 있습니다


로컬 혹은 도커허브에 이미지 저장하는 법


 

 

Dockerfile로 이미지 생성 후 도커 허브에 저장

 

먼저, Dockerfile을 기반으로 이미지를 생성해야 합니다

$ docker build -t 이미지명 .

 

 

이미지를 도커 허브에 저장하려면, 도커 허브에 로그인해야 합니다

$ docker login

 

 

그 후, 이미지에 태그를 추가하여 도커 허브로 푸시할 수 있습니다

$ docker tag 이미지명 사용자이름/저장소이름:태그
$ docker push 사용자이름/저장소이름:태그
$ docker tag myimage myusername/myrepo:1.0
$ docker push myusername/myrepo:1.0

 

도커 허브에서 이미지 다운로드(pull)

 

도커 허브에서 이미지를 다운로드하려면 docker pull 명령

$ docker pull 사용자이름/저장소이름:태그

 

 


 

로컬 서버에 이미지 저장 및 로드

 

 

로컬 서버에 이미지를 저장하려면, 이미지를 tar 파일로 저장해야 합니다

$ docker image save -o 파일명.tar 이미지명

 

저장된 tar 파일을 로드하려면 docker load 명령을 사용하죠

$ docker image load -i 파일명.tar