aspire icon indicating copy to clipboard operation
aspire copied to clipboard

Docker Compose Image Tag for Projects

Open BernhardPollerspoeck opened this issue 3 months ago • 3 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

given the simple AppHost Example here i cant control the Tag that gets created by "aspire publish". A Tag Per Project does not seem nessecary, but for the build a Version would help identification.

var builder = DistributedApplication.CreateBuilder(args);

var compose = builder.AddDockerComposeEnvironment("compose")
    .WithProperties(env =>
    {
        env.DefaultNetworkName = "adv-network";
    });

var api = builder.AddProject<Projects.qsp_AdventureStudio_Api>("adv-api")
    .WithReference(postgres)
    .WaitForCompletion(migrator);

Describe the solution you'd like

Id like a Solution like:

var compose = builder.AddDockerComposeEnvironment("compose")
    .WithProperties(env =>
    {
        env.DefaultNetworkName = "adv-network";
        env.ProjectImageTag = "not-latest";
    });

Additional context

My current CI solution has a workaround, but requires the following steps per service:

  • download latest image
  • check timestamp if it may be the correct (not robust)
  • tag the image
  • upload the new tagged image

this is a not robust and not satisfying way of archieving this behavior.

BernhardPollerspoeck avatar Sep 21 '25 03:09 BernhardPollerspoeck

@BernhardPollerspoeck Thanks for filing this issue!

We're introducing a solution for this in the form of a new DeploymentImageTagCallbackAnnotation in the core API. You can use it to set the tag on individual resources like so:

var api = builder.AddProject<Projects.qsp_AdventureStudio_Api>("adv-api")
  .WithDeploymentImageTag(async (context) =>
  {
      var commitSha = await GetCurrentCommitShaAsync();
      var resourceName = resource.Name.ToLowerInvariant();
      return $"{resourceName}-{commitSha}";
  });

Or globally for all compute resources in your app.

builder.Eventing.Subscribe<BeforeStartEvent>(async (evt, ct) =>
{
    var commitSha = await GetCurrentCommitShaAsync();
    foreach (var resource in evt.Model.Resources)
    {
        builder.CreateResourceBuilder(resource).WithDeploymentImageTag((context) =>
        {
            var resourceName = resource.Name.ToLowerInvariant();
            return $"{resourceName}-{commitSha}";
        });
    }
});

We're also considering setting a default timestamped tag for Docker Compose publishers like we do for the Azure deployment workflow.

captainsafia avatar Sep 22 '25 16:09 captainsafia

@captainsafia Thank you for this cool way of doing.

A question that arises. your examples show the docker image tag itself?

Would this be possible to set "globally" on the Environment like ? (just an idea)

var compose = builder.AddDockerComposeEnvironment("compose")
     .WithDeploymentImageTag((context) =>
        {
            var resourceName = resource.Name.ToLowerInvariant();
            return $"{resourceName}-{commitSha}";
        });

BernhardPollerspoeck avatar Sep 22 '25 16:09 BernhardPollerspoeck

@captainsafia I am confused. DeploymentImageTagCallbackAnnotation doesn't seem to be used when calling dotnet publish for ProjectResource?

lvde0 avatar Nov 04 '25 15:11 lvde0