Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions samples/dotnetapp/dotnetapp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<!-- This property is requried to enable .NET SDK container publishing for
console apps only. It's enabled by default for web apps. -->
<!-- Learn more about .NET SDK container creation:
https://learn.microsoft.com/en-us/dotnet/core/containers/overview?tabs=windows -->
<EnableSdkContainerSupport>true</EnableSdkContainerSupport>
<RuntimeIdentifiers>linux-arm64;linux-x64</RuntimeIdentifiers>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd want this to work for Windows containers too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's technically possible but out of the box Windows containers require extra work for the .NET SDK publishing - because the 'base images' no longer support Windows you have to specify your own ContainerBaseImage and related properties. Nothing I've done prevents that work in this project, it just doesn't make it super-simple.

<RuntimeIdentifiers Condition="'$(Alpine)' == 'true'">linux-musl-arm64;linux-musl-x64</RuntimeIdentifiers>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice to be able to pivot to Alpine Linux easily - this sets the app up for simply showing multi-arch publishing as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this Alpine property built-in?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, I made it up (along with some of the other flags) just for scenario/convenience purposes. I think for real use cases users wouldn't need flags like this, they'd just decide what their deployment modality would be, but since the point is to make it easy to compare/contrast the same app in different modalities having simpler knobs helps.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the documentation associated with this project should demonstrate this and other custom properties.

</PropertyGroup>

<ItemGroup>
<ContainerEntrypoint Include="/app/$(MSBuildThisFileName)" />
</ItemGroup>

</Project>
55 changes: 55 additions & 0 deletions samples/globalapp/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# .NET build artifacts
bin/
obj/
out/

# Visual Studio / VS Code
.vs/
.vscode/
*.suo
*.user
*.userosscache
*.sln.docstates
*.swp
*.*~
project.lock.json

# NuGet
*.nupkg
*.snupkg
packages/
.nuget/

# Test results
TestResults/
[Tt]est[Rr]esult*/
*.trx
*.coverage
*.coveragexml

# Build logs
*.binlog
*.log

# OS files
.DS_Store
Thumbs.db

# Git
.git/
.gitignore
.gitattributes

# Docker
.dockerignore
Dockerfile*
docker-compose*

# CI/CD
.github/
.gitlab-ci.yml
azure-pipelines.yml

# Documentation
*.md
LICENSE
9 changes: 9 additions & 0 deletions samples/globalapp/Dockerfile.aot-sdk-publish
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# This image allows easily building and publishing AOT-compiled .NET applications
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having this image makes it fairly easy to create AOT'd ubuntu container variants using the .NET SDK - you map the Docker socket in and run the same publish command you would normally!

The one below is the same setup, but for Alpine Linux

# To use:
# * mount the Docker socket: `-v /var/run/docker.sock:/var/run/docker.sock`
# * mount the source code directory: `-v /path/to/source:/source`
# * call `dotnet publish -t PublishContainer` with/on a project that
# has been configured for AOT compilation
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-noble-aot AS builder
ARG TARGETARCH
RUN curl -fsSL https://get.docker.com -o get-docker.sh && sh ./get-docker.sh
8 changes: 8 additions & 0 deletions samples/globalapp/Dockerfile.aot-sdk-publish.alpine
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This image allows easily building and publishing AOT-compiled .NET applications
# To use:
# * mount the Docker socket: `-v /var/run/docker.sock:/var/run/docker.sock`
# * mount the source code directory: `-v /path/to/source:/source`
# * call `dotnet publish -t PublishContainer` with/on a project that
# has been configured for AOT compilation
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine-aot AS builder
RUN apk add --no-cache docker
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're using the host's Docker socket you only need the docker-cli package:

Suggested change
RUN apk add --no-cache docker
RUN apk add --no-cache docker-cli

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to find an equivalent for Ubuntu but didn't see anything obvious.

49 changes: 48 additions & 1 deletion samples/globalapp/globalapp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,54 @@
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableSdkContainerSupport>true</EnableSdkContainerSupport>
<RuntimeIdentifiers>linux-arm64;linux-x64</RuntimeIdentifiers>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a few 'pivots' to this project to show how a few relatively simple knobs can influence publishing. Broadly the pivots are

  • platform: Nobel, Nobel-Chiseled, or Alpine
  • Runtime: framework-dependent, self-contained, trimmed, or AOT
  • Globalization: variant or invariant

choosing combinations of those knobs sets up the containerization to do different things. Most of the required changes were just to the ContainerFamily property for actual impact - this changes the base image used. The ContainerImageTag changes are just for us so we can more easily compare and contrast the changes - without changing the tag all of these publishes would use the latest tag by default.

Pivoting through the variants, you get something like the following (ordered by size):

>docker image list globalapp
REPOSITORY   TAG                          IMAGE ID       CREATED          SIZE
globalapp    alpine-aot-invariant         a06647080c9a   7 minutes ago    24.3MB
globalapp    alpine-aot-variant           2f60494c5b87   8 minutes ago    78.6MB
globalapp    chiseled-aot-variant         bfecdd20d2d1   11 minutes ago   81.8MB
globalapp    chiseled-aot-invariant       e12baf4a93b0   11 minutes ago   24.5MB
globalapp    noble-variant                fa56d4783f20   21 minutes ago   415MB
globalapp    alpine                       e2bc432c4a16   21 minutes ago   183MB
globalapp    alpine-trimmed-invariant     bed2221d4a83   22 minutes ago   63.6MB
globalapp    alpine-trimmed-variant       e0fe24f9cfcf   23 minutes ago   133MB
globalapp    alpine-sc-variant            ac41be8d2f19   24 minutes ago   251MB
globalapp    noble-trimmed-variant        ac7cd08f90b4   29 minutes ago   296MB
globalapp    noble-trimmed-invariant      05efcb0dd9cd   32 minutes ago   296MB
globalapp    chiseled-trimmed-invariant   4bc0a3a87ae7   35 minutes ago   69.9MB
globalapp    chiseled-trimmed-variant     bdb06033a905   36 minutes ago   142MB
globalapp    chiseled-sc-variant          a6496ddf8bc8   37 minutes ago   422MB
globalapp    chiseled-variant             bdc0639ba482   37 minutes ago   261MB
globalapp    chiseled                     5a9503be26b2   44 minutes ago   189MB
globalapp    latest                       7587903084fb   47 minutes ago   415MB

<RuntimeIdentifiers Condition="'$(Alpine)' == 'true'">linux-musl-arm64;linux-musl-x64</RuntimeIdentifiers>
</PropertyGroup>

<PropertyGroup Condition="'$(Chiseled)' == 'true'">
<ContainerFamily>noble-chiseled</ContainerFamily>
<ContainerImageTag>chiseled</ContainerImageTag>
</PropertyGroup>

<PropertyGroup Condition="'$(Alpine)' == 'true'">
<ContainerImageTag>alpine</ContainerImageTag>
<ContainerFamily>alpine</ContainerFamily>
</PropertyGroup>

<PropertyGroup Condition="'$(Chiseled)' != 'true' and '$(Alpine)' != 'true'" >
<ContainerFamily>noble</ContainerFamily>
<ContainerImageTag>noble</ContainerImageTag>
</PropertyGroup>

<PropertyGroup Condition="'$(SC)' == 'true'">
<PublishSelfContained>true</PublishSelfContained>
<UseCurrentRuntimeIdentifier>false</UseCurrentRuntimeIdentifier>
<ContainerImageTag>$(ContainerImageTag)-sc</ContainerImageTag>
<AllowSelfContainedWithoutRuntimeIdentifier>true</AllowSelfContainedWithoutRuntimeIdentifier>
</PropertyGroup>

<PropertyGroup Condition="'$(Trimmed)' == 'true'">
<UseCurrentRuntimeIdentifier>false</UseCurrentRuntimeIdentifier>
<AllowSelfContainedWithoutRuntimeIdentifier>true</AllowSelfContainedWithoutRuntimeIdentifier>
<PublishTrimmed>true</PublishTrimmed>
<ContainerImageTag>$(ContainerImageTag)-trimmed</ContainerImageTag>
</PropertyGroup>

<PropertyGroup Condition="'$(AOT)' == 'true'">
<PublishAOT>true</PublishAOT>
<ContainerImageTag>$(ContainerImageTag)-aot</ContainerImageTag>
</PropertyGroup>

<PropertyGroup Condition="'$(InvariantGlobalization)' == 'true'">
<ContainerImageTag>$(ContainerImageTag)-invariant</ContainerImageTag>
</PropertyGroup>

<PropertyGroup Condition="'$(InvariantGlobalization)' != 'true' "> <!-- and ('$(PublishSelfContained)' == 'true' or '$(PublishTrimmed)' == 'true' or '$(PublishAOT)' == 'true')"> -->
<ContainerImageTag>$(ContainerImageTag)-variant</ContainerImageTag>
<ContainerFamily Condition="'$(Chiseled)' == 'true' or '$(Alpine)' == 'true'">$(ContainerFamily)-extra</ContainerFamily>
</PropertyGroup>

<ItemGroup>
<ContainerEntrypoint Include="/app/$(MSBuildThisFileName)" />
</ItemGroup>
</Project>