Skip to content

feat: split image into shared aidc-base + thin per-project layer - #18

Open
ai-anant wants to merge 1 commit into
cyfinoid:mainfrom
ai-anant:feat/shared-base-image
Open

feat: split image into shared aidc-base + thin per-project layer#18
ai-anant wants to merge 1 commit into
cyfinoid:mainfrom
ai-anant:feat/shared-base-image

Conversation

@ai-anant

@ai-anant ai-anant commented Aug 2, 2026

Copy link
Copy Markdown

Summary

Every project was building the entire ~3 GB image from scratch: base OS + apt tools + uv/Python + all five coding agents + all scanners. Measured floor: 3.22 GB with zero toolchains. Ten projects = ~32 GB of images, ~30 GB of it identical content, and every new project paid a 10–20 minute build.

This PR splits the image into:

  1. templates/devcontainer/Dockerfile.base.tmpl (new) — everything common: base OS, apt, uv/Python, agents, scanners, pmg wiring, clipboard bridge, bootstrap-claude. Built once per content hash as aidc-base:<hash> and shared by every project.
  2. templates/devcontainer/Dockerfile.tmpl — now FROM aidc-base:<hash> and only adds the per-project toolchains, opt-in security tools, and project-setup.sh.

This is the "one copy of Python serves 10,000 sandboxes" idea from https://x.com/AlexJonesax/status/2083617647342600591 — projects boot from a shared, pre-verified base instead of rebuilding the world.

Changes

  • lib/aidc.sh
    • aidc::ensure_base_image — builds the hashed base image when missing, called from cmd_up, cmd_rebuild, cmd_rescan, and ensure_container_running before the compose build; exports AIDC_BASE_IMAGE so the project Dockerfile's FROM resolves.
    • aidc::base_image_tag — content hash of Dockerfile.base (+ AIDC_AGENTS for forward-compat with the opt-in agents PR), so template edits flow into a new tag automatically.
    • AIDC_BASE_IMAGE in project.env pins a custom base.
    • .devcontainer/Dockerfile.base added to AIDC_MANAGED_PATHS and scaffolded by aidc init.
  • templates/devcontainer/compose.yaml.tmpl — passes AIDC_BASE_IMAGE as a build arg.
  • .github/workflows/aidc-e2e.yml — asserts the new scaffold file.
  • README.md — documents the shared base.

Verification (measured)

  • Base image builds (aidc-base:4136caa40095, 25 layers) and the thin project image builds FROM it (30 layers).
  • Only 5 of the project image's 30 layers are unique (toolchain delta, ~0–100 MB) — the other 25 (≈3.2 GB) are shared on disk with the base.
  • bash -n, shellcheck -x, bash-3.2 compat, tests/resolve-oauth-token.test.sh (7/7) — clean.

Expected impact

  • Fresh aidc up on a new project: builds only the toolchain delta (minutes, not tens of minutes).
  • N projects cost ~3.2 GB once + small deltas on disk, not N×3.2 GB.
  • Reproducible + revocable: bump/pin the base once, rebuild → old agents/scanners stop everywhere.

Merge note

Touches the same Dockerfile region as #15 (AIDC_AGENTS) — they compose cleanly (this PR already passes AIDC_AGENTS through to the base build), but expect a trivial conflict on the agent block if both merge before rebasing.

Closes #7

Every project built the full ~3GB image (base OS + apt + uv/Python + all
agents + all scanners) from scratch. Split the Dockerfile:

- templates/devcontainer/Dockerfile.base.tmpl — the common layer; built
  once per content hash as aidc-base:<hash> and shared by every project
  on disk (Docker dedupes identical layers).
- templates/devcontainer/Dockerfile.tmpl — now FROM aidc-base:<hash> and
  only adds toolchains, opt-in security tools, and the project setup hook.

lib/aidc.sh:
- aidc::ensure_base_image builds the base when the hashed tag is missing
  (called from up/rebuild/rescan/ensure_container_running before compose
  build); exports AIDC_BASE_IMAGE for the per-project FROM.
- AIDC_BASE_IMAGE in project.env pins a custom base.
- Dockerfile.base added to AIDC_MANAGED_PATHS + scaffolded by init.

compose.yaml passes AIDC_BASE_IMAGE as a build arg. e2e asserts the new
scaffold file. README documents the shared base.

Verified: base (25 layers) + thin project (30 layers, 5 unique = toolchain
delta) build end-to-end; project image reuses all base layers on disk.

Refs cyfinoid#7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Image size: build a prebuilt shared aidc-base image so projects don't rebuild ~3GB of common tooling

1 participant