Skip to content

Docker guide

This guide explains how to build and run an application as a Docker container. It assumes you have already created an application by following the Stadium Builder Bootstrapper guide. This method can be used to build and run a container locally using Docker Desktop or a remote machine running Docker.

Executing the /pack slash-command in Claude Code generates a Dockerfile for the application. It uses a multi-stage build, using the .NET 10 SDK image (mcr.microsoft.com/dotnet/sdk:10.0) to restore and publish the application, and the smaller ASP.NET runtime image (mcr.microsoft.com/dotnet/aspnet:10.0) to run it.

To build and run the application, first package it using the /pack slash-command in Claude Code.

/pack confirms which application project to package, then produces a self-contained tarball at app-backend/artifacts/<ProjectName>.t57. The tarball contains a Dockerfile at its root, the application source under src/<project>, and the solution’s docs folder under src/docs.

Docker can build from the .t57 file directly. In a Windows command line, change to the folder containing the file. The following command passes - < to read the build context from stdin and feed the file in:

docker build -t <app-name> - < <ProjectName>.t57

<app-name> is the image tag — choose any lowercase name, for example myapp. Throughout this guide, anything in angle brackets (for example <app-name> or <ServiceUri>) is a placeholder you replace with your own value — do not type the brackets.

The < before <ProjectName>.t57 is the shell’s stdin redirect.

Once the image is built, run it as a container:

docker run --rm <app-name>

The --rm flag removes the container when it stops, which is convenient while testing.

A container’s ports are not reachable from the host unless you publish them with -p <host-port>:<container-port>:

docker run --rm -p 8080:8080 <app-name>

The address a REST host listens on comes from the application’s settings (the service URI in AppSettings), so the port you publish must match the port the application is actually listening on inside the container. You can set that address at runtime with an environment variable override (see Overriding settings with environment variables below). Bind to 0.0.0.0 rather than localhost so the listener accepts connections from outside the container:

docker run --rm -e Setting.<ServiceUri>="http://0.0.0.0:8080" -p 8080:8080 <app-name>

Replace <ServiceUri> with the name of the setting that holds your service’s URI. With the above, the service is reachable from the host at http://localhost:8080.

To share a folder between the host and the container — for configuration, secrets, or output files — mount it with --mount type=bind,source=<host-path>,destination=<container-path>:

docker run --rm --mount type=bind,source=C:\host\data,destination=/app/data <app-name>

A common use is to supply a secret (such as a connection string) as a file and point a setting at it, which keeps the secret out of your shell history and the container’s environment listing:

docker run --rm --mount type=bind,source=C:\host\secrets,destination=/app/secrets -e Setting.<ConnectionString>.File="/app/secrets/connection-string.txt" <app-name>

Overriding settings with environment variables

Section titled “Overriding settings with environment variables”

Any application setting can be overridden at container start time, without rebuilding the image, by passing an environment variable prefixed with Setting.:

  • Simple settingSetting.<PropertyName>, for example -e Setting.DatabaseName="MyApp".
  • Nested setting — use a dot for each level, for example -e Setting.Service.Timeout="00:00:30".
  • Setting from a file — append .File and give the path to a file (typically a mounted one); the file’s contents become the value, for example -e Setting.ApiKey.File="/app/secrets/api-key.txt".

Values are converted to the setting’s type automatically, including string, enums, Uri, Guid, TimeSpan, nullable types, and any type supported by the standard .NET conversions (such as int, bool and decimal).