aws / aws/aws-cdk

ECR: Use docker image digests to determine ECR tags for DockerImageAsset

Open
#30,937 1 comment 5 reactions 0 assignees View on GitHub
@aws-cdk/aws-ecr @aws-cdk/core effort/medium feature-request p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the feature

Either in an opt-in or default way, AWS CDK should allow using the image Digest (e.g. retrievable with `docker image ls --digest`) instead of the build context fingerprint as the AWS ECR tag.

### Use Case

When building a DockerImageAsset, the automatically generated tag for the asset depends on the hash of the entire build context (by using the function [fingerprint](https://github.com/aws/aws-cdk/blob/597228c1552a21f8dc7250a0be62160f838bb776/packages/aws-cdk-lib/core/lib/fs/fingerprint.ts#L40)). This includes files that are not included in the final generated DockerImageAsset. The image digest, on the other hand, depends on the actual bytes of the image as well as some other metadata.

This can cause unexpected redeploys of services. Consider:
- All code is stored in `src/`
- One ECS task builds a docker image, passing the directory `src/` but only copying `src/first-ecs-task` as well as `src/dockerfiles/first-ecs-task.Dockerfile`
- Another ECS task builds a docker image, passing the directory `src/` but only copying `src/second-ecs-task` as well as `src/dockerfiles/second-ecs-task.Dockerfile`
- If the first ecs task's source code is modified, both services will be redeployed since the build context has changed. However, checking the old and new images for `second-ecs-task` in ECR will show that the docker digest and image ID are identical because the actual copied bytes are identical.

This behaviour is surprising, since developers generally expect a docker image to be considered the same if their contents are identical and thus not redeploy a service. Currently the solution is to pass an appropriate `excludes=` parameter or otherwise restrict the build context to just the files that will be copied. However, this entire situation could be avoided by using the docker digest directly as the tag. This could also have the benefit of reducing the amount of storage used by ECR if multiple apps reference the exact same docker image and possibly make synthesis faster since CDK doesn't need to scan the directory ahead of time.

### Proposed Solution

Instead of calling fingerprint() and using that to provide the tag to the docker daemon:

1. Invoke `docker build` as usual, without a tag.
2. The final line of the process should provide an image ID. Use that image ID to fetch the digest.
3. Tag the image with the digest and push to ECR.

### Other Information

_No response_

### Acknowledgements

- [ ] I may be able to implement this feature request
- [ ] This feature might incur a breaking change

### CDK version used

2.136.0

### Environment details (OS name and version, etc.)

Apple M1 Pro with MacOS Sonoma 14.4.1

Contributor guide

Open the contributing guide

Research direction

Start with packages/aws-cdk-lib/core/lib/fs/fingerprint.ts and trace how DockerImageAsset currently uses fingerprint() to tag images. Review the docker build entry point described in the issue, then determine how its image ID can provide a digest before pushing to ECR; done means identical image contents reuse the same digest-based tag without unrelated build-context changes causing redeploys.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, docker, typescript
Domain
cloud, devops
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.