TMP-Hosting/deploy-techsolidaire.sh
2026-06-07 17:00:01 +02:00

293 lines
10 KiB
Bash

#!/usr/bin/env bash
#
# deploy-techsolidaire.sh
# --------------------------------------------------------------------------
# Déploie via Docker un site vitrine (fictif) pour une association
# communautaire d'entraide technologique : "TechSolidaire".
#
# Le site tient sur une seule page HTML (CSS intégré, aucun menu,
# aucun lien externe). Le script génère les fichiers, construit l'image
# Docker basée sur nginx, puis lance le conteneur.
#
# Usage :
# ./deploy-techsolidaire.sh # déploie sur le port 8080
# PORT=9000 ./deploy-techsolidaire.sh # déploie sur un autre port
# --------------------------------------------------------------------------
set -euo pipefail
# --- Paramètres configurables ---------------------------------------------
PROJECT_DIR="${PROJECT_DIR:-./techsolidaire-site}"
IMAGE_NAME="${IMAGE_NAME:-techsolidaire-vitrine}"
CONTAINER_NAME="${CONTAINER_NAME:-techsolidaire}"
PORT="${PORT:-8080}"
# --- Couleurs pour les messages --------------------------------------------
GREEN='\033[0;32m'; BLUE='\033[0;34m'; YELLOW='\033[1;33m'; NC='\033[0m'
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[ATTENTION]${NC} $*"; }
# --- Vérifications préalables -----------------------------------------------
if ! command -v docker >/dev/null 2>&1; then
echo "Docker n'est pas installé ou pas dans le PATH. Installe Docker d'abord." >&2
exit 1
fi
if ! docker info >/dev/null 2>&1; then
echo "Le démon Docker ne répond pas. Démarre Docker puis relance le script." >&2
exit 1
fi
# --- Préparation de l'arborescence ------------------------------------------
info "Préparation du dossier de projet : ${PROJECT_DIR}"
mkdir -p "${PROJECT_DIR}"
# --- Génération de la page web (une seule page, sans lien externe) ----------
info "Génération de la page web index.html"
cat > "${PROJECT_DIR}/index.html" << 'EOF'
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TechSolidaire — Entraide technologique</title>
<style>
:root {
--bg: #0f1b2d;
--bg-alt: #16263d;
--accent: #3ddc97;
--accent-soft: #2bb37c;
--text: #e7eef7;
--muted: #9fb2c8;
--card: #1b2c44;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.65;
}
.wrap { max-width: 980px; margin: 0 auto; padding: 0 24px; }
/* En-tête / hero */
header {
background: linear-gradient(160deg, var(--bg-alt), var(--bg));
padding: 90px 0 70px;
text-align: center;
border-bottom: 1px solid rgba(255,255,255,0.06);
}
.logo {
display: inline-flex; align-items: center; gap: 12px;
font-weight: 700; letter-spacing: 0.5px; margin-bottom: 28px;
}
.logo .dot {
width: 14px; height: 14px; border-radius: 50%;
background: var(--accent); box-shadow: 0 0 18px var(--accent);
}
header h1 {
font-size: clamp(2rem, 5vw, 3.2rem);
line-height: 1.15; margin-bottom: 18px;
}
header h1 span { color: var(--accent); }
header p {
max-width: 640px; margin: 0 auto;
color: var(--muted); font-size: 1.15rem;
}
.badge {
display: inline-block; margin-top: 30px; padding: 10px 22px;
border: 1px solid var(--accent-soft); border-radius: 999px;
color: var(--accent); font-size: 0.9rem; font-weight: 600;
}
/* Sections */
section { padding: 64px 0; }
section h2 {
font-size: 1.7rem; margin-bottom: 14px;
}
section h2::after {
content: ""; display: block; width: 54px; height: 3px;
background: var(--accent); margin-top: 10px; border-radius: 2px;
}
.lead { color: var(--muted); max-width: 720px; margin-bottom: 8px; }
.alt { background: var(--bg-alt); }
/* Chiffres / mobilisation */
.stats {
display: grid; grid-template-columns: repeat(auto-fit, minmax(160px,1fr));
gap: 20px; margin-top: 36px;
}
.stat {
background: var(--card); border-radius: 14px; padding: 26px 20px;
text-align: center; border: 1px solid rgba(255,255,255,0.05);
}
.stat .num { font-size: 2.1rem; font-weight: 700; color: var(--accent); }
.stat .lbl { color: var(--muted); font-size: 0.92rem; margin-top: 6px; }
/* Projets */
.projects {
display: grid; grid-template-columns: repeat(auto-fit, minmax(260px,1fr));
gap: 22px; margin-top: 36px;
}
.card {
background: var(--card); border-radius: 16px; padding: 28px;
border: 1px solid rgba(255,255,255,0.05);
transition: transform 0.15s ease, border-color 0.15s ease;
}
.card:hover { transform: translateY(-4px); border-color: var(--accent-soft); }
.card .tag {
display: inline-block; font-size: 0.75rem; font-weight: 700;
letter-spacing: 0.5px; text-transform: uppercase;
color: var(--accent); margin-bottom: 14px;
}
.card h3 { font-size: 1.2rem; margin-bottom: 10px; }
.card p { color: var(--muted); font-size: 0.97rem; }
footer {
background: var(--bg); border-top: 1px solid rgba(255,255,255,0.06);
padding: 40px 0; text-align: center; color: var(--muted);
font-size: 0.9rem;
}
</style>
</head>
<body>
<header>
<div class="wrap">
<div class="logo"><span class="dot"></span> TechSolidaire</div>
<h1>L'entraide <span>technologique</span><br>au service de tous</h1>
<p>
Une association communautaire qui démocratise l'accès au numérique :
partage de savoirs, réparation, et accompagnement, par et pour les habitants.
</p>
<div class="badge">Association à but non lucratif · Fictive</div>
</div>
</header>
<section>
<div class="wrap">
<h2>Notre activité</h2>
<p class="lead">
TechSolidaire réunit bénévoles, passionnés et curieux autour d'une idée
simple : la technologie ne doit laisser personne de côté. Nous animons
des ateliers ouverts à tous, accompagnons celles et ceux qui se sentent
démunis face aux outils numériques, et donnons une seconde vie au
matériel informatique plutôt que de le jeter.
</p>
<p class="lead">
Chaque rencontre repose sur l'échange : ici, on apprend en faisant, on
partage ce que l'on sait, et l'on construit ensemble des solutions
concrètes. L'entraide est notre seul mode d'emploi.
</p>
</div>
</section>
<section class="alt">
<div class="wrap">
<h2>Notre mobilisation</h2>
<p class="lead">
Portée par une équipe entièrement bénévole, notre association se mobilise
chaque semaine sur le terrain. Notre force, c'est le collectif.
</p>
<div class="stats">
<div class="stat"><div class="num">120+</div><div class="lbl">bénévoles actifs</div></div>
<div class="stat"><div class="num">48</div><div class="lbl">ateliers par an</div></div>
<div class="stat"><div class="num">900</div><div class="lbl">personnes accompagnées</div></div>
<div class="stat"><div class="num">350</div><div class="lbl">appareils reconditionnés</div></div>
</div>
</div>
</section>
<section>
<div class="wrap">
<h2>Quelques projets</h2>
<p class="lead">Un aperçu de ce que nous menons au quotidien.</p>
<div class="projects">
<div class="card">
<span class="tag">Réparation</span>
<h3>Repair Café numérique</h3>
<p>
Un rendez-vous mensuel pour diagnostiquer et réparer ensemble
ordinateurs, smartphones et petits appareils, plutôt que de les
remplacer.
</p>
</div>
<div class="card">
<span class="tag">Inclusion</span>
<h3>Le numérique pour tous</h3>
<p>
Des sessions d'initiation pour les seniors et les personnes éloignées
du numérique : démarches en ligne, messagerie, sécurité de base.
</p>
</div>
<div class="card">
<span class="tag">Réemploi</span>
<h3>Atelier reconditionnement</h3>
<p>
Nous collectons du matériel inutilisé, le remettons en état et le
redistribuons aux familles et aux associations qui en ont besoin.
</p>
</div>
<div class="card">
<span class="tag">Logiciel libre</span>
<h3>Cloud d'entraide</h3>
<p>
Un hébergement de services libres géré par la communauté, pour
partager fichiers et outils sans dépendre des grandes plateformes.
</p>
</div>
</div>
</div>
</section>
<footer>
<div class="wrap">
TechSolidaire — Association communautaire d'entraide technologique (site fictif).
</div>
</footer>
</body>
</html>
EOF
# --- Génération du Dockerfile -----------------------------------------------
info "Génération du Dockerfile"
cat > "${PROJECT_DIR}/Dockerfile" << 'EOF'
FROM nginx:alpine
# On retire la page par défaut puis on copie notre site
RUN rm -rf /usr/share/nginx/html/*
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
EOF
# --- Construction de l'image ------------------------------------------------
info "Construction de l'image Docker : ${IMAGE_NAME}"
docker build -t "${IMAGE_NAME}" "${PROJECT_DIR}"
# --- Nettoyage d'un éventuel conteneur existant -----------------------------
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
warn "Un conteneur '${CONTAINER_NAME}' existe déjà : suppression."
docker rm -f "${CONTAINER_NAME}" >/dev/null
fi
# --- Lancement du conteneur -------------------------------------------------
info "Démarrage du conteneur sur le port ${PORT}"
docker run -d \
--name "${CONTAINER_NAME}" \
-p "${PORT}:80" \
--restart unless-stopped \
"${IMAGE_NAME}" >/dev/null
ok "Site déployé !"
echo ""
echo " ➜ Accès local : http://localhost:${PORT}"
echo ""
echo "Commandes utiles :"
echo " docker logs ${CONTAINER_NAME} # voir les journaux"
echo " docker stop ${CONTAINER_NAME} # arrêter le site"
echo " docker start ${CONTAINER_NAME} # relancer le site"
echo " docker rm -f ${CONTAINER_NAME} # supprimer le conteneur"