Docker.Container reference
Container
Section titled “Container”Source:
src/Docker/Container.ts
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.
Container: Running Containers
Section titled “Container: Running Containers”const nginx = yield* Docker.Container("nginx", { image: "nginx:alpine", ports: [{ external: 8080, internal: 80 }], start: true,});Container: Secret Environment
Section titled “Container: Secret Environment”const password = yield* Config.Redacted("POSTGRES_PASSWORD");const db = yield* Docker.Container("postgres", { image: "postgres:18-alpine", environment: { POSTGRES_PASSWORD: password, }, start: true,});Container: Environment Files
Section titled “Container: Environment Files”const app = yield* Docker.Container("app", { image: "ghcr.io/acme/app:latest", envFiles: ["./config/base.env", "./config/production.env"], // Explicit values are passed after env files and take precedence. environment: { LOG_LEVEL: "info" },});Editing an env file replaces the container on the next deploy, as does
adopting a container that uses env files (once, so later edits are tracked).
Alchemy reads
the files at plan time but keeps only a digest of their contents, on the
container’s own label; neither the values nor the digest are written to
Alchemy state. Docker exposes the resolved values through docker inspect,
so treat env files as secrets.
Container: Networks and Volumes
Section titled “Container: Networks and Volumes”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);Container: Host Access
Section titled “Container: Host Access”extraHosts writes lines into the container’s /etc/hosts; it changes name
resolution and nothing else. Docker’s host-gateway alias resolves to the
host machine, which is how a container reaches a service on the developer’s
loopback.
On Linux host-gateway is the Docker bridge gateway (typically
172.17.0.1), so a container’s packets to it arrive on the host’s INPUT
chain. Under a default-deny firewall — ufw ships
DEFAULT_INPUT_POLICY="DROP" — the hostname resolves correctly and the
connection then times out, which reads like an application bug rather than a
firewall one. Allow the bridge subnet to fix it:
sudo ufw allow from 172.16.0.0/12.
Reach a service on the developer’s machine
const api = yield* Docker.Container("api", { image: "ghcr.io/acme/api:latest", // `host-gateway` resolves to the host machine, so a database listening // on the developer's loopback is reachable from inside the container. extraHosts: ["host.docker.internal:host-gateway"], environment: { DATABASE_URL: "postgres://postgres@host.docker.internal:5432/app", }, start: true,});Pin a hostname to a fixed address
const api = yield* Docker.Container("api", { image: "ghcr.io/acme/api:latest", // Any `hostname:address` pair — host access is just the common case. extraHosts: ["service.example:192.0.2.10"], start: true,});Container: Runtime Options
Section titled “Container: Runtime Options”Share a donor container’s network namespace
const donor = yield* Docker.Container("donor", { image: "redis:alpine" });const sidecar = yield* Docker.Container("sidecar", { image: "busybox:latest", networkMode: { container: donor.id },});Add capabilities and devices
const worker = yield* Docker.Container("worker", { image: "ubuntu:latest", capAdd: ["SYS_ADMIN"], devices: [{ hostPath: "/dev/fuse", containerPath: "/dev/fuse" }],});Publish on any free host port
const api = yield* Docker.Container("api", { image: "ghcr.io/acme/api:latest", // `external: 0` lets Docker choose; the assigned port is reported back. ports: [{ external: 0, internal: 3000 }], start: true,});const hostPort = api.ports["3000/tcp"];Container: Traefik
Section titled “Container: Traefik”Route a container through Traefik
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,});Use a Docker.Context resource
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,});