Introduction
Le dépannage réseau d'une API Express est souvent la différence entre une app qui « marche chez moi » et une app fiable en CI/CD ou en production. Ce guide se concentre sur ce qu'il faut configurer, la commande qui prouve que la configuration fonctionne, et l'apparence d'un échec quand ce n'est pas le cas. Nous couvrons DNS, ports, routage, pare-feu, tests de connectivité et commandes de diagnostic sûres, avec des exemples en contexte Node.js, MongoDB, REST API et Docker.
Mots-clés intégrés pour faciliter la recherche et la cohérence terminologique: Express API networking, Express API DNS, Express API ports, Express API connectivity, Express API network troubleshooting.
Objectif pratique: comprendre les pièces mobiles, les tester localement, puis réutiliser le même schéma en CI/CD et dans des environnements proches de la production, sans surprises.
Vue d'ensemble du workflow
Un workflow de dépannage efficace tient en trois étapes:
- Identifier la ressource et la modification: service, port, nom DNS, route, règle de pare-feu, variable d'environnement.
- Choisir la commande de preuve: la plus courte possible, qui démontre l'état attendu.
- Définir le signal d'échec: message d'erreur, code de sortie, absence d'écoute, latence inhabituelle, etc.
Pourquoi cela compte: les hypothèses implicites (chemins locaux, tags d'image, noms de réseau, fichiers .env, limites CPU/RAM, permissions) divergent entre portables, runners CI et hôtes. Les rendre explicites évite de "poursuivre" des bogues réseau inexistants.
Bon réflexe: consigner près des fichiers de configuration les prérequis, commandes et sorties attendues. Ainsi, un autre développeur peut reproduire un test à partir d'un checkout propre.
Plan pilote local
Avant de changer quoi que ce soit:
- Entrée attendue: quel hostname, quel port, quel protocole (HTTP/HTTPS), quelles variables d'environnement (PORT, HOST, URL MongoDB), quel réseau Docker.
- Changement: nouvelle valeur d'ENV, nouveau binding d'écoute, exposition de port, règle de pare-feu, ajout d'un alias DNS.
- Sortie attendue: port visible en écoute, résolution DNS vers l'IP escomptée, requête HTTP 200/204 sur /health, latence sous X ms.
- Signal d'échec: ECONNREFUSED, ETIMEDOUT, ENOTFOUND, absence de route, port en conflit, règle de pare-feu bloquante.
Critère de réussite: un test local rejouable par un autre développeur sans contexte tacite, avec commandes et hypothèses listées.
Exemples pratiques et commandes sûres
1) Vérifier que l'API Express écoute au bon endroit
Dans Docker ou sur un hôte, Express doit écouter sur 0.0.0.0 (toutes interfaces) au port attendu.
Exemple minimal server.js:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
const HOST = process.env.HOST || '0.0.0.0';
app.get('/health', (req, res) => res.status(200).send('ok'));
app.listen(PORT, HOST, () => {
console.log(`Listening on http://${HOST}:${PORT}`);
});
Commandes de preuve (Linux/macOS):
- Assurez-vous que le process écoute:
node server.js &
ss -ltnp | grep :3000 || lsof -i -P -n | grep LISTEN | grep 3000
- Test HTTP local:
curl -v http://127.0.0.1:3000/health
Sortie attendue: code 200, corps "ok". Échec typique: ECONNREFUSED (process non lancé) ou aucune ligne d'écoute (mauvais port/host).
2) Exposition et mappage de ports avec Docker
Si vous conteneurisez l'API:
docker build -t my-express: dev .
docker run --name api -p 3000:3000 my-express: dev
Vérifier:
docker ps --format 'table {{.Names}} {{.Ports}}'
curl -v http://localhost:3000/health
Échec typique: container écoute en interne mais pas de mappage (-p manquant), ou l'app écoute sur 127.0.0.1 au lieu de 0.0.0.0.
3) DNS: résoudre les noms correctement
- Résolution externe:
dig +short api.example.test || nslookup api.example.test
- Résolution dans un conteneur (utilisez le service Docker comme hostname):
docker exec -it api getent hosts mongo || docker exec -it api cat /etc/resolv.conf
Sortie attendue: l'IP du service cible. Échec typique: ENOTFOUND côté Node.js, ou aucune entrée getent.
Astuce: dans Docker Compose, utilisez le nom de service comme hostname (ex: "mongo") au lieu d'une IP.
4) Routage: s'assurer qu'un chemin existe
- Route par défaut et sous-réseaux:
ip route show || netstat -rn
- Tracer vers la cible:
traceroute -n 8.8.8.8 || traceroute -n <ip-cible>
Échec typique: pas de route vers l'hôte, saut bloqué par un pare-feu intermédiaire, ou route pointant vers une interface down.
5) Pare-feu: vérifier les règles bloquantes
- Linux avec ufw/iptables:
sudo ufw status verbose || sudo iptables -S
- macOS (exemples généraux): vérifier les règles d'outil de sécurité ou pare-feu système si applicable.
Signal d'échec: connexion qui marche en local (loopback) mais échoue depuis un autre hôte, ports filtrés (pas d'ECONNREFUSED mais timeout), ou RST systématique.
6) Ports en conflit et état d'écoute
- Trouver qui occupe un port:
ss -ltnp | grep :3000 || lsof -i -P -n | grep :3000
- Changer PORT et relancer si conflit:
PORT=3001 node server.js
curl -v http://localhost:3001/health
Échec typique: EADDRINUSE.
7) Tests de connectivité sûrs vers les dépendances (ex: MongoDB)
- Vérifier TCP sans interroger l'application:
nc -vz mongo 27017 || nc -vz 127.0.0.1 27017
- Vérifier depuis le conteneur Express:
docker exec -it api sh -lc 'nc -vz mongo 27017'
Sortie attendue: "succeeded" ou "open". Échec typique: timeout (pare-feu/routage) ou refused (service down ou non lié au bon host/port).
8) Exemple Compose minimal Express + MongoDB
docker-compose.yml:
version: '3.9'
services:
api:
build: .
environment:
- PORT=3000
- HOST=0.0.0.0
- MONGO_URL=mongodb://mongo:27017/app
ports:
- "3000:3000"
depends_on:
- mongo
mongo:
image: mongo:6
ports:
- "27017:27017"
Vérifications:
docker compose up -d
docker compose ps
docker exec -it api sh -lc 'nc -vz mongo 27017'
curl -v http://localhost:3000/health
Attendu: API accessible sur 3000, port 27017 ouvert depuis api vers mongo. Si l'API échoue avec ENOTFOUND, vérifiez que la variable MONGO_URL utilise "mongo" (nom du service) et non une IP dure.
9) Journaliser pour voir l'échec
- Node.js/Express: loggez l'URL cible, l'IP résolue, le port, le code d'erreur (ECONNREFUSED/ETIMEDOUT/ENOTFOUND).
- Docker:
docker logs api --tail=100
- HTTP côté client:
curl -v http://localhost:3000/health
Le -v de curl révèle DNS, connexion TCP, en-têtes et code HTTP.
10) Check-list rapide avant CI/CD
- L'app écoute sur 0.0.0.0: PORT attendu.
- Le port est exposé et mappé correctement (Docker -p).
- La résolution DNS fonctionne dans le même contexte d'exécution (hôte, conteneur, réseau Docker).
- Une route existe vers la dépendance (ip route, traceroute OK).
- Le pare-feu n'interdit pas le flux (ufw/iptables vérifiés).
- Les tests de connectivité passent (curl /health, nc vers DB).
- Les hypothèses et commandes sont documentées près des configs.
Conclusion
Le dépannage réseau d'une API Express fonctionne mieux quand la configuration est traitée comme un artefact testable et non un simple copier-coller. Gardez des exemples petits, exécutez les commandes localement, confirmez le comportement attendu, puis seulement ajoutez des services ou de l'automatisation. Pour la suite, choisissez un service et documentez exactement comment vous le construisez, exécutez, inspectez, arrêtez et recréez. Comparez ensuite avec les besoins de Node.js, MongoDB et REST API pour un modèle d'exploitation cohérent. Un workflow fiable rend l'échec visible: journaux faciles à trouver, données persistantes qui survivent aux reconstructions de conteneurs, et un comportement local assez proche de la production pour détecter les erreurs tôt.