Harden Tailwind Docker build and add deploy verification

This commit is contained in:
Luca Sacchi Ricciardi
2026-04-25 15:08:57 +02:00
parent 32302e2b06
commit 229115ae87
9 changed files with 1311 additions and 14 deletions
-1
View File
@@ -35,7 +35,6 @@ CONTRIBUTING.md
# Development
node_modules/
package-lock.json
Makefile
.env*
+18 -8
View File
@@ -1,22 +1,33 @@
# Multi-stage build per LLM Monitor
# Stage 1: Build CSS with Tailwind
FROM node:18-alpine as css-builder
FROM node:18-alpine AS css-builder
WORKDIR /app
# Copiare file di configurazione
COPY package.json tailwind.config.js ./
COPY app/web/static/css/input.css ./app/web/static/css/
# Copiare file di configurazione e lockfile per install consistente
COPY package.json package-lock.json tailwind.config.js ./
# Installare dipendenze Node
RUN npm install
RUN npm ci
# Copiare input CSS e file usati dal content scan di Tailwind.
# Questo passaggio deve avvenire prima della build per invalidare cache quando cambiano template/js.
COPY app/web/static/css/input.css ./app/web/static/css/
COPY app/web/templates/ ./app/web/templates/
COPY app/web/static/js/ ./app/web/static/js/
# Compilare CSS Tailwind
RUN npm run tailwind:build
# Verifica bloccante: output.css deve essere compilato e non vuoto.
RUN test -s ./app/web/static/css/output.css && \
CSS_LINES=$(wc -l < ./app/web/static/css/output.css) && \
echo "[css-builder] output.css lines: ${CSS_LINES}" && \
test "${CSS_LINES}" -ge 100
# Stage 2: Build Python packages
FROM python:3.11-slim as builder
FROM python:3.11-slim AS builder
WORKDIR /app
@@ -48,10 +59,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY --from=builder /opt/venv /opt/venv
# Copiare codice dell'app
COPY --from=css-builder /app/app/web/static/css/output.css ./app/web/static/css/
COPY --from=css-builder /app/app/web/static/css/output.css ./app/web/static/css/output.css
COPY app/ /app/app/
COPY main.py /app/
COPY .env* /app/
# Impostare PATH
ENV PATH="/opt/venv/bin:$PATH"
+13 -1
View File
@@ -1,4 +1,4 @@
.PHONY: help install dev prod test lint format clean docker-build docker-up docker-down
.PHONY: help install dev prod test lint format clean docker-build docker-up docker-down docker-build-no-cache verify-css deploy-no-cache
help:
@echo "LLM Monitor - Makefile Commands"
@@ -11,8 +11,11 @@ help:
@echo "make format - Formatta il codice"
@echo "make clean - Pulisce cache e file temporanei"
@echo "make docker-build - Build dell'immagine Docker"
@echo "make docker-build-no-cache - Build Docker senza cache (fix Tailwind)"
@echo "make docker-up - Avvia i container con Docker Compose"
@echo "make docker-down - Ferma i container con Docker Compose"
@echo "make verify-css - Verifica output.css compilato nel container"
@echo "make deploy-no-cache - Deploy completo con build no-cache + verifica CSS"
install:
python3 -m venv venv
@@ -41,12 +44,21 @@ clean:
docker-build:
docker build -t llm-monitor:latest .
docker-build-no-cache:
docker compose build --no-cache
docker-up:
docker compose up -d
docker-down:
docker compose down
verify-css:
./scripts/verify-tailwind-css.sh
deploy-no-cache:
./scripts/deploy-no-cache.sh
docker-logs:
docker compose logs -f llm-monitor
+41
View File
@@ -236,6 +236,12 @@ Usa il file `docker-compose.yml` fornito:
# Avviare i servizi
docker compose up -d
# Rebuild completo senza cache (consigliato dopo modifiche UI/Tailwind)
docker compose build --no-cache
# Verificare che il CSS compilato non sia vuoto
docker exec llm-monitor-app wc -l /app/app/web/static/css/output.css
# Visualizzare i log
docker compose logs -f llm-monitor
@@ -246,6 +252,41 @@ docker compose down
docker compose restart llm-monitor
```
### Deploy consigliato (Tailwind-safe)
Se l'interfaccia appare senza stili o una modale non si posiziona correttamente, usa il deploy con rebuild no-cache e verifica CSS:
```bash
cd /opt/llm-monitor
docker compose down
docker compose build --no-cache
docker compose up -d
sleep 5
docker exec llm-monitor-app wc -l /app/app/web/static/css/output.css
```
In alternativa dal repository:
```bash
make deploy-no-cache
```
### Tailwind Build Process
- Lo stage `css-builder` del Dockerfile installa dipendenze Node con `npm ci`.
- Prima della build Tailwind vengono copiati template HTML e JS usati dal content scan.
- Dopo `npm run tailwind:build` una verifica bloccante controlla che `output.css` esista e abbia almeno 100 linee.
- Lo stage runtime copia `output.css` compilato da `css-builder` con `COPY --from=css-builder`.
### Troubleshooting UI
Se la modale non appare o i componenti sembrano "unstyled":
1. Esegui `docker compose build --no-cache`.
2. Riavvia con `docker compose up -d`.
3. Verifica CSS compilato: `docker exec llm-monitor-app wc -l /app/app/web/static/css/output.css`.
4. Se il numero linee e `< 100`, la build Tailwind non e riuscita correttamente.
### Container sempre acceso
Il container `llm-monitor` rimarrà in esecuzione fino al suo arresto manuale:
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,5 +1,3 @@
version: '3.8'
services:
# LLM Monitor Dashboard
llm-monitor:
@@ -24,6 +22,8 @@ services:
# Istruzioni di avvio:
# docker compose up -d # Avvia i servizi
# docker compose build --no-cache # Rebuild completo (consigliato se output.css e vuoto o UI rotta)
# docker exec llm-monitor-app wc -l /app/app/web/static/css/output.css # Verifica CSS compilato
# docker compose logs -f # Visualizza i log
# docker compose down # Ferma i servizi
# docker compose restart # Riavvia i servizi
+1 -1
View File
@@ -5,7 +5,7 @@
"private": true,
"scripts": {
"tailwind:dev": "tailwindcss -i ./app/web/static/css/input.css -o ./app/web/static/css/output.css --watch",
"tailwind:build": "tailwindcss -i ./app/web/static/css/input.css -o ./app/web/static/css/output.css --minify"
"tailwind:build": "tailwindcss -i ./app/web/static/css/input.css -o ./app/web/static/css/output.css"
},
"devDependencies": {
"tailwindcss": "^3.4.0"
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -euo pipefail
PROJECT_DIR="${PROJECT_DIR:-/opt/llm-monitor}"
CONTAINER_NAME="${CONTAINER_NAME:-llm-monitor-app}"
if [[ -d "$PROJECT_DIR" ]]; then
cd "$PROJECT_DIR"
else
echo "[deploy] PROJECT_DIR non trovato: $PROJECT_DIR"
echo "[deploy] uso directory corrente: $PWD"
fi
echo "[deploy] stop stack"
docker compose down
if [[ ! -f ".env" && -f ".env.local" ]]; then
echo "[deploy] .env non trovato, copio .env.local -> .env"
cp .env.local .env
fi
echo "[deploy] build stack (no cache)"
docker compose build --no-cache
echo "[deploy] start stack"
docker compose up -d
echo "[deploy] waiting for container startup"
sleep 5
echo "[deploy] verify Tailwind CSS"
./scripts/verify-tailwind-css.sh "$CONTAINER_NAME"
echo "[deploy] completed successfully"
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail
CONTAINER_NAME="${1:-llm-monitor-app}"
CSS_PATH="/app/app/web/static/css/output.css"
MIN_LINES="${MIN_TAILWIND_LINES:-100}"
if ! docker ps --format '{{.Names}}' | grep -Fxq "$CONTAINER_NAME"; then
echo "[verify-css] ERROR: container '$CONTAINER_NAME' non in esecuzione"
exit 1
fi
if ! docker exec "$CONTAINER_NAME" test -f "$CSS_PATH"; then
echo "[verify-css] ERROR: file CSS non trovato: $CSS_PATH"
exit 1
fi
LINES=$(docker exec "$CONTAINER_NAME" wc -l "$CSS_PATH" | awk '{print $1}')
BYTES=$(docker exec "$CONTAINER_NAME" wc -c "$CSS_PATH" | awk '{print $1}')
echo "[verify-css] $CSS_PATH -> ${LINES} lines, ${BYTES} bytes"
if [[ "$LINES" -lt "$MIN_LINES" ]]; then
echo "[verify-css] ERROR: output.css ha meno di ${MIN_LINES} linee"
exit 1
fi
echo "[verify-css] OK: Tailwind CSS compilato correttamente"