-
Notifications
You must be signed in to change notification settings - Fork 86
Open
Description
Summary
- Current Cloudflare Container resource always builds and pushes an image on deploy.
- Add support to use a prebuilt/static image reference (e.g., from Cloudflare Registry or a remote registry) without rebuilding.
- Keep current behavior as default; introduce a clear, validated path to skip build/push.
Motivation
- Faster CI/CD by reusing immutable, prebuilt images.
- Support external registries and promotion workflows (dev → staging → prod).
- Deterministic deploys with signed/attested images.
- Aligns with Docker provider patterns already present in the repo.
Current Behavior
alchemy/src/cloudflare/container.tsalways derives fromdocker/Imageand triggersdocker buildand push to Cloudflare registry.alchemy/src/docker/image.tsis the only path; no direct acceptance of a prebuilt image reference.workerdeployment consumes the image produced by the build step.
Key files:
alchemy/src/cloudflare/container.ts— Container resource delegates toImageand pushes to CF registry.alchemy/src/cloudflare/worker.ts— Uses the image from the Container resource duringContainerApplication.alchemy/test/cloudflare/container.test.ts— Tests build/update/adoption via build flow.examples/cloudflare-container/*— Demonstrates only the build flow.alchemy/src/docker/remote-image.ts— Remote prebuilt image resource exists but is unused by Cloudflare container.
Proposed Changes
- Extend
ContainerPropsto accept a prebuilt image and allow skipping build/push. - Validate mutual exclusivity between build and prebuilt-image paths.
- Preserve current defaults and ergonomics.
Proposed props (flat, backwards-compatible):
image?: string | RemoteImage— Prebuilt image reference (e.g.,<image name>:<tag>per current wrangler pattern).push?: boolean— Whenimageis provided and not in Cloudflare registry, optionally retag and push to Cloudflare. Defaultfalse.- Existing
build-related props remain supported and unchanged.
Behavior:
- If
imageis provided:- Skip
docker build. - If
imageis astringwithout a registry host: assumeregistry.cloudflare.com/<acct>/<image>:<tag>. - If
imagepoints to a non-Cloudflare registry:- Cloudflare currently requires images to be in the Cloudflare registry. Enforce
push: trueto retag and push into CF; otherwise, throw a clear validation error.
- Cloudflare currently requires images to be in the Cloudflare registry. Enforce
- If
push: falseand the image is already in CF registry: no push performed.
- Skip
- If
imageis not provided:- Preserve current behavior (build and push).
- Validate that
imageandbuildare not used together.
API Examples
- Build and push (unchanged):
await Container("api", { name: "my-api", build: { context: "./", dockerfile: "Dockerfile" } });
- Use prebuilt CF image without push:
await Container("api", { name: "my-api", image: "my-api:1.2.3" });
- Rehost a remote image into CF registry:
const base = await RemoteImage("base", { image: "ghcr.io/org/app:1.2.3" });await Container("api", { name: "my-api", image: base, push: true });
Acceptance Criteria
- Passing
image: "<name>:<tag>"(implicitly CF registry) deploys without building or pushing. - Passing
image: RemoteImage(...)withpush: trueretags and pushes to CF registry, then deploys. - If
imagereferences a non-CF registry andpush !== true, a clear validation error is thrown (since CF currently only accepts CF-hosted images). - Mutual exclusivity enforced between
imageandbuild. - Tests cover:
- pure build flow (existing),
- prebuilt-CF-image flow without push,
- remote-image + push-to-CF flow.
- Docs updated with both flows and guidance on when to use which.
Implementation Plan
- Update
alchemy/src/cloudflare/container.ts:- Extend
ContainerPropswithimage?,push? - Branch logic: prebuilt vs build.
- If
imagehost is non-CF andpush !== true, throw validation error; ifpush: true, retag/push using existing Docker APIs. - Default CF registry resolution when
imageis string without a host. - Validate mutual exclusivity and provide actionable error messages.
- Extend
- Adjust
alchemy/src/cloudflare/worker.tsif needed to consume a consistentimageReffrom the Container output (should be backward-compatible). - Tests:
- Add new cases in
alchemy/test/cloudflare/container.test.ts.
- Add new cases in
- Examples:
- Add a short variant in
examples/cloudflare-containershowing prebuilt usage.
- Add a short variant in
- Docs:
- Update
alchemy-web/.../providers/cloudflare/container.mdto document both flows and registry nuances.
- Update
Backward Compatibility
- No breaking changes; existing build-based usage remains the default path.
- New props are optional and orthogonal.
Constraints (Resolved)
- Cloudflare currently only accepts images hosted in the Cloudflare registry. Non-CF images must be retagged/pushed into CF for deployment.
- No CF registry rate limits or tag naming constraints impact retagging.
Future-Proofing
- Once Cloudflare supports external registries, relax validation to allow direct deploys from non-CF registries with no push. Keep code paths structured to make this a small change.
Risks
- Misconfiguration when
imageis not present/accessible in CF; mitigated by validation and clear errors.
References
- Build-only behavior:
alchemy/src/cloudflare/container.ts - Build pipeline:
alchemy/src/docker/image.ts - Remote images:
alchemy/src/docker/remote-image.ts - Worker consumption:
alchemy/src/cloudflare/worker.ts - Example and docs currently demonstrate build flow only.
Metadata
Metadata
Assignees
Labels
No labels