Rebuild the Docker image on Alpine: ~735MB -> ~89MB
Stage 2 was php:8.3-apache (Debian), which compiles PHP from source with --with-apxs2 for mod_php -- that base image alone is 719MB of our 735MB, before any app code. Replaced with alpine:3.24 + apk's own prebuilt php83/php83-apache2/apache2 packages: same architecture (one process, mod_php, .htaccess-driven rewriting), no fpm/nginx rewrite needed. - docker/apache.conf: rewritten for Alpine's apache2 (mod_rewrite ships but isn't loaded by default; a different default document root/log paths). Logs redirected to stdout/stderr so `docker logs` still shows them -- Alpine's own defaults write to a real file under ServerRoot, unlike the official Debian image's symlinked paths. - docker/entrypoint.sh: su-exec instead of su -- BusyBox's su doesn't take the same -c/user argument order as the GNU one the previous entrypoint relied on. Also moved earlier in the Dockerfile (with the other rarely-changing setup, before COPY . .) so it no longer re-runs on every build for a file that essentially never changes. - Composer's binary is still borrowed from the official composer:2 image via multi-stage COPY, not apk's own `composer` package, which turned out to pull in an entire second PHP interpreter (php85) as a dependency just to run itself. - ext-iconv needed adding explicitly (symfony/polyfill-mbstring depends on it; the official Debian image bundles it by default, apk doesn't). Verified against the real compose stack, not just that it builds: apk install; composer install; migrations on startup; PHPUnit 88/88 (runs on the host, but confirms nothing else broke); and by hand, all through the actual container -- health check, SPA fallback for unknown routes, static assets served directly, the API's 401 guard, and a full magic-link -> verify -> JWT -> authenticated project create/list round trip via the real Mailpit catcher. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,8 +21,11 @@ src/Repository/ Database access (User, EmailVerification, Passkey,
|
||||
src/Support/Validator.php Request-body validation helper
|
||||
migrations/*.sql Schema, applied by bin/migrate.php
|
||||
Dockerfile Multi-stage: Node frontend build + PHP 8.3/Apache runtime
|
||||
(Alpine -- apk's own php83/apache2 packages, not a
|
||||
from-source compile; ~90MB image)
|
||||
docker-compose.yml Local stack: app (SPA + API) + Mailpit
|
||||
docker/ Apache vhost + container entrypoint
|
||||
docker/ Apache vhost (mod_rewrite, document root) + entrypoint
|
||||
(runs pending migrations, then hands off to Apache)
|
||||
web/ Vue 3 + TypeScript + Vite PWA frontend (dev on the host)
|
||||
```
|
||||
|
||||
|
||||
@@ -27,3 +27,4 @@ again in stage 12); see [docs/api.md](api.md) and
|
||||
| 17 | Card detail view (`/cards/:id`) + its own configuration view — a card's text is no longer inline-editable; every list links to its own page instead | ✅ done |
|
||||
| 18 | Project view split into real routes — Explore (`/projects/:id`) and Kanban (`/projects/:id/kanban`) are separate pages under a shared layout, not client-side tab state | ✅ done |
|
||||
| 19 | Backend/frontend refactoring pass — deduplicated controller/repository boilerplate and CSS, dropped the never-surfaced project `description` field, squashed the SQL migration history into one clean initial schema | ✅ done |
|
||||
| 20 | Docker image rebuilt on Alpine (apk's own php83/apache2 packages instead of compiling PHP from source on Debian) — ~735MB down to ~90MB, same architecture otherwise; `.dockerignore` trimmed to match | ✅ done |
|
||||
|
||||
+3
-1
@@ -13,7 +13,9 @@ docker compose up -d
|
||||
```
|
||||
|
||||
This runs a multi-stage build — a Node stage compiles the Vue frontend, then a
|
||||
PHP 8.3 + Apache stage bakes in the PHP source and the built SPA — applies
|
||||
PHP 8.3 + Apache stage (Alpine-based; apk's own prebuilt packages rather than
|
||||
compiling PHP from source, which is most of why the image is ~90MB rather
|
||||
than several times that) bakes in the PHP source and the built SPA — applies
|
||||
migrations, and serves the whole app at <http://localhost:8080>: the SPA at `/`
|
||||
(assets and all) and the REST API under `/api` (e.g.
|
||||
`curl http://localhost:8080/api/health`). Unknown paths fall back to the SPA
|
||||
|
||||
Reference in New Issue
Block a user