From bbc588d933c1ebde3718cbc58e0a3f01fa14822f Mon Sep 17 00:00:00 2001 From: Rene Nochebuena Guerrero Date: Tue, 18 Aug 2026 17:27:04 -0600 Subject: [PATCH] fix(docker): drop inherited VOLUME /srv/www that caused silent stale deploys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VOLUME ["/srv/www"] created an anonymous volume that docker compose reuses across container recreation, shadowing a freshly COPY'd SPA bundle with the previous build — up -d --build exited 0 while serving the old bundle (and poisoned the PWA service worker's ngsw.json). A child image cannot un-declare an inherited VOLUME, so it must not be declared: removing it makes the COPY case deterministic and leaves the runtime bind-mount case unaffected. Also refreshed the README FROM tag v1.0.0 -> v1.6.0. --- CHANGELOG.md | 14 +++++++++++++- Dockerfile | 9 +++++++-- README.md | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3153369..0726af9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,22 @@ This module adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html --- -## [1.6.0] — 2026-08-13 +## [1.6.0] — 2026-08-14 Minor — coordinated framework release (lockstep versioning). No changes to this module's own API. +### Fixed + +- **Dropped `VOLUME ["/srv/www"]` from the base image.** The declaration created an anonymous + volume at the SPA root that `docker compose up` reuses across container recreation, so a + rebuild silently kept serving the previous bundle (`up -d --build` exited 0 while shipping the + old build; on a PWA the stale `ngsw.json` then poisoned the service-worker cache). Consumers + could not un-declare an inherited `VOLUME` and were stuck with `--renew-anon-volumes` forever. + Removing it makes the headline `COPY dist/ /srv/www/` case deterministic, and the runtime + bind-mount case (`-v /path:/srv/www`) is unaffected. *The `v1.6.0` image was rebuilt and + re-pushed with this fix.* Consumers with an already-poisoned anonymous volume need a one-time + `-V` (or `docker volume rm`) to shed it. + ### Changed - Bumped einherjar dependencies to v1.6.0. The framework-wide change in this release is diff --git a/Dockerfile b/Dockerfile index 98f1bfb..4473c79 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,12 @@ LABEL org.opencontainers.image.base.name="alpine:3.21" LABEL org.opencontainers.image.base.digest="$BASE_DIGEST" LABEL dev.nochebuena.healthz="/health" -# Mount your SPA dist/ here, or COPY it in a downstream Dockerfile. -VOLUME ["/srv/www"] +# Provide your SPA build at /srv/www — COPY dist/ in a downstream Dockerfile, or +# bind-mount it at runtime (-v /path/to/dist:/srv/www). No VOLUME is declared here +# on purpose: a VOLUME at this path creates an anonymous volume that `docker compose +# up` reuses across container recreation, shadowing a freshly COPY'd bundle with the +# previous build — a silent stale deploy (worse for PWAs, whose service worker then +# caches the stale ngsw.json). A runtime bind-mount works with or without it, and a +# child image cannot un-declare an inherited VOLUME, so it must not be declared at all. EXPOSE 8080 ENTRYPOINT ["/app/spa-server"] diff --git a/README.md b/README.md index a73c0c7..277ef6e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ The module ships as a ready-to-use Docker base image. Deploying a SPA to a conta ## Container usage ```dockerfile -FROM code.nochebuena.dev/einherjar/spa-server:v1.0.0 +FROM code.nochebuena.dev/einherjar/spa-server:v1.6.0 COPY dist/ /srv/www/ ```