Files
acty ccb93eda21 docs(01): create phase 1 foundation plans
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>
2026-02-03 16:56:50 +09:00

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
01-01
docker-compose.yml
.air.toml
false
truths artifacts key_links
Developer can start local environment with single command
Code changes trigger automatic rebuild
Container can only access /data volume, not host filesystem
Health endpoint returns healthy when /data mounted
Health endpoint returns unhealthy when /data not mounted
path provides contains
docker-compose.yml Development environment orchestration services:
path provides contains
.air.toml Hot reload configuration [build]
from to via pattern
docker-compose.yml docker/Dockerfile build context dockerfile.*docker/Dockerfile
from to via pattern
docker-compose.yml .air.toml air command air.*.air.toml
Set up Docker Compose development environment with hot reload and verify complete foundation.

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=0

volumes: 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 config && echo "Compose config valid"
    
    - 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`
Task 2: Verify container isolation and health endpoint 1. Build production image: ```bash docker build -f docker/Dockerfile -t pirate-station:latest . ```
  1. 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)
    
  2. 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
    
  3. 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
    
  4. 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 .
    
```bash # All tests pass if: # 1. curl localhost:32768/health returns {"status":"healthy"} # 2. curl localhost:32769/health returns unhealthy # 3. buildx multi-arch build completes echo "Verification requires running the tests in " ``` - Production image builds successfully - Container isolation verified (cannot access host filesystem) - Health endpoint returns healthy with /data mounted - Health endpoint returns unhealthy without /data - Multi-arch build works for amd64 and arm64 Complete Phase 1 foundation: - Go HTTP server on port 32768 - Multi-stage Dockerfile with Debian slim runtime - Docker Compose dev environment with hot reload - Health check endpoint that verifies /data volume 1. Start dev environment: `docker compose up --build` 2. In another terminal, test endpoints: - `curl http://localhost:32768/` should return "Pirate Station API" - `curl http://localhost:32768/health` should return {"status":"healthy"} 3. Edit cmd/server/main.go (change the root message text) 4. Watch terminal - Air should detect change and rebuild 5. `curl http://localhost:32768/` should show your change 6. Ctrl+C to stop, then `docker compose down`
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/server produces single executable

Success criteria from roadmap:

  1. Docker container starts with volume mount and runs Go binary - VERIFIED
  2. Container cannot access files outside mounted volume - VERIFIED
  3. Go backend serves HTTP endpoint on specified port (32768) - VERIFIED
  4. Container can be built on x86 and deployed to ARM64 (Pi) - VERIFIED via buildx

<success_criteria>

  • docker compose up starts dev environment
  • Hot reload rebuilds on code changes
  • curl localhost:32768/health returns 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>
After completion, create `.planning/phases/01-foundation/01-02-SUMMARY.md`