Files
attune/docker/BUILD_QUICKSTART.md
2026-02-04 17:46:30 -06:00

4.4 KiB

Docker Build Quick Start

TL;DR - Fastest & Most Reliable Build

make docker-cache-warm    # ~5-6 minutes (first time only)
make docker-build         # ~15-20 minutes (first time), ~2-5 min (incremental)
make docker-up            # Start all services

Why Two Steps?

Building multiple Rust services in parallel can cause race conditions in the shared Cargo cache. Pre-warming the cache prevents this.

Build Methods

Best for: First-time builds, after dependency updates

# Step 1: Pre-load cache
make docker-cache-warm

# Step 2: Build all services
make docker-build

# Step 3: Start
make docker-up

⏱️ Timing: ~20-25 min first time, ~2-5 min incremental

Method 2: Direct Build

Best for: Quick builds, incremental changes

docker compose build
make docker-up

⏱️ Timing: ~25-30 min first time (sequential due to cache locking), ~2-5 min incremental

Method 3: Single Service

Best for: Developing one service

docker compose build api
docker compose up -d api

⏱️ Timing: ~5-6 min first time, ~30-60 sec incremental

Common Commands

Command Description Time
make docker-cache-warm Pre-load build cache ~5-6 min
make docker-build Build all images ~2-5 min (warm cache)
make docker-up Start all services ~30 sec
make docker-down Stop all services ~10 sec
make docker-logs View logs -
docker compose build api Build single service ~30-60 sec (warm cache)

Troubleshooting

"File exists (os error 17)" during build

Race condition detected. Solutions:

# Option 1: Clear cache and retry
docker builder prune -af
make docker-cache-warm
make docker-build

# Option 2: Build sequentially
docker compose build --no-parallel

Builds are very slow

# Check cache size
docker system df -v | grep buildkit

# Prune if >20GB
docker builder prune --keep-storage 10GB

Service won't start

# Check logs
docker compose logs api

# Restart single service
docker compose restart api

# Full restart
make docker-down
make docker-up

Development Workflow

Making Code Changes

# 1. Edit code
vim crates/api/src/routes/actions.rs

# 2. Rebuild affected service
docker compose build api

# 3. Restart it
docker compose up -d api

# 4. Check logs
docker compose logs -f api

After Pulling Latest Code

# If dependencies changed (check Cargo.lock)
make docker-cache-warm
make docker-build
make docker-up

# If only code changed
make docker-build
make docker-up

Environment Setup

Ensure BuildKit is enabled:

export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1

# Or add to ~/.bashrc or ~/.zshrc
echo 'export DOCKER_BUILDKIT=1' >> ~/.bashrc
echo 'export COMPOSE_DOCKER_CLI_BUILD=1' >> ~/.bashrc

Architecture

Dockerfile (multi-stage)
  ├── Stage 1: Builder
  │   ├── Install Rust + build deps
  │   ├── Copy source code
  │   ├── Build service (with cache mounts)
  │   └── Extract binary
  └── Stage 2: Runtime
      ├── Minimal Debian image
      ├── Copy binary from builder
      ├── Copy configs & migrations
      └── Run service

Services built from same Dockerfile:
  - api (port 8080)
  - executor
  - worker
  - sensor
  - notifier (port 8081)
  
Separate Dockerfile.web for React UI (port 3000)

Cache Mounts Explained

Mount Purpose Size Sharing
/usr/local/cargo/registry Downloaded crates ~1-2GB locked
/usr/local/cargo/git Git dependencies ~100-500MB locked
/build/target Compiled artifacts ~5-10GB locked

sharing=locked = Only one build at a time (prevents race conditions)

Next Steps

Questions?

  • Why is first build so slow? Compiling Rust + all dependencies (~200+ crates)
  • Why cache warming? Prevents multiple builds fighting over the same files
  • Can I build faster? Yes, but with reliability trade-offs (see full docs)
  • Do I always need cache warming? No, only for first build or dependency updates