Docker 이미지 작동 방법

완료됨

앞에서 컨테이너 이미지는 애플리케이션을 배포하는 데 사용하는 단위가 된다고 설명했습니다. 또한 컨테이너는 개발자 및 운영 팀이 모두 사용하는 표준화된 컨테이너 형식이라고 설명했습니다.

여기서는 Docker에서 사용되는 소프트웨어, 패키지 및 이미지의 차이점을 살펴보겠습니다. 이 개념 간 차이점을 알고 있으면 Docker 이미지의 작동 방식을 더 잘 이해할 수 있습니다.

또한 호스트에서 실행되는 OS의 역할 및 컨테이너에서 실행되는 OS에 대해 간략하게 설명합니다.

컨테이너로 패키지된 소프트웨어

컨테이너로 패키지된 소프트웨어는 개발자가 빌드하는 애플리케이션으로 제한되지 않습니다. 소프트웨어에 대해 논의할 경우에는 애플리케이션 코드, 시스템 패키지, 이진 파일, 라이브러리, 구성 파일 및 컨테이너에서 실행되는 운영 체제를 나타냅니다.

예를 들어 회사의 다양한 아울렛에서 사용하는 주문 추적 포털을 개발하고 있다고 가정합니다. 웹 애플리케이션을 실행하는 소프트웨어의 전체 스택을 확인해야 합니다. 빌드 중인 애플리케이션은 .NET Core MVC 앱이며 Ubuntu Linux에서 nginx를 역방향 프록시 서버로 사용하여 애플리케이션을 배포할 계획입니다. 이 모든 소프트웨어 구성 요소는 컨테이너 이미지의 일부를 구성합니다.

컨테이너 이미지란 무엇인가요?

컨테이너 이미지는 소프트웨어를 포함하는 이식 가능 패키지입니다. 이 이미지는 실행 시 컨테이너가 됩니다. 컨테이너는 이미지의 메모리 내 인스턴스입니다.

컨테이너 이미지는 변경할 수 없습니다. 이미지를 빌드한 후에는 변경할 수 없습니다. 이미지를 변경하는 유일한 방법은 새 이미지를 만드는 것입니다. 이 기능을 사용하면 프로덕션에서 사용하는 이미지가 개발 및 QA에서 사용되는 이미지와 동일하게 됩니다.

호스트 OS란 무엇인가요?

호스트 OS는 Docker 엔진이 실행되는 OS입니다. Linux에서 실행되는 Docker 컨테이너는 호스트 OS 커널을 공유하며 이진 파일이 OS 커널에 직접 액세스할 수 있는 한 컨테이너 OS가 필요하지 않습니다.

Diagram showing a Docker image with no base OS and the dependency on the host OS Kernel.

그러나 Windows 컨테이너에는 컨테이너 OS가 필요합니다. 컨테이너는 파일 시스템, 네트워크 관리, 프로세스 예약 및 메모리 관리와 같은 서비스를 관리하는 데 OS 커널을 사용합니다.

컨테이너 OS란 무엇인가요?

컨테이너 OS는 패키지된 이미지에 포함된 OS입니다. 컨테이너에는 여러 버전의 Linux 또는 Windows 운영 체제를 유연하게 포함할 수 있습니다. 이 유연성을 통해 특정 OS 기능에 액세스하거나 애플리케이션에서 사용할 수 있는 추가 소프트웨어를 설치할 수 있습니다.

Diagram showing a Docker image with an Ubuntu base OS and the dependency on the host OS Kernel.

컨테이너 OS는 호스트 OS와 격리되며 애플리케이션을 배포하고 실행하는 환경입니다. 이 격리는 이미지의 불변성과 결합되어 개발 시 실행되는 애플리케이션 환경이 프로덕션과 동일함을 의미합니다.

이 예제에서는 Ubuntu Linux를 컨테이너 OS로 사용하며 이 OS는 개발 또는 프로덕션 시에 변경되지 않습니다. 사용할 이미지가 항상 동일합니다.

스택 가능 통합 파일 시스템(Unionfs)이란 무엇인가요?

Unionfs은(는) Docker 이미지를 만드는 데 사용됩니다. Unionfs은(는) 콘텐츠가 병합되는 것처럼 보이도록 분기라는 여러 디렉터리를 쌓을 수 있는 파일 시스템입니다. 그러나 콘텐츠는 실제로 별도로 유지됩니다. Unionfs를 사용하면 파일 시스템을 빌드할 때 분기를 추가하고 제거할 수 있습니다.

Diagram showing the stacking of layers in a Docker image created with unionfs.

예를 들어 앞에서 웹 애플리케이션의 이미지를 빌드하고 있었다고 가정합니다. Ubuntu 배포를 부팅 파일 시스템 위에 기본 이미지로 계층화합니다. 다음으로, nginx 및 웹앱을 설치합니다. 원래 Ubuntu 이미지 위에 nginx 및 웹앱을 효과적으로 계층화하고 있습니다.

컨테이너가 이미지에서 실행된 후 쓰기 가능한 마지막 레이어가 생성됩니다. 그러나 컨테이너가 제거되면 이 레이어는 지속되지 않습니다.

기본 이미지란 무엇인가요?

기본 이미지는 Docker scratch 이미지를 사용하는 이미지입니다. scratch 이미지는 파일 시스템 레이어를 만들지 않는 빈 컨테이너 이미지입니다. 이 이미지는 실행하려는 애플리케이션이 호스트 OS 커널을 직접 사용할 수 있다고 가정합니다.

부모 이미지란 무엇인가요?

부모 이미지는 이미지를 만드는 원본 컨테이너 이미지입니다.

예를 들어 scratch에서 이미지를 만든 후 Ubuntu를 설치하는 대신 Ubuntu 기반 이미지를 사용합니다. nginx가 설치된 이미지를 사용할 수도 있습니다. 일반적으로 부모 이미지에는 컨테이너 OS가 포함됩니다.

기본 이미지와 부모 이미지의 주요 차이점은 무엇인가요?

두 이미지 형식을 사용하여 재사용 가능한 이미지를 만들 수 있습니다. 그러나 기본 이미지를 사용하면 최종 이미지의 콘텐츠를 더 효과적으로 제어할 수 있습니다. 앞에서 이미지를 변경할 수 없으며 이미지에서 제거할 수는 없고 이미지에 추가할 수만 있다고 설명했습니다.

Windows에서는 Windows 기본 컨테이너 이미지를 기반으로 하는 컨테이너 이미지만 만들 수 있습니다. Microsoft는 이러한 Windows 기본 컨테이너 이미지를 제공하고 서비스를 제공합니다.

Dockerfile이란?

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

  • 새 이미지를 만드는 데 사용하는 기본 또는 부모 이미지
  • 기본 OS를 업데이트하고 추가 소프트웨어를 설치하는 명령
  • 개발된 애플리케이션과 같이 포함할 빌드 아티팩트
  • 스토리지 및 네트워크 구성과 같은 노출할 서비스
  • 컨테이너가 시작될 때 실행할 명령

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

# Step 1: Specify the parent image for the new image
FROM ubuntu:18.04

# Step 2: Update OS packages and install additional software
RUN apt -y update &&  apt install -y wget nginx software-properties-common apt-transport-https \
	&& wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
	&& dpkg -i packages-microsoft-prod.deb \
	&& add-apt-repository universe \
	&& apt -y update \
	&& apt install -y dotnet-sdk-3.0

# Step 3: Configure Nginx environment
CMD service nginx start

# Step 4: Configure Nginx environment
COPY ./default /etc/nginx/sites-available/default

# STEP 5: Configure work directory
WORKDIR /app

# STEP 6: Copy website code to container
COPY ./website/. .

# STEP 7: Configure network requirements
EXPOSE 80:8080

# STEP 8: Define the entry point of the process that runs in the container
ENTRYPOINT ["dotnet", "website.dll"]

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

앞서 Docker 이미지가 unionfs을 사용한다고 언급했습니다. 이러한 각 단계는 마지막 컨테이너 이미지를 빌드할 때 캐시된 컨테이너 이미지를 만듭니다. 이 임시 이미지는 이전 이미지 위에 계층화되고 모든 단계가 완료된 후 단일 이미지로 제공됩니다.

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

Docker 이미지를 관리하는 방법

Docker 이미지는 처음에 PC에 저장되는 큰 파일이며 이 파일을 관리하는 도구가 필요합니다.

Docker CLI 및 Docker Desktop을 통해 이미지를 빌드, 나열, 제거 및 실행하여 이미지를 관리할 수 있습니다. docker 클라이언트를 사용하여 Docker 이미지를 관리합니다. 클라이언트는 명령을 직접 실행하지 않으며 모든 쿼리를 dockerd 디먼으로 보냅니다.

여기에서 모든 클라이언트 명령 및 명령 플래그를 다루지는 않지만, 가장 많이 사용되는 명령 중 일부를 살펴보겠습니다. 이 모듈의 마지막에 있는 자세한 정보 섹션에는 모든 명령 및 명령 플래그를 자세히 설명하는 Docker 설명서의 링크가 포함됩니다.

이미지를 빌드하는 방법

docker build 명령을 사용하여 Docker 이미지를 빌드합니다. 앞의 Dockerfile 정의를 사용하여 이미지를 빌드한다고 가정해 보겠습니다. 다음은 빌드 명령을 보여 주는 예제입니다.

docker build -t temp-ubuntu .

빌드 명령이 생성하는 출력은 다음과 같습니다.

Sending build context to Docker daemon  4.69MB
Step 1/8 : FROM ubuntu:18.04
 ---> a2a15febcdf3
Step 2/8 : RUN apt -y update && apt install -y wget nginx software-properties-common apt-transport-https && wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && dpkg -i packages-microsoft-prod.deb && add-apt-repository universe && apt -y update && apt install -y dotnet-sdk-3.0
 ---> Using cache
 ---> feb452bac55a
Step 3/8 : CMD service nginx start
 ---> Using cache
 ---> ce3fd40bd13c
Step 4/8 : COPY ./default /etc/nginx/sites-available/default
 ---> 97ff0c042b03
Step 5/8 : WORKDIR /app
 ---> Running in 883f8dc5dcce
Removing intermediate container 883f8dc5dcce
 ---> 6e36758d40b1
Step 6/8 : COPY ./website/. .
 ---> bfe84cc406a4
Step 7/8 : EXPOSE 80:8080
 ---> Running in b611a87425f2
Removing intermediate container b611a87425f2
 ---> 209b54a9567f
Step 8/8 : ENTRYPOINT ["dotnet", "website.dll"]
 ---> Running in ea2efbc6c375
Removing intermediate container ea2efbc6c375
 ---> f982892ea056
Successfully built f982892ea056
Successfully tagged temp-ubuntu:latest

앞의 결과를 이해하지 못하더라도 걱정하지 마세요. 그러나 출력에 나열된 단계를 확인합니다. 각 단계가 실행되면 빌드 중인 이미지에 새 레이어가 추가됩니다.

또한 소프트웨어를 설치하고 구성을 관리하는 다양한 명령을 실행합니다. 예를 들어 2단계에서는 apt -y updateapt install -y 명령을 실행하여 OS를 업데이트합니다. 이 명령은 해당 단계에 대해 만들어진 실행 중인 컨테이너에서 실행됩니다. 명령이 실행되면 중간 컨테이너가 제거됩니다. 기본 캐시된 이미지는 빌드 호스트에서 유지되며 자동으로 삭제되지 않습니다. 이 최적화를 통해 이후 빌드에서 이 이미지가 다시 사용되어 빌드 시간이 단축됩니다.

이미지 태그란 무엇인가요?

이미지 태그는 이미지 버전을 관리하는 데 사용되는 텍스트 문자열입니다.

앞의 예제 빌드에서 “Successfully tagged temp-ubuntu: latest”라고 표시된 마지막 빌드 메시지를 확인합니다. 이미지를 빌드할 때 -t 명령 플래그를 사용하여 이미지의 이름을 지정하고 선택적으로 태그를 지정합니다. 이 예제에서는 -t temp-ubuntu를 사용하여 이미지 이름을 지정했지만 결과 이미지 이름에는 temp-ubuntu: latest 태그가 지정되었습니다. 태그를 지정하지 않으면 이미지에는 latest 태그로 레이블이 지정됩니다.

이미지 하나에 여러 태그를 할당할 수 있습니다. 규칙에 따라, 가장 최신 버전의 이미지에는 latest 태그 및 이미지 버전 번호를 설명하는 태그가 할당됩니다. 새 버전의 이미지를 릴리스할 때 새 이미지를 참조하도록 latest 태그를 다시 할당할 수 있습니다.

Windows의 경우 Microsoft는 기본 컨테이너 이미지에 최신 태그를 제공하지 않습니다. Windows 기본 컨테이너 이미지의 경우 사용하려는 태그를 지정해야 합니다. 예를 들어, Server Core의 Windows 기본 컨테이너 이미지는 mcr.microsoft.com/windows/servercore입니다. 그 태그 중에는 ltsc2016, ltsc2019, ltsc2022이(가) 있습니다.

다음은 또 다른 예제입니다. .NET Core 샘플 Docker 이미지를 사용하려는 경우를 가정합니다. 선택할 수 있는 4가지 버전은 다음과 같습니다.

  • mcr.microsoft.com/dotnet/core/samples:dotnetapp

  • mcr.microsoft.com/dotnet/core/samples:aspnetapp

  • mcr.microsoft.com/dotnet/core/samples:wcfservice

  • mcr.microsoft.com/dotnet/core/samples:wcfclient

앞의 이미지 목록에서 Microsoft가 여러 .NET Core 샘플을 제공하는 것을 볼 수 있습니다. 태그는 이미지가 참조하는 샘플(ASP.NET, WCF 서비스 등)을 지정합니다.

이미지를 나열하는 방법

Docker 소프트웨어는 머신에서 로컬 이미지 레지스트리를 자동으로 구성합니다. docker images 명령을 사용하여 이 레지스트리에 있는 이미지를 볼 수 있습니다.

docker images

출력은 다음 예와 같습니다.

REPOSITORY          TAG                     IMAGE ID            CREATED                     SIZE
tmp-ubuntu          latest             f89469694960        14 minutes ago         1.69GB
tmp-ubuntu          version-1.0        f89469694960        14 minutes ago         1.69GB
ubuntu              18.04                   a2a15febcdf3        5 weeks ago            64.2MB

이미지의 ‘이름’, ‘태그’ 및 ‘이미지 ID’가 어떻게 나열되는지 확인합니다. 앞에서 이미지에 여러 레이블을 적용할 수 있다고 설명했습니다. 앞의 출력은 예제를 보여줍니다. 이미지 이름이 다르더라도 ID가 동일하다는 것을 알 수 있습니다.

이미지 ID는 이미지의 이름 또는 태그가 모호한 경우 이미지를 식별하고 관리하는 유용한 방법입니다.

이미지를 제거하는 방법

docker rmi 명령을 사용하여 로컬 Docker 레지스트리에서 이미지를 제거할 수 있습니다. 컨테이너 이미지 레이어가 사용 가능한 총 공간에 추가되므로 컨테이너 호스트 디스크의 공간을 절약해야 하는 경우에 유용합니다.

제거할 이미지의 이름 또는 ID를 지정합니다. 이 예제에서는 이미지 이름을 사용하여 샘플 웹앱의 이미지를 제거합니다.

docker rmi temp-ubuntu:version-1.0

컨테이너가 여전히 이미지를 사용하는 경우 이미지를 제거할 수 없습니다. docker rmi 명령은 이미지를 사용하는 컨테이너를 나열하는 오류 메시지를 반환합니다.

Docker 이미지의 기본 사항, 이 이미지를 관리하는 방법 및 이미지에서 컨테이너를 실행하는 방법을 살펴보았습니다. 다음으로, 컨테이너를 관리하는 방법을 살펴보겠습니다.

지식 점검

1.

Docker Desktop은 다음 중 어떤 운영 체제에서 사용 가능한 컨테이너화된 앱 및 마이크로 서비스를 빌드 및 공유하는 앱인가요?

2.

컨테이너 이미지를 다시 빌드하는 올바른 Docker 명령은 무엇인가요?

3.

다음 중 컨테이너 이미지를 가장 잘 설명하는 문장은 무엇인가요?