Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/scaffold-ships-docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-objectstack": minor
---

Scaffolded projects are now container-ready out of the box: the `blank` template ships a `Dockerfile` (two-stage build onto the official `ghcr.io/objectstack-ai/objectstack` runtime image), a `docker-compose.yml` (app + Postgres single-host stack), and a `.dockerignore`, plus a Deploy section in the project README. `docker build -t my-app .` works immediately after `npm create objectstack`.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,14 @@ pnpm dev

Alternatively, with the CLI installed: `os init my-app && cd my-app && os dev`.

Ready for production? The scaffolded project is container-ready:

```bash
docker build -t my-app . && docker compose up -d # app + Postgres on the official runtime image
```

See [Self-Hosted Deployment](https://docs.objectstack.ai/docs/deployment/self-hosting) for bare Node, Kubernetes, and the secrets you must pin.

### For Framework Contributors

```bash
Expand Down
6 changes: 6 additions & 0 deletions packages/create-objectstack/src/templates/blank/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
dist
.git
*.log
.env
cookies.txt
30 changes: 30 additions & 0 deletions packages/create-objectstack/src/templates/blank/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Container build for this ObjectStack app.
#
# docker build -t my-app .
# docker run -p 8080:8080 \
# -e OS_DATABASE_URL="postgres://user:pass@db-host:5432/myapp" \
# -e OS_AUTH_SECRET -e OS_SECRET_KEY \
# my-app
#
# Or run the full app + Postgres stack: see docker-compose.yml.
# Docs: https://docs.objectstack.ai/docs/deployment/self-hosting

# ── Build stage: compile TypeScript metadata to the artifact ─────────
FROM node:22-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npx os build # → dist/objectstack.json

# ── Runtime: the official ObjectStack runtime image ──────────────────
# Ships Node + @objectstack/cli with `os start`, a non-root user, the
# /api/v1/health HEALTHCHECK, and OS_ARTIFACT_PATH/OS_PORT preset (port 8080)
# — see docker/README.md in the framework repo. Pin the tag to the
# @objectstack/cli version in your package.json so the runtime matches the
# CLI that built the artifact.
FROM ghcr.io/objectstack-ai/objectstack:latest
COPY --from=build --chown=node:node /app/dist/objectstack.json /srv/app/objectstack.json

# OS_DATABASE_URL, OS_AUTH_SECRET, and OS_SECRET_KEY are injected at runtime —
# never bake them into the image.
23 changes: 23 additions & 0 deletions packages/create-objectstack/src/templates/blank/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,29 @@ otherwise fail *silently at runtime* — e.g. a bare `done` (instead of
`record.done`) in an action predicate that would hide the action on every
record. See `AGENTS.md` for the full convention.

## Deploy

The project ships container-ready — the `Dockerfile` builds your metadata into
an artifact and runs it on the official ObjectStack runtime image
(`ghcr.io/objectstack-ai/objectstack`):

```bash
# Image only
docker build -t my-app .

# Or the full app + Postgres stack
cat > .env <<EOF
POSTGRES_PASSWORD=$(openssl rand -hex 16)
OS_AUTH_SECRET=$(openssl rand -hex 32)
OS_SECRET_KEY=$(openssl rand -hex 32)
EOF
docker compose up -d
curl -fsS http://localhost:8080/api/v1/health
```

Bare Node, Kubernetes, reverse-proxy wiring, and the required secrets are
covered in [Self-Hosted Deployment](https://docs.objectstack.ai/docs/deployment/self-hosting).

## Next steps

- Add an object: see the `objectstack-data` skill.
Expand Down
39 changes: 39 additions & 0 deletions packages/create-objectstack/src/templates/blank/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Single-host production stack: this app + Postgres.
#
# Create a .env file next to this compose file (never committed) with
# POSTGRES_PASSWORD / OS_AUTH_SECRET / OS_SECRET_KEY (generate secrets with
# `openssl rand -hex 32`), then `docker compose up -d`.
#
# Docs: https://docs.objectstack.ai/docs/deployment/self-hosting

services:
app:
build: .
ports:
- "8080:8080"
environment:
OS_DATABASE_URL: postgres://objectstack:${POSTGRES_PASSWORD}@db:5432/myapp
OS_AUTH_SECRET: ${OS_AUTH_SECRET}
OS_SECRET_KEY: ${OS_SECRET_KEY}
depends_on:
db:
condition: service_healthy
restart: unless-stopped

db:
image: postgres:17
environment:
POSTGRES_USER: objectstack
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: myapp
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U objectstack -d myapp"]
interval: 5s
timeout: 3s
retries: 10
restart: unless-stopped

volumes:
pgdata: