feat: add container image passthrough - #9588
Conversation
Adds docker.imagePassthrough so service targets can consume a final remote image reference without azd building, pulling, tagging, copying, or publishing it.\n\nFixes Azure#9587
|
Azure Pipelines: 7 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: 7 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Adds container image passthrough so azd can deploy existing remote images without local or ACR image operations.
Changes:
- Adds schema, documentation, protobuf, and mapper support.
- Bypasses container build/package/publish operations.
- Adds validation and target-specific tests.
Reviewed changes
Copilot reviewed 15 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
schemas/v1.0/azure.yaml.json |
Adds option and validation. |
schemas/alpha/azure.yaml.json |
Adds alpha schema support. |
docs/reference/azure-yaml-schema.md |
Documents passthrough usage. |
cli/azd/pkg/project/service_target_containerapp.go |
Routes passthrough publishing through the helper. |
cli/azd/pkg/project/service_target_containerapp_test.go |
Tests Container Apps passthrough. |
cli/azd/pkg/project/service_target_appservice.go |
Supports App Service passthrough. |
cli/azd/pkg/project/service_target_appservice_test.go |
Tests App Service passthrough. |
cli/azd/pkg/project/service_target_aks.go |
Enables AKS passthrough without package artifacts. |
cli/azd/pkg/project/mapper_registry.go |
Maps the new option. |
cli/azd/pkg/project/mapper_registry_test.go |
Tests mapper conversions. |
cli/azd/pkg/project/framework_service_docker.go |
Defines the Docker option. |
cli/azd/pkg/project/framework_service_docker_test.go |
Tests build, package, and tool behavior. |
cli/azd/pkg/project/container_helper.go |
Implements passthrough validation and artifacts. |
cli/azd/pkg/project/container_helper_test.go |
Tests resolution and publishing behavior. |
cli/azd/pkg/azdext/models.pb.go |
Updates generated protobuf bindings. |
cli/azd/grpc/proto/models.proto |
Adds the protobuf field. |
Files not reviewed (1)
- cli/azd/pkg/azdext/models.pb.go: Generated file
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 21 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- cli/azd/pkg/azdext/models.pb.go: Generated file
Suppressed comments (1)
cli/azd/pkg/project/service_manager.go:507
- (azd-code-reviewer) This manager-level validation still checks only the publish override. With
--from-package,serviceContext.Packageis pre-populated, soPublishskipssm.Package; an external target then receivesimagePassthrough: trueeven when the service image is empty ordocker.remoteBuildis also true, because it never callsContainerHelper. Validate the full passthrough configuration here before cache lookup and target dispatch.
if err := validatePublishOptions(serviceConfig, publishOptions); err != nil {
return nil, err
}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- cli/azd/pkg/azdext/models.pb.go: Generated file
Suppressed comments (2)
cli/azd/pkg/project/container_helper.go:707
- (azd-code-reviewer) This repeats the canonical-form restriction for deploy overrides, so
azd deploy --from-package docker.io/nginx:latestis rejected even though it is a fully qualified remote reference. Use the same syntax-plus-explicit-registry validation as the configured-image path, without requiring Docker's normalizedlibrary/spelling.
if _, err := reference.ParseNamed(artifact.Location); err != nil {
return "", false, fmt.Errorf(
"docker.imagePassthrough requires --from-package to be a fully qualified remote container image: %w",
err,
)
cli/azd/pkg/project/container_helper.go:279
- (azd-code-reviewer)
reference.ParseNamedrequires Docker's canonical spelling, which is stricter than the documented “fully qualified remote image” requirement. For example, it rejects the valid explicit referencedocker.io/nginx:latestbecause Docker normalizes it todocker.io/library/nginx:latest; passthrough should accept the former and preserve it unchanged. Validate reference syntax and the presence of an explicit registry separately rather than requiring canonical string equality.
This issue also appears on line 703 of the same file.
if _, err := reference.ParseNamed(image); err != nil {
return "", fmt.Errorf("passthrough image must be a fully qualified remote container image: %w", err)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 24 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- cli/azd/pkg/azdext/models.pb.go: Generated file
Suppressed comments (1)
cli/azd/internal/cmd/publish.go:385
- (azd-code-reviewer) The new successful no-publish path contradicts the existing command help:
GetCmdPublishHelpDescriptionand the usage/Fig snapshots still say thatazd publishpublishes to a container registry and automatically publishes the packaged image. Update the help notes to explain the passthrough exception and regenerate the command snapshots soazd publish --helpmatches this behavior.
resultHeader := fmt.Sprintf("Your application was published in %s.", ux.DurationAsText(since(startTime)))
if passthroughServiceCount == len(publishResults) && passthroughServiceCount > 0 {
resultHeader = "No images were published. Existing remote images are configured for deployment."
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 27 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- cli/azd/pkg/azdext/models.pb.go: Generated file
Suppressed comments (1)
cli/azd/pkg/project/container_helper.go:736
- (azd-code-reviewer) This error can also be raised for artifacts added by a service target during ordinary package→publish execution, so saying they came “from --from-package” is misleading. Describe them as package artifacts without attributing their source to the flag.
"docker.imagePassthrough does not support %s artifacts from --from-package; "+
"use a fully qualified remote container image",
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
Summary
Adds an explicit core signal for service targets that deploy an already-published container image by reference:
When
docker.imagePassthroughis true, azd treats the service-levelimageas the final remote container artifact and does not:The exact image reference is passed to the service target through remote package and publish artifacts.
Fixes #9587
Motivation
Core Docker framework packaging runs before extension service-target packaging. For a service with a top-level
imageand no local build artifact, core currently treats the image as an external source image and performsdocker pullfollowed bydocker tag.That behavior is correct for existing Container Apps, AKS, and App Service scenarios that copy an external image into a deployment registry, but it prevents targets that delegate image retrieval to the destination platform. One example is a Foundry hosted agent whose private registry authentication is represented by a Foundry project connection rather than local Docker credentials.
The agents extension currently uses
docker.remoteBuild: trueto suppress local Build and Package. That is not the intended meaning ofremoteBuild, which represents an ACR Tasks build.Behavior
Passthrough
Produces a remote container artifact with the same image reference during Package and Publish. Core performs no local or remote image operations.
Validation
The following combinations are rejected:
A publish image override is also rejected because passthrough preserves the configured image reference unchanged.
Backward compatibility
imagePassthroughdefaults to false. Existing behavior remains unchanged when the property is absent:docker.remoteBuildcontinues to mean an ACR Tasks build with the existing local fallback behavior;--from-packageshort-circuits remain unchanged.Implementation
ImagePassthroughtoDockerProjectOptionsimage_passthrough = 11ContainerHelper.PublishTests
Coverage includes:
remoteBuildconflict validationgolangci-lintandcspellwere unavailable locally; CI will run both.