diff --git a/README.md b/README.md index d4291eb..5ea8767 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,13 @@ npm install npm run dev ``` -Docker (nginx, http://localhost:8090): +Docker (nginx, http://localhost:8090/ue1): ```sh docker compose up -d --build +BASE_PATH=/ docker compose up -d --build # anderer Pfad, hier direkt unter http://localhost:8090/ ``` +Der Pfad wird beim Build festgelegt (Build-Argument `BASE_PATH`, Standard `/ue1`). Der Reverse Proxy muss den Pfad +unverändert an den Container weiterreichen, also ohne das Präfix zu entfernen. Die Web-Version verwendet einen anderen Zufallsgenerator als Python: Läufe mit demselben Seed sind reproduzierbar, stimmen aber nicht mit den Python-Läufen überein. diff --git a/compose.yaml b/compose.yaml index f56681d..e4bf3fa 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,6 +1,9 @@ services: web: - build: ./web + build: + context: ./web + args: + BASE_PATH: ${BASE_PATH:-/ue1} image: waldbrand-simulation ports: - "8090:80" diff --git a/web/Dockerfile b/web/Dockerfile index e500840..5ef2b06 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1,10 +1,17 @@ +# Pfad, unter dem die App ausgeliefert wird, z.B. /ue1 +ARG BASE_PATH=/ + FROM node:26-trixie-slim AS build +ARG BASE_PATH WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . -RUN npm run build +RUN BASE_PATH="$BASE_PATH" npm run build FROM nginx:mainline-trixie +ARG BASE_PATH COPY nginx.conf /etc/nginx/conf.d/default.conf -COPY --from=build /app/dist /usr/share/nginx/html +# Willkommensseite des Images entfernen +RUN rm -rf /usr/share/nginx/html/* +COPY --from=build /app/dist /usr/share/nginx/html/${BASE_PATH} diff --git a/web/nginx.conf b/web/nginx.conf index 87fee8a..5301ad9 100644 --- a/web/nginx.conf +++ b/web/nginx.conf @@ -4,6 +4,9 @@ server { server_name _; root /usr/share/nginx/html; + # Weiterleitung von /ue1 auf /ue1/ relativ, damit sie hinter einem Reverse Proxy stimmt + absolute_redirect off; + gzip on; gzip_types text/css application/javascript image/svg+xml; @@ -12,8 +15,8 @@ server { add_header Cache-Control "no-cache"; } - # Dateinamen in /assets enthalten einen Hash und ändern sich mit jedem Build - location /assets/ { + # Dateinamen in assets/ enthalten einen Hash und ändern sich mit jedem Build + location ~ /assets/ { add_header Cache-Control "public, max-age=31536000, immutable"; } } diff --git a/web/vite.config.ts b/web/vite.config.ts index 7c52c50..443f1c8 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -1,8 +1,12 @@ -import { defineConfig } from "vite"; +import { defineConfig, loadEnv } from "vite"; import react from "@vitejs/plugin-react"; -export default defineConfig({ - // Relative Pfade, damit die App auch unter einem Unterpfad wie /ue1 läuft - base: "./", - plugins: [react()], +export default defineConfig(({ mode }) => { + // Pfad, unter dem die App ausgeliefert wird, z.B. BASE_PATH=/ue1 → https://sim.teier.net/ue1 + // Absolut statt relativ, damit die Assets auch ohne abschließenden Schrägstrich gefunden werden + const pfad = (loadEnv(mode, ".", "").BASE_PATH ?? "").replace(/^\/+|\/+$/g, ""); + return { + base: pfad ? `/${pfad}/` : "/", + plugins: [react()], + }; });