V1.1.0 Responsive

Footer angepasst
Lauffähigkeit auf Server verbessert
deploy.sh mit for loop
This commit is contained in:
rxf
2026-03-22 18:44:22 +01:00
parent b71d92646b
commit 0b9d21c24c
11 changed files with 258 additions and 20 deletions

View File

@@ -1,3 +1,5 @@
# syntax=docker/dockerfile:1
FROM python:3.11-slim FROM python:3.11-slim
WORKDIR /app WORKDIR /app
@@ -5,6 +7,7 @@ WORKDIR /app
# System-Abhängigkeiten installieren # System-Abhängigkeiten installieren
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
gcc \ gcc \
curl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Python-Abhängigkeiten installieren # Python-Abhängigkeiten installieren

View File

@@ -1,3 +1,5 @@
# syntax=docker/dockerfile:1
FROM python:3.13-slim FROM python:3.13-slim
WORKDIR /app WORKDIR /app

89
deploy.sh Executable file
View File

@@ -0,0 +1,89 @@
#!/bin/bash
# Deploy Script für laufschrift
# Baut das Docker Image und lädt es zu docker.citysensor.de hoch
set -e
# Konfiguration
REGISTRY="docker.citysensor.de"
PROJEKT="wetterstation"
IMAGE_NAME=("${PROJEKT}-frontend" "${PROJEKT}-collector" "${PROJEKT}-api")
TAG="${TAG:-$(date +%Y%m%d%H%M)}" # default Datum
# Build-Datum
BUILD_DATE=$(date +%d.%m.%Y)
echo "=========================================="
echo " Deploy Script"
echo "=========================================="
echo "Registry: ${REGISTRY}"
echo "Images: ${IMAGE_NAME[*]}"
echo "Tag: ${TAG}"
echo "Build-Datum: ${BUILD_DATE}"
echo "=========================================="
echo ""
# 1. Login zur Registry (falls noch nicht eingeloggt)
echo ">>> Login zu ${REGISTRY}..."
docker login "${REGISTRY}"
echo ""
# 2. Multiplatform Builder einrichten (docker-container driver erforderlich)
echo ">>> Richte Multiplatform Builder ein..."
if ! docker buildx inspect multiplatform-builder &>/dev/null; then
docker buildx create --name multiplatform-builder --driver docker-container --bootstrap
fi
docker buildx use multiplatform-builder
echo ""
for image in "${IMAGE_NAME[@]}"; do
# Entferne Projekt-Präfix für Verzeichnisnamen
IMAGE_DIR="${image#${PROJEKT}-}"
FULL_IMAGE="${REGISTRY}/${image}:${TAG}"
echo "=========================================="
echo ">>> Baue ${image}..."
echo ">>> Image: ${FULL_IMAGE}"
echo "=========================================="
# Build-Args vorbereiten (für Frontend Version und Build-Date)
BUILD_ARGS="--build-arg BUILD_DATE=${BUILD_DATE}"
if [ "${IMAGE_DIR}" = "frontend" ]; then
VERSION=$(grep '"version"' "${IMAGE_DIR}/package.json" | head -1 | sed 's/.*"version": "\(.*\)".*/\1/')
BUILD_ARGS="${BUILD_ARGS} --build-arg VERSION=${VERSION}"
fi
# 3. Docker Image bauen und pushen (Multiplatform)
docker buildx build \
--platform linux/amd64,linux/arm64 \
${BUILD_ARGS} \
-t "${FULL_IMAGE}" \
--push \
"./${IMAGE_DIR}"
# 4. Tagge auch als :latest
echo ">>> Tagge ${image} als :latest..."
docker buildx imagetools create \
-t "${REGISTRY}/${image}:latest" \
"${FULL_IMAGE}"
echo "${image} erfolgreich gebaut und gepusht!"
echo ""
done
echo ">>> Alle Builds erfolgreich!"
echo ""
echo "=========================================="
echo "✓ Deploy erfolgreich abgeschlossen!"
echo "=========================================="
echo "Registry: ${REGISTRY}"
echo "Projekt: ${PROJEKT}"
echo "Tag: ${TAG}"
echo ""
echo "Auf dem Server ausführen:"
echo " docker compose -f docker-compose.prod.yml pull"
echo " docker compose -f docker-compose.prod.yml up -d"
echo ""

View File

@@ -56,6 +56,12 @@ services:
networks: networks:
- internal - internal
- proxy - proxy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.docker.network=dockge_default" - "traefik.docker.network=dockge_default"
@@ -72,7 +78,8 @@ services:
container_name: wetterstation_frontend_prod container_name: wetterstation_frontend_prod
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- api api:
condition: service_healthy
networks: networks:
- internal - internal
- proxy - proxy

View File

@@ -1,5 +1,11 @@
# syntax=docker/dockerfile:1
# Build stage # Build stage
FROM node:20-alpine AS builder FROM --platform=$BUILDPLATFORM node:20-alpine AS builder
# Build arguments
ARG BUILD_DATE=unknown
ARG VERSION=unknown
WORKDIR /app WORKDIR /app
@@ -12,14 +18,18 @@ RUN npm ci
# Copy source code # Copy source code
COPY . . COPY . .
# Build app # Build app with build info
ENV VITE_BUILD_DATE=${BUILD_DATE}
ENV VITE_VERSION=${VERSION}
RUN npm run build RUN npm run build
# Production stage # Production stage
FROM nginx:alpine FROM nginx:alpine
WORKDIR /usr/share/nginx/html
# Copy built app from builder # Copy built app from builder
COPY --from=builder /app/dist /usr/share/nginx/html COPY --from=builder /app/dist .
# Copy nginx configuration # Copy nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf COPY nginx.conf /etc/nginx/conf.d/default.conf

View File

@@ -4,6 +4,10 @@ server {
root /usr/share/nginx/html; root /usr/share/nginx/html;
index index.html; index index.html;
# Docker DNS resolver für dynamische Service-Auflösung
resolver 127.0.0.11 valid=30s;
resolver_timeout 5s;
# Gzip compression # Gzip compression
gzip on; gzip on;
gzip_vary on; gzip_vary on;
@@ -12,7 +16,8 @@ server {
# API proxy (wird im Docker-Compose-Netzwerk aufgelöst) # API proxy (wird im Docker-Compose-Netzwerk aufgelöst)
location /api/ { location /api/ {
proxy_pass http://api:8000/; set $upstream_api api:8000;
proxy_pass http://$upstream_api/;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade'; proxy_set_header Connection 'upgrade';

View File

@@ -1,7 +1,7 @@
{ {
"name": "wetterstation-frontend", "name": "wetterstation-frontend",
"private": true, "private": true,
"version": "1.0.0", "version": "1.1.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -1,6 +1,6 @@
.dashboard { .dashboard {
width: 100%; width: 100%;
max-width: 795px; max-width: 1900px;
margin: 0 auto; margin: 0 auto;
} }
@@ -65,3 +65,83 @@
color: #666; color: #666;
font-weight: 500; font-weight: 500;
} }
.dashboard-footer {
/* margin-top: 2rem;
*/ padding-top: 1rem;
}
.footer-divider {
border: none;
border-top: 1px solid #ccc;
margin: 0 0 1rem 0;
}
.footer-credits {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.85rem;
color: #666;
margin-bottom: 0.75rem;
}
.footer-left {
text-align: left;
}
.footer-right {
text-align: right;
}
.footer-sponsor {
text-align: center;
font-size: 0.85rem;
color: #666;
}
.footer-sponsor a {
color: #0066cc;
text-decoration: none;
}
.footer-sponsor a:hover {
text-decoration: underline;
}
.version-line {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
}
.version-short {
display: none;
}
.version-full {
display: inline;
}
/* Responsive Design für schmale Bildschirme (Smartphones) */
@media (max-width: 768px) {
.charts-grid {
grid-template-columns: 1fr;
}
.current-values {
grid-template-columns: repeat(2, 1fr);
}
.dashboard {
padding: 0 0.5rem;
}
.version-short {
display: inline;
}
.version-full {
display: none;
}
}

View File

@@ -4,7 +4,9 @@ import HighchartsReact from 'highcharts-react-official'
import { format } from 'date-fns' import { format } from 'date-fns'
import { de } from 'date-fns/locale' import { de } from 'date-fns/locale'
import './WeatherDashboard.css' import './WeatherDashboard.css'
// Build-Informationen (werden beim Build eingef\u00fcgt)
const buildDate = __BUILD_DATE__
const version = __VERSION__
// Deutsche Lokalisierung für Highcharts // Deutsche Lokalisierung für Highcharts
Highcharts.setOptions({ Highcharts.setOptions({
lang: { lang: {
@@ -426,6 +428,30 @@ const WeatherDashboard = ({ data }) => {
</div> </div>
</div> </div>
{/* Footer */}
<div className="dashboard-footer">
<div className="version-line">
<div><a href="mailto:rxf@gmx.de">
mailto:rxf@gmx.de
</a>
</div>
<div>
<span className="version-full">Version</span>
<span className="version-short">V</span>
{' '}{version} {buildDate}
</div>
</div>
<hr />
<div className="footer-credits">
<div className="footer-left">Daten-Erfassung mit einer Davis VantagePro.</div>
<div className="footer-right">Grafiken erzeugt mit HighCharts</div>
</div>
<div className="footer-sponsor">
Die Wetterstation wurde vom Zeitungsverlag Waiblingen <a href="https://www.zvw.de" target="_blank" rel="noopener noreferrer">www.zvw.de</a> gestiftet.
</div>
</div>
</div> </div>
) )
} }

View File

@@ -3,8 +3,10 @@ import react from '@vitejs/plugin-react'
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
base: './', base: './', define: {
server: { __BUILD_DATE__: JSON.stringify(process.env.VITE_BUILD_DATE || 'dev'),
__VERSION__: JSON.stringify(process.env.VITE_VERSION || '0.0.0')
}, server: {
host: '0.0.0.0', host: '0.0.0.0',
port: 3000, port: 3000,
proxy: { proxy: {

View File

@@ -1,24 +1,38 @@
#!/bin/bash #!/bin/bash
# Script zum Bauen und Pushen der Docker Images zur Registry # Script zum Bauen und Pushen der Docker Images zur Registry (Multi-Plattform)
set -e set -e
REGISTRY="docker.citysensor.de" REGISTRY="docker.citysensor.de"
PROJECT="wetterstation" PROJECT="wetterstation"
PLATFORMS="linux/amd64,linux/arm64"
echo "🔨 Building Docker images..." echo "🔧 Setting up buildx builder..."
docker compose build collector # Erstelle oder verwende existierenden Builder
docker compose build api docker buildx create --name multiplatform --use 2>/dev/null || docker buildx use multiplatform
docker compose build frontend
echo "" echo ""
echo "📤 Pushing images to ${REGISTRY}..." echo "🔨 Building and pushing Docker images for ${PLATFORMS}..."
docker compose push collector
docker compose push api # Baue und pushe alle Images mit buildx
docker compose push frontend docker buildx build --platform ${PLATFORMS} \
-t ${REGISTRY}/${PROJECT}/collector:latest \
--push \
./collector
docker buildx build --platform ${PLATFORMS} \
-t ${REGISTRY}/${PROJECT}/api:latest \
--push \
./api
docker buildx build --platform ${PLATFORMS} \
-t ${REGISTRY}/${PROJECT}/frontend:latest \
--push \
./frontend
echo "" echo ""
echo "✅ Done! Images successfully pushed to ${REGISTRY}" echo "✅ Done! Multi-platform images successfully pushed to ${REGISTRY}"
echo " Platforms: ${PLATFORMS}"
echo "" echo ""
echo "To pull and run on another machine:" echo "To pull and run on another machine:"
echo " docker compose pull" echo " docker compose pull"