Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,13 @@
.WithHttpEndpoint(env: "PORT")
.WithHttpHealthCheck("/health");

// Example: Copy static frontend files into the Golang container when publishing
// This demonstrates the IContainerFilesDestinationResource support
// Uncomment the following line to copy files from a static directory:
// golang.WithContainerFiles("/app/static", "../static-frontend");

// Or, when using a frontend build resource (e.g., Vite, React, etc.):
// var frontend = builder.AddViteApp("frontend", "../frontend");
// golang.WithContainerFiles("/app/static", frontend.Resource);

builder.Build().Run();
5 changes: 5 additions & 0 deletions examples/golang/gin-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ func setupRouter() *gin.Engine {
c.String(http.StatusOK, "ok")
})

// Serve static files from /static directory
// When using container files feature, these files will be copied from
// a frontend resource into the container at /app/static
r.Static("/static", "./static")

// Ping test
r.GET("/ping", func(c *gin.Context) {
// _, span := tracer.Start(c.Request.Context(), "ping")
Expand Down
39 changes: 39 additions & 0 deletions examples/golang/static-frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Static Frontend Example

This directory contains a simple static HTML frontend that demonstrates the container files feature of the Golang integration.

## Purpose

When publishing an Aspire application, static files from this directory can be copied into the Golang container using the `WithContainerFiles` method. This is useful for serving frontend assets (HTML, CSS, JavaScript, images, etc.) directly from your Go application.

## Usage

In your AppHost `Program.cs`, you can configure the Golang resource to copy these files:

```csharp
var golang = builder.AddGolangApp("golang", "../gin-api")
.WithHttpEndpoint(env: "PORT")
.WithContainerFiles("/app/static", "../static-frontend");
```

The Golang application is configured to serve these files from the `/static` endpoint. When running in a container, the files will be available at `http://localhost:<port>/static/index.html`.

## Container Files Feature

The Golang resource implements `IContainerFilesDestinationResource`, which tells the Aspire publishing pipeline where to copy files when building the container image. The default destination is `/app/static`, but this can be customized.

This feature works with any resource that produces output files, including:
- Static file directories (like this example)
- Frontend build tools (Vite, webpack, Create React App, etc.)
- Documentation generators
- Any other build output

## Implementation Details

The feature works by:
1. The Golang resource implementing `IContainerFilesDestinationResource`
2. Using `WithContainerFiles` to specify the source and destination
3. During publishing, the Aspire pipeline automatically copies the files into the generated Docker image
4. The Golang application serves the files using Gin's `Static` method

See the main README in the parent directory for more details.
42 changes: 42 additions & 0 deletions examples/golang/static-frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Golang + Static Frontend Example</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 50px auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
color: #00ADD8;
}
.status {
padding: 10px;
margin-top: 20px;
background-color: #e7f3ff;
border-left: 4px solid #00ADD8;
}
</style>
</head>
<body>
<div class="container">
<h1>🚀 Golang + Static Frontend</h1>
<p>This static HTML page is served from the Golang container!</p>
<p>It demonstrates the container files feature, where static frontend files are copied into the Golang container during publishing.</p>
<div class="status">
<strong>Status:</strong> Container files feature working! ✅
</div>
</div>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@
/// <param name="name">The name of the resource.</param>
/// <param name="workingDirectory">The working directory to use for the command.</param>
public class GolangAppExecutableResource(string name, string workingDirectory)
: ExecutableResource(name, "go", workingDirectory), IResourceWithServiceDiscovery;
: ExecutableResource(name, "go", workingDirectory), IResourceWithServiceDiscovery, IContainerFilesDestinationResource
{
/// <inheritdoc/>
public string ContainerFilesDestination => "/app/static";
}
16 changes: 16 additions & 0 deletions src/CommunityToolkit.Aspire.Hosting.Golang/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@ var golang = builder.AddGolangApp("golang", "../gin-api")
runtimeImage: "alpine:3.20");
```

### Container Files Support

The Golang resource supports copying files from other resources into the container during publishing. This is useful for serving static frontend files from your Go application. The resource implements `IContainerFilesDestinationResource` with a default destination of `/app/static`.

To copy files from another resource (such as a frontend build) into your Golang container, use the `WithContainerFiles` method:

```csharp
var frontend = builder.AddViteApp("frontend", "./frontend");

var golang = builder.AddGolangApp("golang", "../gin-api")
.WithHttpEndpoint(env: "PORT")
.WithContainerFiles("/app/static", frontend.Resource);
```

This will copy the output files from the `frontend` resource into the `/app/static` directory in the Golang container when publishing.

### Generated Dockerfile

The automatically generated Dockerfile:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,24 @@ public void GolangAppWithGoModDownloadInstallFalseCreatesInstallerWithExplicitSt
// Verify that the installer has ExplicitStartupAnnotation
Assert.True(installerResource.HasAnnotationOfType<ExplicitStartupAnnotation>());
}

[Fact]
public void GolangAppImplementsIContainerFilesDestinationResource()
{
var builder = DistributedApplication.CreateBuilder();

builder.AddGolangApp("golang", "../../examples/golang/gin-api");

using var app = builder.Build();

var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();

var resource = appModel.Resources.OfType<GolangAppExecutableResource>().SingleOrDefault();

Assert.NotNull(resource);
Assert.IsAssignableFrom<IContainerFilesDestinationResource>(resource);

// Verify the default destination path
Assert.Equal("/app/static", resource.ContainerFilesDestination);
}
}