Cuando un auto se niega a arrancar, un buen mecánico no cambia el motor: mira el tablero (¿qué luz está encendida?), escucha (¿qué ruido, en qué momento?), y solo como último recurso reinicia todo desde cero. El laboratorio se repara igual. Gesto 1, etat: el tablero, quién está corriendo, quién responde. Gesto 2, journal <service>: el ruido, las últimas cien líneas de lo que cuenta ese servicio, donde casi siempre está la frase que lo explica todo. Gesto 3, reinitialiser: el reinicio total, que borra contenedores y datos y te devuelve un laboratorio nuevo en dos minutos. Entre el gesto 2 y el gesto 3, esta lección te da un catálogo de doce fallos vistos y revistos, cada uno con su mensaje exacto, su causa y su remedio. Nueve de cada diez veces, no llegarás hasta el gesto 3.
Lo que cada gesto te dice:
| Gesto | Comando | Lo que lees | Cuánto tiempo |
|---|---|---|---|
| 1 | ./labo.sh etat · .\labo.ps1 etat | columna STATUS: Up … (healthy), Up … (unhealthy), Exited (137), o contenedor ausente; luego ✔/✘ por servicio y los contadores | 10 s |
| 2 | ./labo.sh journal elasticsearch (o kibana, neo4j, opensearch) | últimas 100 líneas; busca ERROR, FATAL, bootstrap check, Exception | 1 min |
| 3 | ./labo.sh reinitialiser luego demarrer, importer, charger-graphe | pide confirmación (oui); elimina contenedores y volúmenes | 3 min |
El gesto 3 solo toca los contenedores labo-* y los tres volúmenes labo-recherche-graphes_es-data, _neo4j-data, _os-data. Pierdes lo que hayas creado tú mismo (índice de bac à sable, tableros, nodos de prueba); los datos del curso se recargan con importer y charger-graphe.
Un journal sano, para reconocer luego un journal enfermo (tres líneas reales tomadas con journal):
labo-elasticsearch | {"@timestamp":"2026-09-09T13:39:45.630Z","log.level": "INFO", "current.health":"GREEN","message":"Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[cours][0]]])." …}
labo-kibana | [2026-09-09T13:37:16.402+00:00][INFO ][status] Kibana is now available
labo-neo4j | 2026-09-09 13:38:32.401+0000 INFO Started.Elasticsearch habla en JSON (una línea por evento, campo message), Kibana en corchetes [fecha][NIVEL][módulo], Neo4j en texto. Las tres frases anteriores son las que queremos ver. Kibana también emite WARN sin gravedad (Error initializing AI assistant resources: Platinum, Enterprise or trial license needed, Error while trying to load prerelease flag): ignóralas.
Los doce fallos, en orden de frecuencia en el aula. Los mensajes marcados «tomado» se reprodujeron en el laboratorio del curso; los demás se citan tal como los emiten los motores.
Puerto ya en uso (tomado). demarrer falla de inmediato con:
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint labo-elasticsearch (…): Bind for 0.0.0.0:9200 failed: port is already allocatedCausa: otro programa ya escucha en 9200 (un Elasticsearch instalado «a mano», otro proyecto Docker), o 5601, 7474, 7687. Remedio: prerequis te dice qué puerto; encuentra al culpable (Get-NetTCPConnection -LocalPort 9200 en PowerShell, sudo ss -ltnp | grep 9200 en Linux/macOS), deténlo o, si debes conservarlo, cambia el puerto del lado del host en docker-compose.yml ("9202:9200") y adapta las direcciones del curso.
Contenedor Exited (137). etat muestra labo-elasticsearch Exited (137) 2 minutes ago, y el journal se detiene sin mensaje de error. Causa: código 137 = matado por la señal 9, casi siempre el OOM killer: Docker no tiene suficiente memoria para tres JVM (Elasticsearch y Neo4j reclaman hasta 1 GB de heap cada uno, más Kibana). docker inspect labo-elasticsearch --format '{{.State.OOMKilled}}' responde true. Remedio: lección 02, paso 1 o 2: sube la memoria de Docker a 6 GB (.wslconfig luego wsl --shutdown en Windows), luego demarrer. No actives el perfil OpenSearch con menos de 6 GB.
Linux: vm.max_map_count demasiado bajo. Elasticsearch (u OpenSearch) sale a los pocos segundos y su journal termina con:
bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
ERROR: Elasticsearch did not exit normally - check the logs at /usr/share/elasticsearch/logs/labo.logCausa: límite del kernel Linux del host, que el contenedor no puede cambiar por sí mismo. Remedio: sudo sysctl -w vm.max_map_count=262144, hazlo permanente en /etc/sysctl.conf (lección 02, paso 3), luego demarrer. En Docker Desktop (Windows, macOS), el valor ya es 262144.
«Kibana server is not ready yet». La página http://localhost:5601 solo muestra esta frase. Causa: Kibana espera a Elasticsearch. O es demasiado pronto (los primeros 40 segundos), o Elasticsearch se cayó (fallo 2 o 3), y journal kibana repite Unable to retrieve version information from Elasticsearch nodes. connect ECONNREFUSED 172.x.x.x:9200. Remedio: etat. Si Elasticsearch está healthy, espera un minuto y recarga; si no, repara Elasticsearch primero, Kibana seguirá solo (restart: unless-stopped).
Disco casi lleno: índices en solo lectura. Al 95 % de disco lleno, un Elasticsearch estándar registra flood stage disk watermark [95%] exceeded on […] all indices on this node will be marked read-only y cualquier escritura responde 429: cluster_block_exception … blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block]. En el laboratorio, no verás este mensaje: el compose fija cluster.routing.allocation.disk.threshold_enabled=false (verificable con GET _nodes/settings?filter_path=nodes.*.settings.cluster.routing). El riesgo que queda es no space left on device en el journal durante importer. Remedio: docker system df para medir, docker image prune para liberar, luego relanza importer.
Neo4j rechaza la contraseña (tomado). En Neo4j Browser: Connection to instance failed — The client is unauthorized due to authentication failure. (detalles: Neo.ClientError.Security.Unauthorized). En etat: ✘ Neo4j ne répond pas, y en línea de comandos cypher-shell dice The client is unauthorized due to authentication failure. Causa A: error de tipeo, la contraseña es aiopsatlas2026. Causa B, más sutil: el volumen neo4j-data se creó en un inicio anterior con otra contraseña; NEO4J_AUTH solo se aplica en la primera inicialización, y el journal lo dice claramente (línea tomada): Changed password for user 'neo4j'. IMPORTANT: this change will only take effect if performed before the database is started for the first time. Remedio A: vuelve a escribirla. Remedio B: reinitialiser luego demarrer y charger-graphe.
Conflicto de nombre de contenedor (tomado). demarrer falla con:
Error response from daemon: Conflict. The container name "/labo-elasticsearch" is already in use by container "a26fe0358d63…". You have to remove (or rename) that container to be able to reuse that name.Causa: ya existe un contenedor labo-elasticsearch que no pertenece a este proyecto Compose, típicamente porque clonaste el kit en una segunda carpeta, o lanzaste un docker run --name labo-elasticsearch a mano. Remedio: docker rm -f labo-elasticsearch (solo el contenedor, los datos del volumen permanecen), luego demarrer. Si el conflicto afecta a los cinco nombres, docker rm -f $(docker ps -aq --filter name=labo-).
Git Bash reescribe las rutas /labo (tomado). En Windows, en Git Bash, un comando escrito a mano como docker compose exec -T neo4j ls /labo/cypher responde:
ls: cannot access 'C:/Program Files/Git/labo/cypher': No such file or directoryCausa: la emulación MSYS de Git Bash convierte cualquier argumento que empiece con / en una ruta de Windows antes de pasarlo a docker. Remedio: labo.sh exporta MSYS_NO_PATHCONV=1 y MSYS2_ARG_CONV_EXCL='*' desde su segunda línea, así que todos los comandos del script están protegidos. Para tus propios comandos en Git Bash, agrégales el prefijo: MSYS_NO_PATHCONV=1 docker compose exec -T neo4j ls /labo/cypher (tomado: aparece la lista de archivos .cypher).
PowerShell 5.1 e Invoke-RestMethod rompen los acentos (tomado). Envías una consulta con una palabra acentuada desde PowerShell:
$corps = '{"analyzer":"french","text":"déployés en production"}'
Invoke-RestMethod -Uri http://localhost:9200/cours/_analyze -Method Post -ContentType 'application/json' -Body $corpsPowerShell 5.1 responde Le serveur distant a retourné une erreur : (400) Demande incorrecte.; del lado de Elasticsearch la razón es x_content_parse_exception … Invalid UTF-8 middle byte 0x70. Causa: PowerShell 5.1 codifica el cuerpo en Latin-1 mientras que Elasticsearch espera UTF-8; el mismo comando en PowerShell 7 funciona. Remedio: usa Kibana Dev Tools para todas las consultas del curso (UTF-8 garantizado); el propio labo.ps1 usa curl dentro de los contenedores. Para escribir scripts de todos modos: PowerShell 7, o -Body ([System.Text.Encoding]::UTF8.GetBytes($corps)).
Docker Desktop no está iniciado. Cualquier comando docker (por lo tanto prerequis, etat, demarrer) falla con:
error during connect: Get "http://%2F%2F.%2Fpipe%2FdockerDesktopLinuxEngine/v1.51/info": open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.(Cannot connect to the Docker daemon at unix:///var/run/docker.sock en macOS/Linux.) prerequis traduce: ✘ le démon Docker ne répond pas — lancez Docker Desktop et attendez l'icône verte. Causa: Docker Desktop cerrado, o todavía iniciando después de una sesión de Windows. Remedio: inicia Docker Desktop, espera a que el icono deje de animarse, relanza el comando. Los contenedores en restart: unless-stopped vuelven a arrancar solos.
Descarga muy lenta o TLS handshake timeout. Durante == Téléchargement des images ==:
Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: TLS handshake timeouto failed to copy: read tcp … connection reset by peer. Causa: red saturada, wifi de escuela, proxy corporativo; las imágenes pesan de 2,5 a 2,8 GB cada una. Remedio: nada que reparar, relanza demarrer: Docker retoma las capas ya descargadas (Already exists). Detrás de un proxy, configúralo en Docker Desktop → Settings → Resources → Proxies.
Volumen lleno o datos corruptos: el reinicio total. Síntomas variados: etat muestra el cluster en red, el journal de Elasticsearch habla de CorruptIndexException o de no space left on device, Neo4j se queda bloqueado en recovery tras un apagado brusco del PC, o simplemente nada tiene sentido después de una manipulación arriesgada. Remedio, el gesto 3:
./labo.sh reinitialiser # responder: oui
./labo.sh demarrer
./labo.sh importer
./labo.sh charger-graphe.\labo.ps1 reinitialiser
.\labo.ps1 demarrer
.\labo.ps1 importer
.\labo.ps1 charger-grapheLo que debes ver: reinitialiser ejecuta docker compose --profile opensearch down -v --remove-orphans y confirma ✔ labo remis à zéro. Las imágenes permanecen en caché: sin nueva descarga, y el siguiente trío toma dos a tres minutos. Lo que debes saber: arreter (sin -v) conserva los datos; reinitialiser los borra, es la única diferencia.
etat no lista ningún contenedor y demarrer recrea todo cada vez → Estás lanzando el script desde una segunda copia del repositorio. Conserva una sola copia del kit y lanza siempre los comandos desde su raíz.
journal muestra miles de líneas JSON ilegibles → Normal para Elasticsearch. Filtra por palabras clave: en PowerShell .\labo.ps1 journal elasticsearch | Select-String 'ERROR|WARN|bootstrap', en bash ./labo.sh journal elasticsearch | grep -E 'ERROR|WARN|bootstrap'.
Después de reinitialiser, Kibana vuelve a mostrar «Vos données ne sont pas sécurisées» → Aviso normal de un Kibana sin seguridad; vuelve porque la configuración de Kibana se borró junto con el volumen. Haz clic en «Rejeter».
etat (qué no funciona), journal <service> (por qué), reinitialiser (último recurso, borra los datos del laboratorio pero no las imágenes).Exited (137) = memoria; port is already allocated = puerto ocupado; vm.max_map_count [65530] is too low = ajuste de Linux pendiente; Neo.ClientError.Security.Unauthorized = contraseña; container name … already in use = docker rm.labo.sh neutraliza la conversión de rutas de Git Bash.Invoke-RestMethod en PowerShell 5.1: Dev Tools y labo.ps1 se encargan de eso correctamente.arreter conserva los datos, reinitialiser los borra. Los datos del curso siempre se recargan en dos comandos.docker inspect --format '{{.State.Health.Status}}' labo-elasticsearch devuelve starting, healthy o unhealthy: es exactamente lo que lee demarrer cada tres segundos. {{json .State.Health.Log}} muestra los cinco últimos resultados del healthcheck.