기존 Docker 이미지를 검색하여 로컬로 배포

완료됨

Docker는 애플리케이션 및 서비스를 쉽고 빠르게 배포할 수 있는 기술입니다. Docker 앱은 Docker 이미지를 사용하여 실행됩니다. Docker 이미지는 애플리케이션 코드와 코드가 실행되는 환경을 포함하고 있는 미리 패키징된 환경입니다.

앞에서 설명한 회사 시나리오에서는 Docker를 사용하여 앱을 패키징하고 실행할 수 있는 가능성을 조사해야 합니다. 여러분은 테스트 웹앱을 실행하는 Docker 이미지를 빌드하여 배포하기로 결정합니다.

이 단원에서는 Docker 이미지에 저장된 컨테이너화된 앱을 실행하기 위한 핵심 개념 및 프로세스를 알아보겠습니다.

Docker의 개요

Docker는 컨테이너화된 앱을 실행하는 도구입니다. 컨테이너화된 앱에는 앱과 앱이 실행되는 환경을 구성하는 파일 시스템이 포함됩니다. 예를 들어 컨테이너화된 앱은 데이터베이스와 기타 관련 소프트웨어 및 애플리케이션을 실행하는 데 필요한 구성 정보로 구성될 수 있습니다.

컨테이너화된 앱은 일반적으로 같은 앱을 실행하도록 구성된 가상 머신보다 공간을 훨씬 적게 차지합니다. 이처럼 더 작은 메모리 공간은 가상 머신이 전체 운영 체제 및 관련된 지원 환경을 제공해야 하기 때문입니다. Docker 컨테이너는 이러한 오버헤드가 없습니다. Docker가 호스트 컴퓨터의 운영 체제 커널을 사용하여 컨테이너를 구동하기 때문입니다. 비슷한 기능을 제공하는 가상 머신을 다운로드하여 실행하는 방법보다는 Docker 이미지를 다운로드하여 시작하는 방법이 빠르고 공간 효율성이 높습니다.

Docker에서 사용하는 파일 세트 및 구성 정보 섹션을 포함하는 이미지를 빌드하여 컨테이너화된 앱을 만듭니다. Docker에 이미지를 기반으로 컨테이너를 시작하라고 요청하여 앱을 실행합니다. 컨테이너가 시작되면 Docker 컨테이너는 이미지 구성을 사용하여 컨테이너 내부에서 실행할 애플리케이션을 결정합니다. Docker는 운영 체제 리소스 및 필수 보안을 제공합니다. 컨테이너가 동시에 실행되고 상대적으로 격리된 상태로 유지되도록 합니다.

중요

Docker는 가상 머신에 사용할 수 있는 정도의 격리 수준을 제공하지 않습니다. 가상 머신은 하드웨어 수준에서 격리를 구현합니다. Docker 컨테이너는 기본 운영 체제 리소스 및 라이브러리를 공유합니다. 그러나 Docker는 한 컨테이너가 다른 컨테이너의 리소스에 액세스할 수 없도록 합니다(컨테이너가 그렇게 하도록 구성된 경우는 예외임).

로컬로 개발하고 테스트하는 경우 데스크톱 또는 랩톱에서 Docker를 실행할 수 있습니다. 프로덕션 시스템의 경우 Linux 및 Microsoft Windows Server 2016의 여러 변형을 포함한 서버 환경에 Docker를 사용할 수 있습니다. 많은 공급 업체가 클라우드에서도 Docker를 지원합니다. 예를 들어 Azure Container Registry에 Docker 이미지를 저장하고 Azure Container Instances를 사용하여 컨테이너를 실행할 수 있습니다.

이 모듈에서는 Docker를 로컬로 사용하여 이미지를 빌드하고 실행합니다. 그런 다음 Azure Container Registry에 이미지를 업로드하고 Azure Container Instance에서 실행할 것입니다. 이 Docker 버전은 로컬로 Docker 이미지를 개발하고 테스트하는 데 적합합니다.

Linux 및 Windows Docker 이미지

Docker는 초기에 Linux용으로 개발되었으며 이후 Windows를 지원하도록 확장되었습니다. 개별 Docker 이미지는 Windows 기반으로 또는 Linux 기반으로 사용할 수 있지만, 둘 다 동시에 사용할 수는 없습니다. 이미지의 운영 체제에 따라 컨테이너 내에서 사용할 운영 체제 환경의 종류가 결정됩니다.

Windows 기반 이미지와 Linux 기반 이미지에서 비슷한 기능을 제공하고 싶은 Docker 이미지 작성자는 각각의 이미지를 별도로 빌드하면 됩니다. 예를 들어 Microsoft는 컨테이너화된 ASP.NET Core 애플리케이션의 기초로 사용할 수 있는 ASP.NET Core 환경을 포함하고 있는 Windows 및 Linux Docker 이미지를 제공합니다.

Docker가 설치된 Linux 컴퓨터는 Linux 컨테이너만 실행할 수 있습니다. Docker가 설치된 Windows 컴퓨터는 두 가지 컨테이너를 모두 실행할 수 있습니다. Windows가 둘 다 실행할 수 있는 이유는 가상 머신을 사용하여 Linux 시스템을 실행하고, 가상 Linux 시스템을 사용하여 Linux 컨테이너를 실행하기 때문입니다.

이 모듈에서는 Linux 기반 이미지를 빌드하고 실행하겠습니다.

Docker 레지스트리 및 Docker 허브

Docker 이미지는 레지스트리에 저장되어 제공됩니다. Docker가 컨테이너 이미지를 업로드 및 다운로드하기 위해 연결하는 웹 서비스가 레지스트리입니다. 가장 잘 알려진 레지스트리는 공개 레지스트리인 Docker 허브입니다. 여러 개인과 조직이 Docker Hub에 이미지를 게시하며 데스크톱, 서버 또는 클라우드에서 실행되는 Docker를 사용하여 이러한 이미지를 다운로드하고 실행할 수 있습니다. Docker Hub 체험용 계정을 만들고 사용자 이미지를 업로드할 수 있습니다.

레지스트리는 일련의 리포지토리로 구성됩니다. 각 리포지토리는 공통 이름 및 일반적으로 동일한 목적과 기능을 공유하는 Docker 이미지를 포함하고 있습니다. 이러한 이미지에는 일반적으로 태그를 사용하여 식별된 서로 다른 버전이 있습니다. 이 메커니즘을 이용하여 호환성을 위해 여러 버전의 이미지를 게시하고 유지할 수 있습니다. 이미지를 다운로드하여 실행할 때 이미지의 레지스트리, 리포지토리 및 버전 태그를 지정해야 합니다. 태그는 텍스트 레이블이며 사용자의 버전 번호 지정 시스템(v1.0, v1.1, v1.2, v2.0 등)을 사용할 수 있습니다.

ASP.NET Core 런타임 Docker 이미지를 사용하려는 경우를 가정해 보겠습니다. 이 이미지는 다음과 같은 두 가지 버전으로 제공됩니다.

  • mcr.microsoft.com/dotnet/core/aspnet:2.2
  • mcr.microsoft.com/dotnet/core/aspnet:2.1

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

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

참고

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

리포지토리는 이미지의 개인 정보 단위이기도 합니다. 이미지를 공유하고 싶지 않으면 리포지토리를 프라이빗으로 만들면 됩니다. 이미지를 공유하고 싶은 다른 사용자에게 액세스 권한을 부여할 수 있습니다.

Docker 허브를 찾아 이미지 끌어오기

참고 항목

다음 섹션에서는 예제를 완료하거나 코드를 실행할 필요가 없습니다. 다음 단원에서 수행할 예정입니다.

종종 여러분이 컨테이너화하려는 유형의 앱과 거의 일치하는 이미지를 Docker Hub에서 찾을 수 있습니다. 이러한 이미지를 다운로드하여 사용자의 애플리케이션 코드로 확장할 수 있습니다.

Docker Hub는 수천 개의 이미지를 포함합니다. 명령줄 또는 Docker Hub 웹 사이트에서 Docker를 사용하여 레지스트리를 검색하고 찾아볼 수 있습니다. 웹 사이트에서 형식 및 게시자별로 이미지를 검색, 필터링 및 선택할 수 있습니다. 아래 그림은 검색 페이지의 예를 보여줍니다.

다양한 컨테이너 이미지를 나열하는 Docker Hub 검색 페이지의 스크린샷.

docker pull 명령을 사용하여 이미지 이름으로 이미지를 검색합니다. 리포지토리 이름만 지정하는 경우 기본적으로 Docker는 Docker Hub의 해당 리포지토리에서 이미지 태그된 latest만을 다운로드합니다. 명령을 수정하여 다른 태그를 다른 리포지토리에서 가져올 수 있습니다. 이 예제에서는 태그가 포함된 이미지 aspnetappmcr.microsoft.com/dotnet/core/samples:aspnetapp 리포지토리에서 가져옵니다. 이 이미지에는 간단한 ASP.NET Core 웹앱이 포함되어 있습니다.

참고

이 단원의 예제는 다양한 Docker 명령 구문을 보여주기 위해 작성되었습니다. 이 단원을 읽는 동안 이러한 명령을 꼭 실행할 필요는 없습니다. 이 단원이 끝난 후 이어지는 연습에서는 Docker로 직접 작업하는 방법을 안내합니다.

docker pull mcr.microsoft.com/dotnet/samples:aspnetapp

이미지를 페치하면 Docker는 이미지를 로컬로 저장하고 실행 중인 컨테이너에 사용할 수 있게 만듭니다. docker image list 명령을 사용하여 로컬 레지스트리의 이미지를 볼 수 있습니다.

docker image list

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

REPOSITORY TAG IMAGE ID CREATED SIZE
mcr.microsoft.com/dotnet/samples   aspnetapp           6e2737d83726        6 days ago          263MB

이미지 이름 ID를 사용하여 다른 여러 Docker 명령에서 이미지를 참조합니다.

Docker 컨테이너 실행

docker run 명령을 사용하여 컨테이너를 시작합니다. 이미지 이름 또는 ID를 사용하여 실행할 이미지를 지정합니다. 아직 이미지를 docker pull 하지 않은 경우 Docker가 알아서 처리합니다.

docker run mcr.microsoft.com/dotnet/samples:aspnetapp

이 예제에서는 이 명령이 다음 메시지로 응답합니다.

warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
 No XML encryptor configured. Key {d8e1e1ea-126a-4383-add9-d9ab0b56520d} may be persisted to storage in unencrypted form.
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.

이 이미지에는 웹앱이 들어 있으며, 현재 HTTP 포트 80에 도착하는 요청을 수신 대기 중입니다. 하지만 웹 브라우저를 열고 http://localhost:80으로 이동하면 앱이 보이지 않게 됩니다.

기본적으로 Docker는 인바운드 네트워크 요청이 컨테이너에 도달하는 것을 허용하지 않습니다. -p 옵션을 docker run에 추가하여 컴퓨터의 특정 포트 번호를 컨테이너의 특정 포트 번호에 할당하라고 Docker에 지시해야 합니다. 이 지시로 지정된 포트의 컨테이너에 대한 네트워크 요청이 가능해집니다.

뿐만 아니라 이 이미지의 웹앱은 명령줄에서 대화형으로 사용하도록 설계되지 않았습니다. 웹앱을 시작하면 Docker가 웹앱을 백그라운드에서 시작하고 단지 실행되는 것만 허용해야 합니다. -d 플래그를 사용하여 웹앱을 백그라운드에서 시작하도록 Docker에 지시합니다.

다음 예제에 나온 것처럼 이미지를 중지한 뒤 다시 시작하려면 Ctrl+C를 누릅니다.

docker run -p 8080:80 -d mcr.microsoft.com/dotnet/samples:aspnetapp

이 명령은 컨테이너의 포트 80을 컴퓨터의 포트 8080에 매핑합니다. 브라우저에서 http://localhost:8080 페이지를 방문하면 샘플 웹앱이 보입니다.

브라우저에서 실행 중인 샘플 웹앱의 스크린샷.

컨테이너 및 파일

실행 중인 컨테이너가 이미지의 파일을 변경하는 경우 해당 변경 내용은 변경이 수행된 컨테이너에만 있습니다. 컨테이너의 상태를 보존하는 특별한 단계를 수행하지 않는 이상, 컨테이너가 제거될 때 이러한 변경 내용도 손실됩니다. 마찬가지로, 동일한 이미지를 기반으로 동시에 실행되는 여러 컨테이너는 이미지의 파일을 공유하지 않습니다. 각 컨테이너에는 독립적인 자체 복사본이 있습니다. 한 컨테이너가 파일 시스템에 쓴 데이터는 다른 컨테이너에서 보이지 않습니다.

쓰기 가능 볼륨을 컨테이너에 추가할 수 있습니다. 볼륨은 컨테이너에 탑재할 수 있는 파일 시스템을 나타내며, 컨테이너에서 실행 중인 애플리케이션에 사용할 수 있습니다. 컨테이너가 중지되면 볼륨의 데이터가 유지되지 않으며, 여러 컨테이너가 같은 볼륨을 공유할 수 있습니다. 볼륨을 만들고 사용하는 방법에 대한 자세한 내용은 이 모듈의 범위를 벗어납니다.

Docker를 사용하여 배포된 애플리케이션용 이미지 파일 시스템에 대해 변경이 필요하지 않도록 하는 것이 좋습니다. 손실되어도 괜찮은 임시 파일에만 사용합니다.

Docker 컨테이너 관리

docker ps 명령을 사용하여 활성 컨테이너를 볼 수 있습니다.

docker ps

출력에는 컨테이너의 상태(실행 중인 경우 Up, 종료된 경우 Exited) 외에도 이미지를 시작할 때 지정된 명령줄 플래그 및 추가 정보가 포함되어 있습니다. Docker를 사용하면 동일한 이미지의 여러 컨테이너를 동시에 실행할 수 있음으로, 각 컨테이너에 고유의 ID와 알기 쉬운 고유의 이름이 할당됩니다. 개별 컨테이너 관리에 사용되는 대부분의 Docker 명령은 ID 또는 이름을 사용하여 특정 컨테이너를 참조할 수 있습니다.

다음 출력에서 두 개의 컨테이너를 볼 수 있습니다. PORTS 필드를 보면 ID가 elegant_ramanujan인 컨테이너는 컴퓨터의 포트 8080에 매핑된 Docker 호스트에서 포트 80으로 실행되는 이미지입니다. youthful_heisenberg 인스턴스는 이전 이미지 실행의 컨테이너입니다. COMMAND 필드는 컨테이너가 이미지의 애플리케이션을 시작하기 위해 실행한 명령을 보여줍니다. 이 예에서는 두 컨테이너 모두 dotnet aspnetapp.dll입니다. 두 컨테이너가 동일한 이미지를 실행하므로 컨테이너의 이미지 ID 역시 동일합니다.

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57b9587583e3        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   42 seconds ago      Up 41 seconds       0.0.0.0:8080->80/tcp   elegant_ramanujan
d27071f3ca27        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   5 minutes ago      Up 5 minutes       0.0.0.0:8081->80/tcp   youthful_heisenberg

참고

docker psdocker container ls의 바로 가기입니다. 이러한 명령의 이름은 각각 실행 중인 프로세스와 파일을 나열하는 Linux 유틸리티 psls를 기반으로 합니다.

docker stop 명령을 사용하고 컨테이너 ID를 지정하여 활성 컨테이너를 중지할 수 있습니다.

docker stop elegant_ramanujan

docker ps 명령을 다시 실행하면 elegant_ramanujan 컨테이너가 더 이상 출력에 보이지 않습니다. 이 컨테이너는 여전히 존재하지만 실행 중인 프로세스를 더 이상 호스트하지 않습니다. 중지된 컨테이너를 docker ps 출력에 포함하려면 -a 플래그를 포함하면 됩니다.

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57b9587583e3        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   2 minutes ago       Exited (0) 21 seconds ago                       elegant_ramanujan
d27071f3ca27        mcr.microsoft.com/dotnet/core/samples:aspnetapp   "dotnet aspnetapp.dll"   7 minutes ago      Up 7 minutes       0.0.0.0:8081->80/tcp   youthful_heisenberg

중지된 컨테이너를 다시 시작하려면 docker start 명령을 사용합니다. 컨테이너의 기본 프로세스가 새로 시작됩니다.

docker start elegant_ramanujan

일반적으로 컨테이너가 중지되면 컨테이너를 제거해야 합니다. 컨테이너를 제거하면 컨테이너가 남긴 리소스가 정리합니다. 컨테이너를 제거하면 해당 이미지 파일 시스템 내에서 수행한 모든 변경 내용이 영구적으로 손실됩니다.

docker rm elegant_ramanujan

실행 중인 컨테이너를 제거할 수 없지만, docker rm 명령에 -f 플래그를 사용하여 컨테이너를 강제로 중지하고 제거할 수 있습니다. 이 방법으로 신속하게 컨테이너를 중지하고 제거할 수 있지만, 컨테이너 내부의 앱이 정상 종료를 수행하지 않아도 되는 경우에만 사용해야 합니다.

docker container rm -f elegant_ramanujan

Docker 이미지 제거

docker image rm 명령을 사용하여 로컬 컴퓨터에서 이미지를 제거할 수 있습니다. 제거할 이미지의 이미지 ID를 지정합니다. 다음 예제는 샘플 웹앱의 이미지를 제거합니다.

docker image rm mcr.microsoft.com/dotnet/core/samples:aspnetapp

이미지를 제거하려면 먼저 이미지를 실행하는 컨테이너를 종료해야 합니다. 컨테이너에서 여전히 이미지를 사용하고 있는 경우 다음과 같은 오류 메시지가 표시됩니다. 이 예제에서는 youthful_heisenberg 컨테이너가 여전히 이미지를 사용 중이기 때문에 오류가 발생합니다.

Error response from daemon: conflict: unable to delete 575d85b4a69b (cannot be forced) - image is being used by running container c13165988cfe