자습서: .NET 앱 컨테이너화

이 자습서에서는 Docker를 사용하여 .NET 애플리케이션을 컨테이너화하는 방법을 알아봅니다. 컨테이너에는 변경할 수 없는 인프라를 제공하고, 이식 가능한 아키텍처를 제공하고, 확장성을 사용하는 등의 많은 기능과 이점이 있습니다. 이미지를 사용하여 로컬 개발 환경이나 프라이빗 클라우드 또는 퍼블릭 클라우드용 컨테이너를 생성할 수 있습니다.

이 자습서에서는 다음을 수행합니다.

  • 간단한 .NET 앱 만들기 및 게시
  • .NET용 Dockerfile 만들기 및 구성
  • Docker 이미지 빌드
  • Docker 컨테이너 만들기 및 실행

.NET 애플리케이션용 Docker 컨테이너 빌드 및 배포 작업을 알아봅니다. Docker 플랫폼은 Docker 엔진을 사용하여 Docker 이미지로 앱을 신속하게 빌드하고 패키지합니다. 이 이미지는 계층화된 컨테이너에서 배포되고 실행되도록 Dockerfile 형식으로 작성됩니다.

참고 항목

이 자습서는 ASP.NET Core 앱에는 적합하지 않습니다. ASP.NET Core를 사용하는 경우 ASP.NET Core 애플리케이션을 컨테이너화하는 방법 알아보기 자습서를 참조하세요.

필수 조건

다음 필수 구성 요소를 설치합니다.

  • .NET 8+ SDK
    .NET가 설치되어 있는 경우 dotnet --info 명령을 사용하여 사용 중인 SDK를 확인합니다.
  • Docker Community Edition
  • Dockerfile 및 .NET 예제 앱의 임시 작업 폴더입니다. 이 자습서에서는 이름 docker-working이 작업 폴더로 사용됩니다.
  • .NET 7+ SDK
    .NET가 설치되어 있는 경우 dotnet --info 명령을 사용하여 사용 중인 SDK를 확인합니다.
  • Docker Community Edition
  • Dockerfile 및 .NET 예제 앱의 임시 작업 폴더입니다. 이 자습서에서는 이름 docker-working이 작업 폴더로 사용됩니다.

.NET 앱 만들기

Docker 컨테이너가 실행되는 .NET 앱이 필요합니다. 아직 없는 경우, 터미널을 열고 작업 폴더를 만든 후 입력합니다. 작업 폴더에서 다음 명령을 실행하여 App이라는 하위 디렉터리에서 새 프로젝트를 만듭니다.

dotnet new console -o App -n DotNet.Docker

폴더 트리는 다음과 같습니다.

📁 docker-working
    └──📂 App
        ├──DotNet.Docker.csproj
        ├──Program.cs
        └──📂 obj
            ├── DotNet.Docker.csproj.nuget.dgspec.json
            ├── DotNet.Docker.csproj.nuget.g.props
            ├── DotNet.Docker.csproj.nuget.g.targets
            ├── project.assets.json
            └── project.nuget.cache

dotnet new 명령은 App이라는 새 폴더를 만들고 “Hello World” 콘솔 애플리케이션을 생성합니다. 디렉터리를 변경하고 터미널 세션에서 App 폴더로 이동합니다. dotnet run 명령을 사용하여 앱을 시작합니다. 애플리케이션이 실행되고 명령 아래에 Hello World!를 인쇄합니다.

cd App
dotnet run
Hello World!

기본 템플릿은 터미널에 출력한 후 종료되는 앱을 만듭니다. 이 자습서에서는 무한 반복되는 앱을 사용합니다. 텍스트 편집기에서 Program.cs 파일을 엽니다.

Visual Studio Code를 사용하는 경우 이전 터미널 세션에서 다음 명령을 입력합니다.

code .

이렇게 하면 Visual Studio Code에서 프로젝트가 포함된 App 폴더가 열립니다.

Program.cs는 다음 C# 코드와 같이 표시됩니다.

Console.WriteLine("Hello World!");

1초마다 숫자를 계산하는 다음 코드로 파일을 바꿉니다.

var counter = 0;
var max = args.Length is not 0 ? Convert.ToInt32(args[0]) : -1;
while (max is -1 || counter < max)
{
    Console.WriteLine($"Counter: {++counter}");
    await Task.Delay(TimeSpan.FromMilliseconds(1_000));
}
var counter = 0;
var max = args.Length is not 0 ? Convert.ToInt32(args[0]) : -1;
while (max is -1 || counter < max)
{
    Console.WriteLine($"Counter: {++counter}");
    await Task.Delay(TimeSpan.FromMilliseconds(1_000));
}

파일을 저장하고 dotnet run을 사용하여 프로그램을 다시 테스트합니다. 이 앱은 무한 실행된다는 점을 명심하세요. 취소 명령 CTRL+C를 사용하여 앱을 중지합니다. 다음은 출력 예제입니다.

dotnet run
Counter: 1
Counter: 2
Counter: 3
Counter: 4
^C

명령줄의 숫자를 앱에 전달하면 해당 양까지만 계산되고 종료됩니다. 앱에서 dotnet run -- 5를 사용하여 5까지 계산해 보세요.

Important

-- 이후 매개 변수는 dotnet run 명령에 전달되지 않고 대신 애플리케이션에 전달됩니다.

.NET 앱 게시

Docker 이미지에 .NET 앱을 추가하기 전에 먼저 앱을 게시해야 합니다. 게시된 버전의 앱을 컨테이너에서 실행하는 것이 가장 좋습니다. 앱을 게시하려면 다음 명령을 실행합니다.

dotnet publish -c Release

이 명령은 앱을 publish 폴더로 컴파일합니다. 작업 폴더에서 publish 폴더의 경로는 .\App\bin\Release\net8.0\publish\여야 합니다.

이 명령은 앱을 publish 폴더로 컴파일합니다. 작업 폴더에서 publish 폴더의 경로는 .\App\bin\Release\net7.0\publish\이어야 합니다.

App 폴더에서 publish 폴더의 디렉터리 목록을 가져오고 DotNet.Docker.dll 파일이 생성되었는지 확인합니다.

dir .\bin\Release\net8.0\publish\

    Directory: C:\Users\default\App\bin\Release\net8.0\publish

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           9/22/2023  9:17 AM            431 DotNet.Docker.deps.json
-a---           9/22/2023  9:17 AM           6144 DotNet.Docker.dll
-a---           9/22/2023  9:17 AM         157696 DotNet.Docker.exe
-a---           9/22/2023  9:17 AM          11688 DotNet.Docker.pdb
-a---           9/22/2023  9:17 AM            353 DotNet.Docker.runtimeconfig.json
dir .\bin\Release\net7.0\publish\

    Directory: C:\Users\default\App\bin\Release\net7.0\publish

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           2/13/2023  1:52 PM            431 DotNet.Docker.deps.json
-a---           2/13/2023  1:52 PM           6144 DotNet.Docker.dll
-a---           2/13/2023  1:52 PM         153600 DotNet.Docker.exe
-a---           2/13/2023  1:52 PM          11052 DotNet.Docker.pdb
-a---           2/13/2023  1:52 PM            253 DotNet.Docker.runtimeconfig.json

Dockerfile 만들기

Dockerfile 파일은 docker build 명령에서 컨테이너 이미지를 만드는 데 사용됩니다. 이 파일은 확장명이 없는 Dockerfile이라는 텍스트 파일입니다.

.csproj를 포함하는 디렉터리에 Dockerfile이라는 파일을 만들고 텍스트 편집기에서 엽니다. 이 자습서에서는 .NET 런타임 이미지를 포함하고 .NET 콘솔 애플리케이션과 일치하는 ASP.NET Core 런타임 이미지를 사용합니다.

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
WORKDIR /App

# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]

참고 항목

mcr.microsoft.com/dotnet/runtime:8.0 이미지를 사용할 수 있지만 여기서는 의도적으로 ASP.NET Core 런타임 이미지가 사용됩니다.

Dockerfile은 빌드를 계층화하고 필요한 아티팩트만 남겨두어 이미지의 최종 크기를 최적화하는 다단계 빌드를 사용합니다. 자세한 내용은 Docker Docs: 다단계 빌드를 참조하세요.

FROM 키워드에는 정규화된 Docker 컨테이너 이미지 이름이 필요합니다. MCR(Microsoft Container Registry, mcr.microsoft.com)은 공개적으로 액세스할 수 있는 컨테이너를 호스트하는 Docker 허브의 신디케이트입니다. dotnet 세그먼트는 컨테이너 리포지토리이고, sdk 또는 aspnet 세그먼트는 컨테이너 이미지 이름입니다. 이미지에는 버전 관리에 사용되는 8.0태그가 지정됩니다. 따라서 mcr.microsoft.com/dotnet/aspnet:8.0은 .NET 8.0 런타임입니다. SDK에서 대상으로 지정된 런타임과 일치하는 런타임 버전을 풀해야 합니다. 예를 들어, 이전 섹션에서 만든 앱은 .NET 8.0 SDK를 사용하고 Dockerfile에서 참조하는 기본 이미지에 8.0 태그가 지정됩니다.

Important

Windows 기반 컨테이너 이미지를 사용하는 경우 단순히 8.0 이외의 이미지 태그를 지정해야 합니다(예: mcr.microsoft.com/dotnet/aspnet:8.0 대신 mcr.microsoft.com/dotnet/aspnet:8.0-nanoserver-1809). Nano Server 또는 Windows Server Core를 사용하는지 여부와 해당 OS 버전에 따라 이미지 이름을 선택합니다. .NET의 Docker Hub 페이지에서 지원되는 모든 태그의 전체 목록을 찾을 수 있습니다.

Dockerfile 파일을 저장합니다. 작업 폴더의 디렉터리 구조는 다음과 같이 표시됩니다. 문서에서 공간을 절약하기 위해 더 깊은 수준의 파일과 폴더의 일부가 생략되었습니다.

📁 docker-working
    └──📂 App
        ├── Dockerfile
        ├── DotNet.Docker.csproj
        ├── Program.cs
        ├──📂 bin
        │   └──📂 Release
        │       └──📂 net8.0
        │           └──📂 publish
        │               ├── DotNet.Docker.deps.json
        │               ├── DotNet.Docker.exe
        │               ├── DotNet.Docker.dll
        │               ├── DotNet.Docker.pdb
        │               └── DotNet.Docker.runtimeconfig.json
        └──📁 obj
            └──...
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env
WORKDIR /App

# Copy everything
COPY . ./
# Restore as distinct layers
RUN dotnet restore
# Build and publish a release
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]

참고 항목

mcr.microsoft.com/dotnet/runtime:7.0 이미지를 사용할 수 있지만 여기서는 의도적으로 ASP.NET Core 런타임 이미지가 사용됩니다.

Dockerfile은 빌드를 계층화하고 필요한 아티팩트만 남겨두어 이미지의 최종 크기를 최적화하는 다단계 빌드를 사용합니다. 자세한 내용은 Docker Docs: 다단계 빌드를 참조하세요.

FROM 키워드에는 정규화된 Docker 컨테이너 이미지 이름이 필요합니다. MCR(Microsoft Container Registry, mcr.microsoft.com)은 공개적으로 액세스할 수 있는 컨테이너를 호스트하는 Docker 허브의 신디케이트입니다. dotnet 세그먼트는 컨테이너 리포지토리이고, sdk 또는 aspnet 세그먼트는 컨테이너 이미지 이름입니다. 이미지에는 버전 관리에 사용되는 7.0태그가 지정됩니다. 따라서 mcr.microsoft.com/dotnet/aspnet:7.0은 .NET 7.0 런타임입니다. SDK에서 대상으로 지정된 런타임과 일치하는 런타임 버전을 풀해야 합니다. 예를 들어, 이전 섹션에서 만든 앱은 .NET 7.0 SDK를 사용하고 Dockerfile에서 참조하는 기본 이미지에 7.0 태그가 지정됩니다.

Dockerfile 파일을 저장합니다. 작업 폴더의 디렉터리 구조는 다음과 같이 표시됩니다. 문서에서 공간을 절약하기 위해 더 깊은 수준의 파일과 폴더의 일부가 생략되었습니다.

📁 docker-working
    └──📂 App
        ├── Dockerfile
        ├── DotNet.Docker.csproj
        ├── Program.cs
        ├──📂 bin
        │   └──📂 Release
        │       └──📂 net7.0
        │           └──📂 publish
        │               ├── DotNet.Docker.deps.json
        │               ├── DotNet.Docker.exe
        │               ├── DotNet.Docker.dll
        │               ├── DotNet.Docker.pdb
        │               └── DotNet.Docker.runtimeconfig.json
        └──📁 obj
            └──...

터미널에서 다음 명령을 실행합니다.

docker build -t counter-image -f Dockerfile .

Docker가 Dockerfile에서 각 줄을 처리합니다. docker build 명령의 .은 이미지의 빌드 컨텍스트를 설정합니다. -f 스위치는 Dockerfile의 경로입니다. 이 명령은 이미지를 빌드하고 해당 이미지를 가리키는 counter-image라는 로컬 리포지토리를 만듭니다. 이 명령이 완료된 후 docker images를 실행하여 설치된 이미지 목록을 확인합니다.

docker images
REPOSITORY                         TAG       IMAGE ID       CREATED          SIZE
counter-image                      latest    2f15637dc1f6   10 minutes ago   217MB

counter-image 리포지토리는 이미지의 이름입니다. latest 태그는 이미지를 식별하는 데 사용되는 태그입니다. 2f15637dc1f6은 이미지 ID입니다. 10 minutes ago는 이미지가 만들어진 시간입니다. 217MB는 이미지의 크기입니다. Dockerfile의 마지막 단계는 이미지에서 컨테이너를 만들고, 앱을 실행하고, 게시된 앱을 컨테이너에 복사하고, 진입점을 정의하는 것입니다.

FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]
docker images
REPOSITORY                         TAG       IMAGE ID       CREATED          SIZE
counter-image                      latest    2f15637dc1f6   10 minutes ago   208MB

counter-image 리포지토리는 이미지의 이름입니다. latest 태그는 이미지를 식별하는 데 사용되는 태그입니다. 2f15637dc1f6은 이미지 ID입니다. 10 minutes ago는 이미지가 만들어진 시간입니다. 208MB는 이미지의 크기입니다. Dockerfile의 마지막 단계는 이미지에서 컨테이너를 만들고, 앱을 실행하고, 게시된 앱을 컨테이너에 복사하고, 진입점을 정의하는 것입니다.

FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /App
COPY --from=build-env /App/out .
ENTRYPOINT ["dotnet", "DotNet.Docker.dll"]

COPY 명령은 컴퓨터의 지정된 폴더를 컨테이너의 폴더에 복사하도록 Docker에 지시합니다. 이 예제에서 publish 폴더는 컨테이너의 App/out 폴더에 복사됩니다.

WORKDIR 명령은 컨테이너 내부의 현재 디렉터리App으로 변경합니다.

다음 명령인 ENTRYPOINT는 컨테이너가 실행 파일로 실행되게 컨테이너를 구성하도록 Docker에 지시합니다. 컨테이너가 시작되면 ENTRYPOINT 명령이 실행됩니다. 이 명령이 종료되면 컨테이너가 자동으로 중지됩니다.

.NET 8 이전에는 읽기 전용으로 실행되도록 구성된 컨테이너가 Failed to create CoreCLR, HRESULT: 0x8007000E로 인해 실패할 수 있습니다. 이 문제를 해결하려면 DOTNET_EnableDiagnostics 환경 변수를 0(ENTRYPOINT 단계 바로 앞)로 지정합니다.

ENV DOTNET_EnableDiagnostics=0

다양한 .NET 환경 변수에 대한 자세한 내용은 .NET 환경 변수를 참조하세요.

참고 항목

.NET 6은 .NET 런타임 동작을 구성하는 환경 변수에 대해 COMPlus_ 대신 접두사 DOTNET_을 표준화합니다. 그러나 COMPlus_ 접두사도 계속 작동합니다. 이전 버전의 .NET 런타임을 사용하는 경우에도 환경 변수에 COMPlus_ 접두사를 사용해야 합니다.

컨테이너 만들기

이제 앱을 포함하는 이미지가 있으므로 컨테이너를 만들 수 있습니다. 두 가지 방법으로 컨테이너를 만들 수 있습니다. 먼저 중지된 새 컨테이너를 만듭니다.

docker create --name core-counter counter-image

docker create 명령은 카운터 이미지 이미지를 기반으로 컨테이너를 만듭니다. 해당 명령의 출력은 생성된 컨테이너의 CONTAINER ID(사용자에 따라 다름)를 표시합니다.

d0be06126f7db6dd1cee369d911262a353c9b7fb4829a0c11b4b2eb7b2d429cf

모든 컨테이너 목록을 보려면 docker ps -a 명령을 사용합니다.

docker ps -a
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS    PORTS     NAMES
d0be06126f7d   counter-image   "dotnet DotNet.Docke…"   12 seconds ago   Created             core-counter

컨테이너 관리

컨테이너는 특정 이름 core-counter를 사용하여 만들어졌으며, 이 이름은 컨테이너를 관리하는 데 사용됩니다. 다음 예제에서는 docker start 명령을 사용하여 컨테이너를 시작한 후 docker ps 명령을 사용하여 실행 중인 컨테이너만 표시합니다.

docker start core-counter
core-counter

docker ps
CONTAINER ID   IMAGE           COMMAND                  CREATED          STATUS          PORTS     NAMES
cf01364df453   counter-image   "dotnet DotNet.Docke…"   53 seconds ago   Up 10 seconds             core-counter

마찬가지로 docker stop 명령은 컨테이너를 중지합니다. 다음 예제에서는 docker stop 명령을 사용하여 컨테이너를 중지한 다음, docker ps 명령을 사용하여 컨테이너가 실행 중이지 않음을 보여 줍니다.

docker stop core-counter
core-counter

docker ps
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

컨테이너에 연결

컨테이너가 실행된 후 컨테이너에 연결하여 출력을 볼 수 있습니다. docker startdocker attach 명령을 사용하여 컨테이너를 시작하고 출력 스트림을 피킹합니다. 이 예제에서는 Ctrl+C 키 입력을 사용하여 실행 중인 컨테이너에서 분리합니다. 이 키 입력은 별도로 지정하지 않는 한 컨테이너의 프로세스를 종료합니다. 그러면 컨테이너가 중지됩니다. --sig-proxy=false 매개 변수는 Ctrl+C가 컨테이너에서 프로세스를 중지하지 않도록 합니다.

컨테이너에서 분리한 후 다시 연결하여 계속 실행 및 계산 중인지 확인합니다.

docker start core-counter
core-counter

docker attach --sig-proxy=false core-counter
Counter: 7
Counter: 8
Counter: 9
^C

docker attach --sig-proxy=false core-counter
Counter: 17
Counter: 18
Counter: 19
^C

컨테이너 삭제

이 문서에서는 아무 작업도 수행하지 않는 컨테이너가 남아 있는 것을 원하지 않습니다. 이전에 만든 컨테이너를 삭제합니다. 컨테이너가 실행 중이면 중지합니다.

docker stop core-counter

다음 예제에는 모든 컨테이너가 나와 있습니다. docker rm 명령을 사용하여 컨테이너를 삭제한 후 실행 중인 컨테이너가 있는지 다시 확인합니다.

docker ps -a
CONTAINER ID    IMAGE            COMMAND                   CREATED          STATUS                        PORTS    NAMES
2f6424a7ddce    counter-image    "dotnet DotNet.Dock…"    7 minutes ago    Exited (143) 20 seconds ago            core-counter

docker rm core-counter
core-counter

docker ps -a
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

단일 실행

Docker는 단일 명령으로 컨테이너를 만들고 실행할 수 있는 docker run 명령을 제공합니다. 이 명령을 사용하면 docker create를 실행한 후 docker start를 실행할 필요가 없습니다. 컨테이너가 중지될 때 컨테이너를 자동으로 삭제하도록 이 명령을 설정할 수도 있습니다. 예를 들어 docker run -it --rm을 사용하여 두 가지 작업을 수행합니다. 먼저 현재 터미널을 사용하여 컨테이너에 연결한 후 컨테이너가 완료되면 컨테이너를 제거합니다.

docker run -it --rm counter-image
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
^C

또한 컨테이너는 .NET 앱의 실행에 매개 변수를 전달합니다. .NET 앱에 3까지만 계산하도록 지시하려면 3을 전달합니다.

docker run -it --rm counter-image 3
Counter: 1
Counter: 2
Counter: 3

docker run -it를 사용하는 경우 Ctrl+C 명령은 컨테이너에서 실행 중인 프로세스를 중지하고, 결과적으로 컨테이너를 중지합니다. --rm 매개 변수가 제공되었으므로 프로세스가 중지되면 컨테이너가 자동으로 삭제됩니다. 컨테이너가 존재하지 않는지 확인합니다.

docker ps -a
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

ENTRYPOINT 변경

docker run 명령을 사용하면 Dockerfile에서 ENTRYPOINT 명령을 수정하고 해당 컨테이너에만 해당하는 다른 작업을 실행할 수 있습니다. 예를 들어 다음 명령을 사용하여 bash 또는 cmd.exe를 실행합니다. 필요에 따라 명령을 편집합니다.

이 예제에서 ENTRYPOINTcmd.exe로 변경됩니다. Ctrl+C를 눌러 프로세스를 종료하고 컨테이너를 중지합니다.

docker run -it --rm --entrypoint "cmd.exe" counter-image

Microsoft Windows [Version 10.0.17763.379]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\>dir
 Volume in drive C has no label.
 Volume Serial Number is 3005-1E84

 Directory of C:\

04/09/2019  08:46 AM    <DIR>          app
03/07/2019  10:25 AM             5,510 License.txt
04/02/2019  01:35 PM    <DIR>          Program Files
04/09/2019  01:06 PM    <DIR>          Users
04/02/2019  01:35 PM    <DIR>          Windows
               1 File(s)          5,510 bytes
               4 Dir(s)  21,246,517,248 bytes free

C:\>^C

필수 명령

Docker에는 컨테이너와 이미지를 만들고, 관리하며, 이와 상호 작용하는 다양한 명령이 있습니다. 이 Docker 명령은 컨테이너 관리에 필수적입니다.

리소스 정리

이 자습서에서는 컨테이너 및 이미지를 만들었습니다. 원하는 경우 이 리소스를 삭제합니다. 다음 명령을 사용하여 다음을 수행합니다.

  1. 모든 컨테이너 나열

    docker ps -a
    
  2. 이름으로 실행 중인 컨테이너를 중지합니다.

    docker stop core-counter
    
  3. 컨테이너 삭제

    docker rm core-counter
    

그런 다음, 머신에서 더 이상 사용하지 않을 이미지를 삭제합니다. Dockerfile에서 만든 이미지를 삭제한 후 Dockerfile이 기반으로 하는 .NET 이미지를 삭제합니다. IMAGE ID 또는 REPOSITORY:TAG 형식 문자열을 사용할 수 있습니다.

docker rmi counter-image:latest
docker rmi mcr.microsoft.com/dotnet/aspnet:8.0
docker rmi counter-image:latest
docker rmi mcr.microsoft.com/dotnet/aspnet:7.0

docker images 명령을 사용하여 설치된 이미지 목록을 확인합니다.

이미지 파일이 클 수 있습니다. 일반적으로 앱을 테스트하고 개발하는 동안 만든 임시 컨테이너를 제거합니다. 일반적으로 해당 런타임을 기반으로 다른 이미지를 빌드할 계획인 경우에는 설치된 런타임과 함께 기본 이미지를 유지합니다.

다음 단계