diff --git a/.changeset/scaffold-ships-docker.md b/.changeset/scaffold-ships-docker.md new file mode 100644 index 0000000000..6a8be4146c --- /dev/null +++ b/.changeset/scaffold-ships-docker.md @@ -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`. diff --git a/README.md b/README.md index 1cddfd1242..29c7eb0857 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/packages/create-objectstack/src/templates/blank/.dockerignore b/packages/create-objectstack/src/templates/blank/.dockerignore new file mode 100644 index 0000000000..0880b59cb0 --- /dev/null +++ b/packages/create-objectstack/src/templates/blank/.dockerignore @@ -0,0 +1,6 @@ +node_modules +dist +.git +*.log +.env +cookies.txt diff --git a/packages/create-objectstack/src/templates/blank/Dockerfile b/packages/create-objectstack/src/templates/blank/Dockerfile new file mode 100644 index 0000000000..58d6e2c2b2 --- /dev/null +++ b/packages/create-objectstack/src/templates/blank/Dockerfile @@ -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. diff --git a/packages/create-objectstack/src/templates/blank/README.md b/packages/create-objectstack/src/templates/blank/README.md index 1b0c5eaeeb..0b7746a6d1 100644 --- a/packages/create-objectstack/src/templates/blank/README.md +++ b/packages/create-objectstack/src/templates/blank/README.md @@ -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 <