(core): Publish pre-built Docker bundling images to ECR Public
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the feature
When using Lambda function constructs with Docker bundling (e.g., `NodejsFunction` with `forceDockerBundling: true`, or when local bundling tools like `esbuild` are unavailable), CDK builds the bundling Docker image from scratch on every `cdk synth` or `cdk deploy`. This is slow and wasteful since the Dockerfile contents rarely change between CDK versions.
**Request:** Publish pre-built Docker bundling images to ECR Public (or Docker Hub) as part of the CDK release process, tagged with the CDK version. CDK should pull these pre-built images instead of building them locally.
### Use Case
**Problem:** Every CI/CD pipeline run and local development cycle incurs the cost of building the bundling Docker image. In my environment, this adds **~45 seconds** to every build.
**Current behavior:**
1. CDK detects Docker bundling is needed
2. CDK runs `docker build` using the Dockerfile in the CDK package
3. Image layers are built from scratch (installing yarn, pnpm, bun, esbuild, etc.)
4. Bundling proceeds using the freshly-built image
NOTE: Image is cached between local builds, but not on CI machines. However, even locally, there's a lot of noise
in cdk logs on each CDK command that requires the docker image for bundling.
```shell
> yarn cdk diff
[+] Building 1.0s (17/17) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.80kB 0.0s
=> [internal] load metadata for public.ecr.aws/sam/build-nodejs22.x:latest 0.8s
=> [auth] aws:: sam/build-nodejs22.x:pull token for public.ecr.aws 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [ 1/12] FROM public.ecr.aws/sam/build-nodejs22.x:latest@sha256:a8f2ac96884ba1b7dc35ca31f496c 0.0s
=> => resolve public.ecr.aws/sam/build-nodejs22.x:latest@sha256:a8f2ac96884ba1b7dc35ca31f496cde 0.0s
=> CACHED [ 2/12] RUN npm install --global yarn@1.22.5 0.0s
=> CACHED [ 3/12] RUN npm install --global pnpm@7.33.7 0.0s
=> CACHED [ 4/12] RUN npm install --global bun@1.2.23 0.0s
=> CACHED [ 5/12] RUN npm install --global typescript 0.0s
=> CACHED [ 6/12] RUN npm install --global --unsafe-perm=true esbuild@0.21 0.0s
=> CACHED [ 7/12] RUN mkdir /tmp/npm-cache && chmod -R 777 /tmp/npm-cache && npm config 0.0s
=> CACHED [ 8/12] RUN mkdir /tmp/yarn-cache && chmod -R 777 /tmp/yarn-cache && yarn con 0.0s
=> CACHED [ 9/12] RUN mkdir /tmp/pnpm-cache && chmod -R 777 /tmp/pnpm-cache && pnpm con 0.0s
=> CACHED [10/12] RUN npm config --global set update-notifier false 0.0s
=> CACHED [11/12] RUN /sbin/useradd -u 1000 user && chmod 711 / 0.0s
=> CACHED [12/12] RUN mkdir /tmp/bun-cache && chmod -R 777 /tmp/bun-cache && echo -e "[ 0.0s
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => exporting manifest sha256:d8e738054ab505cded58add5baefb80dca112eb48421c9004d99d68ae821868 0.0s
=> => exporting config sha256:b275a1a2b2116d7b180a11f1f0d6f4a5f12cab8219d6db104866a4fa169f7d29 0.0s
=> => exporting attestation manifest sha256:27dc10f86c11e67400fb5b3c36a76d960651d3c56c024bea8fb 0.0s
=> => exporting manifest list sha256:8322bb4cd0daf95dd28e25f5335ecaf138b70a7e2e1d61ac1e3d2778d1 0.0s
=> => naming to docker.io/library/cdk-163ba75b52217423c55e7a4f11239d3998423a7b3b76442289a608f92 0.0s
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/tui07fy5ezliqeg84pr6ucold
What's next:
View a summary of image vulnerabilities and recommendations → docker scout quickview
[+] Building 0.3s (16/16) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.80kB 0.0s
=> [internal] load metadata for public.ecr.aws/sam/build-nodejs22.x:latest 0.1s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [ 1/12] FROM public.ecr.aws/sam/build-nodejs22.x:latest@sha256:a8f2ac96884ba1b7dc35ca31f496c 0.0s
=> => resolve public.ecr.aws/sam/build-nodejs22.x:latest@sha256:a8f2ac96884ba1b7dc35ca31f496cde 0.0s
=> CACHED [ 2/12] RUN npm install --global yarn@1.22.5 0.0s
=> CACHED [ 3/12] RUN npm install --global pnpm@7.33.7 0.0s
=> CACHED [ 4/12] RUN npm install --global bun@1.2.23 0.0s
=> CACHED [ 5/12] RUN npm install --global typescript 0.0s
=> CACHED [ 6/12] RUN npm install --global --unsafe-perm=true esbuild@0.21 0.0s
=> CACHED [ 7/12] RUN mkdir /tmp/npm-cache && chmod -R 777 /tmp/npm-cache && npm config 0.0s
=> CACHED [ 8/12] RUN mkdir /tmp/yarn-cache && chmod -R 777 /tmp/yarn-cache && yarn con 0.0s
=> CACHED [ 9/12] RUN mkdir /tmp/pnpm-cache && chmod -R 777 /tmp/pnpm-cache && pnpm con 0.0s
=> CACHED [10/12] RUN npm config --global set update-notifier false 0.0s
=> CACHED [11/12] RUN /sbin/useradd -u 1000 user && chmod 711 / 0.0s
=> CACHED [12/12] RUN mkdir /tmp/bun-cache && chmod -R 777 /tmp/bun-cache && echo -e "[ 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => exporting manifest sha256:d8e738054ab505cded58add5baefb80dca112eb48421c9004d99d68ae821868 0.0s
=> => exporting config sha256:b275a1a2b2116d7b180a11f1f0d6f4a5f12cab8219d6db104866a4fa169f7d29 0.0s
=> => exporting attestation manifest sha256:e8ef70cc2ead4a0c1cd7cf4702a4962bc1401697a8bddf90023 0.0s
=> => exporting manifest list sha256:dc7ee216b885565dca0dee66a1f22e27eede037cc860820fe1cca7f92d 0.0s
=> => naming to docker.io/library/cdk-163ba75b52217423c55e7a4f11239d3998423a7b3b76442289a608f92 0.0s
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/jiukvx035xq7khrzfmlve1v5o
What's next:
View a summary of image vulnerabilities and recommendations → docker scout quickview
```
**Desired behavior:**
1. CDK detects Docker bundling is needed
2. CDK pulls a pre-built image from `public.ecr.aws/aws-cdk/bundling-nodejs:2.x.x` (or similar)
3. Bundling proceeds immediately using the cached/pulled image
This would benefit:
- CI/CD pipelines (no local Docker layer cache)
- Local development with `--no-cache` Docker builds
- Teams using ephemeral build environments (CodeBuild, GitHub Actions, etc.)
- Anyone using `forceDockerBundling` or lacking local bundling tools (e.g., `esbuild`)
### Proposed Solution
1. **Publish images as part of CDK release pipeline:**
- Build images for each runtime (Node.js, Python, Go) during release
- Tag with CDK version: `public.ecr.aws/aws-cdk/bundling-nodejs:2.175.0`
- Also maintain a `latest` tag for convenience
2. **Update CDK bundling logic:**
- Default to pulling pre-built images
- Fall back to local build if pull fails (offline scenarios, custom images)
- Add option to force local build: `buildBundlingImageLocally: true`
3. **Image naming convention:**
```
public.ecr.aws/aws-cdk/bundling-nodejs:2.175.0-18.x
public.ecr.aws/aws-cdk/bundling-nodejs:2.175.0-20.x
public.ecr.aws/aws-cdk/bundling-nodejs:2.175.0-22.x
```
Alternatively, you could version or hash the Dockerfile to avoid pushing images on each CDK release.
### Other Information
**Affected Dockerfiles:**
- `packages/aws-cdk-lib/aws-lambda-nodejs/lib/Dockerfile` - Node.js (stable)
- `packages/@aws-cdk/aws-lambda-python-alpha/lib/Dockerfile` - Python (alpha)
- `packages/@aws-cdk/aws-lambda-go-alpha/lib/Dockerfile` - Go (alpha)
**Related patterns:**
- AWS SAM already publishes build images to `public.ecr.aws/sam/build-*`
- CDK uses these SAM images as base images for its Dockerfiles
- This request is to publish the _final_ bundling images with all tools pre-installed
### Acknowledgements
- [ ] I may be able to implement this feature request
- [ ] This feature might incur a breaking change
### AWS CDK Library version (aws-cdk-lib)
2.232.1
### AWS CDK CLI version
2.1100.1 (build db19110)
### Environment details (OS name and version, etc.)
MacOS
Contributor guide
Research direction
Start with packages/aws-cdk-lib/aws-lambda-nodejs/lib/Dockerfile, packages/@aws-cdk/aws-lambda-python-alpha/lib/Dockerfile, and packages/@aws-cdk/aws-lambda-go-alpha/lib/Dockerfile to understand the current images and bundling inputs. Then trace the CDK release process and bundling logic. Done means versioned images are published and bundling can use them with a documented local-build fallback.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, docker, typescript
- Domain
- build-system, cloud, devops
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100