chore: package de deploiement prod (Dockerfile, compose, backup/restore, guide)
- Dockerfile multi-stage (build Astro -> runtime node standalone) - docker-compose.prod.yml : Astro builde, ports bindes 127.0.0.1, secrets requis - .env.prod.example : template de prod avec generation des secrets - scripts/backup.sh + restore.sh : migration base Directus + photos - DEPLOY.md : guide pas a pas - .dockerignore : exclusion du .env (anti-fuite de secrets) - untrack du tool-log BYAN (churn) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bff653acd6
commit
b0030246e4
9 changed files with 454 additions and 0 deletions
|
|
@ -1,6 +1,10 @@
|
|||
node_modules
|
||||
dist
|
||||
.astro
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
.byan-strict
|
||||
.git
|
||||
.github
|
||||
.claude
|
||||
|
|
|
|||
31
.env.prod.example
Normal file
31
.env.prod.example
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# ============================================================
|
||||
# Variables de PRODUCTION — a copier en `.env` SUR LE SERVEUR
|
||||
# cp .env.prod.example .env puis remplir chaque valeur
|
||||
# Ne JAMAIS commiter le .env rempli (il est gitignore).
|
||||
# ============================================================
|
||||
|
||||
# --- Domaine public ---
|
||||
# L'URL finale du site (avec https). Sert au SSR + au CORS Directus.
|
||||
PUBLIC_SITE_URL=https://mostuki.fr
|
||||
# URL publique de Directus (sous-domaine admin, derriere ton reverse-proxy).
|
||||
DIRECTUS_PUBLIC_URL=https://admin.mostuki.fr
|
||||
|
||||
# --- Secrets Directus (GENERER des valeurs aleatoires) ---
|
||||
# Genere chacune avec : openssl rand -hex 32
|
||||
DIRECTUS_KEY=
|
||||
DIRECTUS_SECRET=
|
||||
|
||||
# --- Compte admin Directus ---
|
||||
# NE PAS reutiliser changeme-please. Mot de passe long et unique.
|
||||
DIRECTUS_ADMIN_EMAIL=corentin.jog@gmail.com
|
||||
DIRECTUS_ADMIN_PASSWORD=
|
||||
|
||||
# --- Token statique d'API Directus (lecture des contenus par Astro) ---
|
||||
# A generer APRES le premier demarrage (voir DEPLOY.md, etape 5).
|
||||
DIRECTUS_TOKEN=
|
||||
|
||||
# --- Postgres ---
|
||||
POSTGRES_USER=directus
|
||||
# Mot de passe DB long et unique : openssl rand -hex 24
|
||||
POSTGRES_PASSWORD=
|
||||
POSTGRES_DB=directus
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -5,9 +5,13 @@ dist
|
|||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.prod.example
|
||||
# Docker volumes
|
||||
postgres_data/
|
||||
directus_uploads/
|
||||
directus_extensions/
|
||||
# BYAN strict-mode local state
|
||||
.byan-strict/
|
||||
|
||||
# BYAN tool log (churn)
|
||||
_byan-output/tool-log.jsonl
|
||||
|
|
|
|||
164
DEPLOY.md
Normal file
164
DEPLOY.md
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# Deploiement Mostuki Photo — guide pas a pas
|
||||
|
||||
Ce guide part du principe que tu as deja un serveur avec Docker + un
|
||||
reverse-proxy (Traefik/nginx) qui gere le TLS et route ton domaine.
|
||||
|
||||
Le principe a retenir : **git porte le code, pas les donnees.** Tes textes,
|
||||
tes series et tes photos vivent dans la base Directus + le volume uploads. Il
|
||||
faut donc les EXPORTER de ta machine et les RESTAURER sur le serveur.
|
||||
|
||||
---
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
```
|
||||
[Ta machine] [Serveur]
|
||||
1. backup.sh --> db.sql.gz --scp--> 6. restore.sh
|
||||
--> uploads.tar.gz |
|
||||
2. git clone
|
||||
3. .env de prod
|
||||
4. up -d --build
|
||||
5. token Directus
|
||||
7. reverse-proxy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ETAPE 1 — Exporter ton contenu (sur TA machine)
|
||||
|
||||
La stack locale doit tourner (Postgres + Directus up).
|
||||
|
||||
```bash
|
||||
cd ~/Documents/03_Dev/site-photo
|
||||
bash scripts/backup.sh
|
||||
```
|
||||
|
||||
Ca cree `backups/db-<date>.sql.gz` et `backups/uploads-<date>.tar.gz`.
|
||||
Note bien la valeur de `DIRECTUS_TOKEN` de ton `.env` local : tu en auras
|
||||
besoin a l'etape 3 (le token est stocke dans la base, il doit correspondre).
|
||||
|
||||
---
|
||||
|
||||
## ETAPE 2 — Recuperer le code (sur le SERVEUR)
|
||||
|
||||
```bash
|
||||
git clone https://git.acadenice.com/Corentin/site-mariage.git mostuki
|
||||
cd mostuki
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ETAPE 3 — Configurer les secrets de prod (sur le SERVEUR)
|
||||
|
||||
```bash
|
||||
cp .env.prod.example .env
|
||||
```
|
||||
|
||||
Edite `.env` et remplis chaque valeur :
|
||||
|
||||
```bash
|
||||
# Genere les 3 secrets aleatoires :
|
||||
openssl rand -hex 32 # -> DIRECTUS_KEY
|
||||
openssl rand -hex 32 # -> DIRECTUS_SECRET
|
||||
openssl rand -hex 24 # -> POSTGRES_PASSWORD
|
||||
```
|
||||
|
||||
- `PUBLIC_SITE_URL` / `DIRECTUS_PUBLIC_URL` : tes vrais domaines (https).
|
||||
- `DIRECTUS_TOKEN` : **la meme valeur que ton `.env` local** (etape 1).
|
||||
- `DIRECTUS_ADMIN_PASSWORD` : un mot de passe fort (sert si la base demarre
|
||||
vide ; sera ecrase par l'admin restaure a l'etape 6 — voir la note).
|
||||
|
||||
---
|
||||
|
||||
## ETAPE 4 — Demarrer la stack (sur le SERVEUR)
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
Le `--build` compile l'image Astro de prod. Verifie que les 3 conteneurs
|
||||
tournent : `docker compose -f docker-compose.prod.yml ps`.
|
||||
|
||||
A ce stade la base est VIDE (branding "Laurel & Vow" par defaut). On la
|
||||
remplace avec ton contenu a l'etape 6.
|
||||
|
||||
---
|
||||
|
||||
## ETAPE 5 — Transferer les backups (depuis TA machine)
|
||||
|
||||
```bash
|
||||
scp backups/db-*.sql.gz backups/uploads-*.tar.gz user@serveur:~/mostuki/backups/
|
||||
```
|
||||
|
||||
(cree le dossier `backups/` sur le serveur s'il n'existe pas)
|
||||
|
||||
---
|
||||
|
||||
## ETAPE 6 — Restaurer ton contenu (sur le SERVEUR)
|
||||
|
||||
```bash
|
||||
bash scripts/restore.sh backups/db-<date>.sql.gz backups/uploads-<date>.tar.gz
|
||||
docker compose -f docker-compose.prod.yml restart directus astro
|
||||
```
|
||||
|
||||
> **IMPORTANT securite.** La base restauree contient ton compte admin LOCAL,
|
||||
> avec son ancien mot de passe (`changeme-please`). Connecte-toi tout de suite
|
||||
> sur Directus admin et change le mot de passe + l'email :
|
||||
> Settings -> Users -> ton compte -> nouveau mot de passe.
|
||||
|
||||
---
|
||||
|
||||
## ETAPE 7 — Brancher le reverse-proxy (sur le SERVEUR)
|
||||
|
||||
Les services ecoutent en local uniquement :
|
||||
- Site Astro -> `127.0.0.1:4321`
|
||||
- Directus -> `127.0.0.1:8055`
|
||||
|
||||
Configure ton reverse-proxy pour router :
|
||||
- `PUBLIC_SITE_URL` (ex: mostuki.fr) -> `127.0.0.1:4321`
|
||||
- `DIRECTUS_PUBLIC_URL` (ex: admin.mostuki.fr) -> `127.0.0.1:8055`
|
||||
|
||||
Avec TLS (Let's Encrypt) sur les deux.
|
||||
|
||||
---
|
||||
|
||||
## ETAPE 8 — Verifications finales
|
||||
|
||||
- [ ] La home affiche bien "Mostuki" (pas "Laurel & Vow") -> sinon la restore
|
||||
DB n'a pas pris, relance l'etape 6.
|
||||
- [ ] Les photos des series s'affichent (proxy `/api/files/...` OK).
|
||||
- [ ] Le formulaire `/contact` enregistre bien (verifie dans Directus admin,
|
||||
collection `contact_requests`).
|
||||
- [ ] Mot de passe admin Directus change (etape 6).
|
||||
- [ ] Port 8055 NON accessible publiquement (seulement via ton sous-domaine
|
||||
admin derriere le proxy).
|
||||
|
||||
---
|
||||
|
||||
## Mises a jour ulterieures (code uniquement)
|
||||
|
||||
```bash
|
||||
cd ~/mostuki
|
||||
git pull
|
||||
docker compose -f docker-compose.prod.yml up -d --build
|
||||
```
|
||||
|
||||
La base et les photos ne sont pas touchees (volumes persistants).
|
||||
|
||||
---
|
||||
|
||||
## Sauvegardes regulieres
|
||||
|
||||
Relance `bash scripts/backup.sh` periodiquement (sur le serveur, en adaptant
|
||||
`PG_CONTAINER=mostuki-postgres DIRECTUS_CONTAINER=mostuki-directus`) et copie
|
||||
les archives ailleurs. C'est ton seul filet en cas de perte du serveur.
|
||||
|
||||
---
|
||||
|
||||
## Note : email du formulaire de contact
|
||||
|
||||
A ce jour, une demande de contact est STOCKEE dans Directus mais n'envoie
|
||||
AUCUN email de notification (TODO dans `src/pages/api/contact.ts`). Pense a
|
||||
checker la collection `contact_requests` regulierement, ou demande l'ajout de
|
||||
la notif email (provider a choisir : Resend recommande) avant la mise en ligne.
|
||||
```
|
||||
37
Dockerfile
Normal file
37
Dockerfile
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Build de production Astro SSR (adapter node standalone).
|
||||
# Multi-stage : on compile dans une image lourde, on ne garde que le runtime.
|
||||
|
||||
# ---- Stage 1 : build ----
|
||||
FROM node:22-alpine AS build
|
||||
WORKDIR /app
|
||||
|
||||
# Dependances (cache : ne se reinstalle que si package*.json change)
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm ci
|
||||
|
||||
# Source + build
|
||||
COPY astro.config.mjs ./
|
||||
COPY tsconfig.json* ./
|
||||
COPY src ./src
|
||||
COPY public ./public
|
||||
RUN npm run build
|
||||
|
||||
# ---- Stage 2 : runtime ----
|
||||
FROM node:22-alpine AS runtime
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
# Le serveur standalone @astrojs/node lit HOST et PORT
|
||||
ENV HOST=0.0.0.0
|
||||
ENV PORT=4321
|
||||
|
||||
# Toutes les deps du projet sont des "dependencies" (pas de devDependencies),
|
||||
# le runtime SSR en a besoin (@astrojs/node, @directus/sdk).
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm ci --omit=dev && npm cache clean --force
|
||||
|
||||
# Artefact compile uniquement
|
||||
COPY --from=build /app/dist ./dist
|
||||
|
||||
EXPOSE 4321
|
||||
CMD ["node", "./dist/server/entry.mjs"]
|
||||
|
|
@ -821,3 +821,53 @@
|
|||
{"timestamp":"2026-06-15T08:30:04.097Z","phase":"pre","tool":"Edit","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/.gitignore","est_input_tokens":81}
|
||||
{"timestamp":"2026-06-15T08:30:04.145Z","phase":"post","tool":"Edit","ok":true,"failure_kind":null,"est_output_tokens":175}
|
||||
{"timestamp":"2026-06-15T08:30:15.998Z","phase":"pre","tool":"Bash","summary":"Init git, stage, audit for secrets before commit","est_input_tokens":217}
|
||||
{"timestamp":"2026-06-15T08:30:16.597Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":224}
|
||||
{"timestamp":"2026-06-15T08:30:37.390Z","phase":"pre","tool":"Bash","summary":"Commit and add remote","est_input_tokens":107}
|
||||
{"timestamp":"2026-06-15T08:30:37.547Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":66}
|
||||
{"timestamp":"2026-06-15T08:30:40.622Z","phase":"pre","tool":"Bash","summary":"Push main to origin","est_input_tokens":40}
|
||||
{"timestamp":"2026-06-15T08:30:42.728Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":70}
|
||||
{"timestamp":"2026-06-15T08:53:57.991Z","phase":"pre","tool":"Bash","summary":"Check seed default content values","est_input_tokens":78}
|
||||
{"timestamp":"2026-06-15T08:54:00.790Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":212}
|
||||
{"timestamp":"2026-06-15T08:55:31.468Z","phase":"pre","tool":"Bash","summary":"Check runtime env reading pattern","est_input_tokens":140}
|
||||
{"timestamp":"2026-06-15T08:55:31.536Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":265}
|
||||
{"timestamp":"2026-06-15T08:55:43.735Z","phase":"pre","tool":"Bash","summary":"Check dockerignore","est_input_tokens":84}
|
||||
{"timestamp":"2026-06-15T08:55:43.798Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":83}
|
||||
{"timestamp":"2026-06-15T08:56:24.959Z","phase":"pre","tool":"Read","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/.dockerignore","est_input_tokens":20}
|
||||
{"timestamp":"2026-06-15T08:56:24.995Z","phase":"post","tool":"Read","ok":true,"failure_kind":null,"est_output_tokens":76}
|
||||
{"timestamp":"2026-06-15T08:56:28.421Z","phase":"pre","tool":"Edit","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/.dockerignore","est_input_tokens":60}
|
||||
{"timestamp":"2026-06-15T08:56:28.462Z","phase":"post","tool":"Edit","ok":true,"failure_kind":null,"est_output_tokens":155}
|
||||
{"timestamp":"2026-06-15T08:56:39.102Z","phase":"pre","tool":"Write","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/Dockerfile","est_input_tokens":279}
|
||||
{"timestamp":"2026-06-15T08:56:39.148Z","phase":"post","tool":"Write","ok":true,"failure_kind":null,"est_output_tokens":298}
|
||||
{"timestamp":"2026-06-15T08:56:58.736Z","phase":"pre","tool":"Write","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/docker-compose.prod.yml","est_input_tokens":722}
|
||||
{"timestamp":"2026-06-15T08:56:58.786Z","phase":"post","tool":"Write","ok":true,"failure_kind":null,"est_output_tokens":741}
|
||||
{"timestamp":"2026-06-15T08:57:10.618Z","phase":"pre","tool":"Write","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/.env.prod.example","est_input_tokens":321}
|
||||
{"timestamp":"2026-06-15T08:57:10.657Z","phase":"post","tool":"Write","ok":true,"failure_kind":null,"est_output_tokens":341}
|
||||
{"timestamp":"2026-06-15T08:57:24.754Z","phase":"pre","tool":"Write","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/scripts/backup.sh","est_input_tokens":430}
|
||||
{"timestamp":"2026-06-15T08:57:24.804Z","phase":"post","tool":"Write","ok":true,"failure_kind":null,"est_output_tokens":449}
|
||||
{"timestamp":"2026-06-15T08:57:38.885Z","phase":"pre","tool":"Write","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/scripts/restore.sh","est_input_tokens":510}
|
||||
{"timestamp":"2026-06-15T08:57:38.924Z","phase":"post","tool":"Write","ok":true,"failure_kind":null,"est_output_tokens":529}
|
||||
{"timestamp":"2026-06-15T08:57:46.216Z","phase":"pre","tool":"Bash","summary":"chmod scripts and check docker","est_input_tokens":79}
|
||||
{"timestamp":"2026-06-15T08:57:46.577Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":30}
|
||||
{"timestamp":"2026-06-15T08:57:51.096Z","phase":"pre","tool":"Bash","summary":"Check docker daemon / colima","est_input_tokens":65}
|
||||
{"timestamp":"2026-06-15T08:57:52.126Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":49}
|
||||
{"timestamp":"2026-06-15T08:58:11.383Z","phase":"pre","tool":"Bash","summary":"Validate scripts and compose coherence offline","est_input_tokens":232}
|
||||
{"timestamp":"2026-06-15T08:58:11.551Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":234}
|
||||
{"timestamp":"2026-06-15T08:58:28.296Z","phase":"pre","tool":"Read","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/scripts/restore.sh","est_input_tokens":27}
|
||||
{"timestamp":"2026-06-15T08:58:28.337Z","phase":"post","tool":"Read","ok":true,"failure_kind":null,"est_output_tokens":152}
|
||||
{"timestamp":"2026-06-15T08:58:36.252Z","phase":"pre","tool":"Read","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/scripts/restore.sh","est_input_tokens":27}
|
||||
{"timestamp":"2026-06-15T08:58:36.294Z","phase":"post","tool":"Read","ok":true,"failure_kind":null,"est_output_tokens":169}
|
||||
{"timestamp":"2026-06-15T08:58:46.411Z","phase":"pre","tool":"Bash","summary":"Count quotes in restore.sh","est_input_tokens":104}
|
||||
{"timestamp":"2026-06-15T08:58:46.471Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":162}
|
||||
{"timestamp":"2026-06-15T08:59:07.897Z","phase":"pre","tool":"Bash","summary":"Re-run bash -n on restore.sh","est_input_tokens":62}
|
||||
{"timestamp":"2026-06-15T08:59:07.952Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":73}
|
||||
{"timestamp":"2026-06-15T08:59:19.835Z","phase":"pre","tool":"Edit","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/scripts/restore.sh","est_input_tokens":80}
|
||||
{"timestamp":"2026-06-15T08:59:19.876Z","phase":"post","tool":"Edit","ok":true,"failure_kind":null,"est_output_tokens":685}
|
||||
{"timestamp":"2026-06-15T08:59:23.527Z","phase":"pre","tool":"Bash","summary":"Re-validate both scripts","est_input_tokens":59}
|
||||
{"timestamp":"2026-06-15T08:59:23.586Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":29}
|
||||
{"timestamp":"2026-06-15T09:00:14.377Z","phase":"pre","tool":"Write","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/DEPLOY.md","est_input_tokens":1274}
|
||||
{"timestamp":"2026-06-15T09:00:14.431Z","phase":"post","tool":"Write","ok":true,"failure_kind":null,"est_output_tokens":1294}
|
||||
{"timestamp":"2026-06-15T09:00:22.323Z","phase":"pre","tool":"Bash","summary":"Stage and show changes","est_input_tokens":47}
|
||||
{"timestamp":"2026-06-15T09:00:22.425Z","phase":"post","tool":"Bash","ok":true,"failure_kind":null,"est_output_tokens":69}
|
||||
{"timestamp":"2026-06-15T09:00:34.099Z","phase":"pre","tool":"Edit","summary":"/Users/corentinjoguet/Documents/03_Dev/site-photo/.gitignore","est_input_tokens":51}
|
||||
{"timestamp":"2026-06-15T09:00:34.137Z","phase":"post","tool":"Edit","ok":true,"failure_kind":null,"est_output_tokens":157}
|
||||
{"timestamp":"2026-06-15T09:00:43.652Z","phase":"pre","tool":"Bash","summary":"Fix tracking, verify env template included","est_input_tokens":147}
|
||||
|
|
|
|||
79
docker-compose.prod.yml
Normal file
79
docker-compose.prod.yml
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# Stack de PRODUCTION Mostuki Photo.
|
||||
#
|
||||
# Difference avec docker-compose.yml (dev) :
|
||||
# - Astro est BUILDE (Dockerfile multi-stage) au lieu de tourner en mode dev
|
||||
# - les ports sont bindes sur 127.0.0.1 : seul le reverse-proxy de l'hote y accede,
|
||||
# rien n'est expose directement sur internet
|
||||
# - aucun secret n'a de valeur par defaut : les vars DOIVENT etre fournies (.env)
|
||||
#
|
||||
# Lancement : docker compose -f docker-compose.prod.yml up -d --build
|
||||
# Le reverse-proxy de l'hote (Traefik/nginx) route ton domaine vers 127.0.0.1:4321
|
||||
# (site) et un sous-domaine admin vers 127.0.0.1:8055 (Directus) si besoin.
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: mostuki-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:?POSTGRES_USER requis}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD requis}
|
||||
POSTGRES_DB: ${POSTGRES_DB:?POSTGRES_DB requis}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
directus:
|
||||
image: directus/directus:11
|
||||
container_name: mostuki-directus
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "127.0.0.1:8055:8055"
|
||||
volumes:
|
||||
- directus_uploads:/directus/uploads
|
||||
- directus_extensions:/directus/extensions
|
||||
environment:
|
||||
KEY: ${DIRECTUS_KEY:?DIRECTUS_KEY requis}
|
||||
SECRET: ${DIRECTUS_SECRET:?DIRECTUS_SECRET requis}
|
||||
ADMIN_EMAIL: ${DIRECTUS_ADMIN_EMAIL:?DIRECTUS_ADMIN_EMAIL requis}
|
||||
ADMIN_PASSWORD: ${DIRECTUS_ADMIN_PASSWORD:?DIRECTUS_ADMIN_PASSWORD requis}
|
||||
DB_CLIENT: "pg"
|
||||
DB_HOST: "postgres"
|
||||
DB_PORT: "5432"
|
||||
DB_DATABASE: ${POSTGRES_DB}
|
||||
DB_USER: ${POSTGRES_USER}
|
||||
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
CACHE_ENABLED: "false"
|
||||
WEBSOCKETS_ENABLED: "true"
|
||||
PUBLIC_URL: ${DIRECTUS_PUBLIC_URL:?DIRECTUS_PUBLIC_URL requis}
|
||||
CORS_ENABLED: "true"
|
||||
CORS_ORIGIN: ${PUBLIC_SITE_URL:?PUBLIC_SITE_URL requis}
|
||||
|
||||
astro:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: mostuki-astro
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- directus
|
||||
ports:
|
||||
- "127.0.0.1:4321:4321"
|
||||
environment:
|
||||
ASTRO_TELEMETRY_DISABLED: "1"
|
||||
# Astro parle a Directus par le reseau interne Docker (pas par le domaine public)
|
||||
DIRECTUS_URL: "http://directus:8055"
|
||||
DIRECTUS_TOKEN: ${DIRECTUS_TOKEN:?DIRECTUS_TOKEN requis}
|
||||
PUBLIC_SITE_URL: ${PUBLIC_SITE_URL}
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
directus_uploads:
|
||||
directus_extensions:
|
||||
41
scripts/backup.sh
Executable file
41
scripts/backup.sh
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# backup.sh — emporte TON CONTENU (base Directus + photos)
|
||||
#
|
||||
# A lancer la ou la stack tourne deja (ta machine locale).
|
||||
# Produit dans ./backups/ :
|
||||
# - db-<date>.sql.gz : dump complet Postgres (textes, series, contacts)
|
||||
# - uploads-<date>.tar.gz : toutes les photos uploadees dans Directus
|
||||
#
|
||||
# Usage : bash scripts/backup.sh
|
||||
# Conteneurs (override si besoin) :
|
||||
# PG_CONTAINER=... DIRECTUS_CONTAINER=... bash scripts/backup.sh
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
# Charge .env pour POSTGRES_USER / POSTGRES_DB
|
||||
if [ -f .env ]; then set -a; . ./.env; set +a; fi
|
||||
|
||||
PG_CONTAINER="${PG_CONTAINER:-laurel-vow-postgres}"
|
||||
DIRECTUS_CONTAINER="${DIRECTUS_CONTAINER:-laurel-vow-directus}"
|
||||
PG_USER="${POSTGRES_USER:-directus}"
|
||||
PG_DB="${POSTGRES_DB:-directus}"
|
||||
|
||||
STAMP="$(date +%Y%m%d-%H%M%S)"
|
||||
OUT="backups"
|
||||
mkdir -p "$OUT"
|
||||
|
||||
echo "==> Dump base Postgres ($PG_CONTAINER / db=$PG_DB)"
|
||||
docker exec "$PG_CONTAINER" pg_dump -U "$PG_USER" "$PG_DB" | gzip > "$OUT/db-$STAMP.sql.gz"
|
||||
|
||||
echo "==> Archive des photos (uploads Directus)"
|
||||
# /directus/uploads est le chemin des fichiers dans le conteneur Directus
|
||||
docker exec "$DIRECTUS_CONTAINER" tar czf - -C /directus/uploads . > "$OUT/uploads-$STAMP.tar.gz"
|
||||
|
||||
echo ""
|
||||
echo "OK. Fichiers crees :"
|
||||
ls -lh "$OUT/db-$STAMP.sql.gz" "$OUT/uploads-$STAMP.tar.gz"
|
||||
echo ""
|
||||
echo "Transfere ces 2 fichiers sur le serveur, puis lance scripts/restore.sh la-bas."
|
||||
44
scripts/restore.sh
Executable file
44
scripts/restore.sh
Executable file
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# restore.sh — restaure TON CONTENU sur le serveur de prod
|
||||
#
|
||||
# A lancer SUR LE SERVEUR, apres avoir demarre la stack prod
|
||||
# (docker compose -f docker-compose.prod.yml up -d) et transfere
|
||||
# les 2 fichiers de backup dans ./backups/.
|
||||
#
|
||||
# Usage :
|
||||
# bash scripts/restore.sh backups/db-XXXX.sql.gz backups/uploads-XXXX.tar.gz
|
||||
#
|
||||
# Conteneurs prod (override si besoin) :
|
||||
# PG_CONTAINER=... DIRECTUS_CONTAINER=... bash scripts/restore.sh ...
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
DB_DUMP="${1:?Chemin du dump DB requis (ex: backups/db-XXXX.sql.gz)}"
|
||||
UPLOADS_TAR="${2:?Chemin de l archive uploads requis (ex: backups/uploads-XXXX.tar.gz)}"
|
||||
|
||||
if [ -f .env ]; then set -a; . ./.env; set +a; fi
|
||||
|
||||
PG_CONTAINER="${PG_CONTAINER:-mostuki-postgres}"
|
||||
DIRECTUS_CONTAINER="${DIRECTUS_CONTAINER:-mostuki-directus}"
|
||||
PG_USER="${POSTGRES_USER:-directus}"
|
||||
PG_DB="${POSTGRES_DB:-directus}"
|
||||
|
||||
echo "ATTENTION : ceci ECRASE la base '$PG_DB' et les photos du serveur."
|
||||
read -r -p "Continuer ? (tape oui) " ans
|
||||
[ "$ans" = "oui" ] || { echo "Annule."; exit 1; }
|
||||
|
||||
echo "==> Restauration base Postgres ($PG_CONTAINER)"
|
||||
# Recree un schema propre avant import pour eviter les doublons
|
||||
docker exec -i "$PG_CONTAINER" psql -U "$PG_USER" -d "$PG_DB" \
|
||||
-c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
|
||||
gunzip -c "$DB_DUMP" | docker exec -i "$PG_CONTAINER" psql -U "$PG_USER" -d "$PG_DB"
|
||||
|
||||
echo "==> Restauration des photos (uploads Directus)"
|
||||
docker exec -i "$DIRECTUS_CONTAINER" sh -c 'rm -rf /directus/uploads/* && tar xzf - -C /directus/uploads' < "$UPLOADS_TAR"
|
||||
|
||||
echo ""
|
||||
echo "OK. Redemarre Directus pour qu'il reprenne la base restauree :"
|
||||
echo " docker compose -f docker-compose.prod.yml restart directus astro"
|
||||
Loading…
Add table
Reference in a new issue