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
37 changes: 33 additions & 4 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# ObjectStack official runtime image — ghcr.io/objectstack-ai/objectstack
#
# A generic, app-agnostic production runtime: Node + @objectstack/cli +
# `os start`. It contains NO app — bring your compiled artifact
# (dist/objectstack.json, built by `os build` in CI):
# A generic, app-agnostic production runtime: Node + @objectstack/cli + the
# `pg` / `mysql2` SQL drivers + `os start`. It contains NO app — bring your
# compiled artifact (dist/objectstack.json, built by `os build` in CI):
#
# FROM ghcr.io/objectstack-ai/objectstack:<version>
# COPY --chown=node:node dist/objectstack.json /srv/app/objectstack.json
Expand Down Expand Up @@ -40,7 +40,36 @@ FROM node:22-slim
# Pinned by CI to the @objectstack/cli release that triggered the publish.
# `latest` is only the fallback for ad-hoc local builds of this file.
ARG OS_CLI_VERSION=latest
RUN npm install -g @objectstack/cli@${OS_CLI_VERSION} \

# The SQL drivers ship WITH the image, not with the app (#14510).
#
# `@objectstack/driver-sql` declares `pg`, `mysql2` and `tedious` as OPTIONAL
# peer dependencies. npm 7+ installs peer dependencies automatically but SKIPS
# the optional ones, so `npm install -g @objectstack/cli` on its own produced a
# tree with no `pg` in it -- while the header of this very file, README.md, and
# the `docker-compose.yml` that `npm create objectstack` generates (whose `db`
# service is `postgres:17`) all hand this image a `postgres://` URL. Every one
# of those paths died at boot on `Cannot find module 'pg'`, with the loud
# fail-fast ADR-0062 D5 requires but nothing documented to act on. Installing
# the drivers here is the "whoever makes the promise installs it" half of the
# fix; the other half is that README.md publishes the list.
#
# The ranges are copied VERBATIM from driver-sql's `peerDependencies`, so the
# image satisfies the driver's own contract rather than a second one invented
# here. Both packages are pure JavaScript with no native build step, which is
# why they are affordable for every user of the image. `tedious` (SQL Server)
# and `@objectstack/driver-turso` are deliberately NOT installed -- extend the
# image when you need one, as README.md shows.
#
# This install line is a PUBLIC PROMISE, published as the driver table in
# ./README.md. Adding or removing a package here changes which databases a
# deployment can reach, so the two files must move in the same commit:
# `pnpm check:docs-image-tag` fails when the install line and that table
# disagree on the package set or on a version range.
RUN npm install -g \
@objectstack/cli@${OS_CLI_VERSION} \
"pg@^8.0.0" \
"mysql2@^3.0.0" \
&& npm cache clean --force

LABEL org.opencontainers.image.source="https://github.com/objectstack-ai/objectstack" \
Expand Down
44 changes: 41 additions & 3 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# ObjectStack Official Runtime Image

`ghcr.io/objectstack-ai/objectstack` — the official production runtime for
standalone ObjectStack apps. It packages Node 22 and `@objectstack/cli`
(`os start`) and nothing else: **your compiled artifact is the app**, the
image is the runtime.
standalone ObjectStack apps. It packages Node 22, `@objectstack/cli`
(`os start`) and the SQL drivers listed below — and no application code:
**your compiled artifact is the app**, the image is the runtime.

```
objectstack.config.ts ──(os build, CI)──▶ dist/objectstack.json ──(this image)──▶ running app
Expand Down Expand Up @@ -46,6 +46,44 @@ docker run -p 8080:8080 \
`OS_ARTIFACT_PATH` also accepts an `https://` URL, so the artifact can come
straight from your release storage.

## Database drivers in the image

**This list is a public promise.** The dialects below need nothing installed —
their driver is already in the image, which is why the `postgres://` invocation
above works exactly as written.

| `OS_DATABASE_URL` scheme | Driver package installed in the image |
|:---|:---|
| `postgres://`, `postgresql://` | `pg@^8.0.0` |
| `mysql://`, `mysql2://` | `mysql2@^3.0.0` |

The ranges are `@objectstack/driver-sql`'s own optional-peer ranges, so the
image satisfies the driver's contract rather than a second one. Both packages
are pure JavaScript — they add no native build step and no compiler to the
image.

Two more dialects work without appearing above, because they arrive with
`@objectstack/cli` rather than from that install line: SQLite (`better-sqlite3`,
for a `file:…` path — one box only, wrong for multi-node) and MongoDB
(`mongodb://…`, **single-tenant only**; see
[Drivers](https://objectstack.ai/docs/data-modeling/drivers)).

**Not in the image:** `tedious` (SQL Server) and `@objectstack/driver-turso`
(`libsql://…` / Turso). Add one by extending the image:

```dockerfile
FROM ghcr.io/objectstack-ai/objectstack:17.2.0
USER root
RUN npm install -g tedious
USER node
COPY --chown=node:node dist/objectstack.json /srv/app/objectstack.json
```

Changing this table is a change to what deployments can connect to, so it does
not move on its own: `pnpm check:docs-image-tag` compares it against
[`Dockerfile`](./Dockerfile)'s install line and fails if the two disagree on the
package set or on a version range.

## What the image presets

- `OS_ARTIFACT_PATH=/srv/app/objectstack.json`, `OS_PORT=8080`,
Expand Down
Loading
Loading