Skip to content

Commit a77b9c8

Browse files
committed
document entrypoint/command changes for .NET 8
1 parent 9a56192 commit a77b9c8

File tree

1 file changed

+139
-30
lines changed

1 file changed

+139
-30
lines changed

docs/ContainerCustomization.md

Lines changed: 139 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ You can control many aspects of the generated container through MSBuild properti
55
> **Note**
66
> 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.
77
8-
## ContainerBaseImage
8+
## Choosing a base image
9+
10+
These properties help the tools determine which image to build your container on top of.
11+
12+
### ContainerBaseImage
913

1014
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:
1115

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

26-
## ContainerFamily
30+
### ContainerFamily
2731

2832
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`:
2933

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

3842
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.
3943

40-
## ContainerRuntimeIdentifier
44+
### ContainerRuntimeIdentifier
4145

4246
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.
4347

@@ -72,7 +76,11 @@ By default, if your project has a RuntimeIdentifier set, that value will be used
7276
> **Note**
7377
> 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`.
7478
75-
## ContainerRegistry
79+
## Modifying the generated container
80+
81+
These properties and items control metadata about the container that's generated for your application.
82+
83+
### ContainerRegistry
7684
7785
This property controls the destination registry - the place that the newly-created image will be pushed to.
7886
@@ -84,7 +92,7 @@ Be default, we push to the local Docker daemon (annotated by `docker://`), but y
8492
</PropertyGroup>
8593
```
8694
87-
## ContainerRepository
95+
### ContainerRepository
8896

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

@@ -99,7 +107,7 @@ By default, the value used will be the `AssemblyName` of the project. In previou
99107
> **Note**
100108
> 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.
101109
102-
## ContainerImageTag(s)
110+
### ContainerImageTag(s)
103111

104112
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`.
105113

@@ -128,7 +136,30 @@ By default in .NET 8, the value used will be `latest` - keeping in line with exp
128136
> **Note**
129137
> 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.
130138
131-
## ContainerWorkingDirectory
139+
### ContainerLabel
140+
141+
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.
142+
143+
ContainerLabel items have two properties:
144+
145+
* Include
146+
* The key of the label
147+
* Value
148+
* The value of the label - this may be empty
149+
150+
See [default container labels](#default-container-labels) for a list of labels that are created by default.
151+
152+
```xml
153+
<ItemGroup>
154+
<ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
155+
</ItemGroup>
156+
```
157+
158+
## Controlling container execution
159+
160+
These properties and items control how the generated container is executed.
161+
162+
### ContainerWorkingDirectory
132163

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

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

143-
## ContainerPort
174+
### ContainerPort
144175

145176
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.
146177

@@ -168,26 +199,8 @@ ContainerPort items have two properties:
168199
> **Note**
169200
> 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.
170201
171-
## ContainerLabel
172202

173-
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.
174-
175-
ContainerLabel items have two properties:
176-
177-
* Include
178-
* The key of the label
179-
* Value
180-
* The value of the label - this may be empty
181-
182-
See [default container labels](#default-container-labels) for a list of labels that are created by default.
183-
184-
```xml
185-
<ItemGroup>
186-
<ContainerLabel Include="org.contoso.businessunit" Value="contoso-university" />
187-
</ItemGroup>
188-
```
189-
190-
## ContainerEnvironmentVariable
203+
### ContainerEnvironmentVariable
191204

192205
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.
193206

@@ -204,7 +217,23 @@ ContainerEnvironmentVariable items have two properties:
204217
</ItemGroup>
205218
```
206219

207-
## ContainerEntrypoint
220+
## Controlling the container's commands
221+
222+
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`.
223+
224+
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:
225+
226+
* identify the binary to run and set it as `ContainerAppCommand`
227+
* identify which arguments are _required_ for your application to run and set them as `ContainerAppCommandArgs`
228+
* identify which arguments (if any) are _optional_ and could be overridden by a user and set them as `ContainerDefaultArgs`
229+
* set `ContainerAppCommandInstruction` to `DefaultArgs`
230+
231+
More detail on each of these configuration points is detailed below:
232+
233+
### ContainerEntrypoint
234+
235+
> **Note**
236+
> In .NET 8 this item is deprecated. See [ContainerAppCommand](#containerappcommand) for more details.
208237
209238
This item can be used to customize the entrypoint of the container - the binary that is run by default when the container is started.
210239

@@ -226,7 +255,10 @@ ContainerEntrypoint items have one property:
226255
</ItemGroup>
227256
```
228257

229-
## ContainerEntrypointArgs
258+
### ContainerEntrypointArgs
259+
260+
> **Note**
261+
> In .NET 8 this item is deprecated. See [ContainerAppCommandArgs](#containerappcommandargs) for more details.
230262
231263
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.
232264

@@ -248,7 +280,84 @@ ContainerEntrypointArg items have one property:
248280
</ItemGroup>
249281
```
250282

251-
## ContainerUser
283+
### ContainerAppCommand
284+
285+
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.
286+
287+
ContainerAppCommand items have one property:
288+
289+
* Include
290+
* The command, option, or argument to use in the entrypoint command
291+
292+
```xml
293+
<ItemGroup Label="ContainerAppCommand Assignment">
294+
<!-- This is how you would start the dotnet ef tool in your container -->
295+
<ContainerAppCommand Include="dotnet" />
296+
<ContainerAppCommand Include="ef" />
297+
298+
<!-- This shorthand syntax means the same thing - note the semicolon separating the tokens. -->
299+
<ContainerAppCommand Include="dotnet;ef" />
300+
</ItemGroup>
301+
```
302+
303+
### ContainerAppCommandArgs
304+
305+
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.
306+
307+
ContainerAppCommandArgs items have one property:
308+
309+
* Include
310+
* The option or argument to apply to the ContainerAppCommand command
311+
312+
```xml
313+
<ItemGroup>
314+
<!-- Assuming the ContainerAppCommand defined above, this would be the way to force the database to update. -->
315+
<ContainerAppCommandArgs Include="database" />
316+
<ContainerAppCommandArgs Include="update" />
317+
318+
<!-- This is the shorthand syntax for the same idea -->
319+
<ContainerAppCommandArgs Include="database;update" />
320+
</ItemGroup>
321+
```
322+
323+
### ContainerDefaultArgs
324+
325+
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.
326+
327+
ContainerDefaultArgs items have one property:
328+
329+
* Include
330+
* The option or argument to apply to the ContainerAppCommand command
331+
332+
```xml
333+
<ItemGroup>
334+
<!-- Assuming the ContainerAppCommand defined above, this would be the way to force the database to update. -->
335+
<ContainerDefaultArgs Include="database" />
336+
<ContainerDefaultArgs Include="update" />
337+
338+
<!-- This is the shorthand syntax for the same idea -->
339+
<ContainerDefaultArgs Include="database;update" />
340+
</ItemGroup>
341+
```
342+
343+
344+
### ContainerAppCommandInstruction
345+
346+
> **Note**
347+
> 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.
348+
349+
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".
350+
351+
* Entrypoint
352+
* In this mode, the entrypoint is purely defined by `ContainerAppCommand`, `ContainerAppCommandArgs`, and `ContainerDefaultArgs`.
353+
* None
354+
* In this mode, the entrypoint is purely defined by `ContainerEntrypoint`, `ContainerEntrypointArgs`, and `ContainerDefaultArgs`.
355+
* DefaultArgs
356+
* 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.
357+
* If both `ContainerEntrypoint` and `ContainerAppCommand` are present, then `ContainerEntrypoint` becomes the entrypoint, and `ContainerAppCommand` becomes the command.
358+
359+
360+
### ContainerUser
252361

253362
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:
254363

0 commit comments

Comments
 (0)