Project updates from Template #1
@@ -1,3 +1,27 @@
|
|||||||
|
# ================================
|
||||||
|
# Asset image
|
||||||
|
# ================================
|
||||||
|
FROM node:22-alpine AS assets
|
||||||
|
|
||||||
|
# Install the minifiers in their own layer, so they are cached across asset changes
|
||||||
|
RUN apk add --no-cache oxipng \
|
||||||
|
&& npm install --global esbuild svgo
|
||||||
|
|
||||||
|
# Copy the static files and minify the JS/CSS/SVG sources and losslessly recompress
|
||||||
|
# the PNG images in place, keeping their names so the URL paths derived from the
|
||||||
|
# StaticFile enumeration stay unchanged.
|
||||||
|
WORKDIR /static
|
||||||
|
COPY ./Services/Website/Resources/Static .
|
||||||
|
RUN esbuild --minify --allow-overwrite --outdir=css css/*.css \
|
||||||
|
&& esbuild --minify --allow-overwrite --outdir=js js/*.js \
|
||||||
|
&& oxipng --opt max --strip safe *.png \
|
||||||
|
&& svgo icon.svg
|
||||||
|
|
||||||
|
# Export stage: `docker build --target assets-export --output <dir>` writes the
|
||||||
|
# minified static files to <dir> for local inspection.
|
||||||
|
FROM scratch AS assets-export
|
||||||
|
COPY --from=assets /static /
|
||||||
|
|
||||||
# ================================
|
# ================================
|
||||||
# Build image
|
# Build image
|
||||||
# ================================
|
# ================================
|
||||||
@@ -45,8 +69,13 @@ RUN cp "/usr/libexec/swift/linux/swift-backtrace-static" ./
|
|||||||
RUN find -L "$(swift build --package-path /build/Services/Website -c release --show-bin-path)/" -regex '.*\.resources$' -exec cp -Ra {} ./ \;
|
RUN find -L "$(swift build --package-path /build/Services/Website -c release --show-bin-path)/" -regex '.*\.resources$' -exec cp -Ra {} ./ \;
|
||||||
|
|
||||||
# Copy the static files directory (served by FileMiddleware) if it exists
|
# Copy the static files directory (served by FileMiddleware) if it exists
|
||||||
|
RUN [ -d /build/Services/Website/Resources ] && mv /build/Services/Website/Resources ./Resources || true
|
||||||
|
|
||||||
|
# Overwrite the static files with the minified copies from the assets stage
|
||||||
|
COPY --from=assets /static ./Resources/Static
|
||||||
|
|
||||||
# Ensure that by default, neither the directory nor any of its contents are writable.
|
# Ensure that by default, neither the directory nor any of its contents are writable.
|
||||||
RUN [ -d /build/Services/Website/Resources ] && { mv /build/Services/Website/Resources ./Resources && chmod -R a-w ./Resources; } || true
|
RUN chmod -R a-w ./Resources
|
||||||
|
|
||||||
# ================================
|
# ================================
|
||||||
# Run image
|
# Run image
|
||||||
|
|||||||
@@ -105,6 +105,17 @@ db-reset: ## Stop and remove the local database instance and delete its data vol
|
|||||||
--profile database down mariadb \
|
--profile database down mariadb \
|
||||||
--volumes
|
--volumes
|
||||||
|
|
||||||
|
# --- Assets minification ------------------------------------------------------
|
||||||
|
|
||||||
|
.PHONY: ast-minify
|
||||||
|
ast-minify: ## Preview the minified JS/CSS assets in .build/minified
|
||||||
|
@docker build \
|
||||||
|
--target assets-export \
|
||||||
|
--output .build/minified \
|
||||||
|
--file Dockerfile \
|
||||||
|
../..
|
||||||
|
@echo "Minified assets written to .build/minified"
|
||||||
|
|
||||||
# --- Registry deployment ------------------------------------------------------
|
# --- Registry deployment ------------------------------------------------------
|
||||||
|
|
||||||
.PHONY: img-check
|
.PHONY: img-check
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ The service:
|
|||||||
- Serves the landing page at `GET /` (rendered once per supported language with [Elementary](https://github.com/elementary-swift/elementary) and cached).
|
- Serves the landing page at `GET /` (rendered once per supported language with [Elementary](https://github.com/elementary-swift/elementary) and cached).
|
||||||
- Negotiates each request's language from its `Accept-Language` header against the languages in the `WebsiteLibrary` String Catalog, falling back to the default (`en`); pages are served from the per-language cache with `Content-Language` and `Vary: Accept-Language` headers.
|
- Negotiates each request's language from its `Accept-Language` header against the languages in the `WebsiteLibrary` String Catalog, falling back to the default (`en`); pages are served from the per-language cache with `Content-Language` and `Vary: Accept-Language` headers.
|
||||||
- Answers a liveness check at `GET /health` with a static JSON payload, and a readiness check at `GET /health/ready` that reports whether the database is reachable (`200` ready / `503` unavailable).
|
- Answers a liveness check at `GET /health` with a static JSON payload, and a readiness check at `GET /health/ready` that reports whether the database is reachable (`200` ready / `503` unavailable).
|
||||||
- Serves static files (CSS, JS, icons, manifest, `robots.txt`) from `Resources/Static` via Hummingbird's `FileMiddleware`, tagged with media-type-specific `Cache-Control`.
|
- Serves static files (CSS, JS, icons, manifest, `robots.txt`) from `Resources/Static` via Hummingbird's `FileMiddleware`, tagged with media-type-specific `Cache-Control`; the production image ships minified copies (see [Static assets](#static-assets)).
|
||||||
- Returns a custom HTML 404 page, localized like the landing page, for any request that matches neither a route nor a static file.
|
- Returns a custom HTML 404 page, localized like the landing page, for any request that matches neither a route nor a static file.
|
||||||
- Compresses responses (gzip/deflate) above a configurable size when the client advertises support.
|
- Compresses responses (gzip/deflate) above a configurable size when the client advertises support.
|
||||||
- Stamps a hardened set of security headers on every response.
|
- Stamps a hardened set of security headers on every response.
|
||||||
@@ -200,6 +200,19 @@ docker compose -f docker-compose.yml pull
|
|||||||
docker compose -f docker-compose.yml up -d
|
docker compose -f docker-compose.yml up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Static assets
|
||||||
|
The image build optimizes the files under `Resources/Static` in its `assets` stage, in place:
|
||||||
|
- CSS and JS are minified with [esbuild](https://esbuild.github.io).
|
||||||
|
- PNG images are losslessly recompressed with [oxipng](https://github.com/oxipng/oxipng) — the output is pixel-identical, only encoded smaller.
|
||||||
|
- The SVG icon is minified with [svgo](https://github.com/svg/svgo).
|
||||||
|
|
||||||
|
Files keep their names and paths, so the URLs derived from the `StaticFile` enumeration are unaffected. The sources in the repository stay readable and unminified: a direct `swift run` serves them as-is, while any image build — including the local `make site-mount` one, which builds the same Dockerfile — serves the optimized copies.
|
||||||
|
|
||||||
|
Preview the optimized output locally — requires only Docker and writes to the git-ignored `.build/minified`:
|
||||||
|
```sh
|
||||||
|
make ast-minify
|
||||||
|
```
|
||||||
|
|
||||||
### Required variables
|
### Required variables
|
||||||
The Makefile and Compose files read these from a `.env` file (or the environment). Provide your own values — do **not** commit secrets.
|
The Makefile and Compose files read these from a `.env` file (or the environment). Provide your own values — do **not** commit secrets.
|
||||||
| Variable | Used for |
|
| Variable | Used for |
|
||||||
|
|||||||
Reference in New Issue
Block a user