3. Software installation simplified

2024. 3. 25. 16:12Docker

이 장에서는 다음을 다룹니다:

  • 소프트웨어 식별
  • Docker Hub를 통한 소프트웨어 검색 및 설치
  • 대체 소스에서 소프트웨어 설치
  • 파일 시스템 격리 이해
  • 이미지 및 레이어 작업

 

1장과 2장은 Docker가 제공하는 새로운 개념과 추상화를 소개했습니다. 이 장은 컨테이너 파일 시스템과 소프트웨어 설치에 대해 더 깊이 파고들었습니다. 이 장은 소프트웨어 설치를 그림 3.1에 나타난 세 단계로 나눠 설명합니다.

그림 3.1 이 장에서 다루는 주제의 흐름

 

소프트웨어를 설치하는 첫 번째 단계는 설치할 소프트웨어를 식별하는 것입니다. 이미지를 통해 소프트웨어가 배포되는 것을 알고는 있지만, 정확히 어떤 이미지를 설치하려는지 Docker에게 알려야 합니다. 이미지는 리포지토리를 통해 배포되며, 이 장에서는 리포지토리와 태그가 이미지를 식별하는 데 어떻게 사용되는지를 설명합니다.

이 장에서는 Docker 이미지를 설치하는 세 가지 주요 방법을 자세히 다룹니다:

  • Docker 레지스트리 사용
  • Docker save 및 Docker load를 사용한 이미지 파일 사용
  • Dockerfile로 이미지 빌드

이 장을 읽으면서 Docker가 설치된 소프트웨어를 어떻게 격리하는지 배우게 되며, 이미지를 다룰 때 중요한 개념인 레이어에 대해 알게 될 것입니다. 레이어는 여러 가지 중요한 기능을 제공합니다. 이 장은 이미지가 작동하는 방식에 대한 섹션으로 마감됩니다. 이 지식은 이미지 퀄리티를 평가하고 이 책의 제2부에 대한 기본 기술을 확립하는 데 도움이 될 것입니다.

 

3.1 Identifying software

만약 TotallyAwesomeBlog 2.0이라는 프로그램을 설치하려면 Docker에게 어떤 것을 설치할 것인지 알려주어야 합니다. 프로그램의 이름을 지정하고, 사용하려는 버전을 지정하고, 설치하려는 소스를 지정해야 합니다. 구체적인 소프트웨어를 식별하는 방법을 배우는 것은 소프트웨어 설치의 첫 번째 단계입니다.

그림 3.2 Step 1—software identification

Docker는 이미지로부터 컨테이너를 생성합니다. 이미지는 파일입니다. 이미지는 해당 이미지로부터 생성된 컨테이너에서 사용될 파일들과 이미지에 대한 메타데이터를 포함합니다. 이 메타데이터에는 레이블, 환경 변수, 디폴트 실행 컨텍스트, 이미지에 대한 커맨드 히스토리 등이 포함됩니다. 모든 이미지는 전역적으로 고유한 식별자를 가지고 있습니다. 이 식별자는 이미지 및 컨테이너 커맨드와 함께 사용할 수 있지만 실제로는 이미지 식별자를 직접 다루는 것은 드뭅니다. 이들은 긴, 고유한 문자와 숫자의 시퀀스입니다. 이미지에 변경이 발생할 때마다 이미지 식별자가 변경됩니다. 이미지 식별자는 예측할 수 없기 때문에 작업하기 어렵습니다. 대신 사용자들은 명명된 리포지토리와 작업합니다.

 

3.1.1 What is a named repository?

Named Repository는 이미지들의 명명된 버킷입니다. 이 이름은 URL과 유사합니다. 리포지토리의 이름은 이미지가 위치한 호스트 이름, 이미지를 소유한 사용자 계정 및 짧은 이름으로 구성됩니다. 예를 들어, 이 장에서는 docker.io/dockerinaction/ch3_hello_registry라는 저장소에서 이미지를 설치할 것입니다.

그림 3.3 The Docker image repository name

 

소프트웨어에 여러 버전이 있을 수 있는 것과 마찬가지로 리포지토리는 여러 이미지들을 보유할 수 있습니다. 리포지토리의 각 이미지는 태그로 고유하게 식별됩니다. docker.io/dockerinaction/ch3_hello_registry와 같은 리포지토리의 새 버전을 릴리스한다면 v2와 같은 태그를 붙일 수 있으며, 이전 버전에는 v1을 태그할 수 있습니다. 이전 버전을 다운로드하려면 v1 태그로 해당 이미지를 명시적으로 식별할 수 있습니다.

2장에서 Docker Hub의 NGINX 저장소에서 latest 태그로 식별된 이미지를 설치했습니다. 리포지토리 이름과 태그는 복합 키 또는 일련의 비고유 구성 요소로 구성된 고유한 참조를 형성합니다. 이 예에서 이미지는 nginx:latest로 식별되었습니다. 이러한 방식으로 구성된 식별자는 때로는 원시 이미지 식별자보다 길 수 있지만 예측 가능하며 이미지의 의도를 전달합니다.

 

Docker Registry
Docker 레지스트리는 Docker 이미지를 저장하고 배포하기 위한 서버 또는 서비스입니다. 레지스트리는 이미지를 저장하는 리포지토리 역할을 하며, 사용자는 이를 통해 이미지를 push하고 pull할 수 있습니다. Docker 이미지는 애플리케이션과 그 종속성을 포함하는 경량의, 이동 가능하고, 자체적으로 충분한 실행 환경을 제공합니다. 레지스트리는 이러한 이미지들을 중앙 집중식으로 관리하고 공유하는 데 사용됩니다.

Docker 레지스트리의 주요 기능:
1. 이미지 저장: Docker 레지스트리는 다양한 이미지 버전을 저장합니다. 개발자는 애플리케이션의 여러 버전을 레지스트리에 push할 수 있습니다.
2. 이미지 공유와 재사용: 레지스트리를 통해 팀 또는 커뮤니티 멤버들이 이미지를 쉽게 공유하고 재사용할 수 있습니다. 이는 협업과 배포 프로세스를 간소화합니다.
3. 버전 관리와 배포: 레지스트리는 이미지의 버전 관리를 용이하게 하며, 지속적인 통합(CI) 및 지속적인 배포(CD) 파이프라인과 통합될 수 있습니다.

Docker 레지스트리의 유형:
1. Public 레지스트리: Docker Hub는 가장 잘 알려진 Public Docker 레지스트리입니다. 누구나 Docker Hub에 이미지를 공개적으로 호스팅하고 공유할 수 있으며, 공개 이미지는 무료로 제공됩니다. 다른 예로는 Google Container Registry (GCR), Amazon Elastic Container Registry (ECR), Microsoft Azure Container Registry (ACR) 등이 있습니다.
2. Private 레지스트리: 기업이나 조직 내부에서만 사용되는 비공개 이미지를 저장하기 위해 사설 Docker 레지스트리를 구축할 수 있습니다. 사설 레지스트리를 사용하면 조직 내부의 보안 요구 사항을 충족시키면서 이미지를 관리할 수 있습니다. Docker Registry 2.0 오픈 소스 소프트웨어를 사용하여 자체 사설 레지스트리를 구축할 수 있습니다. Docker 레지스트리는 Docker 이미지의 중앙 집중식 저장 및 배포 메커니즘을 제공하며, 개발 및 운영 환경에서의 애플리케이션 배포를 간소화하는 데 중요한 역할을 합니다.

 

Docker에서 Named Repository는 이미지를 구분하기 위한 명명된 버킷으로 사용됩니다.
이미지를 구분하기 위한 명명된 버킷이란 표현은 Docker 이미지를 구조화하고 관리하기 위한 방법을 설명합니다.
이 개념을 이해하기 위해서는 Docker 이미지와 리포지토리의 관계를 이해할 필요가 있습니다.

Docker 이미지
Docker 이미지는 컨테이너를 생성하기 위한 템플릿입니다. 이 이미지는 필요한 프로그램, 라이브러리, 종속성, 설정 파일 등을 포함합니다. 사용자는 이 이미지를 기반으로 하여 동일한 환경을 가진 컨테이너를 어디서든 쉽게 생성할 수 있습니다.

Docker 리포지토리
Docker 리포지토리는 관련 Docker 이미지들의 집합을 의미합니다. 한 리포지토리 내에서 여러 버전의 이미지를 태그를 사용하여 관리할 수 있습니다. 예를 들어, ubuntu 도커 리포지토리에는 ubuntu:18.04, ubuntu:20.04와 같이 다양한 버전의 Ubuntu 이미지가 태그와 함께 저장될 수 있습니다.

Named Repository의 의미
Named Repository는 특정 이름을 가진 리포지토리를 의미합니다. 이 이름을 통해 사용자는 Docker Hub나 다른 Docker 이미지 저장소에서 필요한 이미지를 쉽게 찾고, 다운로드할 수 있습니다. 예를 들어, nginx, mysql, redis와 같이 이름이 지정된 리포지토리에서는 각각 Nginx 웹 서버, MySQL 데이터베이스, Redis 캐시 스토어 등에 해당하는 Docker 이미지들을 찾을 수 있습니다. 이러한 방식으로, Named Repository는 관련 이미지를 조직하고, 검색하며, 사용하는 데 있어서 중요한 역할을 합니다. 사용자는 이러한 명명된 리포지토리를 통해 필요한 이미지를 정확하고 신속하게 찾아서 사용할 수 있게 됩니다.

 

docker.io는 Docker의 공식 이미지 저장소인 Docker Hub의 URL입니다. Docker Hub는 Docker 이미지를 찾고, 공유하고, 관리할 수 있는 중앙 집중식 서비스입니다. 여러분이 Docker를 사용하여 컨테이너화된 애플리케이션을 배포하고자 할 때, 필요한 이미지를 Docker Hub에서 검색하거나 자신의 이미지를 공유할 수 있습니다. Docker Hub는 공식 이미지 뿐만 아니라 커뮤니티가 생성한 이미지도 포함하고 있어, 다양한 소프트웨어와 애플리케이션을 컨테이너화하는 데 필요한 리소스를 제공합니다.

 

www.docker.com은 Docker의 공식 웹사이트 주소입니다. 이 웹사이트는 Docker의 제품, 서비스, 기술 문서, 지원, 커뮤니티 포럼 등 Docker와 관련된 다양한 정보를 제공합니다. Docker Hub와는 다르게, www.docker.com은 Docker의 전반적인 정보와 회사 소개, 제품 설명, 기술 지원 정보 등을 제공하는 공식 기업 웹사이트입니다. Docker Hub의 웹사이트 주소는 hub.docker.com이며, 이곳에서 Docker 이미지를 검색하고, 공유하며, 다운로드할 수 있습니다. Docker Hub는 Docker 이미지를 저장하고 관리하는 서비스를 제공하며, www.docker.com과는 별개로 운영됩니다. 하지만 두 사이트 모두 Docker Inc.에 의해 관리되고 있습니다.

 

3.1.2 Using tags

태그는 이미지를 고유하게 식별하는 중요한 방법이면서 유용한 별칭을 만드는 편리한 방법입니다. 태그는 저장소의 단일 이미지에만 적용될 수 있지만, 단일 이미지에는 여러 태그를 적용할 수 있습니다. 이를 통해 저장소 소유자는 유용한 버전 관리 또는 기능 태그를 만들 수 있습니다.

예를 들어 Docker Hub의 Java 저장소는 다음과 같은 태그를 유지합니다:
11-stretch, 11-jdk-stretch, 11.0-stretch, 11.0-jdk-stretch, 11.0.4-stretch 및 11.0.4-jdk-stretch. 

※ 도커 허브에서 "stretch"는 보통 Debian 리눅스 배포판의 코드명을 의미합니다. Debian은 안정성 중심의 리눅스 배포판으로, 각 버전에 토이 스토리(Toy Story) 캐릭터 이름을 코드명으로 사용합니다. "Stretch"는 Debian 9 버전을 나타냅니다.

 

이 모든 태그는 동일한 이미지에 적용됩니다. 이 이미지는 현재 Java 11 개발 키트(JDK)를 Debian Stretch 기본 이미지에 설치하여 빌드됩니다. 현재 Java 11 패치 버전이 증가하고 관리자가 Java 11.0.5를 릴리스하면 11.0.4 태그는 이 세트에서 11.0.5로 대체됩니다. Java 11의 어떤 마이너 또는 패치 버전을 실행 중인지 중요하다면 해당 태그 변경을 계속 주시해야 합니다. Java 11의 가장 최신 버전을 항상 실행 중이라면 11-stretch로 태그된 이미지를 사용하면 됩니다. 이 태그는 항상 Java 11의 최신 릴리스에 할당되어 있어야 합니다. 이러한 태그를 통해 사용자는 큰 유연성을 가집니다.

또한 다른 소프트웨어 구성을 가진 이미지에 대해 다른 태그를 볼 수 있습니다. 예를 들어, 우리는 freegeoip라는 오픈 소스 프로그램에 대해 두 가지 이미지를 릴리스했습니다. 이는 네트워크 주소와 관련된 대략적인 지리적 위치를 가져오는 데 사용할 수 있는 웹 응용 프로그램입니다. 하나의 이미지는 소프트웨어의 디폴트 구성을 사용하도록 구성되어 있습니다. 이는 직접 링크하여 독립적으로 실행될 수 있도록 설계되었습니다. 두 번째 이미지는 웹 로드 밸런서 뒤에서 실행되도록 구성되어 있습니다. 각 이미지에는 필요한 기능을 쉽게 식별할 수 있도록 고유한 태그가 있습니다.

 

TIP: 소프트웨어를 설치할 때는 반드시 리포지토리에서 제공하는 태그를 주의 깊게 살펴보세요. 많은 리포지토리가 종종 다양한 운영 체제에서 또는 다양한 사용 사례를 지원하기 위해 전체 또는 축소된 버전으로 소프트웨어의 여러 릴리스를 게시합니다. 의 문서를 참고하여 리포지토리의 태그가 의미하는 것과 이미지 릴리스 관행에 대한 구체적인 내용을 확인하세요.

 

Docker를 사용하기 위한 소프트웨어를 식별하는 것으로 이 내용을 마칩니다. 이 지식을 바탕으로 Docker를 사용하여 소프트웨어를 찾고 설치할 준비가 되었습니다.

 

3.2 Finding and installing software

소프트웨어를 식별하는 방법은 리포지토리 이름으로 알 수 있지만, 원하는 리포지토리를 어떻게 찾을 수 있을까요? 신뢰할 수 있는 소프트웨어를 발견하는 것은 복잡한 일이며, Docker를 사용하여 소프트웨어를 설치하는 데 필요한 두 번째 단계입니다. 

그림 3.4 Step 2-locating repositories

 

이미지를 찾는 가장 쉬운 방법은 index를 사용하는 것입니다. Index들은 리포지토리를 카탈로그화(분류화)하는 검색 엔진입니다. Public Docker 인덱스는 여러 개 있지만, 디폴트로 Docker는 Docker Hub라는 이름의 인덱스와 통합되어 있습니다.
Docker Hub는 Docker Inc.에서 운영하는 웹 사용자 인터페이스와 함께 레지스트리 및 인덱스입니다. Docker의 기본 레지스트리 및 인덱스이며 호스트는 docker.io에 위치합니다. 대체 레지스트리를 지정하지 않고 docker pull 또는 docker run 명령을 사용할 경우 Docker는 디폴트로 Docker Hub에서 저장소를 찾습니다. Docker Hub는 Docker를 더 유용하게 만들어줍니다.
Docker Inc.는 Docker가 오픈 생태계가 되도록 노력하고 있습니다. 고유한 레지스트리를 실행할 수 있는 퍼블릭 이미지를 게시하며, docker 커맨드 라인 도구를 쉽게 대체 레지스트리를 사용하도록 구성할 수 있습니다. 이 장의 나중 부분에서는 Docker와 함께 제공되는 대체 이미지 설치 및 배포 도구에 대해 다룹니다. 하지만 먼저, 다음 섹션에서는 디폴트 도구 세트를 최대한 활용할 수 있도록 Docker Hub의 사용 방법을 다룹니다.

 

Docker 생태계(에코시스템)
Docker 생태계는 Docker 기술을 중심으로 구축된 도구, 플랫폼, 어플리케이션, 그리고 커뮤니티의 집합을 의미합니다. 이 생태계는 개발자와 시스템 관리자가 컨테이너를 사용하여 어플리케이션을 더 효율적으로 개발, 배포, 실행할 수 있도록 지원합니다. Docker 생태계의 핵심 구성 요소는 다음과 같습니다:

Docker Engine 
Docker의 핵심 컴포넌트로, 컨테이너 생성, 실행, 관리를 담당합니다.

Docker Hub
Docker 이미지를 공유할 수 있는 중앙 집중형 서비스로, 개발자들이 이미지를 업로드하고 공유할 수 있으며, 다른 사람들이 만든 이미지를 검색하고 사용할 수 있습니다.

Docker Compose
여러 컨테이너로 구성된 어플리케이션을 정의하고 실행하기 위한 도구입니다. 하나의 YAML 파일 안에 어플리케이션의 서비스, 네트워크, 볼륨 등을 정의할 수 있습니다.

Docker Swarm
Docker 기반의 컨테이너를 클러스터링하기 위한 도구로, 여러 Docker 호스트를 하나의 가상 호스트처럼 관리할 수 있게 해줍니다.

Docker Desktop
macOS와 Windows에서 Docker를 사용할 수 있게 해주는 애플리케이션으로, 개발자가 로컬 환경에서 컨테이너를 쉽게 생성하고 관리할 수 있도록 지원합니다.

커뮤니티 및 서드파티 도구
Kubernetes 같은 오케스트레이션 도구, Portainer, Rancher 같은 관리 도구, 그리고 보안, 네트워킹, 모니터링을 위한 다양한 서드파티 솔루션 등이 포함됩니다.


커뮤니티
개발자, 사용자, 기업들로 구성된 활발한 커뮤니티가 Docker 생태계의 중요한 부분을 차지합니다. 사용자들은 문제 해결, 최신 정보 공유, 피드백 제공을 위해 다양한 포럼, 블로그, 컨퍼런스, 소셜 미디어 채널 등에서 활동합니다.


Docker 생태계는 컨테이너 기술의 대중화를 주도하며, 모던 애플리케이션 개발과 배포 방식을 혁신적으로 변화시켰습니다. 이를 통해 개발자와 기업들은 어플리케이션의 이식성, 확장성, 관리 편의성을 크게 향상시킬 수 있게 되었습니다.

 

Docker Index
Docker 인덱스는 Docker 이미지의 리포지토리를 찾고, 사용자 인증을 처리하는 중앙 서비스입니다. 하지만, "Docker 인덱스" 용어는 초기 Docker 에코시스템(생태)에서 사용되던 개념으로, 현재는 주로 Docker Hub와 같은 컨테이너 레지스트리 서비스를 지칭하는 데 사용됩니다.

초기 Docker 인덱스
초기 Docker 에코시스템에서, Docker 인덱스는 Docker 이미지와 관련된 메타데이터를 저장하고 검색하는 역할을 했습니다. 사용자는 Docker 인덱스를 통해 이미지를 검색하고, Docker 레지스트리에서 이미지를 pull 할 수 있었습니다. 또한, 인덱스는 사용자 인증과 이미지의 공개/비공개 설정을 관리했습니다.

현재 Docker Hub
시간이 지나면서, Docker 인덱스의 개념은 Docker Hub로 진화했습니다. Docker Hub는 세계 최대의 Public Docker 컨테이너 이미지 레지스트리로, 다음과 같은 기능을 제공합니다:
1. 도커 이미지 리포지토리: 사용자는 Docker Hub에 자신의 컨테이너 이미지를 저장하고 관리할 수 있습니다. 또한, 공개적으로 사용 가능한 수많은 공식 이미지와 커뮤니티 이미지에 접근할 수 있습니다.
2. 도커 이미지 검색과 공유: Docker Hub는 사용자들이 이미지를 쉽게 찾고 공유할 수 있는 플랫폼을 제공합니다. 사용자는 특정 이미지에 대한 정보를 검색하고, 필요에 따라 이미지를 pull하여 사용할 수 있습니다.
3. 버전 관리와 자동 빌드: Docker Hub는 이미지의 버전을 관리하고, GitHub 또는 Bitbucket과 같은 소스 코드 저장소와 통합하여 이미지의 자동 빌드 및 업데이트를 지원합니다.
4. 사용자 인증과 권한 관리: Docker Hub는 사용자 인증 기능을 제공하며, 이미지에 대한 접근 권한을 설정할 수 있습니다. 이를 통해 비공개 이미지를 안전하게 관리할 수 있습니다.

Docker 인덱스는 이제 Docker Hub와 같은 현대적인 컨테이너 레지스트리 서비스의 역할을 수행하는 데 사용되는 용어로 간주될 수 있습니다. 이러한 서비스는 컨테이너 이미지의 저장, 검색, 공유, 그리고 배포를 간소화하는 중요한 역할을 합니다.

 

3.2.1 Working with Docker registries from the command line

도커 이미지 작성자는 Docker Hub와 같은 레지스트리에 이미지를 게시할 때 두 가지 방법을 사용할 수 있습니다:

  • 독립적으로 빌드한 이미지를 커맨드 라인을 사용하여 푸시합니다.
  • Dockerfile을 공개적으로 사용 가능하게 만들고 지속적 빌드 시스템을 사용하여 이미지를 게시합니다. Dockerfile은 이미지를 빌드하기 위한 스크립트입니다. 이러한 자동화된 빌드에서 생성된 이미지는 해당 이미지를 설치하기 전에 Dockerfile의 내용으로 이미지를 체크할 수 있기 때문에 선호됩니다.

대부분의 레지스트리는 이미지 작성자가 게시하기 전에 인증을 요구하고 업데이트되는 리포지토리에 대한 권한 확인을 진행합니다. 이러한 경우에는 docker login 명령을 사용하여 Docker Hub와 같은 특정 레지스트리 서버에 로그인할 수 있습니다. 로그인한 후에는 개인 리포지토리에서 pull을 수행하고 이미지에 태그를 지정하며 제어하는 모든 리포지토리에 push할 수 있습니다. 7장에서는 이미지에 태그를 지정하고 push하는 내용을 다룹니다.

docker login을 실행하면 Docker.com credential을 입력하라는 프롬프트가 나타납니다. 자격 증명을 제공하면 커맨드 라인 클라이언트가 인증되고 개인 저장소에 액세스할 수 있게 됩니다. 계정 작업을 마치면 docker logout 명령으로 로그아웃할 수 있습니다. 다른 레지스트리를 사용하는 경우 docker login 및 docker logout 하위 명령에 서버 이름을 아규먼트로 지정할 수 있습니다.

 

3.2.2 Using alternative registries

Docker는 누구나 실행할 수 있는 레지스트리 소프트웨어를 제공합니다. AWS(ECR) 및 Google(GCR)을 비롯한 클라우드 회사들은 private 레지스트리를 제공하며, Docker EE를 사용하는 회사나 인기 있는 Artifactory 프로젝트를 사용하는 회사는 이미 private 레지스트리를 보유하고 있습니다. 오픈 소스 구성 요소로 레지스트리를 실행하는 방법은 8장에서 다루지만, 조기에 이를 사용하는 방법을 익히는 것이 중요합니다.

대체 레지스트리를 사용하는 것은 간단합니다. 추가 구성이 필요하지 않습니다. 레지스트리의 주소만 있으면 됩니다. 다음 커맨드는 대체 레지스트리에서 다른 "Hello, World" 유형의 예제를 다운로드합니다:

docker pull quay.io/dockerinaction/ch3_hello_registry:latest

 

Quay.io
Quay.io는 CoreOS 팀에 의해 개발되었으며, 현재는 Red Hat이 소유하고 있는 컨테이너 이미지 레지스트리 서비스입니다. Docker 이미지뿐만 아니라 OCI(Open Container Initiative) 포맷의 이미지도 지원합니다. Quay.io는 공개 또는 비공개로 이미지를 저장하고 배포할 수 있는 클라우드 기반 서비스로, 다양한 보안 기능과 함께 엔터프라이즈급 컨테이너 이미지 호스팅을 제공합니다.

Quay.io의 주요 특징:
1. 보안과 접근 제어: Quay.io는 이미지 스캔을 통해 취약점을 식별하고, 자세한 보안 알림을 제공합니다. 또한, 세밀한 접근 제어를 통해 사용자 및 팀이 이미지에 대한 접근 권한을 관리할 수 있게 해줍니다.
2. 자동 빌드 및 배포: GitHub, Bitbucket, GitLab과 같은 VCS(버전 관리 시스템)와의 통합을 통해 소스 코드 변경사항이 자동으로 빌드되고 이미지로 푸시될 수 있습니다. 이는 지속적 통합(CI) 및 지속적 배포(CD) 작업을 간소화합니다.
3. 프라이빗 및 퍼블릭 레지스트리 지원: Quay.io는 사용자가 비공개로 자신만의 컨테이너 이미지를 관리할 수 있는 프라이빗 레지스트리 기능을 제공합니다. 동시에 공개 이미지를 호스팅하여 넓은 커뮤니티와 공유할 수도 있습니다.
4. 고가용성과 성능: Quay.io는 높은 가용성을 제공하며, 글로벌 CDN을 통해 전 세계 어디서나 빠르게 이미지를 다운로드할 수 있습니다.
5. 엔터프라이즈급 지원: Quay.io는 엔터프라이즈급 기능을 제공하며, 큰 규모의 조직이나 프로젝트에서 요구하는 다양한 요구 사항을 충족시킬 수 있도록 설계되었습니다.

Quay.io는 개발자, 팀, 기업이 컨테이너 이미지를 안전하게 저장하고, 관리하며, 배포할 수 있는 강력한 플랫폼입니다. Red Hat이 관리하는 서비스로서, 오픈소스 프로젝트와 엔터프라이즈 환경 모두에 적합한 다양한 기능을 제공합니다.

 

레지스트리 주소는 섹션 3.1에서 다룬 전체 리포지토리 명세의 일부입니다. 전체 패턴은 다음과 같습니다:

[REGISTRYHOST:PORT/][USERNAME/]NAME[:TAG]

 

도커는 디폴트로 도커 레지스트리로써 도커 허브를 사용하기 때문에, 도커 허브 레지스트리 주소(docker.io)를 생략하였지만, 도커 허브가 아닌 다른 도커 레지스트리(위 예에서는, quay.io 레지스트리)에서 도커 이미지를 가져 오려고 할 때는 해당 도커 레지스트리 호스트 주소를 지정합니다. 경우에 따라 레지스트리를 사용하는 것이 인증 단계를 필요로 할 수 있습니다. 이런 경우를 만나면 문서나 레지스트리를 구성한 그룹에 문의하여 자세한 내용을 알아보십시오. hello-registry 이미지를 설치한 후에는 다음 명령을 사용하여 제거하십시오:

docker rmi quay.io/dockerinaction/ch3_hello_registry

 

도커 레지스트리는 강력합니다. 사용자가 이미지 저장 및 전송을 위한 제어를 양도할 수 있게 해줍니다. 그러나 자체 레지스트리를 실행하는 것은 복잡할 수 있으며 배포 인프라에 잠재적인 단일 장애 지점을 만들 수 있습니다. 사용자 정의 레지스트리를 실행하는 것이 사용 사례에 다소 복잡하게 들리는 경우, 그리고 타사 배포 도구를 사용할 수 없는 경우 이미지를 직접 파일에서로드하는 것을 고려할 수 있습니다.

 

3.2.3 Working with images as files

도커는 Docker 허브로부터 이미지를 파일로 로드하기 위한 명령어를 제공합니다. 이 도구를 사용하여 다른 경로를 통해 획득한 이미지를 로드할 수 있습니다. 회사가 이미지를 중앙 파일 서버를 통해 배포하거나 어떤 종류의 버전 제어 시스템을 통해 이미지를 획득했을 수 있습니다. 또는 이미지가 작아서 친구가 이메일이나 플래시 드라이브를 통해 보냈을 수도 있습니다. 어떤 방법으로든 파일을 획득했다면 docker load 명령어를 사용하여 Docker로 로드할 수 있습니다.

docker load 명령어를 보여드리기 전에 로드할 이미지 파일이 필요합니다. 이미지 파일이 있다고 가정하기 어려울 것이므로, busybox:latest 이미지를 예시로 사용하여 이미지를 저장하는 방법을 보여드리겠습니다. 이 이미지는 작고 다루기 쉽습니다. 이 이미지를 파일로 저장하려면 docker save 명령어를 사용합니다. Figure 3.5는 BusyBox에서 파일을 생성하는 docker save를 보여줍니다.

그림 3.5 Parts of the pull and save subcommands

 

이 예제에서는 docker save 명령어가 TAR 아카이브 파일을 생성하기 때문에 .tar 파일 확장자를 사용했습니다. 원하는 파일 이름을 사용할 수 있습니다. -o 플래그를 생략하면 결과 파일이 터미널로 스트리밍됩니다.

 

save 명령을 실행한 후에는 도커 프로그램이 정상적으로 종료됩니다. 현재 작업 중인 디렉토리의 내용을 나열하여 작업이 잘 되었는지 확인하십시오. 지정된 파일이 있다면 다음 명령을 사용하여 도커에서 이미지를 제거하십시오:

docker rmi busybox

 

이미지를 제거한 후에는 생성한 파일을 사용하여 다시 로드합니다. 이를 위해 docker load 명령어를 사용합니다. docker save와 마찬가지로, -i 옵션 없이 docker load를 실행하면 Docker가 파일에서 아카이브를 읽는 대신 표준 입력 스트림을 사용합니다:

docker load –i myfile.tar

 

docker load 명령을 실행한 후에는 이미지가 로드되어야 합니다. 이를 확인하기 위해 다시 docker images 명령을 실행할 수 있습니다. 모든 것이 올바르게 작동했다면, BusyBox가 목록에 포함되어 있어야 합니다.

이미지를 파일로 사용하는 것은 레지스트리를 사용하는 것만큼 간단하지만, 레지스트리가 제공하는 모든 편리한 배포 시설을 놓칠 수 있습니다. 자체 배포 도구를 구축하거나 이미 다른 도구를 사용 중이라면 이러한 명령어를 사용하여 Docker와 통합하는 것이 매우 간단할 것입니다.

 

다른 인기 있는 프로젝트 배포 패턴은 설치 스크립트와 함께 파일 번들을 사용하는 것입니다. 이 방식은 배포를 위해 공개 버전 제어 저장소를 사용하는 오픈 소스 프로젝트에서 인기가 있습니다. 이러한 경우에는 파일을 다루지만 파일은 이미지가 아닌 Dockerfile입니다.

 

3.2.4 Installing from a Dockerfile

Dockerfile은 이미지를 빌드하기 위해 Docker가 수행해야 할 단계를 설명하는 스크립트입니다. 이 스크립트 파일들은 작성자가 이미지에 넣고자 하는 소프트웨어와 함께 배포됩니다. 이 경우에는 기술적으로 이미지를 설치하는 것이 아니라 이미지를 빌드하기 위해 지시 사항을 따르는 것입니다. Dockerfile을 다루는 방법은 7장에서 자세히 다룹니다.

Dockerfile을 배포하는 것은 이미지 파일을 배포하는 것과 유사합니다. 여러분은 자체 배포 메커니즘을 사용해야 합니다. 일반적인 패턴은 Git이나 Mercurial과 같은 공통 버전 제어 시스템에서 소프트웨어와 함께 Dockerfile을 배포하는 것입니다. Git이 설치되어 있다면, 공개 저장소의 예제를 실행하여 시도해볼 수 있습니다:

git clone https://github.com/dockerinaction/ch3_dockerfile.git
docker build -t intheeast0305/dockerfiles:latest ch3_dockerfile

docker push intheeast0305/dockerfiles:latest


이 예제에서는 github에서 프로젝트를 복사하여 컴퓨터에 가져온 다음, 해당 프로젝트에 포함된 Dockerfile을 사용하여 Docker 이미지를 빌드하고 설치합니다. docker build의 -t 옵션에 제공된 값은 이미지를 설치할 저장소입니다. Dockerfile에서 이미지를 빌드하는 것은 기존의 워크플로에 적합한 프로젝트를 이동시키는 경량 방법입니다.

※ ch3_dockerfile 디렉토리의 demo.sh 파일에 윈도우즈 os 형식(CRCF) 문제가 발생되어 이 쉘 스크립트가 수행되지 않는 문제가 있습니다. 해결 방법은 따로 없고, 굳이 demo.sh 파일안에 CRCF를 삭제하기 위해 다음 커맨드로 컨테이너를 수행합니다.

PS C:\Users\inthe> docker run -it --rm intheeast0305/dockerfiles:latest /bin/sh
/demo # ls -al
total 12
drwxr-xr-x    2 root     root          4096 Mar 26 04:47 .
drwxr-xr-x    1 root     root          4096 Apr  4 03:21 ..
-rwxr-xr-x    1 root     root            56 Mar 26 04:46 demo.sh
/demo # cat demo.sh
#!/bin/sh
echo This image was built from a Dockerfile
/demo # ./demo.sh
/bin/sh: ./demo.sh: not found
/demo # ls -al
total 12
drwxr-xr-x    2 root     root          4096 Mar 26 04:47 .
drwxr-xr-x    1 root     root          4096 Apr  4 03:21 ..
-rwxr-xr-x    1 root     root            56 Mar 26 04:46 demo.sh
/demo # pwd
/demo
/demo # cd ..
/ # pwd
/
/ # cd /demo/
/demo # ./demo.sh
/bin/sh: ./demo.sh: not found
/demo # vi ./demo.sh   -> CRCF 해결
/demo # ./demo.sh
/bin/sh: ./demo.sh: not found
/demo # vi ./demo.sh
/demo # ./demo.sh  -> 실행
This image was built from a Dockerfile
/demo # exit

 

이 접근 방식에는 두 가지 단점이 있습니다. 첫째로, 프로젝트의 구체적인 내용에 따라 빌드 프로세스에 시간이 걸릴 수 있습니다. 둘째로, Dockerfile 작성 시점과 사용자의 컴퓨터에서 이미지를 빌드하는 시점 사이에 종속성이 변할 수 있습니다. 이러한 문제로 인해 빌드 파일을 배포하는 것은 사용자에게 이상적이지 않은 경험이 될 수 있습니다. 그러나 이러한 단점에도 불구하고 이 방법은 여전히 인기가 있습니다.

이 예제를 마무리하고 나면 작업 공간을 정리해야 합니다:

docker rmi intheeast0305/dockerfiles
rm -rf ch3_dockerfile

 

3.2.5 Using Docker Hub from the website

아직 도커 웹사이트를 둘러보는 중이라면, 잠시 https://hub.docker.com을 확인해 보는 것이 좋습니다. 도커 허브를 통해 리포지토리, 조직 또는 특정 사용자를 검색할 수 있습니다. 사용자 및 조직 프로필 페이지에는 계정이 유지 관리하는 리포지토리 목록, 계정의 최근 활동 및 계정이 스타를 표시한 리포지토리가 나열됩니다. 리포지토리 페이지에서는 다음과 같은 정보를 확인할 수 있습니다:

  • 이미지 게시자가 제공한 이미지에 대한 일반 정보
  • 리포지토리에서 사용 가능한 태그 목록
  • 리포지토리가 생성된 날짜
  • 다운로드된 횟수
  • 등록된 사용자의 코멘트

 

도커 허브는 가입이 무료이며, 이 책의 후반부에서 계정이 필요합니다. 로그인한 상태에서 리포지토리를 스타로 표시하고 코멘트를 남길 수 있습니다. 또한 자신의 리포지토리를 생성하고 관리할 수 있습니다. 이에 대해 2부에서 자세히 다룰 것입니다. 지금은 그냥 사이트를 둘러보고 제공하는 것을 확인하세요.


Activity: Docker Hub 스캐빈저[ scavenger:물건 찾기 게임 ] 헌트

Chapter 2에서 배운 기술을 활용하여 Docker Hub에서 소프트웨어를 찾아보는 것이 좋습니다. 이 활동은 Docker Hub를 사용하고 컨테이너를 생성하는 연습을 할 수 있도록 설계되었습니다. 또한 docker run 명령에 새로운 세 가지 옵션을 소개합니다.

이 활동에서는 Docker Hub를 통해 사용할 수 있는 두 개의 이미지에서 컨테이너를 생성합니다. 첫 번째 이미지는 dockerinaction/ch3_ex2_hunt 저장소에서 사용할 수 있습니다. 이 이미지에서는 비밀번호를 요청하는 작은 프로그램이 있습니다. 비밀번호를 찾으려면 Docker Hub의 두 번째 미스테리 저장소에서 컨테이너를 찾아 실행해야 합니다. 이러한 이미지의 프로그램을 사용하려면 터미널을 컨테이너에 연결하여 터미널의 입력 및 출력을 실행 중인 컨테이너에 직접 연결해야 합니다. 다음 명령은 이 작업을 수행하고 중지될 때 자동으로 제거되는 컨테이너를 실행하는 방법을 보여줍니다:

docker run -it --rm dockerinaction/ch3_ex2_hunt


이 명령을 실행하면 스캐빈저 헌트 프로그램에서 비밀번호를 입력하라는 메시지가 표시됩니다. 이미 알고 있다면 지금 입력하세요. 그렇지 않으면 아무것이나 입력하면 힌트를 제공합니다. 이 시점에서 활동을 완료하는 데 필요한 모든 도구를 갖추고 있어야 합니다. 다음 다이어그램은 이후의 단계를 설명합니다.


여전히 막혔나요? 한 가지 힌트를 더 드릴 수 있습니다. 미스테리 저장소는 이 책을 위해 생성된 것입니다. 아마도 이 책의 Docker Hub 저장소를 검색해보는 것이 좋을 것입니다. 기억하세요, 저장소는 사용자명/저장소 패턴으로 명명됩니다.

 

 

 


답을 찾으면 자신을 칭찬하고 docker rmi 명령을 사용하여 이미지를 제거하세요. 실행한 명령은 다음과 같아야 합니다:

docker rmi dockerinaction/ch3_ex2_hunt 
docker rmi <미스테리 저장소>


만약 docker run 명령에 --rm 옵션을 사용하고 있었다면 정리해야 할 컨테이너가 없어야 합니다. 이 예제에서 많은 것을 배웠습니다. Docker Hub에서 새 이미지를 찾고 docker run 명령을 새로운 방식으로 사용했습니다. 대화형 컨테이너를 실행하는 방법에 대해 자세히 다루어야 할 것이 많습니다. 다음 섹션에서 그에 대해 자세히 다룹니다.


도커 허브는 소프트웨어의 유일한 소스가 아닙니다. 소프트웨어 발행자의 목표와 관점에 따라 도커 허브는 적절한 배포 지점이 아닐 수 있습니다. 폐쇄 소스 또는 프로프리어터리 프로젝트는 소프트웨어를 제3자를 통해 게시할 위험을 감수하고 싶어하지 않을 수 있습니다. 소프트웨어를 설치하는 세 가지 다른 방법이 있습니다:

  • 대체 리포지토리 레지스트리를 사용하거나 자체 레지스트리를 실행할 수 있습니다.
  • 파일에서 이미지를 수동으로 로드할 수 있습니다.
  • 다른 소스에서 프로젝트를 다운로드하고 제공된 Dockerfile을 사용하여 이미지를 빌드할 수 있습니다.

 

세 가지 옵션 모두 비공개 프로젝트나 기업 인프라에 대해 유용합니다. 다음 몇 개의 소절에서는 각 대체 소스로부터 소프트웨어를 설치하는 방법을 다룹니다. 제9장에서는 Docker 이미지 배포를 자세히 다룹니다. 이 섹션을 읽은 후에는 Docker를 사용하여 소프트웨어를 설치할 수 있는 옵션에 대한 완전한 개괄을 갖게 될 것입니다. 소프트웨어를 설치할 때는 소프트웨어 패키지에 무엇이 들어 있고 컴퓨터에 어떤 변경이 이루어지는지에 대한 개요를 갖고 있어야 합니다.

 

3.3 Installation files and isolation

이미지가 식별되고 발견되며 설치되는 방식을 이해하는 것은 Docker 사용자에게 필수적인 능력입니다. 실제로 설치되는 파일이 무엇이며 이러한 파일이 실행 시간에 어떻게 빌드되고 격리되는지를 이해하면 경험을 통해 발생하는 더 어려운 질문에 대답할 수 있을 것입니다. 예를 들어 다음과 같은 질문들이 있습니다:

  • 다운로드 및 설치 속도에 영향을 미치는 이미지 속성은 무엇입니까?
  • docker images 명령을 사용할 때 나열된 모든 이름이 없는 이미지들은 무엇인가요?
  • docker pull 명령의 출력에는 종속 레이어를 가져오는 메시지가 포함되는 이유는 무엇인가요?
  • 내 컨테이너 파일 시스템에 쓴 파일은 어디에 있나요?

이러한 자료를 학습하는 것은 Docker를 사용한 소프트웨어 설치를 이해하는 마지막 단계입니다. 그림 3.6에 나와 있는 것처럼요.

그림 3.6 Step 3-understanding how software is installed

 

지금까지 소프트웨어 설치에 대해 이야기할 때 이미지라는 용어를 사용했습니다. 이는 사용할 소프트웨어가 단일 이미지에 있고 이미지가 단일 파일에 포함되어 있다는 것을 의미했습니다. 이는 가끔 사실일 수 있지만, 대부분의 경우 우리가 이미지라고 부르는 것은 사실 이미지 레이어의 모음입니다.

레이어는 파일 및 파일 메타데이터의 집합으로, 원자적 단위로 패키지되고 분배됩니다. 내부적으로 Docker는 각 레이어를 이미지처럼 처리하며, 레이어는 종종 중간 이미지라고도 합니다. 심지어 레이어를 이미지로 태그하여 이미지로 승격시킬 수도 있습니다. 대부분의 레이어는 부모 레이어를 기반으로하여 파일 시스템 변경 사항을 부모에 적용함으로써 빌드됩니다. 예를 들어, 레이어는 데비안의 apt update를 사용하여 패키지 관리자로 소프트웨어를 업데이트할 수 있습니다. 그 결과로 생성된 이미지에는 부모와 추가된 레이어의 파일 집합이 포함됩니다. 레이어를 실제로 확인하면 이해하기 쉽습니다.

 

3.3.1 Image layers in action

이 예제에서는 두 개의 이미지를 설치할 것입니다. 두 이미지 모두 Java 11에 의존합니다. 응용 프로그램 자체는 간단한 "Hello, World" 스타일의 프로그램입니다. 각각을 설치할 때 도커가 무엇을 수행하는지 주의 깊게 살펴보시기 바랍니다. 첫 번째와 두 번째를 비교하여 설치에 걸리는 시간이 얼마나 오래 걸리는지 관찰하고 docker pull 커맨드가 터미널에 출력하는 내용을 읽어보세요. 이미지를 설치할 때 도커가 어떤 종속성을 다운로드해야 하는지 결정하고 개별 이미지 레이어 다운로드의 진행 상황을 볼 수 있습니다. 이 예제에는 Java가 적합합니다. 왜냐하면 레이어가 상당히 크기 때문에 Docker가 실제로 작동하는 것을 보는 데 시간이 걸리기 때문입니다.

설치할 두 이미지는 dockerinaction/ch3_myapp와 dockerinaction/ch3_myotherapp입니다. 컨테이너를 시작하지 않고 이미지를 설치하기만 해야하므로 docker pull 커맨드만 사용해야 합니다. 다음은 실행해야 할 커맨입니다:

docker pull dockerinaction/ch3_myapp
docker pull dockerinaction/ch3_myotherapp

 

보셨나요? 여러분의 네트워크 연결이 제가 보다 우수하거나 이미 다른 이미지의 종속성으로 OpenJDK 11.0.4 (slim)을 이미 설치한 경우를 제외하고는 dockerinaction/ch3_myapp의 다운로드가 dockerinaction/ch3_myotherapp보다 훨씬 느렸을 것입니다.
ch3_myapp을 설치할 때 Docker는 요청된 이미지의 직접 종속성(부모 레이어)인 openjdk:11.0.4-jdk-slim 이미지를 설치해야 한다는 것을 결정했습니다. Docker가 이 종속성을 설치하려고 할 때, 해당 레이어의 종속성을 발견하고 먼저 이를 다운로드했습니다. 한 레이어의 모든 종속성이 설치되면 해당 레이어가 설치됩니다. 마지막으로 openjdk:11.0.4-jdk-slim이 설치되고, 그 다음에 아주 작은 ch3_myapp 레이어가 설치되었습니다.

ch3_myotherapp을 설치하는 명령을 실행할 때 Docker는 openjdk:11.0.4-jdk-slim이 이미 설치되어 있음을 확인하고 즉시 ch3_myotherapp 이미지를 설치했습니다. 두 번째 응용 프로그램은 첫 번째 응용 프로그램과 거의 모든 이미지 레이어를 공유했기 때문에 Docker가 수행할 작업이 훨씬 적었습니다. ch3_myotherapp의 고유 레이어를 설치하는 것은 매우 빨랐습니다. 왜냐하면 1MB 미만의 데이터만 전송되었기 때문입니다. 그러나 사용자 관점에서는 프로세스가 동일하게 보입니다.

사용자 관점에서 이 기능은 가지고 있는 것이 좋지만, 최적화를 위해 노력하려고는 하지 않을 것입니다. 단순히 장점을 받아들이면 됩니다. 소프트웨어나 이미지 작성자의 관점에서는 이 기능이 이미지 설계에 중요한 요소로 작용해야 합니다. 제7장에서 이에 대해 더 자세히 다룹니다.

지금 docker images를 실행하면 다음과 같은 저장소가 목록에 표시됩니다:

  • dockerinaction/ch3_myapp
  • dockerinaction/ch3_myotherapp

기본적으로 docker images 명령은 저장소만 표시합니다. 다른 명령어와 마찬가지로 -a 플래그를 지정하면 모든 설치된 중간 이미지 또는 레이어가 포함된 목록이 표시됩니다. docker images -a를 실행하면 여러 저장소가 나열되고 때로는 <none>으로 나열된 것도 있을 수 있습니다. 이름이 지정되지 않은 이미지는 태그를 붙이지 않고 이미지를 빌드하는 등의 여러 이유로 존재할 수 있습니다. 이러한 이미지를 참조하는 유일한 방법은 IMAGE ID 열의 값을 사용하는 것입니다.

 

이 예제에서는 두 개의 이미지를 설치했습니다. 이제 이들을 정리해보겠습니다. 보다 쉽게 정리할 수 있도록 축약된 docker rmi 구문을 사용할 수 있습니다:

docker rmi \
 dockerinaction/ch3_myapp \
 dockerinaction/ch3_myotherapp


docker rmi 명령어를 사용하면 삭제할 이미지들을 공백으로 구분된 목록으로 지정할 수 있습니다. 이것은 예제 이후에 소규모 이미지 세트를 제거해야 할 때 편리합니다. 이 책의 나머지 예제에서 적절한 경우에는 이를 사용하게 될 것입니다.

 

3.3.2 Layer relationships

이미지는 부모/자식 관계를 유지합니다. 이러한 관계에서 그들은 부모로부터 구축되어 레이어를 형성합니다. 컨테이너에 사용 가능한 파일은 컨테이너가 생성된 이미지 계보의 모든 레이어를 통합한 것입니다. 이미지는 소유자가 서로 다른 저장소에 있는 이미지를 포함하여, 다른 이미지와 관계를 가질 수 있습니다. 섹션 3.3.1의 두 애플리케이션 이미지는 OpenJDK 11.0.4 이미지를 부모 이미지로 사용합니다. OpenJDK 이미지의 부모 이미지는 Debian Linux Buster 운영 체제 릴리스의 최소 버전입니다. 그림 3.7은 두 이미지와 각 이미지에 포함된 레이어의 전체 이미지 조상을 보여줍니다.
  그림 3.7의 이미지와 레이어는 애플리케이션 이미지가 openjdk:11.0.4-jdk-slim에서 세 개의 레이어를 상속하고 debian:buster slim에서 한 개의 레이어를 더 상속한다는 것을 보여줍니다. OpenJDK의 세 계층에는 Java 11 소프트웨어의 공통 라이브러리와 종속성이 포함되어 있으며 Debian 이미지는 최소한의 운영 체제 toolchain을 제공합니다.

이미지는 작성자가 태그를 지정하고 발행할 때 이름이 지정됩니다. 사용자는 docker tag 명령을 사용하여 별칭을 만들 수 있습니다. 이미지가 태그되기 전까지는 해당 이미지를 참조하는 유일한 방법은 이미지가 빌드될 때 생성된 고유 식별자(ID)를 사용하는 것입니다. 그림 3.7에서 OpenJDK 11.0.4 이미지의 부모 이미지는 Debian Buster OS로, 해당 이미지의 ID는 83ed3c583403입니다. Debian 이미지 작성자는 이 이미지를 debian:buster-slim으로 태그하고 발행했습니다. 그림은 이러한 이미지를 이미지 ID의 첫 12자리로 라벨을 붙입니다. 이는 일반적인 관례입니다. Docker는 사용자를 위해 일반적인 명령의 출력에서 ID를 65(16진수)자리에서 12자리로 자릅니다. 내부적으로 API 액세스를 통해 Docker는 전체 65자리를 사용합니다.

이러한 "slim" Java 이미지조차도 상당한 크기를 가지고 있으며 일부 사례를 설명하기 위해 선택되었습니다. 이 시점에서 쓰여진 글 기준으로 openjdk:11.0.4-jdk-slim 이미지의 크기는 401MB입니다. 런타임 전용 이미지를 사용하면 약간의 공간을 절약할 수 있지만, openjdk:11.0.4-jre-slim-buster도 204MB입니다. Docker는 이미지와 레이어를 고유하게 식별하기 때문에 애플리케이션 간에 공유된 이미지 종속성을 인식하고 이를 다시 다운로드하지 않고도 처리할 수 있습니다. 이는 런타임에서 애플리케이션 간의 어떠한 조정도 필요하지 않고 빌드 시에만 수행됩니다. 10장에서는 이미지 빌드 파이프라인을 깊이 있게 다룰 것입니다. 이제 컨테이너 파일 시스템을 살펴보겠습니다.

그림 3.7 섹션 3.3.1에서 사용된 두 개의 Docker 이미지의 전체 계보

 

※ Docker 이미지는 여러 계층(layer)으로 구성되어 있으며, 각 레이어는 이미지를 구성하는 파일과 설정의 변경 사항을 저장합니다. scratch는 Docker 이미지 계층에서 특별한 의미를 가지고 있습니다. scratch는 빈 레이어를 의미하며, 실제로는 아무것도 포함하지 않습니다. scratch를 사용하는 것은 Docker 이미지를 완전히 빈 상태에서 시작하겠다는 의미이며, 이를 기반으로 하는 이미지는 모든 파일 시스템의 내용을 이미지 자체에 포함해야 합니다.

scratch를 사용하는 주된 이유는 최소화된 이미지를 생성하기 위해서입니다. 예를 들어, 특정 어플리케이션을 컨테이너화할 때 필요한 최소한의 파일만 포함하여 이미지의 크기를 줄일 수 있습니다. 이런 접근 방식은 보안, 성능, 이미지 크기 등 여러 면에서 이점을 제공할 수 있습니다. 특히, 보안 측면에서는 최소한의 파일만 이미지에 포함하기 때문에 공격 받을 수 있는 표면적(surface area)이 줄어듭니다.

scratch를 기반으로 한 이미지를 만들 때는, 운영체제의 기본적인 라이브러리나 실행 환경을 포함한 모든 것을 직접 추가해야 합니다. 이는 일반적으로 정적으로 컴파일된 바이너리를 사용하여 이루어집니다. 정적으로 컴파일된 바이너리는 외부 라이브러리나 다른 종속성 없이 독립적으로 실행될 수 있어 scratch 기반 이미지에 적합합니다.

요약하자면, scratch는 Docker 이미지를 아주 기본적인 수준에서부터 구축할 수 있는 빈 캔버스와 같습니다. 이를 통해 매우 작고, 보안적으로 강화된 컨테이너 이미지를 생성할 수 있습니다.

 

3.3.3 Container filesystem abstraction and isolation

컨테이너 내에서 실행되는 프로그램은 이미지 레이어들에 대해 전혀 알지 못합니다. 컨테이너 내부에서 파일 시스템은 컨테이너에서 실행되거나 이미지를 운영하고 있는 것처럼 작동하지 않습니다. 컨테이너의 관점에서 보면, 이미지에 의해 제공된 파일의 독점적 복사본을 가지고 있는 것처럼 보입니다. 이는 유니온 파일 시스템(UFS)이라고 불리는 것을 통해 가능해집니다.

유니온 파일 시스템(Union File System)은 여러 파일 시스템을 하나의 가상 파일 시스템으로 통합하는 기술입니다. 이 시스템은 여러 개의 디렉토리와 파일 시스템을 하나로 보이도록 합쳐주는데, 기존의 파일 시스템을 수정하지 않고도 이러한 기능을 제공할 수 있습니다. 유니온 파일 시스템은 여러 개의 파일 시스템을 계층적으로 쌓아 올릴 수 있습니다. 각각의 파일 시스템은 읽기 전용이거나 읽기/쓰기 가능한 파일 시스템이 될 수 있습니다. 이를 통해 사용자는 여러 소스에서 파일을 읽거나 쓸 수 있습니다. 주로 리눅스와 유닉스 시스템에서 사용되며, 컨테이너 기술과 함께 사용될 때 여러 컨테이너 간 파일 시스템을 공유하는 데에 유용하게 사용될 수 있습니다. Docker와 같은 컨테이너 오케스트레이션 툴에서도 유니온 파일 시스템이 활용됩니다.

 

Docker는 다양한 유니온 파일 시스템을 사용하며, 시스템에 가장 적합한 것을 선택합니다. 유니온 파일 시스템이 작동하는 세부 사항은 Docker를 효과적으로 사용하기 위해 알아야 할 것들을 넘어섭니다. 유니온 파일 시스템은 효과적인 파일 시스템 격리를 생성하는데 사용되는 중요한 도구 세트의 일부입니다. 다른 도구들은 MNT 네임스페이스와 chroot 시스템 호출입니다.

MNT 시스템은 리눅스 커널의 네임스페이스 중 하나로, 파일 시스템 마운트 포인트를 격리하는 기능을 제공합니다. 네임스페이스는 리눅스 시스템에서 프로세스 그룹이 시스템의 다른 부분으로부터 독립적으로 보이게 하는 기술입니다. MNT 네임스페이스(Mount Namespace)를 사용하면 각각의 프로세스 또는 프로세스 그룹이 파일 시스템 구조에 대해 독립적인 뷰를 가질 수 있습니다. 이는 프로세스가 시스템의 나머지 부분과는 별도로 자신만의 파일 시스템 마운트를 관리할 수 있게 합니다.
Docker와 같은 컨테이너화 기술에서 MNT 네임스페이스는 중요한 역할을 합니다. Docker가 컨테이너를 생성할 때, 각 컨테이너는 자체 MNT 네임스페이스를 할당받게 되며, 이는 컨테이너가 호스트 시스템의 나머지 부분과 독립적인 파일 시스템 마운트를 가질 수 있게 합니다. 결과적으로, 컨테이너 내부에서 실행되는 애플리케이션은 호스트 시스템의 파일 시스템 구조를 직접 조작하거나 접근할 수 없게 되어 보안과 격리가 강화됩니다.
간단히 말해, MNT 시스템(또는 MNT 네임스페이스)은 리눅스 기반 시스템에서 프로세스가 파일 시스템 마운트를 독립적으로 보고 관리할 수 있게 해 주는 기능으로, 컨테이너의 파일 시스템 격리와 보안을 강화하는 데 중요한 역할을 합니다.

 

파일 시스템은 호스트 파일 시스템에 마운트 포인트를 생성하여 레이어 사용을 추상화하는 데 사용됩니다. 생성된 레이어는 Docker 이미지 레이어로 묶입니다. 마찬가지로, Docker 이미지가 설치될 때, 그 레이어는 풀리고 시스템에 선택된 특정 파일 시스템 제공자에 의해 사용하기 위해 적절하게 구성됩니다.

리눅스 커널은 MNT 시스템에 대한 네임스페이스를 제공합니다. Docker가 컨테이너를 생성할 때, 그 새로운 컨테이너는 자신만의 MNT 네임스페이스를 가지게 되고, 이미지에 대한 컨테이너의 새로운 마운트 포인트가 생성됩니다.

마지막으로, chroot는 이미지 파일 시스템의 루트를 컨테이너의 컨텍스트에서 루트로 만드는 데 사용됩니다. 이는 컨테이너 내부에서 실행되는 것이 호스트 파일 시스템의 다른 부분을 참조하는 것을 방지합니다.

chroot는 UNIX 계열 시스템에서 사용되는 명령어로, 프로세스의 루트 디렉토리를 변경하는 데 사용됩니다. 이 명령어의 이름은 "change root"의 줄임말입니다. chroot를 사용하면 프로세스가 접근할 수 있는 파일 시스템의 최상위를 지정된 디렉토리로 변경할 수 있습니다. 결과적으로, 해당 프로세스와 그 자식 프로세스들은 변경된 루트 디렉토리 밖의 파일 시스템에 접근할 수 없게 됩니다.
chroot의 주요 사용 사례는 시스템의 보안을 강화하는 것입니다. 예를 들어, 서버에서 실행되는 서비스나 애플리케이션을 chroot된 환경 안에서 실행함으로써, 해당 서비스가 시스템의 나머지 부분에 미칠 수 있는 잠재적 영향을 최소화할 수 있습니다. 이는 만약 애플리케이션이 해킹당하더라도 공격자가 `chroot` 환경 밖의 시스템 자원에 접근하는 것을 어렵게 만듭니다.
또한, chroot는 소프트웨어 개발에서 테스트 환경을 격리하거나 소프트웨어를 다른 시스템 환경에 배포하기 전에 패키징하는 데 유용하게 사용됩니다. 개발자는 chroot 환경 안에서 애플리케이션을 실행하여, 해당 애플리케이션이 특정 라이브러리나 의존성 없이도 올바르게 작동하는지 테스트할 수 있습니다. 그러나 chroot는 운영체제의 커널과 격리되지 않기 때문에 완벽한 보안 솔루션으로는 간주되지 않습니다. chroot 환경 내의 프로세스가 충분한 권한을 가지고 있을 경우, 이 환경을 탈출할 수 있는 방법이 존재할 수 있습니다. 따라서, chroot는 컨테이너화 기술과 같은 추가적인 보안 메커니즘과 함께 사용될 때 더욱 효과적입니다.


chroot와 MNT 네임스페이스 사용은 컨테이너 기술에 일반적입니다. 유니온 파일 시스템을 레시피에 추가함으로써, Docker 컨테이너는 여러 가지 이점을 가지게 됩니다.

Docker 이미지와 레이어
Docker 이미지는 컨테이너를 실행하기 위한 템플릿입니다. 이 이미지는 여러 레이어로 구성되어 있으며, 각 레이어는 이미지를 만들 때의 한 단계, 예를 들어 파일 추가나 명령어 실행 등을 나타냅니다.
⦁ 이미지의 각 레이어는 변경할 수 없는, 즉 읽기 전용입니다. 새로운 파일이 추가되거나 기존 파일이 수정될 때마다 새로운 레이어가 생성됩니다.
⦁ 이러한 레이어 방식 덕분에, 여러 이미지가 동일한 레이어를 공유할 수 있어 저장 공간을 효율적으로 사용할 수 있습니다.

마운트 포인트와 파일 시스템
⦁ 컨테이너가 시작될 때, Docker는 이러한 읽기 전용 레이어들을 스택 형태로 쌓아 올리고, 맨 위에 쓰기 가능한 레이어를 하나 더 추가합니다. 이 쓰기 가능한 레이어에서 컨테이너 내의 변경 사항(파일 추가, 수정 등)이 처리됩니다.
호스트 파일 시스템에 마운트 포인트를 생성한다는 것은, 컨테이너 내부에서 호스트의 특정 디렉토리나 파일을 접근할 수 있도록 하는 것을 의미합니다. 이를 통해 데이터를 컨테이너와 호스트 간에 쉽게 공유할 수 있습니다. - 컨테이너 내부에서의 파일 시스템 작업은 이러한 레이어와 마운트 포인트를 통해 추상화되어, 컨테이너가 사용하는 파일 시스템이 실제 호스트의 파일 시스템과는 독립적으로 작동할 수 있습니다.

레이어의 구성과 사용
⦁ Docker 이미지가 설치될 때, 사실상 이미지의 레이어들이 호스트 시스템에 풀리는 것은 아니며, 이미지를 다운로드하고 그 내용을 추출하여 사용할 수 있는 형태로 만드는 과정을 의미합니다. 이미지의 레이어는 컨테이너를 실행할 때 필요한 모든 파일과 설정을 포함하고 있습니다.
⦁ 컨테이너를 실행하면, Docker는 이 레이어들을 조합하여 컨테이너의 파일 시스템을 구성하고, 필요에 따라 추가적인 마운트 포인트를 설정하여 호스트의 파일 시스템과의 상호 작용을 구성합니다.

Docker는 이미지의 여러 읽기 전용 레이어와 컨테이너 실행 시 추가되는 쓰기 가능한 레이어를 조합하여, 각 컨테이너가 독립적인 파일 시스템을 가지도록 합니다. 이 과정에서 호스트의 파일 시스템과의 상호 작용은 마운트 포인트를 통해 이루어집니다.

 

3.3.4 Benefits of this toolset and filesystem structure

이 접근법의 첫 번째이자 아마도 가장 중요한 이점은 공통 레이어를 오직 한 번만 설치해도 된다는 것입니다. 여러 개의 이미지들을 설치할 때 그것들이 공통 레이어에 의존하는 경우, 그 공통 레이어와 그 모든 부모 레이어는 오직 한 번만 다운로드하거나 설치하면 됩니다. 이는 여러분이 컴퓨터에 중복 파일을 저장하거나 중복 레이어를 다운로드하지 않고도 프로그램의 여러 전문화를 설치할 수 있음을 의미합니다. 반면에, 대부분의 가상 머신 기술은 여러분이 컴퓨터에 중복된 가상 머신을 가질 때마다 동일한 파일을 여러 번 저장할 것입니다.

둘째, 레이어는 의존성을 관리하고 관심사를 분리하는 대략적인 도구를 제공합니다. 이는 특히 소프트웨어 개발자들에게 유용하며, 제7장에서 이에 대해 더 자세히 다룹니다. 사용자 관점에서, 이 이점은 여러분이 어떤 소프트웨어를 실행하고 있는지, 어떤 이미지와 레이어를 사용하고 있는지를 빠르게 식별하는 데 도움을 줄 것입니다.

마지막으로, 베이스 이미지 위에 사소한 변경을 레이어로 추가할 수 있다면 소프트웨어 전문화를 쉽게 만들 수 있습니다. 이 역시 제7장에서 자세히 다루는 또 다른 주제입니다. 전문화된 이미지를 제공함으로써 사용자는 최소한의 맞춤화로 소프트웨어에서 정확히 필요한 것을 얻을 수 있습니다. 이는 Docker를 사용하는 최고의 이유 중 하나입니다.

 

3.3.5 Weaknesses of union filesystems

Docker는 시작할 때 합리적인 디폴트 설정을 선택하지만, 모든 작업 부하에 완벽한 구현은 없습니다. 실제로, 특정 사용 사례에서는 잠시 멈추고 다른 Docker 기능을 사용하는 것을 고려해야 할 수 있습니다.

다른 파일 시스템은 파일 속성, 크기, 이름 및 문자에 대한 다른 규칙을 가지고 있습니다. 유니온 파일 시스템은 다른 파일 시스템의 규칙 사이에서 종종 번역해야 하는 위치에 있습니다. 최상의 경우, 그들은 수용할 수 있는 번역을 제공할 수 있습니다. 최악의 경우, 기능이 생략됩니다. 예를 들어, Btrfs나 OverlayFS는 SELinux 작동을 가능하게 하는 확장 속성을 지원하지 않습니다.

유니온 파일 시스템은 복사 후 쓰기(copy-on-write)라는 패턴을 사용하며, 이는 메모리 매핑된 파일(즉, mmap 시스템 호출) 구현을 어렵게 만듭니다. 일부 유니온 파일 시스템은 적절한 조건하에서 작동하는 구현을 제공하지만, 이미지에서 파일을 메모리 매핑하는 것을 피하는 것이 더 나은 아이디어일 수 있습니다.

백업 파일 시스템은 Docker의 또 다른 플러그 가능한 기능입니다. 설치에서 사용 중인 파일 시스템을 info 서브커맨드로 확인할 수 있습니다. 특정 파일 시스템을 Docker에 명시적으로 지시하려면, Docker 데몬을 시작할 때 --storage-driver 또는 -s 옵션을 사용하세요. 유니온 파일 시스템에 쓰기와 관련된 대부분의 문제는 저장소 제공자를 변경하지 않고도 해결될 수 있습니다. 이 문제들은 볼륨, 즉 제4장의 주제로 해결할 수 있습니다.

 

Summary

컴퓨터에서 소프트웨어를 설치하고 관리하는 작업은 독특한 도전 과제를 제공합니다. 이 장에서는 Docker를 사용하여 이러한 문제를 해결하는 방법을 설명합니다. 이 장에서 다룬 핵심 아이디어와 기능은 다음과 같습니다:

  • Docker 사용자는 Docker가 설치할 소프트웨어를 지정하기 위해 리포지토리 이름을 사용합니다.
  • Docker Hub는 디폴트 Docker 레지스트리입니다. Docker Hub에서 소프트웨어를 찾으려면 웹사이트나 Docker 커맨드 라인 프로그램을 사용할 수 있습니다.
  • Docker 커맨드 라인 프로그램을 사용하면 대체 레지스트리 또는 다른 형식으로 배포된 소프트웨어를 간단히 설치할 수 있습니다.
  • 이미지 리포지토리 사양에는 레지스트리 호스트 필드가 포함됩니다.
  • docker loaddocker save 명령어를 사용하면 TAR 아카이브에서 이미지를 불러오거나 저장할 수 있습니다.
  • 프로젝트와 함께 Dockerfile을 배포하면 사용자 컴퓨터에서 이미지 빌드를 간소화할 수 있습니다.
  • 이미지는 일반적으로 부모/자식 관계로 연결되어 있습니다. 이러한 관계는 레이어(layer)를 형성합니다. 이미지를 설치했다고 말할 때, 이는 타겟 이미지와 그 계보에 포함된 모든 이미지 레이어를 설치했음을 의미합니다.
  • 레이어를 사용해 이미지를 구성하면 레이어 재사용이 가능하며, 배포 중 대역폭 절약과 컴퓨터 및 이미지 배포 서버에서의 저장 공간 절약이 가능합니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

'Docker' 카테고리의 다른 글

Docker Redis  (0) 2024.04.07
4. Working with storage and volumes  (0) 2024.03.26
2. Running software in containers  (0) 2024.03.20
1. Welcome to Docker  (0) 2024.03.20
Docker  (0) 2023.11.08