# JavaScript on Kubernetes (js-on-k8s) > Practical recipes for running Node.js and JavaScript applications on Kubernetes: container images, graceful shutdown, health checks, manifests, Helm, Kustomize. Every page is available as Markdown: append `.md` to the URL, or send `Accept: text/markdown`. ## Pages - [Home](https://js-on-k8s.dev/index.md): overview and principles - [Recipes](https://js-on-k8s.dev/recipes.md): list of all recipes ## Recipes - [Run node directly, not npm start](https://js-on-k8s.dev/recipes/run-node-directly.md): Make node PID 1 so Kubernetes signals reach your application code. - [Container images for Node.js](https://js-on-k8s.dev/recipes/container-images.md): What a production image should contain, and the recipes that get you there for plain Node.js, Bun, Next.js and TanStack Start. - [A minimal multi-stage Dockerfile](https://js-on-k8s.dev/recipes/container-images/dockerfile.md): Install with npm ci, build in one stage, copy only what runs into the final image. - [Distroless instead of Alpine or Debian slim](https://js-on-k8s.dev/recipes/container-images/distroless-image.md): Ship the Node.js runtime and your app, nothing else. No shell, no package manager, non-root. - [Private packages with Docker build secrets](https://js-on-k8s.dev/recipes/container-images/build-secrets.md): Pass NPM_TOKEN as a BuildKit secret. Never put it in an ARG, an ENV, or a copied .npmrc. - [Build an image with Cloud Native Buildpacks](https://js-on-k8s.dev/recipes/container-images/buildpacks.md): Get a production Node.js image without writing a Dockerfile, using pack and Paketo. - [Containerize a Hono API](https://js-on-k8s.dev/recipes/container-images/hono.md): A Hono service on the Node.js adapter, built in two stages into a distroless image, with the Bun variant alongside. - [Containerize a Next.js app](https://js-on-k8s.dev/recipes/container-images/nextjs.md): Build with output standalone, copy three folders into a distroless image, run server.js directly. - [Containerize a TanStack Start app with Nitro](https://js-on-k8s.dev/recipes/container-images/tanstack-start.md): Add the Nitro Vite plugin, build a node-server bundle into .output, and run the entry with node in a distroless image. - [Kubernetes manifests for a Node.js app](https://js-on-k8s.dev/recipes/manifests.md): The plain YAML baseline: a Deployment and a Service with probes, resources, security context and a named port. Kustomize and Helm build on it. - [Kustomize base and overlays](https://js-on-k8s.dev/recipes/manifests/kustomize.md): One base with the manifests, one overlay per environment that changes only the image tag, replicas and config. - [A minimal Helm chart](https://js-on-k8s.dev/recipes/manifests/helm-chart.md): A chart with one Deployment, one Service, a PDB and a values file with only the knobs you actually turn. - [Configuration from the environment](https://js-on-k8s.dev/recipes/config-from-environment.md): Build one image, promote it through environments, and read every setting from env vars. - [Kubernetes probes done right](https://js-on-k8s.dev/recipes/probes.md): Liveness restarts, readiness routes. Give them different endpoints, keep dependencies out, and use readiness to shed load. - [Graceful shutdown on SIGTERM](https://js-on-k8s.dev/recipes/graceful-shutdown.md): Stop accepting connections, finish in-flight requests, then exit with a deadline. - [Graceful shutdown with Express](https://js-on-k8s.dev/recipes/graceful-shutdown/express.md): app.listen() returns a plain Node.js http.Server. Close that, not the app. - [Graceful shutdown with Fastify](https://js-on-k8s.dev/recipes/graceful-shutdown/fastify.md): Use app.close() with forceCloseConnections and onClose hooks, and listen on 0.0.0.0. - [Graceful shutdown with Hono](https://js-on-k8s.dev/recipes/graceful-shutdown/hono.md): Hono is runtime-agnostic. Close the server the adapter gave you, on Node or on Bun. - [Graceful shutdown with Elysia](https://js-on-k8s.dev/recipes/graceful-shutdown/elysia.md): Elysia runs on Bun. Call app.stop() on SIGTERM and ship it in the Bun distroless image. - [Graceful shutdown with NestJS](https://js-on-k8s.dev/recipes/graceful-shutdown/nestjs.md): Turn on enableShutdownHooks() and use the lifecycle hooks to flip readiness and close resources in order. - [Graceful shutdown with Next.js](https://js-on-k8s.dev/recipes/graceful-shutdown/nextjs.md): The standalone server already handles SIGTERM. Add readiness and cleanup around it, do not replace it. - [Graceful shutdown with TanStack Start and Nitro](https://js-on-k8s.dev/recipes/graceful-shutdown/tanstack-start.md): Nitro's node server drains in-flight requests on SIGTERM. Tune its timeout and add readiness in the server entry. - [Pod, Service, Ingress, Gateway API and NetworkPolicy](https://js-on-k8s.dev/recipes/networking.md): How a request reaches your container, and why you should say who may talk to it. - [Zero-downtime rolling updates](https://js-on-k8s.dev/recipes/zero-downtime-rollouts.md): Rolling update strategy, a PodDisruptionBudget and spread across nodes so a deploy never drops requests. - [Log JSON lines to stdout](https://js-on-k8s.dev/recipes/logging.md): One JSON object per line on stdout. No files, no log rotation, no agents inside the container. - [Telemetry with OpenTelemetry](https://js-on-k8s.dev/recipes/telemetry.md): Kubernetes collects nothing about your app. Export logs, metrics and traces yourself, in one standard. - [Memory and CPU for Node.js Pods](https://js-on-k8s.dev/recipes/memory-and-cpu.md): Measure before you set numbers. Then give Node.js a full CPU or two, size the heap under the memory limit, and re-measure after every runtime upgrade. ## Source - [Repository](https://github.com/vojtechmares/js-on-k8s) - [Full example](https://github.com/vojtechmares/js-on-k8s/tree/main/examples/full): every recipe applied to one app