Skip to content

Infer container image properties from Project metadata #11

@baronfel

Description

@baronfel

Users should be able to easily set the key aspects of image configuration from their project file. There should be a clear integration point at which those values are 'fixed' and can no longer be changed, and there should be reasonable inference for these properties where it makes sense. Where relevant, we should rely on properties that are already conventionally available - packaging information from NuGet and source control information from SourceLink are good examples of these. That lets us make use of documentation and examples from those projects to lessen the number of new concepts here.

Image Metadata Required* Element Type Element Name Data Type Inference algorithm Example
Base Image Name Property ContainerBaseImageName string Based on the ProjectCapabilities of the project - if AspNetCore is present, prefer the dotnet/aspnet base image, otherwise prefer the dotnet/runtime image mcr.microsoft.com/dotnet/aspnet
Base Image Tag Property ContainerBaseImageTag string Based on the TargetFrameworkVersion of the project - net6.0 maps to the 6.0 tag, for example 6.0
Base Image Property ContainerBaseImage string If this is specified, it completely overrides ContainerBaseImageName and ContainerBaseImage. Otherwise, it is the result of concatenating them together, separated by :. mcr.microsoft.com/dotnet/aspnet:6.0
Image Name Property ContainerImageName string The value of the $(AssemblyName) property, lowercased so that it matches image name requirements weatherapp
Image Tag Property ContainerImageTag string The value of the Version property. This one is a bit loose, would folks prefer multiple tags here? 1.0.0
Working Directory Property ContainerWorkingDirectory string Defaults to /app. This directory will be the 'root' of the project's deployed files. /app
Entrypoint Item? ContainerEntrypoint string[] If the project is self-contained, the entrypoint defaults to the name of the generated apphost. Otherwise, for a framework-dependent project, the entrypoint defaults to dotnet <path to project's output.dll> dotnet weatherapp.dll. The path to the apphost or output dll will change based on the ContainerWorkingDirectory
Cmd Item? ContainerCommand string[] No inference. If specified, these arguments will be supplied to the container's entrypoint -
Ports Item ContainerPort <ContainerPort Include="<port number>" Type="tcp, udp" /> If the project has the AspNetCore capability, port entries for TCP 5000 and TCP 5001 will be created <ContainerPort Include="5000" Type="tcp"/><ContainerPort Include="5001" Type="tcp"/>
Environment Variables Item ContainerEnvironmentVariable <ContainerEnvironmentVariable Include="ASPNETCORE_URLS" Value="http://localhost:5000" /> If the project has the AspNetCore capability, the ASPNETCORE_URLS variable will be set to http://localhost:5000;https://localhost:5001
Labels Item ContainerLabel string key, string value We may set some of the well known labels, see below. <ContainerLabel Include="org.opencontainers.image.created" Value="2022-06-07T12:10:12Z" />
User Property ContainerUser string No default
Group Property ContainerGroup string No default, if specified the User must be specified as well

NOTE
Required in this case means required to have a working container image, not that the user is required to provide a value for the item. We will do inference to fill in all required items, erroring on validation if necessary.

Labels

There are some well-known labels that we should consider setting by default:

Annotation Key Derived from
org.opencontainers.image.created $([System.DateTime]::UtcNow.ToString("o"))
org.opencontainers.image.authors $(Authors)
org.opencontainers.image.url $(RepositoryUrl) if present.
org.opencontainers.image.documentation Since $(PackageLicenseUrl) is deprecated, we may just have to default to $(RepositoryUrl). Users should be able to override this easily though.
org.opencontainers.image.source $(RepositoryUrl) if present.
org.opencontainers.image.version $(Version) if present. Note that there's not really a consistent place to hook into where we can be assured of a version being set, so we'll want to be sometime directly before Build, but as late as possible otherwise.
org.opencontainers.image.vendor There's no $(PackageOwners) or $(Owners) to bootstrap off of, but maybe we should make one?
org.opencontainers.image.licenses $(PackageLicenseExpression)
org.opencontainers.image.ref.name $(RepositoryBranch) or $(RepositoryCommit). There's not a baked-in for git repo tags in SourceLink, which would be ideal. Commit is probably the best one.
org.opencontainers.image.title $(Title)
org.opencontainers.image.description $(Description)
org.opencontainers.image.base.digest The resolved digest of $(ContainerBaseImage)
org.opencontainers.image.base.name $(ContainerBaseImage)

Example project file

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net7.0</TargetFramework>
        <OutputType>Exe</OutputType>
        <Version>1.2.3</Version>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Dotnet.ReproducibleBuilds"  Version="1.1.1" PrivateAssets="all" />
    </ItemGroup>

    <ItemGroup>
        <ContainerPort Include="1234" Type="udp" />
        <ContainerEnvironmentVariable Include="LOG_LEVEL" Value="trace" />
        <ContainerLabel Include="org.contoso.businessunit" Value="C+AI" />
    </ItemGroup>
</Project>

Work Items

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions