Lifecycle & Hooks
Nanokit provides a powerful engine to manage the lifecycle of your services, from the initial provisioning of dependencies to graceful teardown.
Understanding these hooks is essential for managing database migrations, complex build steps, and service discovery updates.
Provisioning Hook (provisioning.install)
The provisioning.install command is designed for one-time initialization of a service. It is specifically optimized for distributed environments where multiple replicas might share the same persistent storage.
How it works
- Host-Side Execution: The command runs on the host (or inside a temporary bootstrap container) before the service containers start.
- Atomic Locking: Nanokit uses a sentinel file located in the service’s primary volume to track installation status.
- Prevention of Race Conditions: If multiple replicas or environments share the same volume, Nanokit ensures only one process performs the installation.
services:
api:
runtime: node
provisioning:
# Executed only once if node_modules is missing or sentinel is absent
# Can also be defined globally in the 'node' runtime
install: "npm install --prefer-offline"[!TIP] Use
provisioning.installfor heavy operations likenpm install,composer install, or downloading large binary dependencies that should persist across container restarts.
Service Hooks (hooks)
Service hooks are executed relative to the container lifecycle. These are defined under the hooks key in your service configuration.
| Phase | Context | Typical Use Case |
|---|---|---|
prestart | Host/Provider | Database migrations (prisma migrate), config generation. |
poststart | Host/Provider | Warm-up scripts, registration in external service discovery. |
prestop | Container | Graceful session flushing, unregistering from load balancers. |
poststop | Host/Provider | Cleanup of temporary files, logging teardown events. |
Example: Database Migrations
The prestart hook is the recommended place for running database migrations. Nanokit ensures all required databases are up and healthy before triggering the hook.
services:
web:
runtime: node
hooks:
prestart: "npx prisma migrate deploy"Example: Post-Startup Notification
You can use poststart to trigger external webhooks or internal logging once a service is live.
services:
worker:
runtime: node
hooks:
poststart: "curl -X POST https://status.internal/v1/event -d '{\"service\": \"worker\", \"status\": \"online\"}'"Deployment Hooks
While service hooks manage the container lifecycle, deployment hooks manage the orchestration process itself.
deploy.prepare
The prepare command runs on your local machine (or CI runner) immediately after code is synchronized but before the reconciler starts on the remote host. It is ideal for local build steps that need to be synced.
deploy:
target: root@my-vps
prepare: "npm run build:css && rsync -avz ./dist ./remote:/opt/nanokit/dist"Environment Variables in Hooks
All hooks have access to standard Nanokit environment variables, allowing you to create context-aware scripts:
NANOKIT_SERVICE: Name of the current service.NANOKIT_ENV: Current environment (e.g.,stage,prod).NANOKIT_PROJECT: Name of the project.LIFECYCLE_PHASE: The name of the hook being executed.
Best Practices
- Idempotency: Ensure hooks can be run multiple times without side effects (especially
prestart). - Timeouts: Hooks that run for too long can block deployments. Offload heavy async tasks to background workers if possible.
- Error Handling: Non-zero exit codes in
prestartorprovisioning.installwill halt the deployment for that service.