perf(docker): reuse the build across restarts instead of rebuilding on every start (#123)
This commit is contained in:
parent
4a82bf0803
commit
a710b560d5
@ -16,17 +16,13 @@ COPY . .
|
||||
EXPOSE 3001
|
||||
|
||||
# Readiness probe against the unauthenticated setup/health endpoint. The long
|
||||
# start period covers migrations plus the boot-time vite build below.
|
||||
# start period covers migrations plus the boot-time vite build (skipped when
|
||||
# the previous start's build is still valid; see docker-entrypoint.sh).
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=300s --retries=3 \
|
||||
CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||3001)+'/api/health').then(function(r){process.exit(r.ok?0:1)}).catch(function(){process.exit(1)})"
|
||||
|
||||
# The preflight validates env BEFORE the slow steps, so misconfiguration fails
|
||||
# in seconds with the exact fix instead of after a multi-minute build.
|
||||
#
|
||||
# The build MUST run at container start, not image-build time: AUTH_MODE (and the
|
||||
# other client envs) are inlined into the client bundle by `vite build`, and the
|
||||
# self-hoster only chooses AUTH_MODE at runtime via Compose. Building here lets
|
||||
# that runtime value bake into the bundle. The repo .npmrc raises the V8 heap
|
||||
# ceiling (node-options) so the ~7400-module SSR build doesn't OOM under Node's
|
||||
# ~2GB default.
|
||||
CMD ["sh", "-c", "echo 'OpenSEO sends an anonymous usage heartbeat (counts only). Disable: OPENSEO_TELEMETRY_DISABLED=1. Details: docs/SELF_HOSTING_DOCKER.md#telemetry' && pnpm exec tsx scripts/selfhost-preflight.ts && pnpm run db:migrate:local && pnpm run build && pnpm exec vite preview --host 0.0.0.0 --port ${PORT:-3001}"]
|
||||
# Startup (preflight, migrations, conditional build, serve) lives in
|
||||
# docker-entrypoint.sh. The repo .npmrc raises the V8 heap ceiling
|
||||
# (node-options) so the ~7400-module SSR build doesn't OOM under Node's ~2GB
|
||||
# default.
|
||||
CMD ["sh", "docker-entrypoint.sh"]
|
||||
|
||||
39
docker-entrypoint.sh
Normal file
39
docker-entrypoint.sh
Normal file
@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
# Self-host container entrypoint. vite build inlines the envPrefix'd client
|
||||
# envs (see vite.config.ts) into the bundle, so the build must run at container
|
||||
# start — but the output stays valid until those envs or the image change.
|
||||
# Fingerprint them and skip the build when the last start's output matches; an
|
||||
# image update lands a fresh container with no build output, so new code always
|
||||
# rebuilds.
|
||||
set -e
|
||||
|
||||
echo 'OpenSEO sends an anonymous usage heartbeat (counts only). Disable: OPENSEO_TELEMETRY_DISABLED=1. Details: docs/SELF_HOSTING_DOCKER.md#telemetry'
|
||||
|
||||
# The preflight validates env BEFORE the slow steps, so misconfiguration fails
|
||||
# in seconds with the exact fix instead of after a multi-minute build.
|
||||
pnpm exec tsx scripts/selfhost-preflight.ts
|
||||
|
||||
pnpm run db:migrate:local
|
||||
|
||||
# POSTHOG_SOURCEMAPS (CI sourcemap uploads) moves vite's outDir; keep the
|
||||
# fingerprint marker beside the output it describes.
|
||||
if [ "${POSTHOG_SOURCEMAPS:-}" = "true" ]; then OUT_DIR=dist-sourcemaps; else OUT_DIR=dist; fi
|
||||
FP_FILE="$OUT_DIR/.openseo-build-env"
|
||||
|
||||
# Everything that changes build output: the envPrefix prefixes from
|
||||
# vite.config.ts (keep in sync) plus POSTHOG_SOURCEMAPS.
|
||||
FINGERPRINT="$(env | grep -E '^(VITE_|AUTH_MODE|BYPASS_EMAIL_VERIFICATION|POSTHOG_PUBLIC_KEY|POSTHOG_HOST|TURNSTILE_SITE_KEY|POSTHOG_SOURCEMAPS)' | sort | sha256sum | cut -d' ' -f1)"
|
||||
# A missing sha256sum would yield an empty, always-matching fingerprint and
|
||||
# silently disable rebuilds — fail loudly instead.
|
||||
test -n "$FINGERPRINT"
|
||||
|
||||
if [ -f "$FP_FILE" ] && [ "$(cat "$FP_FILE")" = "$FINGERPRINT" ]; then
|
||||
echo "Reusing existing build (build-relevant env unchanged)."
|
||||
else
|
||||
echo "Building client + server (first start, changed build env, or new image)..."
|
||||
rm -f "$FP_FILE"
|
||||
pnpm run build
|
||||
printf '%s' "$FINGERPRINT" > "$FP_FILE"
|
||||
fi
|
||||
|
||||
exec pnpm exec vite preview --host 0.0.0.0 --port "${PORT:-3001}"
|
||||
@ -25,7 +25,7 @@ Set `DATAFORSEO_API_KEY` in `.env` using the [DataForSEO setup guide](./DATAFORS
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Open `http://localhost:<PORT>` (default `3001`). Each container start builds the app and may take 1-2 minutes; follow progress with `docker compose logs -f`.
|
||||
Open `http://localhost:<PORT>` (default `3001`). The first start builds the app and may take 1-2 minutes; follow progress with `docker compose logs -f`.
|
||||
|
||||
Optional env values:
|
||||
|
||||
|
||||
@ -270,7 +270,7 @@ export function formatPreflightReport(result: PreflightResult): string {
|
||||
lines.push(
|
||||
result.failed
|
||||
? "\nPreflight failed — fix the [FAIL] items above and restart. Nothing was started."
|
||||
: "\nPreflight passed. The app now builds inside the container (~1-2 minutes on every start before it serves).",
|
||||
: "\nPreflight passed. The app now builds inside the container (~1-2 minutes on first start before it serves).",
|
||||
);
|
||||
|
||||
return lines.join("\n");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user