microsoft / microsoft/aspire

[Aspire.Hosting.Docker] UpdateConfig.MaxFailureRatio serializes as a quoted string and produces invalid Compose YAML

Open Beginner friendly
#19,000 1 comment 0 reactions 0 assignees View on GitHub
area-deployment triage:bot-seen
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

`Aspire.Hosting.Docker.Resources.ServiceNodes.Swarm.UpdateConfig.MaxFailureRatio` is typed as `string?`.

When assigned a valid Docker Swarm failure ratio such as `"0"`, Aspire publishes it as a quoted YAML string:

```yaml
deploy:
update_config:
max_failure_ratio: "0"
```

Docker Compose requires `max_failure_ratio` to be a numeric value. As a result, the generated deployment artifact fails validation:

```text
services.web.deploy.update_config.max_failure_ratio must be a number
```

This appears related to #15566, which corrected the types of `Parallelism` and `FailureAction`, but did not change `MaxFailureRatio`.

### Expected Behavior

`MaxFailureRatio` should use a numeric CLR type, likely `double?`, and serialize as a YAML number:

```yaml
deploy:
update_config:
max_failure_ratio: 0
```

A Compose file generated by Aspire should pass `docker compose config` and `docker stack config` validation without requiring manual edits.

### Steps To Reproduce

Create an Aspire AppHost with the Docker hosting integration and configure a Docker Compose service with `MaxFailureRatio`:

```csharp
using Aspire.Hosting.Docker.Resources.ServiceNodes.Swarm;

var builder = DistributedApplication.CreateBuilder(args);

builder.AddContainer("web", "nginx")
.PublishAsDockerComposeService((_, service) =>
{
service.Deploy ??= new();
service.Deploy.UpdateConfig = new UpdateConfig
{
Parallelism = 1,
FailureAction = "rollback",
MaxFailureRatio = "0",
Order = "start-first"
};
});

builder.AddDockerComposeEnvironment("compose");

builder.Build().Run();
```

Publish the application:

```shell
aspire publish --environment Production --non-interactive
```

The generated Compose YAML contains:

```yaml
update_config:
parallelism: 1
failure_action: "rollback"
max_failure_ratio: "0"
order: "start-first"
```

Validate it:

```shell
docker stack config -c docker-compose.yaml
```

The command fails with:

```text
services.web.deploy.update_config.max_failure_ratio must be a number
```

Removing `MaxFailureRatio` allows the generated Compose file to validate because Docker's default value is numeric zero.

### Exceptions (if any)

No .NET exception is thrown during publishing. The invalid type is detected by Docker when validating the generated Compose file:

```text
services.web.deploy.update_config.max_failure_ratio must be a number
```

### Aspire doctor output

```text
Aspire Environment Check
========================

Aspire
✅ Aspire CLI version 13.4.6 (channel: stable)

AppHost
✅ AppHost version 13.4.6

.NET SDK
✅ .NET 10.0.400-preview.0.26322.102 installed (x64)

Container Runtime
✅ Docker v29.6.2: running (auto-detected (default))

Environment
✅ HTTPS development certificate is trusted

Summary: 5 passed, 0 warnings, 0 failed

Aspire CLI version:
13.4.6+87fe259e4fc244c599019a7b1304c85a1488f248
```

### Anything else?

- Operating system: Windows
- Aspire CLI: 13.4.6
- Aspire AppHost SDK: 13.4.6
- .NET SDK: 10.0.400-preview.0.26322.102
- Docker Engine: 29.6.2
- Deployment target: Docker Compose used with Docker Swarm
- Workaround: omit `MaxFailureRatio`, allowing Docker's default value of `0` to apply
- Related change: https://github.com/microsoft/aspire/pull/15566

Contributor guide

Open the contributing guide

Research direction

Inspect Aspire.Hosting.Docker.Resources.ServiceNodes.Swarm.UpdateConfig, focusing on the MaxFailureRatio declaration and the existing Docker Compose serialization path. Reproduce the issue with the configuration shown, then verify that the generated max_failure_ratio is numeric and that the resulting file passes docker stack config or docker compose config validation.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, docker, docker-compose
Domain
devops
Issue type
Bug
Difficulty
2/5
Estimated time
Half a day
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.