forked from molecule-ai/molecule-core
Closes core#116. Brings local-dev iteration parity with the canvas's
Turbopack HMR — edit a Go file, see the platform restart in <5s
instead of running 'docker compose up --build' (~30s) per change.
USAGE
make dev # docker compose with air-driven live reload
make up # production-shape stack (no air, normal Dockerfile)
WHAT THIS ADDS
workspace-server/.air.toml — air watch config
workspace-server/Dockerfile.dev — air-on-golang:1.25-alpine, dev-only
docker-compose.dev.yml — overlay swapping platform service
to Dockerfile.dev + bind-mounting
workspace-server/ source
Makefile — make {dev,up,down,logs,build,test}
WHAT THIS DOES NOT TOUCH
workspace-server/Dockerfile (production multi-stage build)
docker-compose.yml (prod-shape stack)
CI workflows (build prod image directly)
Tenant deployment / SaaS (image swap stays the model)
Pure additive. Existing 'docker compose up' path unchanged; production
stays on the static binary. Air install pinned via go install at image
build time so the dev image is reproducible-enough for local use (we
don't pin air to a SHA — the dev image is rebuilt locally and updates
opportunistically).
PHASE 4 SELF-REVIEW (FIVE-AXIS)
Correctness: No finding — additive change, no existing path modified.
.air.toml watches .go + .yaml under workspace-server/, excludes
_test.go and tests dir so test edits don't trigger rebuild.
Dockerfile.dev mirrors prod's 'go mod download' so first rebuild
is fast.
Readability: No finding — three small files plus a Makefile, each
with header comments explaining the WHY, not just the WHAT. The
Makefile uses the standard ## help-target pattern.
Architecture: No finding — overlay pattern (docker-compose.dev.yml
on top of docker-compose.yml) is the standard compose convention
for env-specific overrides. Doesn't fork the prod path.
Security: No finding because no production code path; dev-only image
isn't built in CI and isn't published to ECR.
Performance: No finding — air debounce=500ms, exclude_unchanged=true
so a save that doesn't change content is a no-op rebuild.
REFS
core#116 — this issue
Companion: core#117 (workspace-side config-watcher for hot-reload of
config.yaml) — different scope; this issue is platform-only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
39 lines
1.5 KiB
Docker
39 lines
1.5 KiB
Docker
# Dockerfile.dev — local-development image with air-driven live reload.
|
|
#
|
|
# Selected by docker-compose.dev.yml (overlay over docker-compose.yml).
|
|
# Production stays on workspace-server/Dockerfile (static binary, no air).
|
|
#
|
|
# Workflow:
|
|
# 1. docker compose -f docker-compose.yml -f docker-compose.dev.yml up
|
|
# 2. Edit any .go file under workspace-server/
|
|
# 3. air detects, rebuilds, kills old binary, starts new one (~3-5s)
|
|
# 4. No `docker compose up --build` needed
|
|
#
|
|
# Templates + plugins are NOT pre-cloned here — air-mode assumes the
|
|
# developer's filesystem has the workspace-configs-templates/ + plugins/
|
|
# dirs available, mounted at runtime via docker-compose.dev.yml.
|
|
|
|
FROM golang:1.25-alpine
|
|
|
|
# air + git (for go mod) + ca-certs (for TLS) + tzdata (for time-zone DB).
|
|
RUN apk add --no-cache git ca-certificates tzdata wget \
|
|
&& go install github.com/air-verse/air@latest
|
|
|
|
WORKDIR /app/workspace-server
|
|
|
|
# Pre-fetch deps so the first `air` rebuild on a fresh container is fast.
|
|
# These are bind-mount-overridden at runtime, so the COPY here is just
|
|
# to warm the module cache.
|
|
COPY workspace-server/go.mod workspace-server/go.sum ./
|
|
RUN go mod download
|
|
|
|
# Source is bind-mounted at runtime (see docker-compose.dev.yml volumes
|
|
# block) so the Dockerfile doesn't need to COPY it. air watches the
|
|
# bind-mounted dir for changes.
|
|
|
|
ENV CGO_ENABLED=1
|
|
ENV GOFLAGS="-buildvcs=false"
|
|
|
|
# Run air with the .air.toml in the bind-mounted source dir.
|
|
CMD ["air", "-c", ".air.toml"]
|