Skip to content

Commit

Permalink
document entrypoint/command changes for .NET 8
Browse files Browse the repository at this point in the history
  • Loading branch information
baronfel committed Aug 11, 2023
1 parent 9a56192 commit a77b9c8
Showing 1 changed file with 139 additions and 30 deletions.
169 changes: 139 additions & 30 deletions docs/ContainerCustomization.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ You can control many aspects of the generated container through MSBuild properti
> **Note**
> The only exception to this is `RUN` commands - due to the way we build containers, those cannot be emulated. If you need this functionality, you will need to use a Dockerfile to build your container images.
## ContainerBaseImage
## Choosing a base image

These properties help the tools determine which image to build your container on top of.

### ContainerBaseImage

This property controls the image used as the basis for your image. By default, we will infer the following values for you based on the properties of your project:

Expand All @@ -23,7 +27,7 @@ If you set a value here, you should set the fully-qualified name of the image to
<PropertyGroup>
```

## ContainerFamily
### ContainerFamily

Starting in .NET 8, `ContainerFamily` can be used to choose a different family of Microsoft-provided container images as the base image for your application. When set, this value will be appended to the end of the selected TFM-specific tag, changing the tag provided. For example, to use the Alpine Linux variants of the .NET base images, you can set `ContainerFamily` to `alpine`:

Expand All @@ -37,7 +41,7 @@ which results in a final tag of `8.0-alpine` for a .NET 8-targeting application.

This field is very free-form, and often can be used to select different operating system distributions, default package configurations, or any other 'flavor' of changes to a base image. Consult your base image's documentation for more details.

## ContainerRuntimeIdentifier
### ContainerRuntimeIdentifier

This property controls the OS and platform used by your container if your [`ContainerBaseImage`](#containerbaseimage) is a 'Manifest List'. Manifest Lists are images that support more than one architecture behind a single, common, name. For example, the `mcr.microsoft.com/dotnet/runtime` image is a manifest list that supports the `linux-x64`, `linux-arm`, `linux-arm64` images.

Expand Down Expand Up @@ -72,7 +76,11 @@ By default, if your project has a RuntimeIdentifier set, that value will be used
> **Note**
> Starting in .NET 8, the Microsoft container images will not include the Windows variants of the images in the manifest list. If you need to target Windows, you will need to use a specific image tag as your `<ContainerBaseImage>`, for example `mcr.microsoft.com/dotnet/aspnet:8.0-preview-windowsservercore-ltsc2022` or `mcr.microsoft.com/dotnet/aspnet:8.0-preview-nanoserver-ltsc2022`.
## ContainerRegistry
## Modifying the generated container
These properties and items control metadata about the container that's generated for your application.
### ContainerRegistry
This property controls the destination registry - the place that the newly-created image will be pushed to.
Expand All @@ -84,7 +92,7 @@ Be default, we push to the local Docker daemon (annotated by `docker://`), but y
</PropertyGroup>
```
## ContainerRepository
### ContainerRepository

This property controls the name of the generated image itself, e.g `dotnet/runtime` or `my-awesome-app`.

Expand All @@ -99,7 +107,7 @@ By default, the value used will be the `AssemblyName` of the project. In previou
> **Note**
> Image names consist of one or more slash-delimited segments, each of which can only contain lowercase alphanumeric characters, periods, underscores, and dashes, and must start with a letter or number - any other characters will result in an error being thrown.
## ContainerImageTag(s)
### ContainerImageTag(s)

This property controls the tag that is generated for the image. Tags are often used to refer to different versions of an application, but they can also refer to different operating system distributions, or even just different baked-in configuration. This property also can be used to push multiple tags - simply use a semicolon-delimited set of tags in the `ContainerImageTags` property, similar to setting multiple `TargetFrameworks`.

Expand Down Expand Up @@ -128,7 +136,30 @@ By default in .NET 8, the value used will be `latest` - keeping in line with exp
> **Note**
> Tags can only contain up to 127 alphanumeric characters, periods, underscores, and dashes. They must start with an alphanumeric character or an underscore. Any other form will result in an error being thrown.
## ContainerWorkingDirectory
### ContainerLabel

This item adds a metadata label to the container. Labels have no impact on the container at runtime, but are often used to store version and authoring metadata for use by security scanners and other infrastructure tools.

ContainerLabel items have two properties:

* Include
* The key of the label
* Value
* The value of the label - this may be empty

See [default container labels](#default-container-labels) for a list of labels that are created by default.

```xml
<ItemGroup>
<ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>
```

## Controlling container execution

These properties and items control how the generated container is executed.

### ContainerWorkingDirectory

This property controls the working directory of the container - the directory that commands are executed within if not other command is run.

Expand All @@ -140,7 +171,7 @@ By default, we use the `/app` directory as the working directory.
</PropertyGroup>
```

## ContainerPort
### ContainerPort

This item adds TCP or UDP ports to the list of known ports for the container. This enables container runtimes like Docker to map these ports to the host machine automatically. This is often used as documentation for the container, but can also be used to enable automatic port mapping.

Expand Down Expand Up @@ -168,26 +199,8 @@ ContainerPort items have two properties:
> **Note**
> This item typically does not influence running the container directly - most runtimes will still need to explicitly assign port mappings. Some tooling, like the Docker Tools for Visual Studio Code, will read this data and automatically open ports on your behalf.
## ContainerLabel

This item adds a metadata label to the container. Labels have no impact on the container at runtime, but are often used to store version and authoring metadata for use by security scanners and other infrastructure tools.

ContainerLabel items have two properties:

* Include
* The key of the label
* Value
* The value of the label - this may be empty

See [default container labels](#default-container-labels) for a list of labels that are created by default.

```xml
<ItemGroup>
<ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
</ItemGroup>
```

## ContainerEnvironmentVariable
### ContainerEnvironmentVariable

This item adds a new environment variable to the container. Environment variables will be accessible to the application running in the container immediately, and are often used to change the runtime behavior of the running application.

Expand All @@ -204,7 +217,23 @@ ContainerEnvironmentVariable items have two properties:
</ItemGroup>
```

## ContainerEntrypoint
## Controlling the container's commands

By default, the container tools will launch your application using either the generated AppHost binary for your application (if your application uses an AppHost), or the `dotnet` command plus your application's DLL. However, you can control how your application is executed by using some combination of `ContainerAppCommand`, `ContainerAppCommandArgs`, `ContainerDefaultArgs`, and `ContainerAppCommandInstruction`.

We have these different configuration points because different base images use different combinations of the container Entrypoint and Command properties, and we want to be able to support all of them. Our defaults should be useable for most apps, but if you want to customize your app launch behavior you should:

* identify the binary to run and set it as `ContainerAppCommand`
* identify which arguments are _required_ for your application to run and set them as `ContainerAppCommandArgs`
* identify which arguments (if any) are _optional_ and could be overridden by a user and set them as `ContainerDefaultArgs`
* set `ContainerAppCommandInstruction` to `DefaultArgs`

More detail on each of these configuration points is detailed below:

### ContainerEntrypoint

> **Note**
> In .NET 8 this item is deprecated. See [ContainerAppCommand](#containerappcommand) for more details.
This item can be used to customize the entrypoint of the container - the binary that is run by default when the container is started.

Expand All @@ -226,7 +255,10 @@ ContainerEntrypoint items have one property:
</ItemGroup>
```

## ContainerEntrypointArgs
### ContainerEntrypointArgs

> **Note**
> In .NET 8 this item is deprecated. See [ContainerAppCommandArgs](#containerappcommandargs) for more details.
This item controls the default arguments provided to the `ContainerEntrypoint`. This should be used when the ContainerEntrypoint is a program that the user might want to use on its own.

Expand All @@ -248,7 +280,84 @@ ContainerEntrypointArg items have one property:
</ItemGroup>
```

## ContainerUser
### ContainerAppCommand

This item is the logical entry point of your application. For most apps, this will be the 'apphost' - the generated executable binary for your application. If your application doesn't generate an apphost, then this command will typically be `dotnet <your project dll>`. These values will be applied after any Entrypoint in your base container, or directly if no Entrypoint is defined.

ContainerAppCommand items have one property:

* Include
* The command, option, or argument to use in the entrypoint command

```xml
<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

This item represents any logically-required arguments for your application that should be applied to the `ContainerAppCommand`. By default, none are generated for an application. If present, these will always be applied to your container when it is run.

ContainerAppCommandArgs items have one property:

* Include
* The option or argument to apply to the ContainerAppCommand command

```xml
<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

This item represents any user-overrideable arguments for your application. This is a good way to provide any defaults that your app might need to run in a way that makes it easy to start your application, but still easy to customize.

ContainerDefaultArgs items have one property:

* Include
* The option or argument to apply to the ContainerAppCommand command

```xml
<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

> **Note**
> This is advanced stuff - most applications shouldn't need to customize their entrypoint to this degree. We'd love to hear more about your use case at https://github.com/dotnet/sdk-container-builds/discussions.
This property helps control the way the `ContainerEntrypoint`, `ContainerEntrypointArgs`, `ContainerAppCommand`, `ContainerAppCommandArgs`, and `ContainerDefaultArgs` are combined to form the final command that is run in the container. This depends greatly on if an Entrypoint is present in the base image. This property can take one of three values: "DefaultArgs", "Entrypoint", or "None".

* Entrypoint
* In this mode, the entrypoint is purely defined by `ContainerAppCommand`, `ContainerAppCommandArgs`, and `ContainerDefaultArgs`.
* None
* In this mode, the entrypoint is purely defined by `ContainerEntrypoint`, `ContainerEntrypointArgs`, and `ContainerDefaultArgs`.
* DefaultArgs
* This is the most complex mode - if none of the `ContainerEntrypoint[Args]` items are present, we defer to `ContainerAppCommand[Args]` and `ContainerDefaultArgs` to create the entrypoint and command - skipping the base image entrypoint for base images that have it hard-coded to `dotnet` or `/usr/bin/dotnet` so that you have complete control.
* If both `ContainerEntrypoint` and `ContainerAppCommand` are present, then `ContainerEntrypoint` becomes the entrypoint, and `ContainerAppCommand` becomes the command.


### ContainerUser

This item controls the default user that the container will run as. This is often used to run the container as a non-root user, which is a best practice for security. There are a few constraints to know about this field:

Expand Down

0 comments on commit a77b9c8

Please sign in to comment.