This topic tells you how to use the Tanzu .NET Core Buildpack.

The Tanzu .NET Core Buildpack supports building several configurations of .NET Core applications.

Supported Dependencies

The Tanzu .NET Core Buildpack supports several versions of the .NET Core Framework. For more information about the specific versions supported in a given buildpack version, see the release notes.

Known Issues

Version 1.18.0 of the Tanzu .NET Core Buildpack has a known issue in which an app will fail to start after being rebuilt by the buildpack. Any workload built with version 1.18.0 of the buildpack is susceptible to this failure mode.

To mitigate:

  1. Delete any built images for the affected workload(s) from the image registry where Tanzu Build Service stores output images.
  2. Upgrade to a version of the buildpack v1.18.1 or later.
  3. Re-apply the workloads.

If impacted by this known issue, apps fail to start with an error message similar to:

Setting ASPNETCORE_URLS=http://0.0.0.0:8080
You must install or update .NET to run this application.

App: /workspace/WebApi
Architecture: x64
Framework: 'Microsoft.AspNetCore.App', version '6.0.0' (x64)
.NET location: /workspace/.dotnet_root

No frameworks were found.

Learn about framework resolution:
https://aka.ms/dotnet/app-launch-failed

To install missing framework, download:
https://aka.ms/dotnet-core-applaunch?framework=Microsoft.AspNetCore.App&framework_version=6.0.0&arch=x64&rid=ubuntu.18.04-x64

Alternately, apps fail to build with an error message similar to:

ERROR: failed to export: layer 'tanzu-buildpacks/dotnet-core-aspnet-lite:dotnet-core-aspnet' is cache=true but has no contents

To solve these failures, follow the mitigation steps listed above.

Application Types

The .NET Core Buildpack supports several types of application source code that can be built into a container image. Developers can provide raw source code, or built artifacts like Framework-Dependent Deployments/Executables or Self-Contained Deployments when building their application.

Source Applications

The .NET Core Buildpack is capable of building application source code into Framework-Dependent Deployments (FDD) or Executables (FDE). This is achieved using the dotnet publish command. By default, an FDE is produced.

Framework-Dependent Deployments or Framework-Dependent Executables

When building an application that has already been published as a Framework-Dependent Deployment or Framework-Dependent Executable, the buildpack will include the required .NET Core Framework dependencies and set the start command.

Self-Contained Deployment

When building an application as a Self-Contained Deployment(SCD), the buildpack will ensure the correct start command will be used to run your app. No .NET Core Framework dependencies will be included in the built image as they are already included in the SCD artifact.

Example Sample App Builds

This section demonstrates building the Paketo .NET Core Framework-Dependent Executable (FDE) sample app on different platforms.

How to use in Tanzu Application Platform

  1. Create a workload.yaml.

    ---
    apiVersion: carto.run/v1alpha1
    kind: Workload
    metadata:
      labels:
        app.kubernetes.io/part-of: dotnet-sample
        apps.tanzu.vmware.com/has-tests: "true"
        apps.tanzu.vmware.com/workload-type: web
      name: dotnet-sample
    spec:
      params:
      - name: ports
        value:
        - port: 80
          containerPort: 8000
          name: http
      source:
        git:
          ref:
            branch: main
          url: https://github.com/paketo-buildpacks/samples
        subPath: dotnet-core/fde-app
    

    Where metadata.name is the application name the workload is a part of, and spec.source.git points to the remote source code.

  2. Trigger an image build in the my-apps namespace by running:

    tanzu apps workload apply --file workload.yaml --namespace my-apps
    
  3. After the build completes, you can view the result by running:

    tanzu apps workload get dotnet-sample --namespace my-apps
    

How to use in Tanzu Build Service

The .NET Core buildpack is available in both the full and lite descriptors from Tanzu Build Service. Use kp image create to create an image resource. For more information, see the Tanzu Build Service documentation.

How to use with pack CLI

The pack CLI can be used to build your application image.

  1. From the app directory, build the image with pack:

    pack build dotnet-sample --buildpack gcr.io/tanzu-buildpacks/dotnet-core
    
  2. After the build has succeeded, run the image:

    docker run --interactive --tty --env PORT=8080 --publish 8080:8080 dotnet-sample
    
  3. View the running application by visiting http://localhost:8080 in a browser.

Specifying ASP.NET Core/Runtime Version

The .NET Core ASP.NET Runtime buildpack allows you to specify a version of the ASP.NET Core Runtime to use during deployment. This version can be specified in several ways including through a runtimeconfig.json, MSBuild Project file or through build-time environment variables. When specifying a version of the ASP.NET Core Runtime, you must choose a version that is available within these buildpacks. You can find these versions in the release notes.

.NET Core ASP.NET will only be included in the build process if your application declares its Runtime Framework as either Microsoft.AspNetCore.App or Microsoft.AspNetCore.All.

Using BP_DOTNET_FRAMEWORK_VERSION

To configure the buildpack to use a certain version of the .NET Core Runtime and ASP.NET when deploying your app, set the $BP_DOTNET_FRAMEWORK_VERSION environment variable at build time.

Using project.toml

[build]
  [[build.env]]
    name = 'BP_DOTNET_FRAMEWORK_VERSION'
    value = '6.0.14'

Passed to the platform

pack build myapp --env BP_DOTNET_FRAMEWORK_VERSION=6.0.14
Important

If you specify a particular version using the above environment variable, the buildpack will not run runtime version roll-forward logic. To learn more about roll-forward logic, see the Microsoft .NET Runtime documentation.

Using runtimeconfig.json

If you are using a runtimeconfig.json file, you can specify the .NET Core Runtime version within that file. To configure the buildpack to use .NET Core Runtime v6.0.14 when deploying your app, include the values below in your runtimeconfig.json file:

{
  "runtimeOptions": {
    "framework": {
      "version": "6.0.14"
    }
  }
}

Using a Project file

If you are using a Project file (eg. *.csproj, *.fsproj, or *.vbproj), you can specify the .NET Core Runtime version within that file. To configure the buildpack to use .NET Core Runtime v6.0.14 when deploying your app, include the values below in your Project file:

<Project>
  <PropertyGroup>
    <RuntimeFrameworkVersion>6.0.14</RuntimeFrameworkVersion>
  </PropertyGroup>
</Project>

Alternatively, for applications that do not rely upon a specific ASP.NET or Runtime patch version, you can specify the Target Framework and the buildpack will choose the appropriate .NET Core Runtime version. To configure the buildpack to use a .NET Core Runtime version in the 6.0 .NET Core Target Framework when deploying your app, include the values below in your Project file:

<Project>
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
</Project>

For more information about specifying a .NET Core version using a Project file, see the Microsoft documentation.

.NET Core Framework Version Selection

The .NET Core Buildpack uses the same version selection policy that Microsoft has put together for .NET Core Framework. For more information about the policy, see the Microsoft documentation.

(Deprecated) Using buildpack.yml

Specifying the .NET Core Framework version through buildpack.yml configuration will be deprecated in the next major version release of the buildpack. To migrate from using buildpack.yml, please set the BP_DOTNET_FRAMEWORK_VERSION environment variable.

Specifying an SDK Version

By default, the .NET Core SDK Buildpack installs the latest available patch version of the SDK that is compatible with the installed .NET Core runtime. You can find the available SDK versions for each buildpack release in the release notes.

However, a compatible .NET Core SDK version will be inferred by versions set in BP_DOTNET_FRAMEWORK_VERSION (used to specify the .NET Core runtime version), a global.json file, an MSBuild project file, or a runtimeconfig.json file. The .NET Core SDK buildpack will automatically install an SDK version that is compatible with the selected .NET Core runtime version.

(Deprecated) Using buildpack.yml

Specifying the .NET Core SDK version through buildpack.yml configuration will be deprecated in the next major version release of the buildpack.

Specifying a Project Path in a Multi-Project Solution

By default, the .NET Core Build Buildpack will consider the root directory of your codebase to be the project directory. This directory should contain a C#, F#, or Visual Basic Project file. If your project directory is not located at the root of your source code you will need to set a custom project path. This is a common scenario for multi-project solutions.

Using BP_DOTNET_PROJECT_PATH

You can specify a project path by setting the $BP_DOTNET_PROJECT_PATH environment variable at build time.

Using project.toml

[build]
  [[build.env]]
    name = 'BP_DOTNET_PROJECT_PATH'
    value = './App'

Passed to the platform

pack build myapp --env BP_DOTNET_PROJECT_PATH=./App

(Deprecated) Using buildpack.yml

Specifying the project path through buildpack.yml configuration will be deprecated in the next major version release of the buildpack. To migrate from using buildpack.yml, set the $BP_DOTNET_PROJECT_PATH environment variable.

Custom Project Path Example

The following is an example of setting a custom project path in your .NET Core application. The following directory structure reflects a common .NET project setup, in which the startup project, App, depends on other projects in the solution: ComponentProject and OtherComponentProject.

./MultiProjectApp
├── MultiProjectApp.sln
├── ComponentProject
│   ├── Component.cs
│   └── ComponentProject.csproj
├── OtherComponentProject
│   ├── OtherComponent.cs
│   └── OtherComponentProject.csproj
└── App
    ├── Program.cs
    ├── appsettings.Development.json
    ├── appsettings.json
    └──  App.csproj

To build the App project, pack build from the root of the MultiProjectApp directory and specify App as the project to build using the BP_DOTNET_PROJECT_PATH environment variable.

Important

Do not use pack build myapp --path=./App to build the App project. Using the --path flag excludes ComponentProject and OtherComponentProject from the build container. If App depends on those components, the build will fail when publishing App, because its dependencies will not be present in the build container.

Configuring the dotnet publish command

The .NET Core buildpack builds apps using the dotnet publish command, with certain opinionated flags by defaults. It is possible to override or add to these defaults.

Default dotnet publish values

  • --configuration Release
  • --runtime ubuntu.18.04-x64
  • --self-contained false
  • --output <temp-directory>

For information about the build configuration, see the dotnet CLI documentation.

Overriding Defaults Using BP_DOTNET_PUBLISH_FLAGS

You can provide additional flags or override the default values by setting the BP_DOTNET_PUBLISH_FLAGS environment variable at build time.

[build]
  [[build.env]]
    name = "BP_DOTNET_PUBLISH_FLAGS"
    value = "--verbosity=normal --self-contained=true"

Supported Service Bindings

The .NET Core buildpack can be configured using service bindings.

type Required Files # Bindings of This Type Accepted
nugetconfig type, nuget.config 0 or 1

Provide NuGet Configurations

A NuGet configuration file can be provided to the build process in two different ways. The provided file will have an effect on the dotnet publish command within the build process.

Use Service Bindings

Configuration can be provided to the build without explicitly including the file, which might contain credentials or other sensitive data, in the application directory. When building with the pack CLI, a service binding containing a nuget.config file can be provided. In addition to the nuget.config file, the binding must be of type nugetconfig. Check out the service bindings documentation for more details on service bindings.

The binding will be made available as a "user-level" NuGet configuration at $HOME/.nuget/NuGet/NuGet.Config during the build process. The configuration applies across all operations involving NuGet, but will be overriden by project-level configurations.

The resulting command will look like:

pack build myapp --env SERVICE_BINDING_ROOT=/bindings --volume <absolute-path-to-binding>:/bindings/nugetconfig

Use Application Source Code

A NuGet configuration file can also be provided in the application source directory following .NET Core rules. The project-level configuration takes precedence over a NuGet configuration provided by using service binding.

For more info, see Paketo docs

Enable Process Reloading

By default, your .NET server will be the only process running in your app container at runtime. You can enable restarting the server process when files in the app's working directory change, which might facilitate a shorter feedback loop for iterating on code changes. This feature may be used in conjunction with a dev orchestrator like Tilt.

Using BP_LIVE_RELOAD_ENABLED

To enable reloadable processes, set the $BP_LIVE_RELOAD_ENABLED environment variable at build time, either by passing a flag to the platform or by adding it to your project.toml.

Using project.toml

[build]
  [[build.env]]
    name = 'BP_LIVE_RELOAD_ENABLED'
    value = 'true'

Passed to the platform

pack build myapp --env BP_LIVE_RELOAD_ENABLED=true

Using a Tiltfile with pack

You can use the .NET Core buildpack with Tilt. This example uses the pack extension for Tilt, and shows how to configure watched files.

pack(
  'myapp',
  env_vars=[
    'BP_DOTNET_PROJECT_PATH="./src"',
    'BP_LIVE_RELOAD_ENABLED=true'
    ],
  live_update=[
    sync('./build', '/workspace/build'),
    sync('./src', '/workspace/src'),
    run('cp -rf /workspace/build/* /workspace/', trigger='./build')
  ]
)
# (Re)build locally when source code changes
local_resource(
  'dotnet-publish',
  cmd='rm -rf ./build && dotnet publish src --configuration Release --runtime ubuntu.18.04-x64 --self-contained false --output ./build',
  deps=['src'],
  ignore=[
    'src/obj',
    'src/bin'
  ]
)

Pointers on Process Reloading with Tilt

  • The .NET Core buildpack works best with Tilt and hot reloading when all of your app's source code is in a subdirectory (./src in the above example). Use BP_DOTNET_PROJECT_PATH to indicate the location of the source code.
  • The .NET Core buildpack will not recompile your source code inside the running app container. You must use a local_resource to rebuild your app when source code changes, and copy the built artifacts into the container with sync and run steps, as shown.
  • The cmd that is run as part of the dotnet-publish local resource matches the command that the .NET Core buildpack runs to build the app.

Access the Software Bill of Materials

The .NET Core Buildpack includes support for Software Bill of Materials (SBOM). Check out the SBOM documentation for details on how to access the SBOM supplied by the buildpacks.

SBOMs will be generated for all supported .NET Core applications.

Enable Remote Debugging

Remote debugging for .NET Core applications is possible via the Visual Studio Debugger (vsdbg) to provide insight into complex program and interactions in remote environments. The debugger can attach to a running .NET Core process and be bound to a client-side debugger via STDIN across a connection invoked via docker exec.

This feature is not yet supported by Tanzu Developer Tools Extension for VS Code. In order to use this feature, you will have to use the pack cli to build your code and run it using your local docker daemon.

Using BP_DEBUG_ENABLED

To enable remote debugging, set the $BP_DEBUG_ENABLED environment variable at build time.

Using project.toml

[build]
  [[build.env]]
    name = 'BP_DEBUG_ENABLED'
    value = 'true'

Passed to the platform

pack build myapp --env BP_DEBUG_ENABLED=true

Setting up Visual Studio Code for Remote Debugging

You can configure Visual Studio Code to attach a remote debugging session into a running container by using docker exec. For instructions, see Attaching to remote processes in GitHub. After your application is built, do the following steps to set up Visual Studio Code for remote debugging:

  1. Add .vscode/launch.json to app source directory

    {
      "configurations": [
        {
          "name": ".NET Core Docker Attach",
          "type": "coreclr",
          "request": "attach",
          "processId": "${command:pickRemoteProcess}",
          "pipeTransport": {
            "pipeProgram": "docker",
            "pipeArgs": [ "exec", "-i", "<container id>" ],
            "debuggerPath": "/cnb/lifecycle/launcher vsdbg",
            "pipeCwd": "${workspaceRoot}",
            "quoteArgs": false
          },
          "sourceFileMap": {
            "/workspace": "${workspaceRoot}"
          }
        }
      ]
    }
    
  2. Install the Microsoft C# extension

Start Debugging in Visual Studio Code

  1. Run the app with docker run -p 8080:8080 <app-image-name>.
  2. Open a browser window to http://localhost:8080.
  3. Update <container id> field in launch.json with actual container ID.

From here you might set a breakpoint and start debugging via the menu bar or by pressing F5. In the event that you are prompted to select a process to attach to, select the name of your app process if it is listed. See the Visual Studio Code debugging docs for more about how to use the debugger.

Note

The steps above are intended for remote debugging in a non-production context. Setting BP_DEBUG_ENABLED to true will ensure that a .NET app is published in Debug configuration instead of Release configuration and is the currently the only official way to include Visual Studio Debugger in your application image. It is possible to perform remote debugging on Release-configured apps, see Building and deploying the application and PDBs in GitHub. However, that workflow is not officially supported by the .NET Core Buildpack.

Enable Kerberos

For apps that leverage Kerberos or its libraries those dependencies can be installed via the Tanzu Kerberos buildapck which is part of the Tanzu .NET Core language family. In order to install Kerberos and its libraries set the BP_INCLUDE_KERBEROS_CLIENT_LIBRARIES to true. This will cause the Tanzu Kerberos buildpack to run its build process which will install Kerberos and its libraries.

Buildpack-Set Environment Variables

DOTNET_ROOT

The DOTNET_ROOT environment variable specifies the path to the directory where .NET Runtimes are installed for usage at run-time. This is largely needed for Framework-Dependent Executables (FDE).

  • Set by: dotnet-core-aspnet-runtime buildpack
  • Phases: launch
  • Value: path to the .NET Core Runtime installation

PATH

The PATH environment variable is modified to enable the dotnet CLI to be found during subsequent build and launch phases.

  • Set by: dotnet-core-sdk and dotnet-core-aspnet-runtime buildpack
  • Phases: build and launch
  • Value: path the directory containing the dotnet executable

ASPNETCORE_ENVIRONMENT

The ASPNETCORE_ENVIRONMENT environment variable is set to Development when user-set BP_DEBUG_ENABLED=true is enabled for remote debugging.

  • Set by: dotnet-execute buildpack
  • Phases: launch
  • Value: Development

Launch Process

The .NET Execute Buildpack will ensure that your application image is built with a valid launch process command. These commands differ slightly depending upon the type of built artifact produced during the build process.

For more information about which built artifact is produced for a Source Application, see Application Types earlier in this topic.

Framework-Dependent Deployments and Source Applications

For Framework-Dependent Deployments (FDD), the dotnet CLI will be invoked to start your application. The application will be given configuration to help it bind to a port inside the container. The default port is 8080, but can be overridden using the $PORT environment variable.

dotnet myapp.dll --urls http://0.0.0.0:${PORT:-8080}

Self-Contained Deployment and Framework-Dependent Executables

For Self-Contained Deployments and Framework-Dependent Executables, the executable will be invoked directly to start your application. The application will be given configuration to help it bind to a port inside the container. The default port is 8080, but can be overridden using the $PORT environment variable.

./myapp --urls http://0.0.0.0:${PORT:-8080}

Additional Configuration

Install a Custom CA Certificate

.NET Core buildpack users can provide their own CA certificates and have them included in the container root truststore at build-time and runtime by following the instructions in the CA Certificates section of our configuration docs.

Enable DEBUG logging

Users of the .NET Core buildpack can access extra debug logs during the image build process by setting the BP_LOG_LEVEL environment variable to DEBUG at build time. Additional debug logs will appear in build logs if the relevant buildpacks have debug log lines.

Using project.toml

[build]
  [[build.env]]
    name = 'BP_LOG_LEVEL'
    value = 'DEBUG'

Passed to the platform

pack build my-app --buildpack gcr.io/tanzu-buildpacks/dotnet-core \
  --env BP_LOG_LEVEL=DEBUG

Override the Start Process Set by the Buildpack

.NET Core buildpack users can set custom start processes for their app image by following the instructions in the Procfiles section of our configuration docs.

Set Environment Variables for App Launch Time

.NET Core buildpack users can embed launch-time environment variables in their app image by following the documentation for the Environment Variables Buildpack.

Add Custom Labels to the App Image

.NET Core buildpack users can add labels to their app image by following the instructions in the Applying Custom Labels section of our configuration docs.

check-circle-line exclamation-circle-line close-line
Scroll to top icon