Skip to main content

Service fields

Each entry in the services array defines one container.
FieldTypeRequiredDescription
namestringrequiredUnique service name within the app
imagestringrequiredOCI image reference (registry/repo:tag or digest)
commandstring[]optionalOverride container entrypoint
envmap[string]stringoptionalEnvironment variables
portsport[]optionalPort exposure definitions
mountsmount[]optionalBind-style mounts from the state area
stateVolumesstring[]optionalNamed volume mounts (name:/path)
dependsOnstring[]optionalService names that must start before this service

ports[]

FieldTypeRequiredDescription
containerintrequiredContainer port number (1–65535)
hostExposureenumoptionalauto — system assigns host port; none — no host exposure. Default: auto

mounts[]

FieldTypeRequiredDescription
sourcestringrequiredFormat: state:<volume-name> for state-backed mounts
targetstringrequiredAbsolute path inside the container

stateVolumes

A shorthand for attaching named volumes. Each entry is name:/path:
stateVolumes:
  - dbdata:/var/lib/postgresql/data
The volume dbdata must have a matching entry in state.volumes.

Startup ordering

Use dependsOn to declare startup order. The runtime starts services in topological order (dependency-first). Cycles are rejected at validation time.
services:
  - name: web
    image: node:20-alpine
    dependsOn: ["db", "cache"]
  - name: db
    image: postgres:16
  - name: cache
    image: redis:7-alpine

Example

services:
  - name: web
    image: ghcr.io/example/todo-web:1.0.0
    command: ["node", "server.js"]
    env:
      NODE_ENV: production
      DATABASE_URL: postgres://todo@db:5432/todo
    ports:
      - container: 3000
        hostExposure: auto
    mounts:
      - source: state:uploads
        target: /data/uploads
    dependsOn: ["db"]

  - name: db
    image: postgres:16
    env:
      POSTGRES_DB: todo
      POSTGRES_USER: todo
    stateVolumes:
      - dbdata:/var/lib/postgresql/data