fix: pass ContainerEngine to dotnet publish when Podman is used#8527
Conversation
When users have Podman instead of Docker, `dotnet publish /t:PublishContainer` defaults to Docker and fails silently, producing empty stdout. This causes azd to error with "empty dotnet configuration output". This change threads the detected container engine from docker.Cli through to the dotnet publish commands via a new `containerEngine` parameter. When the engine is "podman", azd appends `-p:ContainerEngine=podman` to the MSBuild command, telling the .NET SDK to use Podman for container operations. Changes: - Export `ContainerEngine()` getter on `docker.Cli` - Add `ContainerEngine()` delegate on `ContainerHelper` - Add `containerEngine` parameter to `BuildContainerLocal` and `PublishContainer` - Add `appendContainerEngine` helper in dotnet package - Add tests for podman/docker/empty engine scenarios Fixes #8525 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes Aspire container publish failures when users are running Podman instead of Docker by threading the detected container runtime into dotnet publish /t:PublishContainer. It ensures the .NET SDK is explicitly told which engine to use (via -p:ContainerEngine=podman) so the generated container configuration output is produced correctly and azd doesn’t hit the “empty dotnet configuration output” error.
Changes:
- Expose the detected container engine from
docker.Cliand surface it viaproject.ContainerHelper. - Extend
dotnet.Clicontainer publish/build helpers to acceptcontainerEngineand append-p:ContainerEngine=<engine>when appropriate. - Add unit tests covering podman/docker/empty engine behavior for both local-build and publish paths.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| cli/azd/pkg/tools/dotnet/dotnet.go | Adds containerEngine parameter plumbing and appends -p:ContainerEngine=... for non-docker engines. |
| cli/azd/pkg/tools/dotnet/dotnet_commands_test.go | Adds test coverage ensuring ContainerEngine property is appended (podman) or omitted (docker/empty). |
| cli/azd/pkg/tools/docker/docker.go | Exposes ContainerEngine() getter (wrapping existing engine-selection logic). |
| cli/azd/pkg/project/service_target_dotnet_containerapp.go | Passes detected container engine through dotnet container build/publish call sites. |
| cli/azd/pkg/project/container_helper.go | Adds ContainerEngine() delegate and threads engine into runDotnetPublish. |
📋 Prioritization NoteThanks for the contribution! The linked issue isn't in the current milestone yet. |
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
hemarina
left a comment
There was a problem hiding this comment.
Nice targeted fix. The property name -p:ContainerEngine=podman matches the .NET SDK container build contract (per dotnet/sdk-container-builds and the publish-as-container docs), and the threading from docker.Cli → ContainerHelper → dotnet.Cli lines up with the existing engine-detection path in docker.Cli.CheckInstalled(). The appendContainerEngine helper has the right defensive shape — "" and "docker" are both no-ops, so the .NET SDK's own default keeps working untouched and the rollout is backward-compatible. All call sites are updated (2 production, all existing test sites bumped by one arg) and the 4 new test cases cover the matrix that matters: podman appends, docker no-op, empty no-op, and the PublishContainer (remote push) path in addition to local build.
Two non-blocking thoughts:
-
Consider a wiring test, not just a unit test. The new
Test_Cli_ContainerEnginecases provedotnet.Clihonors whatever engine string it's given. They don't prove the call sites incontainer_helper.go/service_target_dotnet_containerapp.goactually pass the detected engine vs. an empty string — a future refactor could regress this and only manual testing on a Podman box would catch it. A small test that wires a fakedocker.CliwithcontainerEngine = "podman"throughContainerHelper.runDotnetPublishand asserts the captured exec args include-p:ContainerEngine=podmanwould close that gap. -
Redundant exported wrappers.
docker.Cli.ContainerEngine()is a one-line passthrough togetContainerEngine(), andContainerHelper.ContainerEngine()is a one-line passthrough toch.docker.ContainerEngine(). Either promotinggetContainerEnginedirectly toContainerEngine(rename + update internal callers) or inlining theContainerHelperhelper would trim two layers without losing anything. Total style nit — fine to leave.
LGTM otherwise.
Problem
When users have Podman instead of Docker,
dotnet publish /t:PublishContainerdefaults to Docker and fails silently — producing empty stdout. This causes azd to error with:Upstream issue: microsoft/aspire#17593
Root Cause
azd detects the container runtime (Docker vs Podman) in
docker.Cli.CheckInstalled(), but this information was never passed todotnet publish. The .NET SDK supports a-p:ContainerEngine=podmanMSBuild property, but azd was not setting it.Fix
Thread the detected container engine from
docker.Clithrough to the dotnet publish commands:docker.Cli: ExportContainerEngine()getter (wraps existing privategetContainerEngine())ContainerHelper: AddContainerEngine()delegate methoddotnet.Cli: AddcontainerEngineparameter toBuildContainerLocalandPublishContainer; append-p:ContainerEngine=podmanwhen engine is not DockerdotnetContainerAppTarget,ContainerHelper)Testing
-p:ContainerEngine=podmanis appendedPublishContainer(remote push) pathFixes #8525