Phase 01: Foundation - 2 plans in 2 waves - Plan 01: Go project + Dockerfile (wave 1) - Plan 02: Dev environment + verification (wave 2) - Ready for execution Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
8.7 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-foundation | 02 | execute | 2 |
|
|
false |
|
Purpose: Creates the local development workflow so changes are automatically rebuilt. Then verifies the entire Phase 1 deliverable works end-to-end: container isolation, HTTP serving, and health checks.
Output: Working development environment with hot reload; verified Phase 1 requirements (INFRA-01, INFRA-02).
<execution_context> @/home/acty/.claude/get-shit-done/workflows/execute-plan.md @/home/acty/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/01-foundation/01-CONTEXT.md @.planning/phases/01-foundation/01-RESEARCH.md @.planning/phases/01-foundation/01-01-SUMMARY.md Task 1: Create Docker Compose development environment docker-compose.yml .air.toml 1. Create docker-compose.yml at project root: ```yaml services: backend: build: context: . dockerfile: docker/Dockerfile target: builder # Stop at build stage for dev command: air -c .air.toml ports: - "32768:32768" volumes: - .:/workspace:cached # Bind mount for live editing - data:/data # Named volume for persistent data working_dir: /workspace environment: - CGO_ENABLED=0volumes: data:
2. Create .air.toml for hot reload:
```toml
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/server"
cmd = "go build -o ./tmp/server ./cmd/server"
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", ".planning", "docker", ".git"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true
Key points:
- target: builder uses build stage (has Go toolchain)
- Bind mount .:/workspace for live editing
- Named volume data:/data for persistent storage
- Air watches for .go file changes and rebuilds
- docker-compose.yml exists and is valid YAML - .air.toml configures hot reload for Go files - Development environment can be started with `docker compose up`
docker compose config && echo "Compose config valid"
-
Test container isolation - verify container cannot access host filesystem:
# Create a test file outside of data volume echo "secret" > /tmp/host-secret.txt # Run container with data volume and try to access host file docker run --rm -d --name isolation-test -p 32768:32768 -v pirate-test-data:/data pirate-station:latest # Container should NOT be able to see /tmp/host-secret.txt # (It's isolated to its own filesystem + /data volume only) -
Test health endpoint with volume mounted:
# Wait for container to start sleep 2 # Health check should return healthy curl -s http://localhost:32768/health # Expected: {"status":"healthy"} # Root endpoint should return API message curl -s http://localhost:32768/ # Expected: Pirate Station API # Stop test container docker stop isolation-test docker volume rm pirate-test-data -
Test health endpoint WITHOUT volume (should be unhealthy):
# Run container without /data volume mounted docker run --rm -d --name no-data-test -p 32769:32768 pirate-station:latest sleep 2 # Health check should return unhealthy curl -s http://localhost:32769/health # Expected: {"status":"unhealthy","reason":"data volume not mounted"} docker stop no-data-test -
Verify multi-arch build capability (don't push, just verify it works):
# Create builder if not exists docker buildx create --name pirate-builder --use 2>/dev/null || docker buildx use pirate-builder # Build for both platforms (local only, no push) docker buildx build --platform linux/amd64,linux/arm64 -f docker/Dockerfile -t pirate-station:multiarch .
Expected: Server starts, endpoints respond, hot reload works.
Type "approved" if dev environment works, or describe any issues
Phase 1 requirements verification:
INFRA-01: Docker container runs isolated to mounted volume only
- Container uses non-root user (appuser)
- Only /data volume is mounted from host
- Container filesystem is isolated (debian slim base)
- Verified by: Cannot access host files outside /data
INFRA-02: Single binary Go backend
- Go compiles to single static binary (CGO_ENABLED=0)
- Binary includes all dependencies (stdlib only)
- No runtime dependencies except libc (debian slim provides)
- Verified by:
go build ./cmd/serverproduces single executable
Success criteria from roadmap:
- Docker container starts with volume mount and runs Go binary - VERIFIED
- Container cannot access files outside mounted volume - VERIFIED
- Go backend serves HTTP endpoint on specified port (32768) - VERIFIED
- Container can be built on x86 and deployed to ARM64 (Pi) - VERIFIED via buildx
<success_criteria>
docker compose upstarts dev environment- Hot reload rebuilds on code changes
curl localhost:32768/healthreturns healthy JSON- Production build works for amd64 and arm64
- Container isolation verified (no host filesystem access beyond /data)
- Human verification confirms dev workflow works </success_criteria>