# syntax=docker/dockerfile:1 # # Standalone Nosterm client image. # # The full SvelteKit source lives alongside this Dockerfile, so the build has no # dependency on anything outside this directory. Build context is THIS # directory: # # docker build -t nosterm:latest . # # The output is a static SPA served by Caddy. All PUBLIC_ build args are baked # into the client bundle (they are browser-visible, so never put secrets here). # # Relays are configured at RUNTIME, not build time: the entrypoint regenerates # /config.json from NOSTERM_DEFAULT_RELAYS on startup, so one prebuilt image can # be deployed with different relays per environment. PUBLIC_DEFAULT_RELAYS # remains a build-time fallback for images run without the runtime var. # --- Build stage ----------------------------------------------------------- FROM node:20-alpine AS build WORKDIR /app # Install dependencies against a clean lockfile for reproducible builds. # Copied separately so the dependency layer caches independently of source. COPY package.json package-lock.json .npmrc ./ RUN npm ci # Build the static SPA. COPY . ./ ARG PUBLIC_DEFAULT_RELAYS="" ARG PUBLIC_DEFAULT_THEME="nord" ARG PUBLIC_DEFAULT_CHANNEL="nosterm" ARG PUBLIC_MAX_TERMINAL_ENTRIES="1000" ARG PUBLIC_MAX_MESSAGE_LENGTH="2000" ARG PUBLIC_MAX_CACHED_MESSAGES_PER_ROOM="500" ENV PUBLIC_DEFAULT_RELAYS=$PUBLIC_DEFAULT_RELAYS \ PUBLIC_DEFAULT_THEME=$PUBLIC_DEFAULT_THEME \ PUBLIC_DEFAULT_CHANNEL=$PUBLIC_DEFAULT_CHANNEL \ PUBLIC_MAX_TERMINAL_ENTRIES=$PUBLIC_MAX_TERMINAL_ENTRIES \ PUBLIC_MAX_MESSAGE_LENGTH=$PUBLIC_MAX_MESSAGE_LENGTH \ PUBLIC_MAX_CACHED_MESSAGES_PER_ROOM=$PUBLIC_MAX_CACHED_MESSAGES_PER_ROOM RUN npm run build # --- Runtime stage (Caddy serves the static build) ------------------------- FROM caddy:2-alpine AS runtime COPY Caddyfile /etc/caddy/Caddyfile COPY --from=build /app/build /srv # Entrypoint regenerates /srv/config.json from NOSTERM_DEFAULT_RELAYS at start. COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh RUN chmod +x /usr/local/bin/docker-entrypoint.sh # Liveness check against the served shell. HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget -q --spider http://localhost:80/ || exit 1 EXPOSE 80 ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"] CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]