Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 12, 2025

  • Understand the current Golang integration structure
  • Add a PublishAsGolangDockerfile extension method with Dockerfile builder support for Golang
  • Update the Golang integration to call PublishAsGolangDockerfile with custom Dockerfile builder
  • Add tests for the Dockerfile generation feature (verified existing tests pass)
  • Update README documentation with publishing information
  • Build and test the changes
  • Run existing tests to ensure no regressions
  • Fix code formatting issues
  • Use explicit container image tags per repository guidelines
  • Add DockerfileBaseImageAnnotation support for custom base images
  • Implement automatic Go version detection from go.mod and installed toolchain
  • Update README to use WithDockerfileBaseImage extension method
  • Add unit tests for Go version detection
  • Fix potential deadlock in process output reading
  • Use specific exception types instead of generic catch clauses
  • Add CA certificates and working directory to runtime stage

Summary

Added automatic Dockerfile generation for Golang applications using Aspire 13's experimental WithDockerfileBuilder API. The implementation:

  • Automatically generates a multi-stage Dockerfile when publishing Golang resources
  • Detects Go version from go.mod file or installed toolchain, falling back to 1.23
  • Uses golang:{detected-version} for the build stage and alpine:3.21 for the runtime stage
  • Installs CA certificates in the runtime image for HTTPS support
  • Sets working directory to /app in the runtime stage
  • Supports DockerfileBaseImageAnnotation to customize both build and runtime images
  • Provides clean WithDockerfileBaseImage() API for easier customization
  • Respects build tags if specified
  • Builds the executable specified in the AddGolangApp call
  • Requires no additional configuration from developers

Code quality improvements:

  • Fixed potential deadlock when reading process output by using async read operations
  • Used specific exception types (IOException, UnauthorizedAccessException, RegexMatchTimeoutException, Win32Exception) instead of generic catch clauses
  • Added comprehensive unit tests for Go version detection covering multiple scenarios
  • Made DetectGoVersion method internal and added InternalsVisibleTo for testing

Runtime improvements:

  • Added CA certificates installation (apk --no-cache add ca-certificates) to Alpine runtime image for HTTPS support
  • Set working directory to /app in runtime stage for better organization

Test coverage:

  • Tests version detection from go.mod with patch versions (e.g., 1.22.3 -> 1.22)
  • Tests version detection from go.mod with major.minor only (e.g., 1.20)
  • Tests handling of non-existent directories
  • Tests handling of invalid go.mod format
  • All tests pass successfully against the example Golang project

All unit tests pass (8/8) and the code follows the project's style guidelines.

Fixes #968

Original prompt

This section details on the original issue you should resolve

<issue_title>Add support for Golang dockerfile generation</issue_title>
<issue_description>### Related to an existing integration?

Yes

Existing integration

CommunityToolkit.Aspire.Hosting.Golang

Overview

Aspire 13 allows to define how dockerfile should be generated for certain resources:

  .PublishAsDockerFile(publish =>
  {
      publish.WithDockerfileBuilder("/path/to/app", context =>
      {
          var buildStage = context.Builder
              .From("golang:1.23", "builder")
              .WorkDir("/build")
              .Copy(".", "./")
              .Run("go build -o /app/server .");

          context.Builder
              .From("alpine:latest")
              .CopyFrom(buildStage.StageName!, "/app/server", "/app/server")
              .Entrypoint(["/app/server"]);
      });

documented here: https://aspire.dev/whats-new/aspire-13/#dockerfile-builder-api-experimental

this should be added to the golang resource, so that the dev can avoid define its own dockerfile for golang apps.

Usage example

adding the golang app this way

var golang = builder.AddGolangApp("golang", "../gin-api")
    .WithHttpEndpoint(env: "PORT")
    .WithHttpHealthCheck("/health");

would automatically support the publish as dockerfile without defining one.

Breaking change?

No

Alternatives

var golang = builder.AddGolangApp("golang", "../gin-api")
    .WithHttpEndpoint(env: "PORT")
    .WithHttpHealthCheck("/health")
    .PublishAsDockerfile();

this would work given the dockerfile is found in the working directory.

Additional context

No response

Help us help you

Yes, I'd like to be assigned to work on this item</issue_description>

Comments on the Issue (you are @copilot in this section)

Custom agent used: Hosting Integration Creator
This agent helps users create new hosting integration in Aspire by scaffolding the correct projects and files based on user input.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits November 12, 2025 10:24
Co-authored-by: tommasodotNET <12819039+tommasodotNET@users.noreply.github.com>
Co-authored-by: tommasodotNET <12819039+tommasodotNET@users.noreply.github.com>
Co-authored-by: tommasodotNET <12819039+tommasodotNET@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for Golang dockerfile generation Add automatic Dockerfile generation for Golang integration Nov 12, 2025
Copilot AI requested a review from tommasodotNET November 12, 2025 10:35
Copilot finished work on behalf of tommasodotNET November 12, 2025 10:35
Copilot AI temporarily deployed to azure-artifacts November 15, 2025 14:16 Inactive
@aaronpowell aaronpowell added this to the 13 milestone Nov 15, 2025
buildArgs.Add(executable);

var buildStage = context.Builder
.From("golang:1.23", "builder")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot See the code here https://github.com/dotnet/aspire/blob/04bae8e2f0dfa71823b74dc3a7a48c630f441e99/src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs#L316-L322. Use DockerfileBaseImageAnnotation to override the default base image. Also handle detecting the default go version based on the go installed and fallback to version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Added DockerfileBaseImageAnnotation support to customize both build and runtime images, and implemented automatic Go version detection from go.mod and installed toolchain with fallback to 1.23. The implementation follows the JavaScript integration pattern. (46c54ea)

…tection

Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Copilot AI changed the title Add automatic Dockerfile generation for Golang integration Add automatic Dockerfile generation with version detection for Golang integration Nov 16, 2025
Copilot AI requested a review from davidfowl November 16, 2025 00:58
Copilot finished work on behalf of davidfowl November 16, 2025 00:58
```csharp
var golang = builder.AddGolangApp("golang", "../gin-api")
.WithHttpEndpoint(env: "PORT")
.WithAnnotation(new DockerfileBaseImageAnnotation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot You can use WithDockerfileBaseImage:

builder.AddPythonApp("myapp", "path/to/app", "main.py")
             .WithDockerfileBaseImage(
            buildImage: "ghcr.io/astral-sh/uv:python3.12-bookworm-slim",
            runtimeImage: "python:3.12-slim-bookworm");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated README to use WithDockerfileBaseImage() extension method for a cleaner API. (4fb890c)

Co-authored-by: davidfowl <95136+davidfowl@users.noreply.github.com>
Copilot AI requested a review from davidfowl November 16, 2025 01:09
Copilot finished work on behalf of davidfowl November 16, 2025 01:09
@tommasodotNET tommasodotNET marked this pull request as ready for review November 16, 2025 18:57
Copilot AI review requested due to automatic review settings November 16, 2025 18:57
Copilot finished reviewing on behalf of tommasodotNET November 16, 2025 18:59
Co-authored-by: tommasodotNET <12819039+tommasodotNET@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 16, 2025

@copilot we want to have unit testing for the Golang version detection. test the method against the golang example (./examples/golang).

Added comprehensive unit tests for Go version detection in GoVersionDetectionTests.cs. Tests cover:

  • Version detection from go.mod in the golang example (detects 1.22 from 1.22.3)
  • Version detection with patch versions
  • Version detection with major.minor only
  • Handling of non-existent directories
  • Handling of invalid go.mod format

Made DetectGoVersion method internal and added InternalsVisibleTo for testing. All 5 new tests pass. (6897c21)

Copilot AI requested a review from tommasodotNET November 16, 2025 23:24
Copilot finished work on behalf of tommasodotNET November 16, 2025 23:24
@davidfowl
Copy link
Contributor

I wrote something similar here (with less features), I think you should consider the go mod tidy / go download https://github.com/davidfowl/aspire-13-samples/blob/731a43a848706cf0bbcece1506122e5b6c19f2d8/golang-api/apphost.cs#L53-L61

@aaronpowell
Copy link
Member

I wrote something similar here (with less features), I think you should consider the go mod tidy / go download https://github.com/davidfowl/aspire-13-samples/blob/731a43a848706cf0bbcece1506122e5b6c19f2d8/golang-api/apphost.cs#L53-L61

Do you mean extending the current Go integration to support the installer model? If so, I'd prefer that we do it as a separate PR, so that we don't overcomplicate each PR produced.

@tommasodotNET
Copy link
Contributor

tommasodotNET commented Nov 17, 2025

I wrote something similar here (with less features), I think you should consider the go mod tidy / go download https://github.com/davidfowl/aspire-13-samples/blob/731a43a848706cf0bbcece1506122e5b6c19f2d8/golang-api/apphost.cs#L53-L61

that's a great idea. i'll handle this in another pr so we can keep this one tied to the issue --> #975

@tommasodotNET
Copy link
Contributor

@copilot looking at this sample https://github.com/davidfowl/aspire-13-samples/blob/731a43a848706cf0bbcece1506122e5b6c19f2d8/golang-api/apphost.cs#L31C39-L51C42 it looks like we are missing some steps in the container creation such as the certificate management

Co-authored-by: tommasodotNET <12819039+tommasodotNET@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 17, 2025

@copilot looking at this sample https://github.com/davidfowl/aspire-13-samples/blob/731a43a848706cf0bbcece1506122e5b6c19f2d8/golang-api/apphost.cs#L31C39-L51C42 it looks like we are missing some steps...

Added CA certificates installation and working directory to the runtime stage. The generated Dockerfile now includes:

  • Run("apk --no-cache add ca-certificates") for HTTPS support
  • WorkDir("/app") for proper directory structure

This matches the pattern from the referenced sample. (8c72923)

Copilot AI requested a review from tommasodotNET November 17, 2025 09:39
Copilot finished work on behalf of tommasodotNET November 17, 2025 09:39
@davidfowl
Copy link
Contributor

One more thing worth considering, if we want to support pushing files into go containers from other resources would be to implement IContainerFilesDestinationResource. Can be done in a follow up PR. Take a look at how the other resources implement this.

@tommasodotNET
Copy link
Contributor

tommasodotNET commented Nov 17, 2025

One more thing worth considering, if we want to support pushing files into go containers from other resources would be to implement IContainerFilesDestinationResource. Can be done in a follow up PR. Take a look at how the other resources implement this.

#977

as far as i understand, we just need to implement IContainerFilesDestinationResource on the golangappresource, which doesn't require much custom code.
we might want to update the golang sample to actually have a static frontend to show how to push those file in the golang container.

@davidfowl
Copy link
Contributor

@tommasodotNET
Copy link
Contributor

@tommasodotNET no it does require custom code. https://github.com/dotnet/aspire/blob/9c0a92bb2d0fa509e871e5a70a21ad495db46c82/src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs#L167

yeah saw that after. updated my comment and the issue. sry

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for Golang dockerfile generation

4 participants