import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; import type { PlatformError } from "effect/PlatformError"; import * as Redacted from "effect/Redacted"; import * as Provider from "../Provider.ts"; import { Resource } from "../Resource.ts"; import { Docker } from "./Docker.ts"; import type { Providers } from "./Providers.ts"; export interface ContainerProps { /** Image reference or Docker image resource. */ image: Container.Image; /** Docker context name or context resource. */ context?: Docker.ContextRef; /** * Container name. * * @default Generated from stack, stage, logical id, and instance id. */ name?: string; /** Command to run in the container. */ command?: string[]; /** Container environment variables. Use Redacted for secrets. */ environment?: Record>; /** Host/container port mappings. */ ports?: Container.PortMapping[]; /** Volume or bind mounts. */ volumes?: Container.VolumeMapping[]; /** Restart policy. */ restart?: "no" | "always" | "on-failure" | "unless-stopped"; /** * Container labels. Alchemy's internal ownership labels are added * automatically. */ labels?: Record; /** * Grace period before Docker forcefully kills the container after stopping * it. */ stopTimeout?: Duration.Input; /** Networks to connect after create. */ networks?: Container.NetworkMapping[]; /** Remove the container when it exits. @default false */ removeOnExit?: boolean; /** Start the container after creation/reconciliation. @default false */ start?: boolean; /** Docker healthcheck configuration. */ healthcheck?: Container.Healthcheck; } export declare namespace Container { type Status = "created" | "running" | "paused" | "restarting" | "removing" | "exited" | "dead"; type Image = string | { imageRef: string; }; interface PortMapping { /** External port on the host. */ external: number | string; /** Internal port inside the container. */ internal: number | string; /** Protocol used for the mapping. @default "tcp" */ protocol?: "tcp" | "udp"; } interface VolumeMapping { /** Host path or named volume source. */ hostPath: string; /** Container path. */ containerPath: string; /** Mount read-only. @default false */ readOnly?: boolean; } interface NetworkMapping { /** Network name or ID. */ name: string; /** Network aliases for the container. */ aliases?: string[]; } interface Healthcheck { /** Command to run for health checks. */ cmd: string[] | string; /** Time between checks. */ interval?: Duration.Input; /** Maximum time a check may run. */ timeout?: Duration.Input; /** Consecutive failures before unhealthy. */ retries?: number; /** Startup grace period. */ startPeriod?: Duration.Input; /** Check interval during startup. Requires Docker API 1.44+. */ startInterval?: Duration.Input; } } export interface Container extends Resource<"Docker.Container", ContainerProps, { /** Docker container id. */ id: string; /** Docker container name. */ name: string; /** Docker container state. */ status: Container.Status; /** Creation timestamp in milliseconds since epoch. */ createdAt: number; /** Image reference used to create the container. */ imageRef: string; /** * Map of internal container ports to their bound host ports. * Format: `"80/tcp" -> 8080`. */ ports: Record; }, never, Providers> { } /** * A Docker container managed through the active Docker context. * * This resource creates, starts, stops, inspects, and removes containers through * the Docker CLI. It is not interchangeable with `Cloudflare.Container`, which * manages Cloudflare's container platform; use pushed image references to bridge * Docker-built images into cloud container runtimes. * * * ### Running Containers * **Example:** Nginx with a published port * ```typescript * const nginx = yield* Docker.Container("nginx", { * image: "nginx:alpine", * ports: [{ external: 8080, internal: 80 }], * start: true, * }); * ``` * * ### Secret Environment * **Example:** Redacted env var * ```typescript * const password = yield* Config.redacted("POSTGRES_PASSWORD"); * const db = yield* Docker.Container("postgres", { * image: "postgres:18-alpine", * environment: { * POSTGRES_PASSWORD: password, * }, * start: true, * }); * ``` * * ### Networks and Volumes * **Example:** PostgreSQL with persistent storage * ```typescript * const network = yield* Docker.Network("app-network"); * const data = yield* Docker.Volume("postgres-data"); * const postgresName = "app-postgres"; * yield* Docker.Container("postgres", { * name: postgresName, * image: "postgres:18-alpine", * ports: [{ external: 15432, internal: 5432 }], * volumes: [{ hostPath: data.name, containerPath: "/var/lib/postgresql/data" }], * networks: [{ name: network.name, aliases: ["postgres"] }], * start: true, * }); * const runtime = yield* Docker.inspectContainer(postgresName); * ``` * * ### Traefik * **Example:** Route a container through Traefik * ```typescript * const api = yield* Docker.Container("api", { * image: "ghcr.io/acme/api:latest", * networks: [{ name: "traefik" }], * labels: { * "traefik.enable": "true", * "traefik.http.routers.api.rule": "Host(`api.example.com`)", * "traefik.http.services.api.loadbalancer.server.port": "3000", * }, * stopTimeout: "30 seconds", * start: true, * }); * ``` * * **Example:** Use a Docker.Context resource * ```typescript * const remote = yield* Docker.Context("remote", { * name: "remote-build", * docker: "host=ssh://docker@example.com", * }); * * const api = yield* Docker.Container("api", { * image: "nginx:alpine", * context: remote, * }); * ``` * * @resource */ export declare const Container: import("../Resource.ts").ResourceClass; /** * Inspect a Docker container by name and return normalized runtime details. * * This is a small public wrapper around Docker's raw inspect output. It returns * the stable data Alchemy callers typically need, including bound host ports. */ export declare const inspectContainer: (name: string, context?: Docker.ContextRef) => Effect.Effect; export declare const ContainerProvider: () => import("effect/Layer").Layer, never, Docker | import("../Stack.ts").Stack | import("../Stage.ts").Stage>; //# sourceMappingURL=Container.d.ts.map