# App management - Lucien-sens-bon Ce document explique comment diagnostiquer les conteneurs, la base de donnees et le reverse proxy (Apache). ## 1) Diagnostic Docker Statut des services : ``` docker compose ps ``` Logs temps reel : ``` docker compose logs -f docker compose logs -f backend docker compose logs -f storefront ``` Redemarrer un service : ``` docker compose restart backend ``` Rebuild force d'un service : ``` docker compose build --no-cache backend docker compose up -d --build backend ``` Entrer dans un conteneur : ``` docker exec -it medusa-backend sh ``` ## 2) Verifier la connexion PostgreSQL La connexion est definie dans `.env` : ``` DATABASE_URL=postgres://user:password@host:5432/nom_db ``` ### 2.1 Tester depuis le serveur (si psql est installe) ``` psql "$DATABASE_URL" -c "select 1;" ``` ### 2.2 Tester depuis un conteneur temporaire ``` docker run --rm -it postgres:16-alpine psql "$DATABASE_URL" -c "select 1;" ``` ### 2.3 Tester le port (reseau) ``` nc -vz 5432 ``` Si la DB est sur la machine hote : - eviter `localhost` dans `DATABASE_URL` - utiliser l'IP de la machine hote Documentation PostgreSQL : https://www.postgresql.org/docs/current/app-psql.html https://www.postgresql.org/docs/current/app-pg-isready.html ## 3) Tests applicatifs rapides Storefront : ``` curl http://localhost:8000 ``` API Medusa : ``` curl http://localhost:9000/store/products ``` ## 3.1) Depannage avance: backend 9000 ne repond pas Cette section documente les commandes utilisees en incident et explique ce qu'elles permettent de verifier. ### A) Etre dans le bon dossier compose ``` cd /var/www/lucien-sens-bon ls -l docker-compose.yml ``` - `cd ...` : se place dans le dossier ou se trouve `docker-compose.yml`. - `ls -l docker-compose.yml` : confirme que le fichier compose existe (sinon `docker compose` renvoie "no configuration file provided"). ### B) Etat et logs du backend ``` sudo docker compose ps sudo docker compose logs -f backend ``` - `docker compose ps` : liste les conteneurs, leur statut et les ports publies. - `docker compose logs -f backend` : suit les logs du backend en temps reel pour identifier l'erreur exacte. ### C) Test HTTP local (depuis le serveur) ``` curl -v http://localhost:9000/store/products ``` - `curl -v` : verifie que l'API repond et montre les details de connexion. - Si "connection reset by peer" -> le backend crash apres accept. ### D) Verifier la base (depuis un conteneur temporaire) ``` sudo docker compose run --rm backend node -e "const { Client }=require('pg'); const c=new Client({connectionString: process.env.DATABASE_URL}); c.connect().then(()=>console.log('DB OK')).catch(e=>{console.error('DB ERROR:', e.message); process.exit(1)})" ``` - `docker compose run --rm backend` : lance un conteneur temporaire base sur l'image backend (meme environnement que le service). - `node -e ...` : teste la connexion a PostgreSQL via `DATABASE_URL`. ### E) Tester droits et extension PostgreSQL ``` sudo docker compose run --rm backend node -e "const {Client}=require('pg'); const c=new Client({connectionString: process.env.DATABASE_URL}); c.connect().then(async()=>{const p=await c.query(\"select has_database_privilege(current_user, current_database(), 'CREATE') as can_create\"); console.log(p.rows); try{await c.query('CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"'); console.log('EXT OK');}catch(e){console.error('EXT ERROR:', e.message);} await c.end();}).catch(e=>{console.error('DB ERROR:', e.message); process.exit(1);});" ``` - Verifie que l'utilisateur a le droit de creer dans la base. - Cree l'extension `uuid-ossp` si elle manque (souvent requise par Medusa). ### F) Migrations Medusa (creation des tables) ``` sudo docker compose run --rm backend npx medusa migrations run ``` - Applique les migrations en base. Sans ca, le backend peut echouer a demarrer. ### G) Seed de donnees (optionnel) ``` sudo docker compose run --rm backend npm run seed ``` - Ajoute des donnees de demo si un fichier seed existe. - Si le fichier `data/seed.json` manque, cette commande echoue sans impact sur le demarrage de l'API. ### H) Redemarrage et rebuild ``` sudo docker compose restart backend sudo docker compose up -d --build backend ``` - `restart` : redemarre seulement le backend. - `up -d --build` : reconstruit l'image puis redemarre le service. ### I) Cas erreur PaymentProviderService (crash apres init) ``` sudo docker compose run --rm backend node -e "const {Client}=require('pg'); const c=new Client({connectionString: process.env.DATABASE_URL}); c.connect().then(async()=>{const rows=await c.query('select * from payment_provider'); console.log(rows.rows); await c.end();}).catch(e=>{console.error('DB ERROR:', e.message); process.exit(1);});" ``` - Controle le contenu de `payment_provider` si le backend plante au demarrage dans le service des providers de paiement. ## 3.2) Procedure complete + explications (incident backend 9000) Objectif : demarrer le backend sans crash, appliquer les correctifs, puis verifier que l'API repond. ### A) Confirmer les symptomes ``` sudo docker compose ps sudo docker compose logs --tail=200 backend curl -v http://localhost:9000/store/products ``` - `ps` : confirme si le conteneur redemarre en boucle. - `logs` : montre l'erreur exacte (ex: TypeORM "Empty criteria"). - `curl -v` : valide la reponse HTTP (200 attendu). ### B) Comprendre la cause racine (pourquoi ca casse) Cause principale : - Dans certaines versions de Medusa, plusieurs services font `update({}, { is_installed: false })` sans criteres. - Avec la version de TypeORM utilisee, `update` refuse les criteres vides -> crash au demarrage. - Le code fautif est dans les fichiers compiles de `node_modules` (pas dans les sources du projet). Effet domino : - Chaque correctif debloque l'etape suivante du demarrage, revelant une autre erreur du meme type. ### C) Correctif technique (patch postinstall) Le projet applique un patch automatique dans l'image Docker via : - `backend/scripts/patch-medusa.js` (script) - `backend/package.json` -> `postinstall` - `backend/Dockerfile` -> `COPY scripts ./scripts` avant `npm install` Le patch remplace les `update({}, ...)` par un update explicite : `createQueryBuilder().update().set(...).where('1=1').execute()`. ### D) Forcer l'application du patch ``` cd /var/www/lucien-sens-bon sudo docker compose build --no-cache backend sudo docker compose up -d backend ``` - `--no-cache` : force `npm install` + `postinstall`, donc le patch. - `up -d` : redeploie le conteneur avec la nouvelle image. ### E) Verifier que le patch est bien applique ``` sudo docker compose run --rm backend sh -c "grep -n \"update({}, { is_installed: false })\" node_modules/@medusajs/medusa/dist/services/tax-provider.js || echo 'OK: patch present'" ``` - Si le grep ne trouve rien, la patch est presente. ### F) Validation finale ``` sudo docker compose logs --tail=200 backend curl -v http://localhost:9000/store/products ``` - Le log doit contenir `Server is ready on port: 9000`. - L'API doit repondre `200` avec JSON. ### G) Cas "Compiling Webpack" trop long Le plugin `@medusajs/admin` peut prendre du temps a compiler. Si blocage > 10 min, on peut le desactiver temporairement dans `backend/medusa-config.js` pour demarrer l'API, puis le reactiver. ## 3.3) Verifier que l'image est saine apres reboot Objectif : s'assurer que le redemarrage ne casse pas l'API. ### A) Redemarrer proprement ``` sudo docker compose restart backend ``` ### B) Verifier etats + port ``` sudo docker compose ps curl -v http://localhost:9000/store/products ``` - Le conteneur doit etre `Up` (pas `Restarting`). - L'API doit repondre en `200`. ### C) Verifier la patch dans l'image (controle rapide) ``` sudo docker compose run --rm backend sh -c "rg -n \"update\\(\\{\\}, \\{ is_installed: false \\}\\)\" node_modules/@medusajs/medusa/dist/services || echo 'OK: aucun update vide'" ``` - Si aucun match, les patchs sont bien en place. ### D) Conseils pour eviter les surprises - Toujours rebuild `--no-cache` apres modification du patch. - Ne pas editer `node_modules` a la main dans un conteneur running. - Garder `backend/scripts/patch-medusa.js` versionne. ## 3.4) Seed des produits + connexion storefront ### A) Seed (donnees demo) ``` sudo docker compose run --rm backend npm run seed ``` - Necessite `backend/data/seed.json`. - Sinon la commande echoue sans casser le backend. ### B) Verifier l'API apres seed ``` curl -v http://localhost:9000/store/products ``` ### C) Connecter la boutique (storefront) Verifier `NEXT_PUBLIC_MEDUSA_BACKEND_URL` dans `.env` : ``` NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://api.lsb.huitral.ruka.lan ``` Puis reconstruire le storefront : ``` sudo docker compose up -d --build storefront ``` Si on travaille en local (pas via Apache), utiliser l'URL directe : ``` NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://:9000 ``` ## 4) Apache / Reverse proxy Verifier les services Apache : ``` sudo systemctl status apache2 ``` Logs Apache : ``` sudo journalctl -u apache2 -f sudo tail -f /var/log/apache2/error.log sudo tail -f /var/log/apache2/access.log ``` Modules proxy : ``` sudo a2enmod proxy sudo a2enmod proxy_http ``` Reload Apache : ``` sudo systemctl reload apache2 ``` Documentation Apache reverse proxy : https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html ## 5) Ports a verifier - `8000` : storefront - `9000` : backend - `5432` : PostgreSQL - `6379` : Redis Verifier l'ouverture locale : ``` ss -lntp | egrep '8000|9000|5432|6379' ``` Verifier le firewall (UFW) : ``` sudo ufw status ``` ## 6) Git - Remise en ordre apres modifications locales Cette section documente les commandes utilisees pour remettre la branche locale en etat propre, definir le suivi distant, et pousser les changements. ### A) Retirer les fichiers sensibles ou locaux du commit ``` git reset HEAD .env output*.txt ``` - Retire `.env` et les fichiers `output*.txt` du staging. - Evite d'inclure des secrets ou des artefacts locaux dans le commit. ### B) Corriger les droits si `.git` est en lecture seule ``` sudo chown -R "$USER":"$USER" /var/www/lucien-sens-bon ``` - Redonne les droits d'ecriture a l'utilisateur courant sur le depot. - Corrige l'erreur `Permission denied` lors de la creation du commit. ### C) Committer en definissant l'identite temporairement ``` GIT_AUTHOR_NAME="toshiro" GIT_AUTHOR_EMAIL="toshiro@chillka" GIT_COMMITTER_NAME="toshiro" GIT_COMMITTER_EMAIL="toshiro@chillka" git commit -m "local changes on huitral" ``` - Injecte l'identite uniquement pour ce commit, sans modifier la configuration globale de git. - Permet de valider le commit quand `user.name`/`user.email` ne sont pas definis. ### D) Definir la branche distante suivie ``` git branch --set-upstream-to=origin/docs-git-dns ``` - Associe `docs-git-dns` a la branche distante pour autoriser `git pull`. ### E) Rebaser sur la remote puis pousser ``` git pull --rebase git push origin docs-git-dns ``` - `pull --rebase` aligne la branche locale sur la remote sans commit de merge. - `push` publie les commits locaux sur la remote. ### F) Recuperer le dernier code sur un serveur (alignement strict) ``` cd /var/www/lucien-sens-bon git fetch origin git checkout docs-git-dns git reset --hard origin/docs-git-dns ``` - S'assure d'etre a la racine du depot (pas dans `backend/`). - Aligne la branche locale strictement sur la remote (`origin/docs-git-dns`). - Ecrase les changements locaux sur cette branche. Verifier la presence d'un fichier sur la remote : ``` git ls-tree -r origin/docs-git-dns --name-only | grep "backend/scripts/patch-medusa.js" ``` - Confirme que le fichier existe bien sur la branche distante. Nettoyer les fichiers non suivis (optionnel) : ``` git clean -fd ``` - Supprime les fichiers/dossiers non suivis (ex: `output*.txt`, `uploads/`). ### G) Push refuse (non-fast-forward) + rebase avec identite temporaire Si `git push` refuse avec `non-fast-forward`, integrer la remote puis repousser. 1) Mettre de cote les fichiers locaux non committes : ``` git status git stash push -u -m "wip avant rebase" ``` 2) Rebaser avec identite temporaire (sans modifier la config git) : ``` git -c user.name="toshiro" -c user.email="toshiro@chillka" pull --rebase origin docs-git-dns ``` 3) Si un rebase est en cours et demande un commit : ``` git -c user.name="toshiro" -c user.email="toshiro@chillka" commit -m "local changes on huitral" git -c user.name="toshiro" -c user.email="toshiro@chillka" rebase --continue ``` 4) Pousser puis restaurer le stash : ``` git push origin docs-git-dns git stash pop ``` - Le rebase rejoue les commits locaux au-dessus de la remote. - L'option `-c user.name/user.email` injecte l'identite uniquement pour la commande. ### H) Ignorer les fichiers locaux (.env, output*.txt) Option 1 - Ignorer pour tout le depot (partage en equipe) : ``` # .gitignore (exemples) .env output*.txt ``` - Ajoute ces patterns au `.gitignore` si ces fichiers ne doivent jamais etre commits. - Utile pour les fichiers generes localement. Option 2 - Ignorer localement sans toucher au `.gitignore` : ``` git update-index --skip-worktree .env ``` - Masque les changements locaux de `.env` sans impacter le depot distant. - Annuler si besoin : ``` git update-index --no-skip-worktree .env ``` ### I) Pull refuse (divergent branches) sans modifier la config Probleme : ``` fatal: Need to specify how to reconcile divergent branches. ``` Cause : - La branche locale et la branche distante ont diverge. - Git demande une strategie explicite (merge, rebase, ff-only). Solution recommandee (rebase ponctuel) : ``` git fetch origin git pull --rebase origin docs-git-dns git push origin docs-git-dns ``` - `--rebase` aligne l'historique local sans commit de merge. - A utiliser sans changer `git config`, juste pour cette commande. Si des changements locaux non committes existent : ``` git stash push -u -m "wip avant rebase" git pull --rebase origin docs-git-dns git push origin docs-git-dns git stash pop ```