/
20231020 (사내 세미나) Introduction to Docker containers

20231020 (사내 세미나) Introduction to Docker containers

 

 

 

 

 

 

소개

 

Docker 컨테이너를 컨테이너화 플랫폼으로 사용하는 이점에 관해 설명합니다. Docker 플랫폼에서 제공하는 인프라에 관해 설명합니다.

현대 조직은 비즈니스를 유치 및 유지하려면 신속하게 앱을 릴리스해야 합니다. 이 요구 사항에 따라 소프트웨어 개발 및 지원 팀은 항상 시간을 절약하고 비용을 절감하는 솔루션을 확인해야 합니다. 적합한 솔루션은 배포 환경을 만들고 구성하는 데 소요되는 시간을 줄이고 소프트웨어 배포 프로세스를 간소화합니다.

소프트웨어 컨테이너화 기술을 시간 절약 및 비용 절감 솔루션으로 사용하는 아이디어가 널리 사용됩니다. 하드웨어를 구성할 필요가 없으며, 배포를 호스팅하기 위한 운영 체제 및 소프트웨어를 설치하느라 시간을 소비하지 않아도 되는 것은 컨테이너의 장점 중 하나 입니다. 컨테이너는 서로 격리되며 여러 컨테이너가 동일한 하드웨어에서 실행될 수 있습니다. 이 구성을 통해 하드웨어를 보다 효율적으로 사용하고 애플리케이션의 보안을 개선할 수 있습니다.

 

Container/ MSA/DevOps

 

 

Dockershim deprecation and AKS

컨테이너를 중심으로 기술 커뮤니티에 활력을 불어넣은 Docker의 엄청난 성공은 정말 놀라웠습니다. 컨테이너가 Kubernetes의 기반인 만큼, Docker가 플랫폼의 핵심적인 부분이었다는 것은 당연한 결과입니다. Kubernetes가 성숙해지고 커뮤니티와 고객의 요구가 커짐에 따라 dockershim(Kubernetes 플랫폼과 Docker 런타임 간의 인터페이스)을 통한 Docker와 Kubernetes의 긴밀한 결합은 진화해야 했습니다. 2020년 12월 2일, Kubernetes 1.20 릴리즈와 함께, Kubernetes는 향후 릴리즈에서 컨테이너 런타임으로 dockershim을 사용하는 Docker를 더 이상 사용하지 않는다고 발표했습니다.

곧 출시될 Kubernetes 1.24 릴리스에서는 dockershim이 제거될 예정입니다.

AKS에서 지원되는 모든 Kubernetes 버전은 Kubernetes 1.19 이상에서 기본 런타임으로 컨테이너를 사용합니다.
Windows Server 2019 노드 풀의 경우, 2021년 1월에 Kubernetes 1.23 이상에서 컨테이너를 기본 컨테이너 런타임으로 사용할 수 있게 되었다고 발표했습니다. 1.23 이전 버전의 Kubernetes 클러스터를 사용 중인 경우, 1.23에서 기본값으로 전환되기 전에 컨테이너를 활성화하여 새 노드 풀을 생성한 다음 파드를 새 풀로 이동할 수 있습니다.

 

 

 

 

Docker란 무엇인가요?

 

Docker는 컨테이너를 개발, 제공 및 실행하는 데 사용되는 컨테이너화 플랫폼입니다. Docker는 하이퍼바이저를 사용하지 않으며, 애플리케이션을 개발하고 테스트하는 경우 데스크톱 또는 노트북에서 Docker를 실행할 수 있습니다. Docker의 데스크톱 버전은 Linux, Windows 및 macOS를 지원합니다. 프로덕션 시스템의 경우 Linux 및 Microsoft Windows Server 2016 이상의 여러 변형을 포함한 서버 환경에 Docker를 사용할 수 있습니다. Azure를 포함한 많은 클라우드가 Docker를 지원합니다.

Docker 컨테이너 둘러보기를 시작하기 전에 팀에서 애플리케이션을 개발하고 배포하는 방법을 살펴보겠습니다. 또한 팀이 직면하는 몇 가지 문제에 대해 간략하게 논의합니다.

일반적으로 회사에서 애플리케이션을 개발하고 관리하는 프로세스에는 팀이 하나 이상 포함됩니다. 소프트웨어를 만드는 개발 팀과 이 애플리케이션의 배포를 담당하는 운영 팀이 있습니다. 운영 팀은 애플리케이션 호스팅 인프라의 관리도 담당합니다.

예를 들어, 앱 개발 및 퍼블리싱 프로세스 중에 여러 가지 환경에서 애플리케이션을 호스트합니다. 먼저 개발 팀은 개발 환경에서 소프트웨어를 개발하고 테스트합니다. 여기에서 소프트웨어는 QA(품질 보증) 환경에 배포된 후 사전 프로덕션 및 최종 프로덕션 환경에 배포됩니다.

앞의 시나리오에서 고려해야 할 몇 가지 과제가 있습니다.

  • 호스팅 환경 관리

    종류와 관계없이 모든 환경에는 소프트웨어 및 하드웨어 관리가 둘 다 필요합니다. 각 환경에 설치된 소프트웨어 및 구성된 하드웨어가 모두 동일한지 확인해야 합니다. 또한 일관되고 쉽게 재현할 수 있는 방식으로 환경별로 네트워크 액세스, 데이터 스토리지 및 보안과 같은 측면을 구성해야 합니다.

     

 

  • 소프트웨어 제공의 연속성

    환경에 애플리케이션을 배포하는 작업은 일관되게 수행해야 합니다. 각 배포 패키지에는 모든 시스템 패키지, 이진 파일, 라이브러리, 구성 파일 및 모든 기능을 갖춘 애플리케이션을 보장하는 기타 항목이 포함되어야 합니다. 또한 이 종속성이 모두 소프트웨어 버전 및 아키텍처와 일치하는지 확인해야 합니다.

     

  • 효율적인 하드웨어 사용

    배포된 각 애플리케이션은 동일한 하드웨어에서 실행되는 다른 애플리케이션과 격리된 방식으로 실행해야 합니다. 서버당 애플리케이션을 두 개 이상 실행하여 서로 성능을 저하하지 않고 리소스를 최대한 활용하려고 합니다.

     

  • 애플리케이션 이동성

    애플리케이션 이동성이 필수적인 이유는 다양합니다. 호스팅 환경에서 오류가 발생하거나 애플리케이션 규모를 확장해야 합니다. 두 경우에 모두 잠재적인 결과는 새 환경에 소프트웨어를 다시 배포하는 것입니다. 기본 인프라가 서로 다른 경우에도 한 호스트에서 다른 호스트로 소프트웨어를 이동하려고 합니다. 이 애플리케이션 이동은 고객의 가동 중지 시간을 줄이기 위해 최대한 빨리 이루어져야 합니다.

 

이 과제를 해결하는 데 도움이 되는 Docker 기능을 살펴보기 전에 몇 가지 개념을 설명하고 Docker 아키텍처의 간략한 개요를 살펴보겠습니다.

 

 

컨테이너란?

컨테이너는 소프트웨어 패키지를 빌드하고 실행할 수 있는 격리된 환경입니다. 이 소프트웨어 패키지에는 모든 컴퓨팅 환경에서 빠르고 안정적으로 애플리케이션을 실행하기 위한 코드 및 모든 종속성이 포함됩니다. 이 패키지를 컨테이너 이미지라고 합니다.

컨테이너 이미지는 애플리케이션을 배포하는 데 사용하는 단위가 됩니다.

 

 

 

VM vs Container

 

전통적인 배포 시대: 초기 조직은 애플리케이션을 물리 서버에서 실행했었다. 한 물리 서버에서 여러 애플리케이션의 리소스 한계를 정의할 방법이 없었기에, 리소스 할당의 문제가 발생했다. 예를 들어 물리 서버 하나에서 여러 애플리케이션을 실행하면, 리소스 전부를 차지하는 애플리케이션 인스턴스가 있을 수 있고, 결과적으로는 다른 애플리케이션의 성능이 저하될 수 있었다. 이에 대한 해결책은 서로 다른 여러 물리 서버에서 각 애플리케이션을 실행하는 것이 있다. 그러나 이는 리소스가 충분히 활용되지 않는다는 점에서 확장 가능하지 않았으므로, 물리 서버를 많이 유지하기 위해서 조직에게 많은 비용이 들었다.

 

가상화된 배포 시대:해결책으로 가상화가 도입되었다. 이는 단일 물리 서버의 CPU에서 여러 가상 시스템 (VM)을 실행할 수 있게 한다. 가상화를 사용하면 VM간에 애플리케이션을 격리하고 애플리케이션의 정보를 다른 애플리케이션에서 자유롭게 액세스 할 수 없으므로, 일정 수준의 보안성을 제공할 수 있다.

가상화를 사용하면 물리 서버에서 리소스를 보다 효율적으로 활용할 수 있으며, 쉽게 애플리케이션을 추가하거나 업데이트할 수 있고 하드웨어 비용을 절감할 수 있어 더 나은 확장성을 제공한다. 가상화를 통해 일련의 물리 리소스를 폐기 가능한(disposable) 가상 머신으로 구성된 클러스터로 만들 수 있다.

각 VM은 가상화된 하드웨어 상에서 자체 운영체제를 포함한 모든 구성 요소를 실행하는 하나의 완전한 머신이다.

 

컨테이너 개발 시대: 컨테이너는 VM과 유사하지만 격리 속성을 완화하여 애플리케이션 간에 운영체제(OS)를 공유한다. 그러므로 컨테이너는 가볍다고 여겨진다. VM과 마찬가지로 컨테이너에는 자체 파일 시스템, CPU 점유율, 메모리, 프로세스 공간 등이 있다. 기본 인프라와의 종속성을 끊었기 때문에, 클라우드나 OS 배포본에 모두 이식할 수 있다.

컨테이너는 다음과 같은 추가적인 혜택을 제공하기 때문에 인기가 있다.

  • 기민한 애플리케이션 생성과 배포: VM 이미지를 사용하는 것에 비해 컨테이너 이미지 생성이 보다 쉽고 효율적임.

  • 지속적인 개발, 통합 및 배포: 안정적이고 주기적으로 컨테이너 이미지를 빌드해서 배포할 수 있고 (이미지의 불변성 덕에) 빠르고 효율적으로 롤백할 수 있다.

  • 개발과 운영의 관심사 분리: 배포 시점이 아닌 빌드/릴리스 시점에 애플리케이션 컨테이너 이미지를 만들기 때문에, 애플리케이션이 인프라스트럭처에서 분리된다.

  • 가시성(observability): OS 수준의 정보와 메트릭에 머무르지 않고, 애플리케이션의 헬스와 그 밖의 시그널을 볼 수 있다.

  • 개발, 테스팅 및 운영 환경에 걸친 일관성: 랩탑에서도 클라우드에서와 동일하게 구동된다.

  • 클라우드 및 OS 배포판 간 이식성: Ubuntu, RHEL, CoreOS, 온-프레미스, 주요 퍼블릭 클라우드와 어디에서든 구동된다.

  • 애플리케이션 중심 관리: 가상 하드웨어 상에서 OS를 실행하는 수준에서 논리적인 리소스를 사용하는 OS 상에서 애플리케이션을 실행하는 수준으로 추상화 수준이 높아진다.

  • 느슨하게 커플되고, 분산되고, 유연하며, 자유로운 마이크로서비스: 애플리케이션은 단일 목적의 머신에서 모놀리식 스택으로 구동되지 않고 보다 작고 독립적인 단위로 쪼개져서 동적으로 배포되고 관리될 수 있다.

  • 리소스 격리: 애플리케이션 성능을 예측할 수 있다.

  • 자원 사용량: 리소스 사용량: 고효율 고집적.

 

 

VM과 Container 주요 차이점

가상 머신은 하이퍼바이저라는 소프트웨어를 사용하여 소프트웨어로 에뮬레이트된 하드웨어와 그 아래에 있는 실제 하드웨어를 연결합니다. 모든 의도와 목적에 있어서 가상 머신은 실제 컴퓨터입니다. 실제 컴퓨터이기 때문에 한 번에 여러 개의 앱을 실행할 수 있으며, 실행 중인 호스트를 보거나 호스트와 상호 작용할 수 없습니다.

앞서 컨테이너는 컨트롤 그룹과 네임스페이스를 사용한다고 언급했습니다. 네임스페이스는 리눅스 시스템에서 컨테이너가 액세스할 수 있는 것을 지정하고, 컨트롤 그룹은 컨테이너가 사용할 수 있는 특정 리소스의 양을 지정합니다.

컨테이너는 컨테이너 런타임과 함께 작동하여 이러한 속성을 구성합니다. 컨테이너는 하드웨어를 에뮬레이션하지 않습니다. 컨테이너는 머신의 다른 앱과 동일한 하드웨어를 사용합니다. 따라서 컨테이너는 잠재적으로 호스트와 상호 작용할 수 있지만, 컨테이너가 호스트와 상호 작용하는 방식을 제어할 수 있다는 것입니다.

 

 

<출처> https://github.com/docker/labs/blob/master/beginner/chapters/alpine.md

 

 

1. 첫 컨테이너 실행하기

 

 Alpine Linux(경량 리눅스 배포판)를 실행하고 도커 실행 명령어를 사용해 보겠습니다.

202310-DockerBasic# docker pull alpine Using default tag: latest latest: Pulling from library/alpine 96526aa774ef: Pull complete Digest: sha256:eece025e432126ce23f223450a0326fbebde39cdf496a85d8c016293fc851978 Status: Downloaded newer image for alpine:latest 202310-DockerBasic# docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest 8ca4688f4f35 2 weeks ago 7.34MB zeroacrdemo.azurecr.io/appmod-contapp latest 8629e2fcf972 7 months ago 121MB zeroacrtf.azurecr.io/appmod-contapp latest 8629e2fcf972 7 months ago 121MB

 

pull 명령은 Docker 레지스트리에서 알파인 이미지를 가져와 시스템에 저장합니다. docker images 명령을 사용하여 시스템의 모든 이미지 목록을 볼 수 있습니다.

Docker 아키텍처 및 용어

 

Images - 컨테이너를 생성하는 데 사용되는 애플리케이션의 파일 시스템 및 구성입니다. Docker 이미지에 대해 자세히 알아보려면 docker inspect alpine을 실행하세요.

Containers - Docker 이미지의 인스턴스 실행 - 컨테이너는 실제 애플리케이션을 실행합니다. 컨테이너에는 애플리케이션과 애플리케이션의 모든 종속성이 포함됩니다. 컨테이너는 다른 컨테이너와 커널을 공유하며 호스트 OS의 사용자 공간에서 격리된 프로세스로 실행됩니다.

Docker client - 사용자가 Docker 데몬과 상호 작용할 수 있는 명령줄 도구입니다.

Docker daemon - 호스트에서 실행되는 백그라운드 서비스로, Docker 컨테이너의 빌드, 실행 및 배포를 관리합니다.

Docker Registry - Docker 이미지의 레지스트리입니다. 

 

  1. 이미지 빌드 요청이 전송되거나(docker 빌드) 미리 빌드된 이미지를 사용하라는 요청이 전송됩니다(

docker pull, docker run).

  1. 두 번째 단계는 실행할 이미지를 찾거나 실제로 빌드하는 것 입니다.

  1. 이미지가 확인 및 검증(체크섬 비교)된 후 호스트 머신에 저장되어 Docker 데몬에서 사용할 수 있게 됩니다.

  1. 이 부분은 Docker 실행이 명시적으로 실행될 때만 발생합니다. 2단계와 3단계의 이미지로 Docker 컨테이너가 빌드되며, 호스팅 OS에 관계없이 호스트 머신에서 실행됩니다.

 

Docker 실행

이제 이 이미지를 기반으로 Docker 컨테이너를 실행해 보겠습니다. 이를 위해 docker 실행 명령을 사용합니다.

202310-DockerBasic# docker run alpine ls -l total 56 drwxr-xr-x 2 root root 4096 Sep 28 11:18 bin drwxr-xr-x 5 root root 340 Oct 19 01:51 dev drwxr-xr-x 1 root root 4096 Oct 19 01:51 etc drwxr-xr-x 2 root root 4096 Sep 28 11:18 home drwxr-xr-x 7 root root 4096 Sep 28 11:18 lib drwxr-xr-x 5 root root 4096 Sep 28 11:18 media drwxr-xr-x 2 root root 4096 Sep 28 11:18 mnt drwxr-xr-x 2 root root 4096 Sep 28 11:18 opt dr-xr-xr-x 245 root root 0 Oct 19 01:51 proc drwx------ 2 root root 4096 Sep 28 11:18 root drwxr-xr-x 2 root root 4096 Sep 28 11:18 run drwxr-xr-x 2 root root 4096 Sep 28 11:18 sbin drwxr-xr-x 2 root root 4096 Sep 28 11:18 srv dr-xr-xr-x 11 root root 0 Oct 19 01:51 sys drwxrwxrwt 2 root root 4096 Sep 28 11:18 tmp drwxr-xr-x 7 root root 4096 Sep 28 11:18 usr drwxr-xr-x 12 root root 4096 Sep 28 11:18 var

 

  1. Docker 클라이언트가 Docker 데몬에 연결합니다.

  1. 도커 데몬은 로컬 스토어에서 이미지(이 경우 알파인)를 로컬에서 사용할 수 있는지 확인하고, 그렇지 않은 경우 도커 스토어에서 다운로드합니다. (이전에 docker pull alpine을 발급했기 때문에 다운로드 단계는 필요하지 않습니다.)

  1. Docker 데몬이 컨테이너를 생성한 다음 해당 컨테이너에서 명령을 실행합니다.

  1. Docker 데몬은 명령의 출력을 Docker 클라이언트로 스트리밍합니다.

 

docker run alpine을 실행할 때 명령(ls -l)을 제공했으므로 Docker가 지정된 명령을 시작하고 목록을 볼 수 있습니다.

 

좀 더 흥미로운 것을 시도해 봅시다.

202310-DockerBasic# docker run alpine echo "hello from alpine" hello from alpine

 

이 경우, Docker 클라이언트는 알파인 컨테이너에서 echo 명령을 실행한 다음 종료했습니다. 이 모든 일이 매우 빠르게 진행되었습니다. 가상 머신을 부팅하고 명령을 실행한 다음 종료한다고 상상해 보세요. 이제 컨테이너가 빠르다고 말하는 이유를 알 수 있습니다!

다른 명령을 시도합니다.

 

it 플래그를 사용하여 실행 명령을 실행하면 컨테이너의 대화형 tty에 연결됩니다. \

실행에 대해 자세히 알아보려면 docker run --help를 사용하여 지원하는 모든 플래그 목록을 확인하세요. 더 진행하면서 도커 실행의 몇 가지 변형을 더 보게 될 것입니다.

 

 

2. 정적 웹 컨테이너 실행하기

 

Dockerfile 작성

Docker 빌드

 

Docker 실행

 

결과 확인

 

Docker 로그 확인

 

Docker 종료

 

 

Dockerfile이란?

Dockerfile은 Docker 이미지를 빌드하고 실행하는 데 사용하는 지침을 포함하는 텍스트 파일입니다. 이미지의 다음 측면을 정의합니다.

  • 새 이미지를 만드는 데 사용하는 기본 또는 부모 이미지

  • 기본 OS를 업데이트하고 추가 소프트웨어를 설치하는 명령

  • 개발된 애플리케이션과 같이 포함할 빌드 아티팩트

  • 스토리지 및 네트워크 구성과 같은 노출할 서비스

  • 컨테이너가 시작될 때 실행할 명령

이 측면을 예제 Dockerfile에 매핑하겠습니다. http://ASP.NET Core 웹 사이트용 Docker 이미지를 만든다고 가정합니다. Dockerfile은 다음 예제와 같이 표시될 수 있습니다.

 

여기서는 Dockerfile 파일 사양 또는 앞의 예제에 있는 각 명령의 세부 정보를 설명하지 않습니다. 그러나 이 파일에는 이미지 구조를 조작할 수 있는 여러 명령이 있습니다. 예를 들어 COPY 명령은 로컬 컴퓨터의 특정 폴더에서 빌드 중인 컨테이너 이미지로 콘텐츠를 복사합니다.

앞서 Docker 이미지가 unionfs을 사용한다고 언급했습니다. 이러한 각 단계는 최종 컨테이너 이미지를 빌드할 때 캐시된 컨테이너 이미지를 만듭니다. 이러한 임시 이미지는 이전 이미지 위에 레이어링되며 모든 단계가 완료되면 단일 이미지로 표시됩니다.

마지막으로, 마지막 단계인 8단계를 확인합니다. 파일의 ENTRYPOINT는 이미지에서 컨테이너를 실행한 후 실행될 프로세스를 나타냅니다. 실행할 ENTRYPOINT 또는 다른 프로세스가 없는 경우 Docker는 컨테이너가 수행할 작업이 없는 것으로 해석하고 컨테이너는 종료됩니다.