너굴 개발 일지

[리뷰] 도커 교과서 - 컨테이너, 도커 이미지 본문

독서

[리뷰] 도커 교과서 - 컨테이너, 도커 이미지

너굴냥 2023. 8. 3. 22:28

도커 교과서의 1장, 2장, 3장을 읽으면서 공부한 것을 정리한 글입니다.

 

Docker 탄생 배경

Docker는 2013년에 dotCloud의 Solomon Hykes와 그의 팀에 의해 처음 데모되었습니다. 

이 당시에는 클라우드 환경에서 애플리케이션을 배포시 어려운 문제가 있었습니다. 커져가는 클라우드 환경에서 서버가 10대라면 문제가 되지 않지만, 수천 대의 서버를 관리하는 것은 매우 어려웠으며 기존 가상화 기술을 사용하면 리소스가 많이 소모되는 단점도 존재했습니다.

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

전체 운영 체제를 가상화하는 대신 애플리케이션과 해당 종속성만 가상화하는 것이 더 효율적이라는 것을 깨닫고 Docker의 핵심인 컨테이너 개념을 도입했습니다.

클라우드
기존에는 애플리케이션을 제대로 동작시키기 위해서, 서버가 항상 가동되어야 했는데 새로운 서버 도입시 하드웨어, OS, 서버 애플리케이션 설치 및 테스트, 문제 대처 등 서버 운용 관리에 시간과 비용이 많이 들어갔습니다.
그래서 서버를 직접 관리하지 않고 인터넷을 통해 서버의 기능만 이용할 수 있는 클라우드 서비스가 탄생했습니다.
(직접 서버를 운용, 관리하던 기존 서버 운영 방식을 온프레미스(on-premise)라고 합니다.)

장점은 클라우드 서비스 사업자가 서버를 도입하고 관리하기에 매우 편리합니다. 예를 들어 파일 서버 저장 용량이 부족하면, 사용자는 서비스 계약만 변경하면 끝이기에 모든 관리에 신경쓸 필요가 없습니다.

하지만 단점으로는 보아니안 가용성에 주의가 필요합니다. 자신의 관리가 미치지 않는 범위에서 데이터가 유지되고 서비스를 이용할 수 없다는 가능성도 있다는 것을 염두해야 합니다. 또한 운영 환경 자체가 클라우드 제공자에게 종속되기에 클라우드 서비스에 문제가 생기면 내가 관리하는 환경에도 영향을 미칠 수 있습니다.

 

컨테이너 기반 가상화와 기존 가상화의 차이

먼저 컨테이너가 무엇인지 알기 위해 컨테이너화 전과 후를 비교해보겠습니다.

컨테이너화 이전에는 종속성을 격리하는 유일한 방법이 가상 머신을 사용하는 것이었습니다.(격리 조건은 아래 참고)

그러면 가상 머신의 정의와 장단점은 무엇일까요?

  • 정의
    • 컴퓨터 환경을 가상화하여, 하나의 하드웨어에서 여러 대의 컴퓨터 시스템이 실행되도록 애뮬레이션하는 기술
    • 애뮬레이션이란, 소프트웨어 기술을 사용하면서 하나의 컴퓨터가 다른 기종의 컴퓨터와 동일한 방식으로 작동하는 것처럼 보이게 만드는 기술
    • 하나의 컴퓨터에서 하나의 OS만 운영하는 방식의 비효율 해결
    • 가상 머신은 아래 사진처럼 하이퍼바이저 위에 하드웨어 기반의 여러 게스트 운영체제가 생성됨 
    • 즉, 물리적 컴퓨터처럼 애플리케이션과 운영체제를 실행하며 물리적 컴퓨터와 동일한 기능을 제공하는 소프트웨어 컴퓨터
    • 하이퍼바이저란, 가상 머신을 생성 및 실행하는 프로세스
  • 장점
    • 가상머신을 통해 생성된 가상 환경은 서로 독립된 환경으로 호환성 문제를 줄이고 애플리케이션을 다양한 환경에서 실행할 수 있음
    • 한대의 컴퓨터에서 여러 운영체제를 동시에 구동할 수 있음
  • 단점
    • 거의 모든 장치들을 가상으로 생성하기에 실제 컴퓨터보다 속도가 느림
    • 호스트 컴퓨터의 자원을 빌려 사용하므로 호스트 컴퓨터의 성능에 영향을 미치며 호스트 컴퓨터의 성능에 많은 영향을 받음

위처럼 가상 머신을 사용해 종속성을 격리할 수 있지만 가벼운 프로그램 하나를 실행하려해도 OS, 하드웨어까지 모두 묶어버리기에 용량도 크고, OS위에서 OS를 돌리기에 무겁고 느립니다.

이런 무겁고 느린 하이퍼바이저 가상화 방식을 해결하기 위해 프로세스를 격리하는 방안인 컨테이너가 등장했습니다.

컨테이너의 정의와 장단점은 다음과 같습니다.

  • 정의
    •  종속성, 필요한 라이브러리 및 바이너리와 함께 애플리케이션을 컨테이너 이미지라고 하는 독립된 패키지로 패키지화하여 호스트 컴퓨터의 운영체제를 공유하면서 독립적인 실행 환경을 제공하는 기술
    • 즉, 애플리케이션을 실행하기 위해 모든 것을 하나의 패키지로 묶어서, 애플리케이션과 실행 환경을 추상화한 형태로 제공
    • 컨테이너는 OS가 아닌 애플리케이션만 관리하며, 필요한 만큼의 호스트 OS 자원을 컨테이너에 할당
  • 장점
    • Guest OS가 없기에 가벼우며 컨테이너 복제, 배포가 빠름
    • 애플리케이션이 독립된 환경에 격리되어 있기에 서버 관리에 용이
  • 단점
    • VM처럼 다양한 OS를 사용할 수 없음
    • 컨테이너는 호스트 시스템의 커널을 공유하기에 한 컨테이너의 보안 취약점이 다른 컨테이너에 영향을 줄 수 있음

 

언뜻 보면 가상머신과 컨테이너는 별 차이점이 없어보이지만 가장 큰 차이점은 OS수준 가상화입니다.

가상 머신은 처음에 OS 설치부터 해야합니다. 하지만 컨테이너는 그럴 필요가 없는데 이유는 컨테이너의 OS수준의 가상화라는 개념이 존재하기 때문입니다.

OS수준 가상화는 사용하려는 OS를 호스트 OS와 독립하는 방식이 아닌, 커널만 공유해 프로세스로 실행하는 개념입니다. 그래서 별도의 공간이나 메모리 등을 설정해야 하는 가상머신보다 호스트에게 부담도 적고, 실행속도가 빠릅니다.

  하이퍼바이저 가상화 컨테이너형 가상화
격리 수준 하드웨어 운영체제
이미지 크기 OS + 애플리케이션 + 런타임 소프트웨어 애플리케이션 + 런타임 소프트웨어
Guest OS Windows/Linux 등 다양한 선택 가능 호스트 OS와 동일한 OS
이식성 대부분 가상 이미지에 대한 변환 필요 컨테이너 이미지 그대로 사용 가능
데이터 VM 내부 또는 연결된 스토리지에 저장 컨테이너 내부에 있는 데이터는 종료시 소멸, 필요에 따라 스토리지를 이용하여 저장
부팅 시간 분단위 초단위
Guest OS와의 관계 Guest OS는 하드웨어(가상)로 인식 Host OS를 커널 수준으로 분리해 OS를 가상화 형태로 사용, 필요에 따라 호스트와 리소스 공유 가능
유지 관리 각 Guest OS를 개별적으로 패치 Host OS만 업데이트

 

Docker engine은 기본적으로 linux위에서만 돌아갑니다. 그러면 Windows 환경에서는 docker 사용이 불가할까요?

Windows에서는 Docker Desktop App을 실행하기 위해 WSL이 필요합니다. 

WSL은 Windows Subsystem for Linux, hyper-v virtual machine으로  결국 가상머신을 의미합니다.

즉, 리눅스 가상 머신 위에서 Docker 컨테이너를 구동하게 됩니다. 

 

 

1. 클라우드 환경으로 이주

기존에는 클라우드 환경으로 이주하려면 Iaas, Paas 두가지의 선택지가 있었습니다.

  • Paas (서비스로서의 플랫폼)
    • 애플리케이션을 구성하는 각 컴포넌트가 클라우드 서비스 제공자의 매니지드 서비스에 종속
    • 클라우드 제공자가 데이터베이스, 개발 플랫폼까지 제공하는 경우
    • 운영비가 저렴하고 관리가 쉽지만 애플리케이션이 특정 클라우드에 종속되며 이주 과정이 복잡
  • Iaas (서비스로서의 인프라)
    • 애플리케이션을 구성하는 각 컴포넌트가 모두 가상 머신에서 독립적으로 동작
    • 클라우드 제공자가 가상 컴퓨터까지 제공하는 경우
    • 이주 과정이 쉽고 특정 클라우드에 종속되지 않지만, 운영비가 비쌈

도커는 위 단점이 없는 또 다른 선택지를 제공합니다. 

도커는 애플리케이션의 각 컴포넌트가 컨테이너에서 동작합니다. 그렇기에 특정 클라우드에 종속되지 않고 낮은 운영비와 이식성을 확보할 수 있습니다.

 

2. 컨테이너

도커 사용 워크 플로우

  1. 빌드 - 애플리케이션을 컨테이너에 실행할 수 있도록 패키징 (이미지 생성)
  2. 공유 - 다른 사람이 패키지를 사용할 수 있도록 공유
  3. 실행 - 패키지를 내려받은 사람이 컨테이너를 통해 애플리케이션 실행

 

컨테이너 개념

말그대로 물건을 담는 컨테이너 개념으로, 도커에서 컨테이너란 애플리케이션과 실행할 컴퓨터를 담고 있습니다.

실행할 컴퓨터 정보에는 호스트명, IP 주소, 디스크 드라이브와 같은 정보가 있으며 이는 도커가 만들어낸 가상 리소스입니다.

컨테이너 안에서는 밖의 환경을 볼 수 없으며 컨테이너끼리는 서로 독립적인 환경을 갖지만 실행되는 컴퓨터 CPU, 메모리, 운영체제를 공유합니다.

이러한 구조는 격리와 밀집이라는 모순돼 보이는 조건을 동시에 만족할 수 있습니다.

같은 컴퓨터에서 운영체제, CPU, 메모리를 공유하는 여러 개의 컨테이너

밀집과 격리의 모순

  • 컴퓨터에 CPU, 메모리가 허용하는한 많은 수의 애플리케이션을 실행할 수 있어야 함 (밀집)
  • 그러나 서로 다른 애플리케이션 실행시, 런타임 버전 차이, 호환되지 않는 라이브러리 버전 등과 같은 제약으로 서로 독립된 환경에서 실행되어야 함 (격리)
  • 따라서 한 컴퓨터에서 여러 애플리케이션을 실행할 수 있는 밀집이라는 조건 달성 불가

그러면 밀집과 격리 조건을 모두 달성할 수있는 수단은 어떤 것이 있을까요?

  • 가상 머신
    • 컨테이너와 달리 호스트 컴퓨터 운영체제를 공유하지 않고, 별도의 운영체제가 요구됨 (격리)
    • 운영체제는 애플리케이션이 사용할 CPU, 메모리 자원을 많이 소모하기에 운영체제 라이선스 비용, 업데이트 설치 부담과 같은 문제 발생 (밀집 X)
  • 컨테이너
    • 호스트 컴퓨터의 운영체제를 공유하기에 리소스가 적게 들어가고 실행이 빠름
    • 가상 머신에 비해 약 5배나 많은 애플리케이션 실행 가능 (밀집)
    • 외부와 독립된 환경 제공 (격리)

도커는 리눅스 컨테이너 기반 오픈소스 가상화 플랫폼으로 컨테이너를 사용하기에 밀집, 격리 조건을 모두 달성할 수 있습니다.

 

호스트 컴퓨터, 컨테이너 네트워크 관계

도커 설치시, 호스트 컴퓨터 네트워크 계층에 도커가 끼어들게 됩니다. 호스트 컴퓨터에서 발생하는 네트워크 트래픽을 가로채 도커카 그중 필요한 것을 컨테이너에게 전달하게 됩니다.

컨테이너에 포트를 공개하는 것은 도커가 호스트 컴퓨터를 주시하다 해당 포트로 들어오는 트래픽을 컨테이너로 전달하게 됩니다.

docker container run --detach --publish 8088:80 test

위 명령어를 실행하면 백그라운드에서 컨테이너가 계속 동작하게 되는데  호스트 컴퓨터의 8088번 포트로 들어온 트래픽은 컨테이너의 80번 포트로 전달됩니다.

도커 구조

도커의 구조는 아래와 같으며 다음과 같은 기능을 수행합니다.

  • 도커 엔진
    • 도커 관리 기능을 맡는 컴포넌트로 로컬 이미지 캐시 담당, 도커 리소스를 만드는 일을 수행
    • 항시 동작하는 백그라운드 프로세스
    • containerd라는 컴포넌트로 컨테이너를 관리하며 containerd는 호스트 컴퓨터 운영체제가 제공하는 기능을 통해 컨테이너를 생성 및 관리함
    • REST API 기반의 도커 API를 통해 맡은 기능 수행하며 도커 엔진과 상호 작용하는 유일한 수단인 도커 API를 사용해야함
  • 도커 명령행 인터페이스 (도커 CLI)
    • 도커 API의 클라이언트로 docker 명령어 사용시 실제 도커 API를 호출

 

도커를 구성하는 컴포넌트

 

3. 도커 이미지

도커 이미지란

소스 코드, 라이브러리, 종속성, 도구 등 응용 프로그램을 실행하는데 필요한 파일을 포함하는 읽기 전용 파일입니다.

 

도커 이미지 내려받기 과정

docker image pull diamol/cho03-web-ping

위 명령어 실행시 도커 이미지를 내려받게 되며 과정은 다음과 같습니다.

  • 이미지를 내려 받을 때, 도커는 가장 먼저 레지스트리라고 하는 이미지 제공 저장소인 도커 허브에서 이미지를 찾음
  • 내려 받는 동안, 여러 건의 파일을 동시에 내려 받으며 각각의 파일을 이미지 레이어라고 함
  • 모든 레이어를 다 받으면, 이미지 사용 가능

이미지는 물리적으로 여러 개의 작은 파일들로 구성되어 있고, 도커는 이 파일들을 조립해 컨테이너 내부 파일 시스템을 만듭니다.

 

컨테이너 환경 변수 설정

환경 변수란 운영체제에서 제공하는 key-value 형태의 쌍으로 도커는 호스트 컴퓨터가 아닌 도커가 부여한 환경 변수만을 가집니다.

도커는 기본적으로 컨테이너 호스트명, IP 주소처럼 환경 변수를 부여하며 --env 플래그를 활용해 다른 값으로 설정할 수 있습니다.

따라서 같은 이미지의 컨테이너를 여러 대 실행해도 변경한 환경 변수 값에 따라 다르게 동작할 수 있습니다.

docker container run --env TARGET=google.com diamol/ch03-web-ping

 

Dockerfile

Dockerfile이란 애플리케이션을 패키징하기 위한 스크립트로 일련의 인스트럭션으로 구성되어 있으며, 실행 결과로 도커 이미지가 생성됩니다.

FROM diamol/node

ENV TARGET="blog.sixeyed.com"
ENV METHOD="HEAD"
ENV INTERVAL="3000"

WORKDIR /web-ping
COPY app.js .

CMD ["node", "/web-ping/app.js"]

위는 Dockerfile 스크립트 예시로 자주 사용되는 인스트럭션은 다음과 같습니다.

  • FROM - 새로운 빌드 단계를 초기화하고 기본 이미지를 설정, 모든 이미지는 다른 이미지로부터 출발하며 
  • ENV - 환경 변수 값 지정
  • WORKDIR - 컨테이너 이미지 파일 시스템에 디렉터리 생성 후 해당 디렉터리를 작업 디렉터리로 지정
  • COPY - 로컬 파일 시스템의 파일 혹은 디렉터리를 컨테이너 이미지로 복사, [원본경로] [복사경로] 형식으로 지정
  • CMD - 도커가 이미지로부터 컨테이너 실행시 실행할 명령어 지정

 

컨테이너 이미지 빌드

이미지 빌드시 Dockerfile 말고도 이미지 이름, 패키징에 필요한 파일 경로를 추가로 지정해야 합니다.

아래 build 명령어 실행시 Dockerfile 스크립트의 인스트럭션이 순차적으로 실행되며 --tag 플래그로 이미지 이름을 지정하고  .은 Dockerfile 및 이미지에 포함시킬 파일 경로인 컨텍스트를 지정했습니다.

docker image build --tag web-ping .

 

도커 이미지, 이미지 레이어 관계

도커 이미지는 이미지 레이어가 모인 논리적 대상으로, Dockerfile 스크립트의 인스트럭션과 1:1 관계를 가집니다.

이미지 레이어는 여러 이미지와 컨테이너에서 공유되기에 예를 들어 Node.js 애플리케이션이 실행되는 컨테이너가 여러 개라면 해당 컨테이너들은 모두 Node.js 런타임이 있는 이미지 레이어를 공유합니다.

결론적으로, 캐시 덕분에 사용되는 디스크 용량이 절약되고 대체로 런타임 같은 기반 레이어를 공유하는 애플리케이션이 많을 수록 절약이 많이 됩니다.

또한 공유되는 이미지 레이어가 수정될 수 있다면 공유하는 이미지에도 영향이 가기에 도커는 이미지 레이어를 읽기 전용으로 생성해 문제를 예방합니다.

 

이미지 레이어 캐시를 이용한 Dockerfile 스크립트 최적화

애플리케이션의 일부 파일을 수정 후, 재빌드시 새로운 이미지 레이어가 생성됩니다. 도커의 이미지 레이어는 특정한 순서대로만 배치하기에 중간 레이어 변경시, 변경된 레이어 위에 오는 레이어들은 재사용이 불가합니다.

Dockerfile 인스트럭션은 각각 이미지 레이어와 1:1로 연결되며, 해시값을 이용해 캐시에 일치하는 레이어가 있다면 이전 캐시 레이어를 재사용합니다.

이때 해시값은 인스트럭션과 인스트럭션에 의해 복사된 파일 내용으로 계산되며, 캐시 레이어가 없다면 해당 인스트럭션이 실행됩니다. 그 다음 인스트럭션은 수정 사항이 없어도 모두 실행됩니다.

따라서 Dockerfile 스크립트는 잘 수정되지 않는 인스트럭션에서 자주 수정되는 순으로 배치해 캐시에 저장된 이미지 레이어를 많이 사용함으로써 시간, 디스크 용량, 네트워크 대역폭을 절약할 수 있습니다.

 

결론

  • 환경 변수 설정을 통해 다른 환경에서도 애플케이션을 배포할 수 있도록 이식성 있는 도커 이미지를 만들 수 있음
  • 캐시된 이미지 레이어와 인스트럭션의 배치를 통한 Dockerfile 스크립트 최적화 가능

 

참고 자료

https://appmaster.io/ko/blog/dokeo-keonteineo-gaeyo

 

도커 컨테이너 개요 | AppMaster

Docker란 무엇이며 아키텍처는 무엇이며 왜 사용해야 합니까? Docker를 사용하여 클라우드에 분산 애플리케이션을 쉽게 구축하고 배포하는 방법을 배웁니다.

appmaster.io

https://www.alibabacloud.com/ko/knowledge/difference-between-container-and-virtual-machine