From e36364b3d96202e6b7370c3daf63fe5af1b0e03a Mon Sep 17 00:00:00 2001 From: Nicola Date: Wed, 24 Jun 2026 13:08:41 +0200 Subject: [PATCH] Add Docker configuration and environment setup for Tennis Roots project --- .env.example | 23 ++++++++++++++++++++++ .gitignore | 1 + README.md | 48 +++++++++++++++++++++++++++++++++++++++++++++- docker-compose.yml | 27 ++++++++++++++++++++++++++ server/Dockerfile | 15 +++++++++++++++ 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 .env.example create mode 100644 docker-compose.yml create mode 100644 server/Dockerfile diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a4ebfbd --- /dev/null +++ b/.env.example @@ -0,0 +1,23 @@ +# Tennis Roots – Configurazione Docker +# Copia questo file in .env e personalizza i valori + +# Dominio pubblico per il servizio (obbligatorio) +DOMAIN=tennis.ricordatiilatte.it + +# Nome del container +CONTAINER_NAME=tennis-roots + +# Rete Traefik esterna +TRAEFIK_NETWORK=traefik-public + +# Certificato SSL +CERT_RESOLVER=letsencrypt + +# Entrypoint Traefik +ENTRYPOINT=https + +# Porta interna del server Express +INTERNAL_PORT=3000 + +# (Opzionale) Porta esterna per debug diretto senza Traefik +# HOST_PORT=3000 diff --git a/.gitignore b/.gitignore index 2c42d01..4450e8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules/ .env +!.env.example *.log .DS_Store Thumbs.db diff --git a/README.md b/README.md index 4ede3d0..1959360 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,49 @@ cd server npm run dev # node --watch ``` +## Deploy su VPS (Docker + Traefik) + +Il progetto include `Dockerfile` e `docker-compose.yml` pronti per il deploy +su un'infrastruttura con **Traefik** come reverse proxy. + +### Prerequisiti + +- Docker e Docker Compose installati +- Rete `traefik-public` già esistente (`docker network create traefik-public`) +- Dominio configurato (es. `tennis.ricordatiilatte.it`) + +### Procedura + +```bash +# Clona il progetto sulla VPS +git clone tennis-roots +cd tennis-roots + +# Avvia +docker compose up -d + +# Log +docker compose logs -f +``` + +### Accessi + +| Risorsa | URL | +|---------|-----| +| Controller | `https://tennis.ricordatiilatte.it/controller/` | +| Scoreboard | `https://tennis.ricordatiilatte.it/overlay/scoreboard.html` | +| Match Info | `https://tennis.ricordatiilatte.it/overlay/match-info.html` | +| Clock | `https://tennis.ricordatiilatte.it/overlay/clock.html` | +| Server Ind. | `https://tennis.ricordatiilatte.it/overlay/server-indicator.html` | +| API stato | `https://tennis.ricordatiilatte.it/api/state` | +| WebSocket | `wss://tennis.ricordatiilatte.it/ws` | + +### Note + +- Il server è stateless (stato in memoria). Un restart azzera il match. +- Il WebSocket funziona nativamente con Traefik (upgrade HTTP → WS automatico). +- Se vuoi un dominio diverso, cambia il valore di `Host(...)` in `docker-compose.yml`. + ## Regole punteggio implementate - Punti game: 0, 15, 30, 40, Deuce, Vantaggio @@ -156,6 +199,9 @@ tennis-roots/ │ └── server-indicator.html ├── controller/ │ └── index.html # Pannello di controllo -├── start.sh # Script avvio rapido +├── server/ +│ ├── Dockerfile # Immagine container +│ └── ... +├── docker-compose.yml # Deploy con Traefik └── README.md ``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0901b36 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +services: + tennis-roots: + build: + context: ./server + dockerfile: Dockerfile + container_name: ${CONTAINER_NAME:-tennis-roots} + restart: unless-stopped + security_opt: + - no-new-privileges:true + networks: + - ${TRAEFIK_NETWORK:-traefik-public} + labels: + - "traefik.enable=true" + - "traefik.docker.network=${TRAEFIK_NETWORK:-traefik-public}" + - "traefik.http.routers.tennis-roots.rule=Host(`${DOMAIN:-tennis.localhost}`)" + - "traefik.http.routers.tennis-roots.entrypoints=${ENTRYPOINT:-https}" + - "traefik.http.routers.tennis-roots.tls=true" + - "traefik.http.routers.tennis-roots.tls.certresolver=${CERT_RESOLVER:-letsencrypt}" + - "traefik.http.services.tennis-roots.loadbalancer.server.port=${INTERNAL_PORT:-3000}" + # Middleware per WebSocket (upgrade HTTP→WS) + - "traefik.http.routers.tennis-roots.middlewares=tennis-roots-headers" + - "traefik.http.middlewares.tennis-roots-headers.headers.customrequestheaders.X-Forwarded-Proto=https" + - "traefik.http.middlewares.tennis-roots-headers.headers.customresponseheaders.X-Robots-Tag=noindex" + +networks: + ${TRAEFIK_NETWORK:-traefik-public}: + external: true diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..2155046 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,15 @@ +# ---- Build ---- +FROM node:22-alpine AS builder +WORKDIR /app +COPY package.json package-lock.json ./ +RUN npm ci --omit=dev + +# ---- Run ---- +FROM node:22-alpine +WORKDIR /app +COPY --from=builder /app/node_modules ./node_modules +COPY index.js ./ + +EXPOSE 3000 +USER node +CMD ["node", "index.js"]