Files
nocobase/playground/docker-compose.yml
T
chenos d5a18ff33c feat(templates): ship a Dockerfile with every application template (#416)
* feat(templates): build every application template into a Docker image from source

Each template now ships a Dockerfile and Dockerfile.dockerignore. The build
stage runs pnpm build on the builder's own architecture and cross-targets
native modules, so multi-platform images compile nothing under emulation. The
runtime stage holds only dist/ and config.example.yml, runs node directly as
the node user without pnpm, and reads /app/config.yml and /app/storage from
mounts. The same file builds a generated application from its root and a
template inside this repository from the repository root via APP_DIR.

The official Hub image is now built from the Hub template's Dockerfile at the
release tag, replacing Dockerfile.hub. This also fixes the published image
failing with EACCES on /app/storage when HUB_STORAGE_DIR is unset, which the
playground Compose file hit and the smoke test, setting it, never did.

app-tools now carries the application's registry lines into dist/.npmrc.
dist/ is its own pnpm root, so the production install ignored the registry
create-app records and failed with a 404 on any machine without it in user
configuration, including every container build.

* feat(templates): package a prebuilt dist into the Docker image with DIST=prebuilt

--build-arg DIST=prebuilt skips the build stage and packages the dist/ in the
build context, selected through FROM dist-${DIST} so BuildKit never runs the
unused stage. It works in a template's own directory, where a source build
cannot resolve workspace dependencies.

The stage refuses a dist/ whose buildTarget is not linux, glibc, the target
architecture and the image's Node major, and one whose client was built for a
different APP_BASE_PATH, since either builds an image that fails only at
runtime. The ignore file re-includes dist/ last so dependency directories
named like excluded paths survive, then excludes dist/.env, which pnpm build
fills from local .env files. A source build without a lockfile in the context
now says how to build instead of failing inside pnpm.

* fix(templates): point a prebuilt dist built for another architecture at --platform

A dist/ built with --target linux-x64 on Apple silicon was rejected with advice
to rebuild for arm64, when the usual intent is an amd64 image for an amd64
server. The check now names the --platform flag that matches the dist/, and the
documented examples pass --platform alongside --target.
2026-09-24 12:47:30 +08:00

42 lines
1.2 KiB
YAML

# Run from playground/ so its .env stays separate from application development.
name: nocobase-hub
services:
hub:
image: ${NOCOBASE_IMAGE:-ghcr.io/nocobase/hub:latest}
restart: unless-stopped
init: true
stop_grace_period: 30s
ports:
- '${NOCOBASE_BIND_HOST:-127.0.0.1}:${NOCOBASE_PORT:-13000}:13000'
environment:
APP_CONFIG_FILE: /app/config.yml
AUTH_SECRET: ${AUTH_SECRET:?Set AUTH_SECRET in .env}
SESSION_SECRET: ${SESSION_SECRET:?Set SESSION_SECRET in .env}
APP_PUBLIC_ORIGIN: ${APP_PUBLIC_ORIGIN:-http://localhost:13000}
volumes:
- type: bind
source: ./config.yml
target: /app/config.yml
read_only: true
bind:
create_host_path: false
- hub_data:/app/storage
healthcheck:
test:
- CMD
- node
- -e
- >-
fetch('http://127.0.0.1:13000' + (process.env.APP_BASE_PATH || '') + '/api/healthz',
{signal: AbortSignal.timeout(3000)})
.then(async response => process.exit(response.ok && (await response.json()).ok === true ? 0 : 1))
.catch(() => process.exit(1))
interval: 30s
timeout: 5s
start_period: 60s
retries: 3
volumes:
hub_data: