Services & Provisioning
Services are the building blocks of your application. Each service represents a containerized workload that Nanokit orchestrates.
Property Reference
Core Configuration
| Property | Type | Description |
|---|---|---|
image | string | Docker image (e.g., node:20-slim). Optional if a runtime is used. |
build | string | Path to Dockerfile or build context. |
runtime | string | Runtime ID (from the global runtimes block). Also used for auto-discovery. |
port | number | Public port mapped on the host. |
expose | number | Internal container port. Defaults to port if omitted. |
path | string | Local directory to mount as a volume (enables hot-reload during development). |
start | string | Command to run as the container entrypoint. |
host | string | Custom domain(s) for this service. Multiple domains can be comma-separated. |
depends_on | string[] | Ordered dependencies. Ensures start/stop hierarchy. |
updateStrategy | recreate | rolling | Update strategy. recreate (default) stops then starts. rolling provides zero-downtime. |
instances | number | Number of container replicas. Set to 0 to disable the service in a given environment. |
Environment Variables
| Property | Type | Description |
|---|---|---|
env | object | Key-value pairs injected as environment variables into the container. |
secrets | object | Sensitive values resolved from Vault or other providers. See Secrets. |
Resources & Scaling
| Property | Type | Description |
|---|---|---|
cpu | number | string | CPU limit (e.g., 0.5, 2.0). |
memory | string | Memory limit (e.g., 512mb, 1gb). |
volumes | string[] | Persistent data mappings using source:target syntax. |
scale | object | Auto-scaling configuration for the service. |
Scale Options
| Property | Type | Description |
|---|---|---|
scale.min | number | Minimum number of replicas. |
scale.max | number | Maximum number of replicas. |
scale.cpu_threshold | string | CPU utilization target for scaling (e.g., "70%"). |
Provisioning
| Property | Type | Description |
|---|---|---|
provisioning.install | string | One-time install command. Inherited from the Global Runtime if omitted. |
Host Mapping
The host property maps custom domains to a service via the integrated Caddy gateway:
services:
web:
runtime: node
host: my-app.localhost # Single domain
api:
runtime: node
host: api.my-app.localhost, api.localhost # Multiple domains (comma-separated)In production environments, Caddy automatically obtains SSL certificates via ACME (Let’s Encrypt).
Update Strategies
recreate (Default)
The container is stopped, removed, and recreated. Brief downtime occurs during the switch.
rolling
A new container is started alongside the old one. Traffic is switched after the new container is healthy. The old container is then removed. Zero downtime.
services:
api:
image: my-app:latest
updateStrategy: rollingBuild & Compilation Strategies
Nanokit handles the transition from source code to container images using a dual-mode strategy designed for both local development and professional CI/CD pipelines.
1. Artifact-based (Pre-build)
If Nanokit detects pre-compiled artifacts (e.g., dist/, .next/, out/, build/) in the service path or project root, it automatically includes them in the Docker context and copies them into the image.
- Workflow:
nx build→nkapp deploy. - Benefit: Faster image creation as compilation happens once outside of Docker. Ideal for CI/CD environments where builds are a separate stage.
2. Source-based (In-Container Build)
If a build command is specified in nanokit.yml, Nanokit executes it inside the Docker container during the image creation phase.
- Workflow:
nkapp deploy(Nanokit handles compilation internally). - Benefit: Guarantees that the code is compiled in an environment identical to the runtime. This is crucial for services with native dependencies (C++/Rust) that must match the target architecture (e.g.
linux/amd64).
services:
api:
runtime: node
build: npm run build # Executed inside the Docker build process
start: node dist/index.js3. Native Dockerfile (Full Control)
If you need complete control over the container environment, you can provide your own Dockerfile. Nanokit will bypass its automatic generation and use yours instead.
- Workflow:
build: trueorbuild: ./Dockerfile. - Benefit: Support for specialized system dependencies, multi-stage builds, and custom base images.
See the dedicated Native Dockerfile page for more details.
Lifecycle & Hooks
Nanokit allows you to hook into different stages of a service’s lifecycle for tasks like database migrations, installation of dependencies, or cleanup.
For detailed information on prestart, poststart, provisioning.install, and more, see the dedicated Lifecycle & Hooks page.
Disabling a Service
Set instances: 0 to completely disable a service in a specific environment:
environments:
stage:
services:
hub:
instances: 0 # Hub is not deployed to stagingDependencies (depends_on)
The depends_on property defines the orchestration order of your project. Nanokit calculates a Directed Acyclic Graph (DAG) to determine which services can start in parallel and which must wait for others.
Common Patterns
1. Database Readiness
The most frequent use case is ensuring an application waits for its database to be healthy before attempting a connection.
services:
api:
runtime: node
depends_on:
- test_mongo_db2. Provisioning Master
When sharing volumes (like node_modules or a shared cache) between services, you can designate one “Master” service to handle the heavy lifting (installation, compilation) by making other services depend on it.
[!TIP] For a more elegant approach, define this dependency at the Runtime Level instead of repeating it in every service.
3. Service Hierarchy
In microservice architectures, you may want to ensure that a gateway or a central authentication service is up before the rest of the stack.
Complete Example
services:
web:
runtime: node
path: ./apps/web
port: 3000
host: my-app.localhost
updateStrategy: rolling
cpu: 1.0
memory: 1gb
depends_on:
- api
env:
NODE_ENV: production
start: npm run start
hooks:
prestart: "npx prisma migrate deploy"
volumes:
- ./uploads:/workspace/uploads[!TIP] Atomic Install: The
provisioning.installcommand is executed only if the shared volume’s sentinel file is missing, preventing redundant installs across distributed clusters.