2026-05-16 17:52 America/New_York

# Speed Up Docker Deploys

Summary Docker app images now cache dependency installation separately from source changes, and Docker rollouts now build only the images required by the selected deploy scope before restarting containers.

## Summary

Implemented the Docker deployment speed-up plan from `/Users/kell/Desktop/speed-up-docker.md`. The first build after this change may still be slow, but source-only changes should no longer invalidate the expensive Bun and Python dependency layers.

## Changes Made

- Refactored `deployment/docker/Dockerfile.service` to copy workspace manifests, run cached `bun install --frozen-lockfile`, then copy source.
- Applied the same dependency-first build model to `deployment/docker/Dockerfile.web`, keeping the Next.js build after source copy.
- Updated `deployment/docker/Dockerfile.ingest-options` with separate cached pip and Bun install layers before copying source.
- Changed `scripts/deploy.ts` so Docker rollouts run explicit `docker compose build <services>` followed by `docker compose up -d <services>`.
- Documented the faster-build model, scoped rollouts, and appropriate `--no-build` usage in `deployment/docker/README.md`.

## Context

The previous Dockerfiles copied all app, service, and package source before dependency installation. That made nearly every code change invalidate `bun install`, increasing VPS deploy time. The deployment helper also used broad `up -d --build` behavior rather than a clean build phase scoped to the selected service set.

## Important Implementation Details

Each app image now copies root deployment manifests plus every workspace `package.json` before installing dependencies. The source tree is copied only after the install layer is complete.

    RUN --mount=type=cache,target=/root/.bun/install/cache \
      bun install --frozen-lockfile

The `ingest-options` image also copies `services/ingest-options/py/requirements.txt` before source and uses a pip cache mount:

    RUN --mount=type=cache,target=/root/.cache/pip \
      "${VIRTUAL_ENV}/bin/pip" install -r services/ingest-options/py/requirements.txt

For full Docker deploys, the helper builds the six core app services explicitly. For scoped deploys, it builds and restarts only the requested services.

## Expected Impact for End-Users

Users should see faster deployment turnaround after ordinary source edits because dependency installation is reused when manifests and locks have not changed. Scoped deploys should also disturb fewer containers, reducing restart surface for web-only, API-only, and backend-only updates.

## Validation

- Passed: `bun run check:docker-workspace`
- Passed: `./deploy --help`
- Passed: `docker compose -f deployment/docker/docker-compose.yml config --quiet` with a temporary copy of `.env.example`
- Passed: `bun --cwd=apps/web run build`
- Passed: `bun test` with 222 passing tests
- Not run: targeted Docker image builds because this session could not connect to the Docker daemon at `unix:///Users/kell/.orbstack/run/docker.sock`.

## Issues, Limitations, and Mitigations

Docker daemon access was unavailable locally, so image builds still need to be exercised on a machine with a running Docker daemon or during the next VPS rollout. Static Compose validation and repo test coverage passed, and the Dockerfiles use standard BuildKit cache mounts supported by modern Docker Compose v2.

## Follow-up Work

No separate follow-up issue was created. The remaining verification is operational: run the targeted image builds once Docker or OrbStack is available.