# zlayer-builder
Dockerfile parsing, ZImagefile support, pipeline orchestration, and buildah-based container image building.
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
zlayer-builder = "0.8"
```
## Overview
`zlayer-builder` provides:
- High-level `ImageBuilder` API for single image builds
- `PipelineExecutor` for multi-image builds with dependency ordering
- Low-level Dockerfile/ZImagefile parsing and buildah command generation
### Build Sources
The builder accepts three kinds of build input (checked in this order):
1. **Runtime template** -- specify a runtime like `node22` or `rust` and the
builder generates a production-optimized Dockerfile automatically.
2. **ZImagefile** -- a YAML-based alternative to Dockerfiles (see below).
3. **Dockerfile** -- standard Dockerfile syntax with full multi-stage support.
## Modules
| `builder` | High-level `ImageBuilder` API for single images |
| `pipeline` | Multi-image build orchestration with wave-based execution |
| `dockerfile` | Dockerfile parsing, types, and variable expansion |
| `zimage` | ZImagefile YAML parsing and Dockerfile conversion |
| `buildah` | Buildah command generation and execution |
| `templates` | Runtime templates for common dev environments |
| `tui` | Terminal UI for build progress |
| `error` | Error types |
## ImageBuilder API
Build a single image from Dockerfile, ZImagefile, or runtime template:
```rust,no_run
use zlayer_builder::ImageBuilder;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let image = ImageBuilder::new("./my-app").await?
.tag("myapp:latest")
.build()
.await?;
println!("Built image: {}", image.image_id);
Ok(())
}
```
### With ZImagefile
```rust,no_run
use zlayer_builder::ImageBuilder;
async fn example() -> Result<(), zlayer_builder::BuildError> {
let image = ImageBuilder::new("./my-project").await?
.zimagefile("./my-project/ZImagefile")
.tag("myapp:latest")
.build()
.await?;
Ok(())
}
```
### With Runtime Template
```rust,no_run
use zlayer_builder::ImageBuilder;
async fn example() -> Result<(), zlayer_builder::BuildError> {
let image = ImageBuilder::new("./my-node-app").await?
.runtime("node22")
.tag("myapp:latest")
.build()
.await?;
Ok(())
}
```
## Pipeline API
Build multiple images with dependency ordering:
```rust,no_run
use zlayer_builder::pipeline::{PipelineExecutor, parse_pipeline};
use zlayer_builder::BuildahExecutor;
use std::path::PathBuf;
async fn example() -> Result<(), zlayer_builder::BuildError> {
let yaml = std::fs::read_to_string("ZPipeline.yaml")?;
let pipeline = parse_pipeline(&yaml)?;
let executor = BuildahExecutor::new_async().await?;
let result = PipelineExecutor::new(pipeline, PathBuf::from("."), executor)
.fail_fast(true)
.run()
.await?;
println!("Built {} images in {}ms", result.succeeded.len(), result.total_time_ms);
Ok(())
}
```
### Wave-Based Execution
The pipeline executor resolves dependencies into "waves":
- **Wave 0**: Images with no dependencies (run in parallel)
- **Wave 1**: Images depending only on Wave 0 images
- **Wave N**: Images depending only on earlier waves
## ZImagefile Format
YAML-based alternative to Dockerfiles with four build modes:
| Runtime template | `runtime` | Shorthand like `runtime: node22` |
| Single-stage | `base` + `steps` | One base image with ordered build steps |
| Multi-stage | `stages` | Named stages (last stage is output) |
| WASM | `wasm` | WebAssembly component builds |
### Single-Stage Example
```yaml
base: "alpine:3.19"
steps:
- run: "apk add --no-cache curl"
- copy: "app.sh"
to: "/usr/local/bin/app.sh"
chmod: "755"
- workdir: "/app"
env:
NODE_ENV: production
expose: 8080
cmd: ["./app.sh"]
```
### Multi-Stage Example
```yaml
stages:
builder:
base: "rust:1.90-bookworm"
workdir: "/src"
steps:
- copy: "."
to: "/src"
- run: "cargo build --release"
cache:
- target: /usr/local/cargo/registry
id: cargo-registry
sharing: shared
runtime:
base: "debian:bookworm-slim"
steps:
- copy: "target/release/myapp"
from: builder
to: "/usr/local/bin/myapp"
chmod: "755"
cmd: ["/usr/local/bin/myapp"]
expose: 8080
```
### Step Types
| `run` | Execute a shell command |
| `copy` | Copy files from context or previous stage |
| `add` | Add files with URL/archive support |
| `env` | Set environment variables |
| `workdir` | Change working directory |
| `user` | Set the user |
### Copy/Add Fields
| `copy` / `add` | Source file(s) - string or list |
| `to` | Destination path |
| `from` | Source stage name (multi-stage only) |
| `owner` | Owner (user:group) |
| `chmod` | File permissions (e.g., "755") |
### Cache Mounts
```yaml
- run: "npm ci"
cache:
- target: /root/.npm
id: npm-cache
sharing: shared
readonly: false
```
## ZPipeline Format
Multi-image build pipeline with dependency ordering:
```yaml
version: "1"
vars:
VERSION: "1.0.0"
REGISTRY: "ghcr.io/myorg"
defaults:
format: oci
build_args:
RUST_VERSION: "1.90"
images:
base:
file: images/Dockerfile.base
tags:
- "${REGISTRY}/base:${VERSION}"
app:
file: images/ZImagefile.app
depends_on: [base]
tags:
- "${REGISTRY}/app:${VERSION}"
push:
after_all: true
```
### Pipeline Fields
| `version` | Pipeline format version ("1") |
| `vars` | Variables for `${VAR}` substitution in tags |
| `defaults` | Default settings for all images |
| `images` | Named images to build (order preserved) |
| `push.after_all` | Push all images after successful builds |
### Image Fields
| `file` | Yes | Path to Dockerfile or ZImagefile |
| `context` | No | Build context directory (default: ".") |
| `tags` | No | Image tags with variable substitution |
| `depends_on` | No | Images that must build first |
| `build_args` | No | Build arguments (merged with defaults) |
| `no_cache` | No | Skip cache for this image |
| `format` | No | Output format: "oci" or "docker" |
## License
MIT - See [LICENSE](../../LICENSE) for details.