-
Couldn't load subscription status.
- Fork 713
Add ContainerFilesDestinationAnnotation support to ProjectResource #12355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Implement pipeline step factory for ProjectResource to support copying static files from other container resources before building docker images. Co-authored-by: eerhardt <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot - apply the following feedback
…ource build steps - Added CopyContainerFilesAsync method to IContainerRuntime interface with implementations in ContainerRuntimeBase - Changed CopyContainerFilesToProjectAsync to use IContainerRuntime instead of calling docker directly - Fixed GetPublishDirectoryAsync to use 'dotnet msbuild -c Release -getProperty:PublishDir' instead of hardcoded path - Changed source resource build step to use generic CreateBuildImageStep instead of CreateProjectBuildImageStep Co-authored-by: eerhardt <[email protected]>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 12355Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 12355" |
|
@copilot - respond to the feedback |
… Dockerfile - Build ProjectResource image with normal flow first - Tag built image with temporary GUID tag - Generate Dockerfile that FROMs temp image and COPY --from source containers - Build final image from generated Dockerfile with real tag - Removed CopyContainerFilesAsync from IContainerRuntime (no longer needed) - Removed GetPublishDirectoryAsync helper (no longer needed) Co-authored-by: eerhardt <[email protected]>
The new design uses DockerfileBuilder with COPY --from: instead of extracting files from containers to the host filesystem, so the CopyContainerFilesAsync method is no longer needed. Co-authored-by: eerhardt <[email protected]>
All feedback has been addressed in commits cd9a23f and 1b0aa02: ✅ Line 1118 feedback: Refactored implementation to build ProjectResource image first, tag with temp GUID, generate Dockerfile using DockerfileBuilder API with COPY --from: statements, then build final image. ✅ Previous feedback resolved:
The implementation now uses Docker multi-stage builds with COPY --from: instead of filesystem operations, eliminating the need for CopyContainerFilesAsync and PublishDir determination. |
playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/AppHost.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request implements support for copying container files between resources during the publish pipeline, enabling scenarios where assets (like static files from a JavaScript build) need to be incorporated into a project's container image.
Key changes:
- Adds
RemoveImageAsyncmethod toIContainerRuntimeinterface for cleanup of temporary images - Refactors
FakeContainerRuntimeandMockImageBuildertest helpers into shared files for reuse across test projects - Implements logic in
ProjectResource.BuildProjectImageto layer container files on top of project images using temporary tagged images and generated Dockerfiles - Demonstrates the feature in the AspireWithJavaScript playground by publishing React/Vite static files into the weather API project
Reviewed Changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/Aspire.Hosting/Publishing/IContainerRuntime.cs | Adds RemoveImageAsync method to the interface |
| src/Aspire.Hosting/Publishing/ContainerRuntimeBase.cs | Implements RemoveImageAsync using "rmi" command |
| src/Aspire.Hosting/Publishing/ResourceContainerImageBuilder.cs | Refactors container runtime resolution to use DI instead of lazy initialization |
| src/Aspire.Hosting/DistributedApplicationBuilder.cs | Registers IContainerRuntime as singleton with factory that resolves from DcpOptions |
| src/Aspire.Hosting/ApplicationModel/ProjectResource.cs | Implements BuildProjectImage method to handle container file copying with temporary images and Dockerfile generation |
| src/Aspire.Hosting/ProjectResourceBuilderExtensions.cs | Adds pragma warnings to suppress experimental API diagnostics |
| tests/Aspire.Hosting.Tests/Publishing/FakeContainerRuntime.cs | Moves FakeContainerRuntime to shared file and adds RemoveImageAsync support |
| tests/Aspire.Hosting.Tests/MockImageBuilder.cs | Moves MockImageBuilder to shared file for reuse |
| tests/Aspire.Hosting.Tests/Publishing/ResourceContainerImageBuilderTests.cs | Removes inline FakeContainerRuntime class now that it's shared |
| tests/Aspire.Hosting.Tests/ProjectResourceTests.cs | Adds tests for container files destination annotation functionality |
| tests/Aspire.Hosting.Azure.Tests/ProvisioningTestHelpers.cs | Removes duplicate MockImageBuilder now that it's shared |
| playground/AspireWithJavaScript/* | Updates playground to demonstrate the feature by serving Vite-built static files from the API project |
| private async Task BuildProjectImage(PipelineStepContext ctx) | ||
| { | ||
| var containerImageBuilder = ctx.Services.GetRequiredService<IResourceContainerImageBuilder>(); | ||
| var logger = ctx.Services.GetRequiredService<ILogger<ProjectResource>>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this actually use the Logger in the PipelineStepContext?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in #12476
…mprove debugging - Get $(ContainerWorkingDirectory) from project using dotnet msbuild instead of hardcoding /app - Add GetContainerWorkingDirectoryAsync helper method with fallback to /app - Keep temporary Dockerfile on build failure for debugging purposes - Log debug message with path to temporary Dockerfile when build fails Co-authored-by: eerhardt <[email protected]>
playground/AspireWithJavaScript/AspireJavaScript.Angular/default.conf.template
Outdated
Show resolved
Hide resolved
…12355) * Initial plan * Add ContainerFilesDestinationAnnotation support to ProjectResource Implement pipeline step factory for ProjectResource to support copying static files from other container resources before building docker images. Co-authored-by: eerhardt <[email protected]> * Address PR feedback: use IContainerRuntime, fix PublishDir, generic source build steps - Added CopyContainerFilesAsync method to IContainerRuntime interface with implementations in ContainerRuntimeBase - Changed CopyContainerFilesToProjectAsync to use IContainerRuntime instead of calling docker directly - Fixed GetPublishDirectoryAsync to use 'dotnet msbuild -c Release -getProperty:PublishDir' instead of hardcoded path - Changed source resource build step to use generic CreateBuildImageStep instead of CreateProjectBuildImageStep Co-authored-by: eerhardt <[email protected]> * Make it work in the playground * Refactor to build project image first, then layer container files via Dockerfile - Build ProjectResource image with normal flow first - Tag built image with temporary GUID tag - Generate Dockerfile that FROMs temp image and COPY --from source containers - Build final image from generated Dockerfile with real tag - Removed CopyContainerFilesAsync from IContainerRuntime (no longer needed) - Removed GetPublishDirectoryAsync helper (no longer needed) Co-authored-by: eerhardt <[email protected]> * Revert CopyContainerFilesAsync from IContainerRuntime - no longer needed The new design uses DockerfileBuilder with COPY --from: instead of extracting files from containers to the host filesystem, so the CopyContainerFilesAsync method is no longer needed. Co-authored-by: eerhardt <[email protected]> * Make it work by using the correct image name. * Update for latest code * Add RemoveImageAsync to IContainerRuntime for cleanup of temporary images - Added RemoveImageAsync method to IContainerRuntime interface - Implemented in ContainerRuntimeBase using 'rmi' command - Uncommented cleanup code in ProjectResource to remove temporary tagged images - Ensures temporary images are cleaned up after layering container files Co-authored-by: eerhardt <[email protected]> * move test * Clean up code. * Clean up code Add more tests * Fix the playground app * Address PR feedback * Address PR feedback: Get ContainerWorkingDirectory from project and improve debugging - Get $(ContainerWorkingDirectory) from project using dotnet msbuild instead of hardcoding /app - Add GetContainerWorkingDirectoryAsync helper method with fallback to /app - Keep temporary Dockerfile on build failure for debugging purposes - Log debug message with path to temporary Dockerfile when build fails Co-authored-by: eerhardt <[email protected]> * Apply suggestion from @eerhardt * Refactor copilots code. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: eerhardt <[email protected]> Co-authored-by: Eric Erhardt <[email protected]>

Implementation Complete: Static Files Copying Support for ProjectResource
Successfully enhanced ProjectResource to support copying static files from other container resources before building docker images, following the pattern established in PR #12265.
✅ Completed - All Feedback Addressed
Latest Design (per review feedback):
Instead of copying files to PublishDir before building, the implementation now:
temp-{GUID})FROMthe temp-tagged ProjectResource imageCOPY --from:to layer files from source container images$(ContainerWorkingDirectory)property for destination pathsRemoveImageAsync📝 Implementation Summary
Files Modified:
src/Aspire.Hosting/ApplicationModel/ProjectResource.cs$(ContainerWorkingDirectory)from project dynamically usingdotnet msbuild -getPropertysrc/Aspire.Hosting/ProjectResourceBuilderExtensions.csCreateBuildImageStepfor generic resource image buildingCreateProjectBuildImageStepto implement layered build approachsrc/Aspire.Hosting/Publishing/IContainerRuntime.csRemoveImageAsyncmethod for cleaning up temporary imagessrc/Aspire.Hosting/Publishing/ContainerRuntimeBase.csRemoveImageAsyncusingrmicommand (works for both Docker and Podman)tests/Aspire.Hosting.Tests/ProjectResourceTests.cs🔧 Technical Details
New Approach:
COPY --from:for efficient file copying$(ContainerWorkingDirectory)from project (defaults to /app if not available)RemoveImageAsyncto IContainerRuntime interface for proper resource cleanupBenefits:
🎯 Usage
Files are layered into the project's container image using Docker COPY --from: during image build. The destination path respects the project's configured
$(ContainerWorkingDirectory). Temporary images are automatically cleaned up after the final image is built.✅ Testing & Validation
This pull request was created as a result of the following prompt from Copilot chat.
Original prompt
This pull request was created as a result of the following prompt from Copilot chat.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.