Skip to main content

Static site or single-binary web app

slipway.yaml
version: 1

services:
  web:
    build:
      context: .
    ports:
      - { port: 3000, public: true }
    env:
      NODE_ENV: production
    healthcheck:
      readiness: { http: { path: /api/health, port: 3000 } }

Web + worker (no public port for the worker)

slipway.yaml
version: 1

services:
  web:
    build:
      context: .
    ports:
      - { port: 3000, public: true }
    env:
      LOG_LEVEL: ${var.LOG_LEVEL}
      DATABASE_URL: ${secret.DATABASE_URL}
      REDIS_URL: ${secret.REDIS_URL}
    healthcheck:
      readiness: { http: { path: /healthz, port: 3000 } }

  worker:
    image: ghcr.io/acme/worker:1.2.3
    env:
      LOG_LEVEL: ${var.LOG_LEVEL}
      DATABASE_URL: ${secret.DATABASE_URL}
      REDIS_URL: ${secret.REDIS_URL}
    healthcheck:
      liveness: { exec: { command: [/usr/local/bin/worker-healthcheck] } }
web is reachable at <env-name>-web-<id>.<apps-base>. worker has no ports — internal-only, no URL, no readiness gate. DATABASE_URL and REDIS_URL resolve from the environment or org secret store (environment first, org fallback) — never from this file.

Custom build args + private registry pull

slipway.yaml
version: 1

services:
  api:
    build:
      context: ./api
      dockerfile: Dockerfile.prod
      args:
        NPM_TOKEN: ${secret.NPM_TOKEN}
        BUILD_REV: ${var.BUILD_REV}
    ports:
      - { port: 8080, public: true }
    env:
      DATABASE_URL: ${secret.DATABASE_URL}
    healthcheck:
      readiness: { tcp: { port: 8080 } }
      liveness:  { http: { path: /metrics, port: 8080 } }

  cache:
    image: ghcr.io/acme/private-cache:tag
    ports:
      - { port: 6379 }
cache pulls from a private registry. Configure the credentials once at the org level under Settings → Registries (see Private registries) — no per-service config is needed.

Custom domain for one public port

slipway.yaml
version: 1

services:
  web:
    build: { context: . }
    ports:
      - { port: 3000, public: true, domain: app.acme.com }
    healthcheck:
      readiness: { http: { path: /healthz, port: 3000 } }
app.acme.com must be a verified parent zone for the org (claim and verify it under Settings → Domains first — see Custom domains). The deployed URL becomes <env-name>-web-<id>.app.acme.com, where <id> is the short, stable identifier for the environment-instance.