Skip to content

Container Build

Build Docker images and push them to container registries. Returns an image URI for use in TypeKro compositions.

typescript
import { buildContainer } from 'typekro/containers';

const { imageUri } = await buildContainer({
  context: './apps/my-app',
  imageName: 'my-app',
  registry: { type: 'orbstack' },
});

// Use in a composition
await factory.deploy({ app: { image: imageUri, port: 3000 } });

Registries

Orbstack (Local Development)

Images are automatically available to the local Kubernetes cluster. No push needed.

typescript
const result = await buildContainer({
  context: './apps/api',
  imageName: 'api',
  registry: { type: 'orbstack' },
});
// result.imageUri → 'api:latest'
// result.pushed → false

Amazon ECR

Authenticates via the AWS SDK's credential chain — env vars, profiles, SSO sessions, instance roles, and role assumption all work automatically.

typescript
const result = await buildContainer({
  context: './apps/api',
  imageName: 'api',
  tag: 'content-hash',
  platform: 'linux/amd64',
  registry: {
    type: 'ecr',
    region: 'us-west-2',
    // Optional: auto-detected from STS if omitted
    accountId: '374080338393',
    // Optional: create repo if it doesn't exist (default: true)
    createRepository: true,
    // Optional: pass any AWS credential option
    credentials: {
      profile: 'production',
      roleArn: 'arn:aws:iam::374080338393:role/deploy',
    },
  },
});
// result.imageUri → '374080338393.dkr.ecr.us-west-2.amazonaws.com/api:sha-abc123def456'
// result.pushed → true

GCR / ACR

Interfaces defined for future implementation. Currently throws with a clear message.

Content-Hash Tagging

Use tag: 'content-hash' for deterministic, content-based tags. The hash is computed from the Dockerfile and all files in the build context (respecting .dockerignore).

typescript
const result = await buildContainer({
  context: './apps/api',
  imageName: 'api',
  tag: 'content-hash',
  registry: { type: 'orbstack' },
});
// result.tag → 'sha-a1b2c3d4e5f6'
  • Same content always produces the same tag
  • Changing any source file produces a different tag
  • .dockerignore is respected — ignored files don't affect the hash
  • Docker's layer cache means unchanged builds return instantly

Full Stack Example

Build a container and deploy it with the full infrastructure stack:

typescript
import { buildContainer } from 'typekro/containers';
import { webAppWithProcessing } from 'typekro/webapp';

// Build the app image
const { imageUri } = await buildContainer({
  context: './apps/my-app',
  imageName: 'my-app',
  tag: 'content-hash',
  registry: { type: 'orbstack' },
});

// Deploy: PostgreSQL + Valkey + Inngest + App
const factory = webAppWithProcessing.factory('direct', {
  namespace: 'production',
  waitForReady: true,
  kubeConfig,
});

await factory.deploy({
  name: 'my-app',
  namespace: 'my-app',
  app: { image: imageUri, port: 3000 },
  database: { storageSize: '10Gi', database: 'myapp', owner: 'app' },
  cache: { shards: 3 },
  processing: {
    eventKey: process.env.INNGEST_EVENT_KEY!,
    signingKey: process.env.INNGEST_SIGNING_KEY!,
  },
});

Options Reference

OptionTypeDefaultDescription
contextstringrequiredPath to build context directory
imageNamestringrequiredImage name (lowercase, no registry prefix)
dockerfilestring'Dockerfile'Dockerfile path relative to context
tagstring'latest'Tag or 'content-hash' for SHA-based
platformstringnativeTarget platform (e.g., 'linux/amd64')
buildArgsRecord<string, string>Docker build arguments
targetstringMulti-stage build target
extraDockerArgsstring[]Extra CLI args (--secret, --ssh, etc.)
quietbooleanfalseSuppress build output
timeoutnumber300000Build timeout in ms
registryRegistryConfigrequiredRegistry configuration

Security

  • Build-arg values are redacted in logs and error messages
  • Docker login uses --password-stdin (no credentials in process list)
  • Build-arg keys are validated against /^[a-zA-Z_][a-zA-Z0-9_]*$/ to prevent flag injection
  • Image names are validated to prevent malformed Docker URIs

Released under the Apache 2.0 License.