Images on cloud runtimes
Cloud container runtimes don’t reach your engine. They pull images from a registry, so an image built on your machine has to be pushed before a cloud can run it. What you give the runtime is a reference: a tag like ghcr.io/acme/api:latest, or a digest like ghcr.io/acme/api@sha256:9c2e…, which names exactly one image.
Hand the reference to a runtime
Section titled “Hand the reference to a runtime”Build and push with Docker.Image, then pass its imageRef as the runtime’s image:
const image = yield* Docker.Image("api", { name: "acme/api", build: { context: "./api" }, registry: { server: "ghcr.io", username: "acme", password: yield* Config.Redacted("GITHUB_TOKEN"), },});
const task = yield* AWS.ECS.Task("Api", { image: image.imageRef,});image.repoDigest holds the digest, for when a moving tag isn’t precise enough. The same reference works as the image of a Cloudflare Container, a container in a Cloud Run service or a Kubernetes Deployment or Job. An ECS Task copies it into ECR before it runs. A private registry needs its credentials on the runtime’s side as well; see each runtime’s page.
Or let the runtime build it
Section titled “Or let the runtime build it”You often don’t need Docker.Image at all. ECS, Cloudflare Containers and Kubernetes workloads build your Dockerfile themselves from a context prop, and Cloud Run and the others bundle an Effect program from main. They build with the same local Docker, then push to their own registry:
const task = yield* AWS.ECS.Task("Api", { context: "./api",});Reach for Docker.Image when you want to pick the registry yourself, or share one image between several runtimes or stages.
Write the Dockerfile inline
Section titled “Write the Dockerfile inline”A runtime that bundles your Effect program with main takes a dockerfile for the base it runs on. Dockerfile.inline writes it in the Stack, for a base plus a few system packages:
import * as Dockerfile from "@alchemy.run/docker/Dockerfile";
const transcoder = yield* AWS.ECS.Task( "Transcoder", { main: import.meta.url, dockerfile: Dockerfile.inline` FROM oven/bun:1 RUN apt-get update && apt-get install -y ffmpeg `, }, impl,);Interpolate another resource’s output, and the runtime depends on it, rebuilding when it changes:
const base = yield* AWS.ECR.Image("MlBase", { context: "./ml-base" });
const trainer = yield* AWS.ECS.Task( "Trainer", { main: import.meta.url, dockerfile: Dockerfile.inline` FROM ${base.imageUri} RUN pip install -r /opt/requirements.txt `, }, impl,);Anything in a Dockerfile is baked into the image’s layers, so never interpolate a secret. Use a build secret instead.
Cache builds in CI
Section titled “Cache builds in CI”Every runtime that builds takes the same cache option as Docker.Image. See Build caches.