Create a single Docker image that runs both the frontend (Vite/React) and the backend (Go/Gin) together, displaying their logs side-by-side in a split terminal view. The simulator is excluded from the image.
Goals
- Minimal image size — use multi-stage builds and Alpine/scratch-based images
- Single container runs both services, managed via
tmux (or a lightweight process supervisor like overmind/s6-overlay)
- Split terminal output — when attached to the container, the user sees frontend Vite logs in one pane and backend logs in another
Technical Details
Stack
| Component |
Tech |
Port |
| Frontend |
React 18 + Vite 6 + TailwindCSS 3 |
5173 |
| Backend |
Go 1.25 + Gin + SQLite (modernc) |
8080 |
Proposed Approach
-
Multi-stage Dockerfile
- Stage 1 — Frontend build:
node:22-alpine → npm ci + npm run build → produces frontend/dist/
- Stage 2 — Backend build:
golang:1.25-alpine → go build with CGO disabled → produces a static binary
- Stage 3 — Runtime:
alpine:latest (tiny base) → copy frontend dist + backend binary + install tmux
-
Entrypoint script (docker-entrypoint.sh)
- Starts a
tmux session with two panes:
- Left pane: Backend binary (
./backend)
- Right pane: Vite dev server (
npx vite --host) or a lightweight static file server (e.g. caddy/serve) pointing at frontend/dist/
- Attaches to the tmux session so
docker run -it shows the split view
-
.dockerignore
- Exclude:
simulator/, esp32_firmware/, node_modules/, .git/, *.exe, frontend/dist/
Dev vs Prod Mode
- Production (default): Frontend is pre-built (
npm run build) and served via the Go backend or a tiny static server — no Node.js needed at runtime, smallest footprint
- Development (optional future flag): Mount source, run Vite dev server with HMR — larger image but enables live reload
Acceptance Criteria
Create a single Docker image that runs both the frontend (Vite/React) and the backend (Go/Gin) together, displaying their logs side-by-side in a split terminal view. The simulator is excluded from the image.
Goals
tmux(or a lightweight process supervisor likeovermind/s6-overlay)Technical Details
Stack
51738080Proposed Approach
Multi-stage Dockerfile
node:22-alpine→npm ci+npm run build→ producesfrontend/dist/golang:1.25-alpine→go buildwith CGO disabled → produces a static binaryalpine:latest(tiny base) → copy frontend dist + backend binary + installtmuxEntrypoint script (
docker-entrypoint.sh)tmuxsession with two panes:./backend)npx vite --host) or a lightweight static file server (e.g.caddy/serve) pointing atfrontend/dist/docker run -itshows the split view.dockerignoresimulator/,esp32_firmware/,node_modules/,.git/,*.exe,frontend/dist/Dev vs Prod Mode
npm run build) and served via the Go backend or a tiny static server — no Node.js needed at runtime, smallest footprintAcceptance Criteria
docker build -t sebakit .builds successfullydocker run -it sebakitshows a tmux split with frontend & backend logsdata/dir).dockerignoreis present and correct