Skip to content

.env is sorted alphabetically, leading to environment placeholders breaking #13067

@Falco20019

Description

@Falco20019

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Not sure if this is already resolved by #12656. 13.0 sorts the .env file alphabetically which destroys cross references made using AsEnvironmentPlaceholder in PublishAsDockerComposeService. With 9.5, the order is preserved and existing .env variables on top were kept. This is related to #12009 which now broke.

I use it to ensure the docker compose create the image in the form of image: "${ABC_DOCKER_REPOSITORY}:${ABC_IMAGE_TAG:-2.12.44}".

var interfaceDockerRepositoryParam = builder.AddParameter("interface-docker-repository", "${DOCKER_REGISTRY_HOSTNAME}/myPrefix/", true)
...
// Workaround since resource.AddEnvironmentVariable is not accessible...
static ParameterResource GetUntrackedParameter(string name, string value)
{
    return new ParameterResource(name, _ => value)
    {
        // This is necessary, as https://github.com/dotnet/aspire/blob/88da0b94e248d131a8b333bebd4c98031ef35f7f/src/Aspire.Hosting.Docker/DockerComposePublishingContext.cs#L184
        // checks for Default to be set, which makes no sense...
        // Default is only meant to allow the value to be added to the manifest. The GetValueAsync would work either way...
        Default = new GenerateParameterDefault()
    };
}
...
var repositoryName = $"{interfaceDockerRepositoryParam.AsEnvironmentPlaceholder(resource)}{resource.Name}";
var resourceDockerRepoParam = GetUntrackedParameter(resource.Name + "-docker-repository", repositoryName);
var resourceImageTagParam = GetUntrackedParameter(resource.Name + "-image-tag", string.Empty);

// Get environment names:
var resourceDockerRepoEnvName = resourceDockerRepoParam.AsEnvironmentPlaceholder(resource)[2..^1];
var resourceImageTagEnvName = resourceImageTagParam.AsEnvironmentPlaceholder(resource)[2..^1];
service.Image = $"${{{resourceDockerRepoEnvName}}}:${{{resourceImageTagEnvName}:-{fallbackVersion}}}";

If the resource.Name is alphabetically after INTERFACE_DOCKER_REPOSITORY, the reference will work. If not, the reference can't be resolved on startup...

In the past, this was created as

INTERFACE_DOCKER_REPOSITORY=${DOCKER_REGISTRY_HOSTNAME}/myPrefix/
ABC_DOCKER_REPOSITORY=${INTERFACE_DOCKER_REPOSITORY}/abc
ABC_IMAGE_TAG=

now it is created as

ABC_DOCKER_REPOSITORY=${INTERFACE_DOCKER_REPOSITORY}/abc
ABC_IMAGE_TAG=
INTERFACE_DOCKER_REPOSITORY=${DOCKER_REGISTRY_HOSTNAME}/myPrefix/

with INTERFACE_DOCKER_REPOSITORY failing to resolve.

Expected Behavior

The .env file is created as until 9.5 with existing user variables being kept and order working in regards to the placeholders.

Steps To Reproduce

  1. Create a prameter as described above
  2. Use it in PublishAsDockerComposeService as placeholder
  3. Run aspire do prepare-compose
  4. Start the docker-compose

Exceptions (if any)

WARN[0000] The "INTERFACE_DOCKER_REPOSITORY" variable is not set. Defaulting to a blank string.

.NET Version info

.NET SDK:
Version: 10.0.100
Commit: b0f34d51fc
Workload version: 10.0.100.1
MSBuild version: 18.0.2+b0f34d51f

Runtime Environment:
OS Name: Mac OS X
OS Version: 26.1
OS Platform: Darwin
RID: osx-arm64
Base Path: /usr/local/share/dotnet/sdk/10.0.100/

.NET workloads installed:
There are no installed workloads to display.
Configured to use workload sets when installing new manifests.

Host:
Version: 10.0.0
Architecture: arm64
Commit: b0f34d51fc

.NET SDKs installed:
9.0.307 [/usr/local/share/dotnet/sdk]
9.0.308 [/usr/local/share/dotnet/sdk]
10.0.100 [/usr/local/share/dotnet/sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 9.0.11 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 10.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 9.0.11 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
None

Environment variables:
DOTNET_INSTALL_DIR [/usr/local/share/dotnet/]

global.json file:
/Users//GitRepos//global.json

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

Anything else?

ASP.NET Core: 10.0.100
.NET Aspire: 10.0.0
IDE: Rider

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions