zlayer-storage
S3-backed container layer persistence with crash-tolerant uploads and SQLite replication.
Features
- Layer Persistence - Persist container OverlayFS upper layers to S3
- Crash-Tolerant Uploads - Multipart S3 uploads with resume capability
- SQLite State Tracking - Track sync state in SQLite (via SQLx)
- SQLite S3 Replication - WAL-based SQLite replication to S3 with auto-restore
- Compression - Zstd compression for efficient storage
Installation
Add to your Cargo.toml:
[]
= "0.8"
Usage
Layer Sync Manager
Persist container layers to S3:
use ;
let config = LayerStorageConfig ;
let manager = new.await?;
// Sync a container's upper layer to S3
let snapshot = manager.sync_layer.await?;
// Restore a layer from S3
let restored = manager.restore_layer.await?;
SQLite S3 Replicator
Replicate any SQLite database to S3 with WAL-based incremental backups:
use ;
let replicator_config = SqliteReplicatorConfig ;
let s3_config = LayerStorageConfig ;
let replicator = new.await?;
// Start background replication
replicator.start.await?;
// Check status
let status = replicator.status;
println!;
// Force sync before shutdown
replicator.flush.await?;
Auto-Restore
If auto_restore: true and the local database is missing, it will be automatically restored from S3:
// Database will be restored from S3 if missing
let replicator = new.await?;
// Or manually restore
replicator.restore.await?;
Architecture
┌─────────────────────────────────────────────────────────────┐
│ zlayer-storage │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────┐ ┌────────────────────────────┐ │
│ │ LayerSyncManager │ │ SqliteReplicator │ │
│ │ - Multipart upload│ │ - WAL monitoring │ │
│ │ - Resume support │ │ - Local write cache │ │
│ │ - Restore layers │ │ - Async S3 shipping │ │
│ └─────────┬──────────┘ └─────────────┬──────────────┘ │
│ │ │ │
│ ┌─────────▼──────────────────────────────▼──────────────┐ │
│ │ SQLite (SQLx Pool) │ │
│ │ - WAL mode │ │
│ │ - State persistence │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
└──────────────────────────────┼───────────────────────────────┘
│ async
┌───────────────▼───────────────┐
│ S3 Bucket │
│ - Layer tarballs (.tar.zst) │
│ - SQLite snapshots │
│ - WAL segments │
│ - Metadata │
└───────────────────────────────┘
S3 Key Structure
Layer Storage
s3://{bucket}/{prefix}/
├── {digest}.tar.zst # Compressed layer tarball
└── {digest}.meta.json # Layer metadata
SQLite Replication
s3://{bucket}/{prefix}/
├── snapshots/
│ └── {timestamp}.sqlite.zst # Full database snapshots
├── wal/
│ └── {sequence:020}.wal.zst # WAL segments
└── metadata.json # Replication state
Configuration
LayerStorageConfig
| Field | Type | Default | Description |
|---|---|---|---|
bucket |
String | required | S3 bucket name |
prefix |
String | "layers/" |
S3 key prefix |
region |
Option | None | AWS region |
endpoint_url |
Option | None | Custom S3 endpoint |
staging_dir |
PathBuf | /var/lib/zlayer/staging |
Local staging directory |
state_db_path |
PathBuf | /var/lib/zlayer/layer-state.sqlite |
SQLite state DB |
part_size_bytes |
u64 | 64MB | Multipart part size |
max_concurrent_uploads |
usize | 4 | Concurrent uploads |
compression_level |
i32 | 3 | Zstd compression (1-22) |
SqliteReplicatorConfig
| Field | Type | Default | Description |
|---|---|---|---|
db_path |
PathBuf | required | SQLite database path |
s3_bucket |
String | required | S3 bucket for backups |
s3_prefix |
String | required | S3 key prefix |
cache_dir |
PathBuf | required | Local cache directory |
max_cache_size |
u64 | 100MB | Max cache before blocking |
auto_restore |
bool | true | Auto-restore if DB missing |
snapshot_interval_secs |
u64 | 3600 | Snapshot interval |
S3-Compatible Services
Works with any S3-compatible storage:
// MinIO
let config = LayerStorageConfig ;
// Cloudflare R2
let config = LayerStorageConfig ;
// Backblaze B2
let config = LayerStorageConfig ;
License
MIT - See LICENSE for details.