feat: add frontend dev container to docker-compose #7

Merged
marcel merged 10 commits from feat/frontend-dockerfile into main 2026-03-19 12:07:20 +01:00
Owner

Summary

  • frontend/Dockerfile: Node 20 Alpine image, installs deps, runs npm run dev
  • docker-compose.yml: Frontend service added with depends_on for db, minio, and backend — so docker compose up frontend starts the full stack
  • vite.config.ts: API proxy target made configurable via API_PROXY_TARGET env var (defaults to localhost:8080 for local dev without Docker)
  • .env: PORT_FRONTEND corrected to 5173 (actual Vite dev server port)

How it works

Concern Local dev (no Docker) Docker
Browser /api calls Vite proxy → localhost:8080 Vite proxy → backend:8080 (via API_PROXY_TARGET)
SSR /api calls API_INTERNAL_URL defaults to localhost:8080 API_INTERNAL_URL=http://backend:8080

The frontend_node_modules named volume prevents the host's node_modules from overwriting the container's (avoids OS binary conflicts on macOS/Windows hosts).

Usage

docker compose up frontend       # starts frontend + db + minio + backend
docker compose up                # starts everything

Test plan

  • docker compose up frontend starts without errors
  • Frontend is reachable at http://localhost:5173
  • Login works (SSR API call reaches backend via internal network)
  • Document search works (browser API call proxied to backend)
  • Hot reload works (edit a .svelte file, browser updates)
  • npm run dev locally still works unchanged (no Docker)
## Summary - **`frontend/Dockerfile`**: Node 20 Alpine image, installs deps, runs `npm run dev` - **`docker-compose.yml`**: Frontend service added with `depends_on` for db, minio, and backend — so `docker compose up frontend` starts the full stack - **`vite.config.ts`**: API proxy target made configurable via `API_PROXY_TARGET` env var (defaults to `localhost:8080` for local dev without Docker) - **`.env`**: `PORT_FRONTEND` corrected to `5173` (actual Vite dev server port) ## How it works | Concern | Local dev (no Docker) | Docker | |---|---|---| | Browser `/api` calls | Vite proxy → `localhost:8080` | Vite proxy → `backend:8080` (via `API_PROXY_TARGET`) | | SSR `/api` calls | `API_INTERNAL_URL` defaults to `localhost:8080` | `API_INTERNAL_URL=http://backend:8080` | The `frontend_node_modules` named volume prevents the host's `node_modules` from overwriting the container's (avoids OS binary conflicts on macOS/Windows hosts). ## Usage ```bash docker compose up frontend # starts frontend + db + minio + backend docker compose up # starts everything ``` ## Test plan - [ ] `docker compose up frontend` starts without errors - [ ] Frontend is reachable at `http://localhost:5173` - [ ] Login works (SSR API call reaches backend via internal network) - [ ] Document search works (browser API call proxied to backend) - [ ] Hot reload works (edit a `.svelte` file, browser updates) - [ ] `npm run dev` locally still works unchanged (no Docker)
marcel added 10 commits 2026-03-19 12:03:57 +01:00
- frontend/Dockerfile: Node 20 Alpine image running npm run dev
- docker-compose: frontend service with depends_on db/minio/backend,
  source mounted as volume, named volume for node_modules to avoid
  OS binary conflicts between host and container
- vite.config.ts: make API proxy target configurable via
  API_PROXY_TARGET env var (defaults to localhost:8080 for local dev,
  set to http://backend:8080 inside Docker)
- .env: update PORT_FRONTEND to 5173 (actual vite dev server port)

Usage:
  docker compose up frontend   # starts frontend + all dependencies
  docker compose up            # starts everything

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the devcontainer (sleep infinity + VS Code image) with a proper
dev setup:
- Dockerfile: eclipse-temurin:21-jdk-alpine running ./mvnw spring-boot:run
- Source mounted at /app, Maven deps cached in named volume maven_cache
- Healthcheck on /actuator/health so frontend waits until backend is ready
- frontend depends_on backend: service_healthy (was service_started)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adding explicit spring.flyway.* config (url/user/password) ensures Flyway
creates its own JDBC connection and runs migrations independently of the JPA
datasource initialization order in Spring Boot 4.0.

Fix DataInitializer creating a Document with title=null, which would hit the
NOT NULL constraint in the documents table once the admin user init succeeds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The CI health check (curl -sf) and Docker Compose health check (wget)
both hit /actuator/health unauthenticated. With anyRequest().authenticated()
the endpoint returned 401, curl -f treated it as failure, and the health
check loop never exited successfully.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Spring Boot 4.0 Flyway auto-configuration is not triggering in the CI
environment — confirmed by empty DB and no flyway_schema_history table.
Replace YAML-based auto-config with an explicit @Bean that creates and
runs Flyway directly on startup, independent of any auto-configuration
conditions. Disable the auto-config via spring.flyway.enabled=false to
prevent interference. Add @DependsOn("flyway") to DataInitializer to
enforce that CommandLineRunner beans are only registered after migrations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mvnw is a bash script; eclipse-temurin:21-jdk-alpine only provides ash
(busybox), causing the container to exit silently with code 0 before the
JVM starts. The Debian-based eclipse-temurin:21-jdk image includes bash.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Local dev databases that existed before Flyway was introduced have tables
but no flyway_schema_history. Flyway refuses to migrate a non-empty schema
without a history table. baselineOnMigrate=true with baselineVersion=4
stamps those databases as already at V4 without re-running migrations.
Fresh databases (CI) have an empty schema so the baseline is never
triggered and all 4 migrations run normally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add unit-tests job using Playwright Docker image (no apt install needed)
- Add backend-unit-tests job with Java 21 + Maven
- Add e2e-tests job: PostgreSQL + MinIO via docker-compose, Spring Boot backend,
  SvelteKit dev server, Playwright Chromium
- Use non-conflicting host ports (DB: 15432, MinIO: 19000/19001)
- Install Docker CLI via official Docker apt repo (Playwright image has no daemon)
- Connect job container to archive-net for direct DB/MinIO access
- Pin DOCKER_API_VERSION=1.43 for Docker socket compatibility
- Start backend with java -jar + health-check loop (curl /actuator/health)
- Use continue-on-error on cleanup step to handle SIGKILL gracefully
- Downgrade upload-artifact to v3 (v4 not supported on self-hosted Gitea)
- Always run npm ci unconditionally (actions/cache@v4 broken on this runner)
- Log /tmp/backend.log on startup timeout so Spring Boot errors are visible
- Add diagnostic steps for DB tables and Flyway schema history

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace __dirname with fileURLToPath(import.meta.url) for ESM compatibility
- Start SvelteKit dev server on port 3000 with 120s webServer timeout
- Add data-hydrated attribute (set in onMount) so tests wait for hydration
- Fix nav active class assertions: text-brand-navy (not border-brand-navy)
- Fix filter button selector: exact match to avoid matching "Alle Filter löschen"
- Fix date validation test: use pressSequentially('99') to trigger dateInvalid
- Fix person/document search: navigate directly to URL with query param
  (avoids debounced oninput → goto race condition in CI)
- Fix heading selector: level: 1 to avoid strict-mode with h1+h2 on page
- Fix auth redirect: return 401 from handleFetch instead of throwing redirect

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs: add Red/Green TDD workflow to COLLABORATING.md
Some checks failed
CI / Unit & Component Tests (pull_request) Successful in 8m48s
CI / Backend Unit Tests (pull_request) Successful in 1m56s
CI / E2E Tests (pull_request) Failing after 58s
CI / Unit & Component Tests (push) Successful in 8m22s
CI / Backend Unit Tests (push) Successful in 1m59s
CI / E2E Tests (push) Failing after 52s
0918e75803
marcel force-pushed feat/frontend-dockerfile from 154001de66 to 0918e75803 2026-03-19 12:03:57 +01:00 Compare
marcel merged commit 0918e75803 into main 2026-03-19 12:07:20 +01:00
marcel deleted branch feat/frontend-dockerfile 2026-03-19 12:07:21 +01:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#7