다음을 통해 공유


.NET 앱 참조 컨테이너화

이 참조 문서에서는 .NET 앱을 컨테이너로 게시할 때 생성되는 컨테이너 이미지를 구성하는 방법에 대해 알아봅니다. 이 문서에서는 컨테이너가 시작될 때 실행되는 이미지, 실행 환경 및 명령을 제어하도록 설정할 수 있는 다양한 속성에 대해 설명합니다.

컨테이너 이미지 구성

MSBuild 속성을 통해 생성된 컨테이너의 여러 측면을 제어할 수 있습니다. 일반적으로 Dockerfile 명령을 사용하여 일부 구성을 설정할 수 있는 경우 MSBuild를 통해 동일한 작업을 수행할 수 있습니다.

메모

이에 대한 유일한 예외는 RUN 명령입니다. 컨테이너를 빌드하는 방식으로 인해 컨테이너를 에뮬레이트할 수 없습니다. 이 기능이 필요한 경우 Dockerfile 사용하여 컨테이너 이미지를 빌드하는 것이 좋습니다.

.NET SDK를 사용하여 RUN 명령을 수행할 수 있는 방법은 없습니다. 이러한 명령은 종종 일부 OS 패키지를 설치하거나 새 OS 사용자 또는 임의의 항목을 만드는 데 사용됩니다. .NET SDK 컨테이너 빌드 기능을 계속 사용하려는 경우 이러한 변경 내용으로 사용자 지정 기본 이미지를 만든 다음 이 기본 이미지를 사용할 수 있습니다. 자세한 내용은 ContainerBaseImage참조하세요.

ContainerArchiveOutputPath

tar.gz 보관 파일 내에 컨테이너 이미지를 만들려면 ContainerArchiveOutputPath 속성을 사용합니다. 이 기능은 워크플로가 간단하지 않고 이미지를 푸시하기 전에 이미지에 대해 검사 도구를 실행해야 하는 경우에 유용합니다. 보관이 만들어지면 이동하거나, 스캔하거나, 로컬 Docker 도구 체인에 로드할 수 있습니다.

보관 파일에 게시하려면 dotnet publish 명령에 ContainerArchiveOutputPath 속성을 추가합니다. 예를 들면 다음과 같습니다.

dotnet publish \
  -p PublishProfile=DefaultContainer \
  -p ContainerArchiveOutputPath=./images/sdk-container-demo.tar.gz

폴더 이름 또는 특정 파일 이름을 가진 경로를 지정할 수 있습니다. 폴더 이름을 지정하면 이미지 보관 파일에 대해 생성된 파일 이름이 $(ContainerRepository).tar.gz. 이러한 보관 파일에는 모든 ContainerImageTags대해 단일 파일이 생성되므로 내부에 여러 태그가 포함될 수 있습니다.

컨테이너 이미지 명명 구성

컨테이너 이미지는 특정 명명 규칙을 따릅니다. 이미지의 이름은 여러 부분, 레지스트리, 선택적 포트, 리포지토리 및 선택적 태그 및 패밀리로 구성됩니다.

REGISTRY[:PORT]/REPOSITORY[:TAG[-FAMILY]]

예를 들어 정규화된 mcr.microsoft.com/dotnet/runtime:8.0-alpine 이미지 이름을 고려합니다.

  • mcr.microsoft.com 레지스트리입니다(이 경우 Microsoft 컨테이너 레지스트리를 나타낸다).
  • dotnet/runtime 리포지토리입니다(그러나 일부는 user/repository고려).
  • 8.0-alpine 태그 및 패밀리입니다(패밀리는 OS 패키징을 명확하게 하는 데 도움이 되는 선택적 지정자입니다).

다음 섹션에서 설명하는 일부 속성은 생성된 이미지 이름의 일부를 관리하는 데 해당합니다. 이미지 이름과 빌드 속성 간의 관계를 매핑하는 다음 테이블을 고려합니다.

이미지 이름 부분 MSBuild 속성 예제 값
REGISTRY[:PORT] ContainerRegistry mcr.microsoft.com:443
PORT ContainerPort :443
REPOSITORY ContainerRepository dotnet/runtime
TAG ContainerImageTag 8.0
FAMILY ContainerFamily -alpine

다음 섹션에서는 생성된 컨테이너 이미지를 제어하는 데 사용할 수 있는 다양한 속성에 대해 설명합니다.

ContainerBaseImage

컨테이너 기본 이미지 속성은 이미지의 기준으로 사용되는 이미지를 제어합니다. 기본적으로 다음 값은 프로젝트의 속성에 따라 유추됩니다.

  • 프로젝트가 자체 포함된 경우 mcr.microsoft.com/dotnet/runtime-deps 이미지가 기본 이미지로 사용됩니다.
  • 프로젝트가 ASP.NET Core 프로젝트인 경우 mcr.microsoft.com/dotnet/aspnet 이미지가 기본 이미지로 사용됩니다.
  • 그렇지 않으면 mcr.microsoft.com/dotnet/runtime 이미지가 기본 이미지로 사용됩니다.

이미지의 태그는 선택한 TargetFramework숫자 구성 요소로 유추됩니다. 예를 들어 net6.0 대상으로 하는 프로젝트는 유추된 기본 이미지의 6.0 태그를 생성하고 net7.0-linux 프로젝트는 7.0 태그 등을 사용합니다.

여기서 값을 설정하는 경우 원하는 태그를 포함하여 기본으로 사용할 이미지의 정규화된 이름을 설정해야 합니다.

<PropertyGroup>
    <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime:8.0</ContainerBaseImage>
</PropertyGroup>

.NET SDK 버전 8.0.200을 사용하면 크기 및 보안을 최적화하기 위해 ContainerBaseImage 유추가 향상됩니다.

  • linux-musl-x64 또는 linux-musl-arm64 런타임 식별자를 대상으로 지정하면 alpine 이미지 변형을 자동으로 선택하여 프로젝트가 실행되도록 합니다.
    • 프로젝트에서 PublishAot=true 사용하는 경우 최상의 크기와 보안을 위해 기본 이미지의 nightly/runtime-depsjammy-chiseled-aot 변형입니다.
    • 프로젝트에서 InvariantGlobalization=false 사용하는 경우 -extra 변형을 사용하여 지역화가 계속 작동하는지 확인합니다.

이미지 변형 크기 및 특성에 대한 자세한 내용은 .NET 8.0 컨테이너 이미지 크기 보고서참조하세요.

ContainerFamily

.NET 8부터 ContainerFamily MSBuild 속성을 사용하여 다른 Microsoft 제공 컨테이너 이미지 제품군을 앱의 기본 이미지로 선택할 수 있습니다. 이 값을 설정하면 선택한 TFM별 태그의 끝에 이 값이 추가되고 제공된 태그가 변경됩니다. 예를 들어 .NET 기본 이미지의 Alpine Linux 변형을 사용하려면 ContainerFamilyalpine설정할 수 있습니다.

<PropertyGroup>
    <ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>

위의 프로젝트 구성은 .NET 8 대상 앱에 대한 최종 8.0-alpine 태그를 생성합니다.

이 필드는 자유 형식이며, 종종 다른 운영 체제 배포, 기본 패키지 구성 또는 다른 버전 기본 이미지 변경 내용을 선택하는 데 사용할 수 있습니다. 이 필드는 ContainerBaseImage 설정되면 무시됩니다. 자세한 내용은 .NET 컨테이너 이미지참조하세요.

ContainerRuntimeIdentifier

ContainerBaseImage 여러 플랫폼을 지원하는 경우 ContainerRuntimeIdentifier 속성은 컨테이너에 대한 OS 및 아키텍처를 지정합니다. 예를 들어 mcr.microsoft.com/dotnet/runtime 이미지는 linux-x64, linux-arm, linux-arm64win10-x64지원합니다. 기본적으로 컨테이너를 게시할 때 사용되는 RuntimeIdentifier 설정됩니다. 일반적으로 이 속성을 명시적으로 설정할 필요가 없습니다. 대신 dotnet publish 명령과 함께 -r 옵션을 사용합니다. 선택한 이미지가 지정된 RuntimeIdentifier지원하지 않으면 지원되는 식별자를 나타내는 오류가 발생합니다.

이 속성을 사용하지 않도록 항상 ContainerBaseImage 속성을 태그를 포함한 정규화된 이미지 이름으로 설정할 수 있습니다.

<PropertyGroup>
    <ContainerRuntimeIdentifier>linux-arm64</ContainerRuntimeIdentifier>
</PropertyGroup>

.NET에서 지원하는 런타임 식별자에 대한 자세한 내용은 RID 카탈로그참조하세요.

ContainerRegistry

컨테이너 레지스트리 속성은 새로 만든 이미지를 푸시할 대상 레지스트리를 제어합니다. 기본적으로 로컬 Docker 디먼으로 푸시되지만 원격 레지스트리를 지정할 수도 있습니다. 인증이 필요한 원격 레지스트리를 사용하는 경우 잘 알려진 docker login 메커니즘을 사용하여 인증합니다. 자세한 내용은 컨테이너 레지스트리 인증하는 참조하세요. 이 속성을 사용하는 구체적인 예제는 다음 XML 예제를 참조하세요.

<PropertyGroup>
    <ContainerRegistry>registry.mycorp.com:1234</ContainerRegistry>
</PropertyGroup>

이 도구는 Docker 레지스트리 HTTP API V2지원하는 모든 레지스트리에 게시를 지원합니다. 여기에는 다음 레지스트리가 명시적으로 포함되며 암시적으로 더 많을 수 있습니다.

  • Azure Container Registry
  • amazon Elastic Container Registry
  • Google Artifact Registry
  • docker Hub
  • GitHub 패키지
  • GitLab 호스팅 Container Registry
  • Quay.io

이러한 레지스트리 작업에 대한 참고 사항은레지스트리 관련 참고 사항을 참조하세요.

ContainerRepository

컨테이너 리포지토리는 이미지 자체의 이름(예: dotnet/runtime 또는 my-app)입니다. 기본적으로 프로젝트의 AssemblyName 사용됩니다.

<PropertyGroup>
    <ContainerRepository>my-app</ContainerRepository>
</PropertyGroup>

이미지 이름은 하나 이상의 슬래시로 구분된 세그먼트로 구성되며, 각 세그먼트는 소문자 영숫자, 마침표, 밑줄 및 대시만 포함할 수 있으며 문자 또는 숫자로 시작해야 합니다. 다른 문자는 오류가 발생합니다.

ContainerImageTag(s)

컨테이너 이미지 태그 속성은 이미지에 대해 생성된 태그를 제어합니다. 단일 태그를 지정하려면 ContainerImageTag 사용하고 여러 태그에는 ContainerImageTags사용합니다.

중요하다

ContainerImageTags사용하면 고유한 태그당 하나씩 여러 개의 이미지가 표시됩니다.

태그는 종종 다른 버전의 앱을 참조하는 데 사용되지만 다른 운영 체제 배포 또는 다른 구성을 참조할 수도 있습니다.

.NET 8부터 태그가 제공되지 않는 경우 기본값은 latest.

기본값을 재정의하려면 다음 중 하나를 지정합니다.

<PropertyGroup>
    <ContainerImageTag>1.2.3-alpha2</ContainerImageTag>
</PropertyGroup>

여러 태그를 지정하려면 여러 TargetFrameworks설정하는 것과 유사하게 ContainerImageTags 속성에 세미콜론으로 구분된 태그 집합을 사용합니다.

<PropertyGroup>
    <ContainerImageTags>1.2.3-alpha2;latest</ContainerImageTags>
</PropertyGroup>

태그에는 최대 127개의 영숫자 문자, 마침표, 밑줄 및 대시만 포함될 수 있습니다. 영숫자 문자 또는 밑줄로 시작해야 합니다. 다른 양식에서는 오류가 발생합니다.

메모

ContainerImageTags사용하는 경우 태그는 ; 문자로 구분됩니다. 명령줄에서 dotnet publish 호출하는 경우(대부분의 CI/CD 환경과 마찬가지로) 값을 단일 ' 바깥쪽 래핑하고 "큰따옴표(예:='"tag-1;tag-2"')로 내부 래핑해야 합니다. 다음 dotnet publish 명령을 고려합니다.

dotnet publish -p ContainerImageTags='"1.2.3-alpha2;latest"'

그러면 my-app:1.2.3-alpha2my-app:latest두 개의 이미지가 생성됩니다.

ContainerImageTags 속성에 문제가 발생하는 경우 환경 변수 ContainerImageTags 범위를 지정하는 것이 좋습니다.

$Env:ContainerImageTags='1.2.3;latest'; dotnet publish --os linux --arch x64 /t:PublishContainer

ContainerLabel

컨테이너 레이블은 컨테이너에 메타데이터 레이블을 추가합니다. 레이블은 종종 보안 스캐너 및 기타 인프라 도구에서 사용할 버전 및 제작 메타데이터를 저장하는 데 사용됩니다. 원하는 수의 컨테이너 레이블을 지정할 수 있습니다.

ContainerLabel 노드에는 두 가지 특성이 있습니다.

  • Include: 레이블의 키입니다.
  • Value: 레이블의 값입니다(비어 있을 수 있음).
<ItemGroup>
    <ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>

기본적으로 생성되는 레이블 목록은기본 컨테이너 레이블을 참조하세요.

컨테이너 실행 구성

컨테이너의 실행을 제어하려면 다음 MSBuild 속성을 사용할 수 있습니다.

ContainerWorkingDirectory

컨테이너 작업 디렉터리 노드는 컨테이너의 작업 디렉터리를 제어합니다. 다른 명령이 실행되지 않는 경우 명령이 실행되는 디렉터리입니다.

기본적으로 /app 디렉터리 값은 작업 디렉터리로 사용됩니다.

<PropertyGroup>
    <ContainerWorkingDirectory>/bin</ContainerWorkingDirectory>
</PropertyGroup>

ContainerPort

컨테이너 포트는 컨테이너의 알려진 포트 목록에 TCP(Transmission Control Protocol) 또는 UDP(사용자 데이터그램 프로토콜) 포트를 추가합니다. 이렇게 하면 Docker와 같은 컨테이너 런타임에서 이러한 포트를 호스트 컴퓨터에 자동으로 매핑할 수 있습니다. 컨테이너에 대한 설명서로 자주 사용되지만 자동 포트 매핑을 사용하도록 설정하는 데도 사용할 수 있습니다.

ContainerPort 노드에는 두 가지 특성이 있습니다.

  • Include: 노출할 포트 번호입니다.
  • Type: 기본값은 tcp, 유효한 값은 tcp 또는 udp.
<ItemGroup>
    <ContainerPort Include="80" Type="tcp" />
</ItemGroup>

.NET 8부터는 잘 알려진 몇 가지 ASP.NET 환경 변수를 기반으로 명시적으로 제공되지 않은 경우 ContainerPort 유추됩니다.

  • ASPNETCORE_URLS
  • ASPNETCORE_HTTP_PORTS
  • ASPNETCORE_HTTPS_PORTS

이러한 환경 변수가 있는 경우 해당 값은 구문 분석되고 TCP 포트 매핑으로 변환됩니다. 이러한 환경 변수는 기본 이미지(있는 경우) 또는 프로젝트에 정의된 환경 변수에서 ContainerEnvironmentVariable 항목을 통해 읽습니다. 자세한 내용은 ContainerEnvironmentVariable참조하세요.

ContainerEnvironmentVariable

컨테이너 환경 변수 노드를 사용하면 컨테이너에 환경 변수를 추가할 수 있습니다. 환경 변수는 컨테이너에서 즉시 실행되는 앱에 액세스할 수 있으며 실행 중인 앱의 런타임 동작을 변경하는 데 자주 사용됩니다.

ContainerEnvironmentVariable 노드에는 두 가지 특성이 있습니다.

  • Include: 환경 변수의 이름입니다.
  • Value: 환경 변수의 값입니다.
<ItemGroup>
  <ContainerEnvironmentVariable Include="LOGGER_VERBOSITY" Value="Trace" />
</ItemGroup>

자세한 내용은 .NET 환경 변수참조하세요.

메모

현재 컨테이너 이미지를 게시할 때 .NET CLI에서 환경 변수를 설정할 수 없습니다. 자세한 내용은 GitHub: .NET SDK 컨테이너 빌드참조하세요.

컨테이너 명령 구성

기본적으로 컨테이너 도구는 앱에 대해 생성된 AppHost 이진 파일(앱에서 AppHost를 사용하는 경우) 또는 dotnet 명령과 앱의 DLL을 사용하여 앱을 시작합니다.

그러나 ContainerAppCommand, ContainerAppCommandArgs, ContainerDefaultArgsContainerAppCommandInstruction조합하여 앱이 실행되는 방식을 제어할 수 있습니다.

서로 다른 기본 이미지가 컨테이너 ENTRYPOINTCOMMAND 속성의 서로 다른 조합을 사용하고 모든 속성을 지원할 수 있기를 원하기 때문에 이러한 다양한 구성 요소가 존재합니다. 기본값은 대부분의 앱에서 사용할 수 있지만 앱 시작 동작을 사용자 지정하려면 다음을 수행해야 합니다.

  • 실행할 이진 파일을 식별하고 ContainerAppCommand
  • 애플리케이션을 실행하는 데 필요한 인수를 식별하고
  • 선택적 사용자가 재정의할 수 있는 인수(있는 경우)를 식별하고 ContainerDefaultArgs
  • ContainerAppCommandInstruction DefaultArgs 설정

자세한 내용은 다음 구성 항목을 참조하세요.

ContainerAppCommand

앱 명령 구성 항목은 앱의 논리적 진입점입니다. 대부분의 앱에서 앱에 대해 생성된 실행 파일 이진 파일인 AppHost입니다. 앱에서 AppHost를 생성하지 않는 경우 이 명령은 일반적으로 dotnet <your project dll>. 이러한 값은 기본 컨테이너의 ENTRYPOINT 이후 또는 ENTRYPOINT 정의되지 않은 경우 직접 적용됩니다.

ContainerAppCommand 구성에는 진입점 명령에 사용할 명령, 옵션 또는 인수를 나타내는 단일 Include 속성이 있습니다.

<ItemGroup Label="ContainerAppCommand Assignment">
  <!-- This is how you would start the dotnet ef tool in your container -->
  <ContainerAppCommand Include="dotnet" />
  <ContainerAppCommand Include="ef" />

  <!-- This shorthand syntax means the same thing, note the semicolon separating the tokens. -->
  <ContainerAppCommand Include="dotnet;ef" />
</ItemGroup>

ContainerAppCommandArgs

이 앱 명령 인수 구성 항목은 ContainerAppCommand적용해야 하는 앱에 대해 논리적으로 필요한 인수를 나타냅니다. 기본적으로 앱에 대해 생성되는 항목은 없습니다. 있는 경우 인수는 실행 시 컨테이너에 적용됩니다.

ContainerAppCommandArgs 구성에는 ContainerAppCommand 명령에 적용할 옵션 또는 인수를 나타내는 단일 Include 속성이 있습니다.

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above,
       this would be the way to force the database to update.
  -->
  <ContainerAppCommandArgs Include="database" />
  <ContainerAppCommandArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerAppCommandArgs Include="database;update" />
</ItemGroup>

ContainerDefaultArgs

이 기본 인수 구성 항목은 앱에 대해 사용자가 재정의할 수 있는 인수를 나타냅니다. 이는 앱을 쉽게 시작할 수 있지만 사용자 지정하기 쉬운 방식으로 실행해야 하는 기본값을 제공하는 좋은 방법입니다.

ContainerDefaultArgs 구성에는 ContainerAppCommand 명령에 적용할 옵션 또는 인수를 나타내는 단일 Include 속성이 있습니다.

<ItemGroup>
  <!-- Assuming the ContainerAppCommand defined above,
       this would be the way to force the database to update.
  -->
  <ContainerDefaultArgs Include="database" />
  <ContainerDefaultArgs Include="update" />

  <!-- This is the shorthand syntax for the same idea -->
  <ContainerDefaultArgs Include="database;update" />
</ItemGroup>

ContainerAppCommandInstruction

앱 명령 명령 구성은 ContainerEntrypoint, ContainerEntrypointArgs, ContainerAppCommand, ContainerAppCommandArgsContainerDefaultArgs 결합하여 컨테이너에서 실행되는 최종 명령을 구성하는 방법을 제어하는 데 도움이 됩니다. 이는 기본 이미지에 ENTRYPOINT 있는지여부에 따라 크게 달라집니다. 이 속성은 "DefaultArgs", "Entrypoint"또는 "None"세 가지 값 중 하나를 사용합니다.

  • Entrypoint:
    • 이 모드에서 진입점은 ContainerAppCommand, ContainerAppCommandArgsContainerDefaultArgs의해 정의됩니다.
  • None:
    • 이 모드에서 진입점은 ContainerEntrypoint, ContainerEntrypointArgsContainerDefaultArgs의해 정의됩니다.
  • DefaultArgs:
    • 가장 복잡한 모드입니다. ContainerEntrypoint[Args] 항목이 없으면 ContainerAppCommand[Args]ContainerDefaultArgs 사용하여 진입점 및 명령을 만듭니다. dotnet 또는 /usr/bin/dotnet 하드 코딩된 기본 이미지의 기본 이미지 진입점은 완전히 제어할 수 있도록 건너뜁히게 됩니다.
    • ContainerEntrypointContainerAppCommand 모두 있는 경우 ContainerEntrypoint 진입점이 되고 ContainerAppCommand 명령이 됩니다.

메모

ContainerEntrypointContainerEntrypointArgs 구성 항목은 .NET 8을 기준으로 더 이상 사용되지 않습니다.

중요하다

이는 고급 사용자용입니다. 대부분의 앱은 진입점을 이 정도까지 사용자 지정할 필요가 없습니다. 자세한 내용 및 시나리오에 대한 사용 사례를 제공하려는 경우 GitHub: .NET SDK 컨테이너가토론 빌드를 참조하세요.

ContainerUser

사용자 구성 속성은 컨테이너가 실행되는 기본 사용자를 제어합니다. 이는 종종 보안을 위한 모범 사례인 루트가 아닌 사용자로 컨테이너를 실행하는 데 사용됩니다. 이 구성에 대해 알아야 할 몇 가지 제약 조건이 있습니다.

  • 사용자 이름, Linux 사용자 ID, 그룹 이름, Linux 그룹 ID, username:groupname및 기타 ID 변형 등 다양한 형식을 사용할 수 있습니다.
  • 지정된 사용자 또는 그룹이 이미지에 있는지 확인하지 않습니다.
  • 사용자를 변경하면 특히 파일 시스템 권한과 관련해서 앱의 동작이 변경됩니다.

이 필드의 기본값은 프로젝트 TFM 및 대상 운영 체제에 따라 다릅니다.

  • .NET 8 이상을 대상으로 하고 Microsoft 런타임 이미지를 사용하는 경우 다음을 수행합니다.
    • Linux에서 루트 없는 사용자 app 사용됩니다(사용자 ID로 참조됨).
    • Windows에서 루트 없는 사용자 ContainerUser 사용됩니다.
  • 그렇지 않으면 기본 ContainerUser 사용되지 않습니다.
<PropertyGroup>
  <ContainerUser>my-existing-app-user</ContainerUser>
</PropertyGroup>

APP_UID 환경 변수는 컨테이너에서 사용자 정보를 설정하는 데 사용됩니다. 이 값은 기본 이미지에 정의된 환경 변수(예: Microsoft .NET 이미지처럼)에서 비롯되거나 ContainerEnvironmentVariable 구문을 통해 직접 설정할 수 있습니다.

루트 사용자로 실행되도록 앱을 구성하려면 ContainerUser 속성을 root. 프로젝트 파일에 다음을 추가합니다.

<PropertyGroup>
  <ContainerUser>root</ContainerUser>
</PropertyGroup>

또는 명령줄에서 dotnet publish 호출할 때 이 값을 설정할 수 있습니다.

dotnet publish -p ContainerUser=root

기본 컨테이너 레이블

레이블은 컨테이너 이미지에 일관된 메타데이터를 제공하는 데 자주 사용됩니다. 이 패키지는 생성된 이미지의 유지 관리 가능성을 높이기 위해 몇 가지 기본 레이블을 제공합니다.

  • org.opencontainers.image.created DateTime.UtcNow현재 값의 ISO 8601 형식으로 설정됩니다.

자세한 내용은 기존 레이블 인프라위에 기존 레이블 구현을 참조하세요.

참고 항목

  • dotnet 게시 사용하여 .NET 앱 컨테이너화
  • .NET 컨테이너 이미지