Skip to content
Docs Try Aspire
Docs Try

Working with container-built resources in an Aspire application

Aspire sample
File-based AppHost

Clone, run, and explore this sample

This sample demonstrates integrating applications into an Aspire app via Dockerfiles and container-based builds. This is especially helpful to integrate applications written in languages that Aspire does not have a native integration for, or to reduce the prerequisites required to run the application.

C#DashboardDockerGoMetrics
AppHost

The entry point that composes every resource and dependency in this sample's distributed application.

View on GitHub
apphost.cs
#:sdk Aspire.AppHost.Sdk@13.4.0
using Microsoft.Extensions.Hosting;
var builder = DistributedApplication.CreateBuilder(args);
var goVersion = builder.AddParameter("goversion", "1.25.4", publishValueAsDefault: true);
IResourceBuilder<ContainerResource> ginapp;
if (builder.ExecutionContext.IsPublishMode)
{
// Production build: multi-stage Dockerfile for optimized image
ginapp = builder.AddDockerfile("ginapp", "./ginapp")
.WithBuildArg("GO_VERSION", goVersion);
}
else
{
// Development build: use Air for hot reload with bind mount
ginapp = builder.AddDockerfile("ginapp", "./ginapp", "Dockerfile.dev")
.WithBuildArg("GO_VERSION", goVersion)
.WithBindMount("./ginapp", "/app");
}
ginapp
.WithHttpEndpoint(targetPort: 5555, env: "PORT")
.WithHttpHealthCheck("/")
.WithExternalHttpEndpoints()
.WithOtlpExporter()
.WithDeveloperCertificateTrust(trust: true);
if (builder.ExecutionContext.IsPublishMode)
{
ginapp
.WithEnvironment("GIN_MODE", "release")
// Trust all proxies when running behind a reverse proxy. If deploying to an environment
// without a reverse proxy that ensures X-Forwarded-* headers are not forwarded from clients,
// this should be removed.
.WithEnvironment("TRUSTED_PROXIES", "all");
}
builder.Build().Run();

The sample integrates a simple app written using Go and the Gin Web Framework by using a Dockerfile:

  • ginapp: This is a simple "Hello, World" HTTP API that returns a JSON object like { "message": "Hello, World!" } from / and sends OpenTelemetry instrumentation to the Aspire dashboard.

This sample includes hot reload for local development! The Go application uses:

  • Bind mounts - Your local source code is mounted directly into the container at /app
  • Air - A live reload tool for Go that watches for file changes and rebuilds automatically
  • Polling-based file watching - Configured to work reliably with Docker bind mounts on Windows

When you edit any .go file in the ginapp directory, Air automatically detects the change, rebuilds the Go binary, and restarts the app in just a few seconds—without rebuilding the entire container. This provides a much faster development feedback loop compared to full container rebuilds.

  • Development mode (default): Uses Dockerfile.dev with Air for hot reload

    • Source files are bind-mounted from your local machine
    • Changes to .go files trigger automatic rebuilds
    • Dependencies are resolved on-demand via go get
  • Production mode (aspire publish): Uses the standard Dockerfile

    • Multi-stage build for optimized images
    • No bind mounts or development tools
    • Minimal runtime container based on distroless images

If using the Aspire CLI, run aspire run from this directory.

If using VS Code, open this directory as a workspace and launch the apphost.cs file using either the Aspire or C# debuggers.

If using the .NET CLI, run dotnet run apphost.cs from this directory.

From the Aspire dashboard, click on the endpoint URL for the ginapp resource to see the response in the browser.

Preview

Sample screenshots

Select the image to zoom in.

Screenshot of the Aspire dashboard showing the ginapp container resource built from a Dockerfile
Screenshot of the Aspire dashboard showing the ginapp container resource built from a Dockerfile