02 - Installer Logstash avec Docker en 5 minutes
Ce que tu vas apprendre
- Installer Logstash, Elasticsearch et Kibana avec Docker Compose
- Structurer les fichiers de configuration Logstash
- Configurer
logstash.ymletpipelines.yml - Verifier que tout tourne
- Résoudre les problèmes courants au démarrage
Prerequisites
- Docker et Docker Compose installes (ou avoir lu la serie Docker pour les devs)
- Avoir lu l'article 01 - L'Elastic Stack
Pourquoi Docker et pas une installation native
J'ai installe Logstash "a la main" exactement une fois. Sur un Ubuntu 20.04. Il fallait ajouter le repo Elastic, installer Java 11 (pas 17, pas 8, spécifiquement 11 a l'epoque), gerer les conflits de packages, configurer les permissions sur les fichiers de config, et démarrer le service systemd. Ca m'a pris 45 minutes.
Avec Docker, c'est un fichier compose.yaml et un docker compose up. La JVM est incluse dans l'image, les versions sont fixees, les chemins sont connus. Si ca casse, tu supprimes le conteneur et tu recommences. Pas de residus.
Pour le dev et l'apprentissage, Docker est la bonne approche. En production, certaines équipes preferent des installations natives ou des packages .deb/.rpm. Mais pour cette serie, on reste sur Docker.
Structure du projet
Voici l'arborescence qu'on va utiliser tout au long de la serie :
logstash-lab/
├── compose.yaml
├── .env
├── logstash/
│ ├── config/
│ │ ├── logstash.yml
│ │ └── pipelines.yml
│ └── pipeline/
│ └── main.conf
└── data/
└── sample.log
Chaque dossier a un rôle precis :
logstash/config/: configuration globale de Logstash (pas les pipelines)logstash/pipeline/: les fichiers.confqui definissent les pipelinesdata/: fichiers de test (logs, CSV, JSON) qu'on utilisera dans les articles suivants
Cree cette structure :
bashmkdir -p logstash-lab/logstash/config
mkdir -p logstash-lab/logstash/pipeline
mkdir -p logstash-lab/data
cd logstash-lab
Le compose.yaml complet
yamlservices:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0
container_name: es
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- xpack.security.enrollment.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ports:
- "9200:9200"
volumes:
- es-data:/usr/share/elasticsearch/data
healthcheck:
test: ["CMD-SHELL", "curl -fs http://localhost:9200/_cluster/health || exit 1"]
interval: 10s
timeout: 5s
retries: 10
kibana:
image: docker.elastic.co/kibana/kibana:8.17.0
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
depends_on:
elasticsearch:
condition: service_healthy
logstash:
image: docker.elastic.co/logstash/logstash:8.17.0
container_name: logstash
environment:
- "LS_JAVA_OPTS=-Xms256m -Xmx256m"
volumes:
- ./logstash/pipeline/:/usr/share/logstash/pipeline/
- ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro
- ./logstash/config/pipelines.yml:/usr/share/logstash/config/pipelines.yml:ro
- ./data/:/data/:ro
ports:
- "5044:5044"
- "9600:9600"
depends_on:
elasticsearch:
condition: service_healthy
volumes:
es-data:
Quelques points importants :
Les healthchecks. Logstash et Kibana ne demarrent pas tant qu'Elasticsearch n'est pas pret. Le healthcheck interroge _cluster/health toutes les 10 secondes. Sans ca, Logstash crash au démarrage parce qu'il ne trouve pas Elasticsearch.
Les ports. Elasticsearch sur 9200, Kibana sur 5601, Logstash Beats input sur 5044, et l'API de monitoring Logstash sur 9600.
Les volumes. Les fichiers de config sont montes en lecture seule (:ro). Le dossier pipeline/ ne l'est pas, parce qu'on va souvent le modifier pendant le dev. Le volume es-data persiste les donnees Elasticsearch entre les redemarrages.
La mémoire. ES_JAVA_OPTS=-Xms512m -Xmx512m donne 512 Mo de heap a Elasticsearch. LS_JAVA_OPTS=-Xms256m -Xmx256m donne 256 Mo a Logstash. C'est le minimum viable pour du dev local.
Le fichier logstash.yml
C'est la configuration globale de Logstash. Pas les pipelines, juste le comportement du processus lui-meme.
yaml# logstash/config/logstash.yml
# API de monitoring (accessible sur le port 9600)
api.http.host: "0.0.0.0"
api.http.port: 9600
# Rechargement automatique des pipelines quand les fichiers changent
config.reload.automatic: true
config.reload.interval: 3s
# Logs Logstash (pas les donnees, les logs du process lui-meme)
log.level: info
# Desactiver le monitoring X-Pack pour simplifier le setup
monitoring.enabled: false
Le paramètre config.reload.automatic: true est important. Il permet de modifier les fichiers .conf sans redemarrer Logstash. Tu edites ton pipeline, tu sauvegardes, et Logstash le recharge en 3 secondes. Indispensable pour le dev.
Le fichier pipelines.yml
Ce fichier definit quels pipelines Logstash doit charger. Pour l'instant, on en a un seul :
yaml# logstash/config/pipelines.yml
- pipeline.id: main
path.config: "/usr/share/logstash/pipeline/main.conf"
pipeline.workers: 2
pipeline.batch.size: 125
Chaque entree definit un pipeline avec :
pipeline.id: un identifiant uniquepath.config: le chemin vers le fichier.conf(ou un glob pour plusieurs fichiers)pipeline.workers: le nombre de threads de traitementpipeline.batch.size: le nombre d'événements traites en une fois
On explorera les pipelines multiples dans l'article 20. Pour l'instant, un seul suffit.
Le premier pipeline
Le pipeline le plus simple : lire depuis stdin, afficher dans stdout.
# logstash/pipeline/main.conf
input {
stdin {}
}
output {
stdout {
codec => rubydebug
}
}
On le remplacera dans les articles suivants, mais celui-ci permet de vérifier que Logstash démarré correctement.
Démarrage
Lance le tout :
bashdocker compose up -d
Verifie que les trois services tournent :
bashdocker compose ps
Tu devrais voir :
NAME IMAGE STATUS
es docker.elastic.co/elasticsearch/elasticsearch:8.17.0 Up (healthy)
kibana docker.elastic.co/kibana/kibana:8.17.0 Up
logstash docker.elastic.co/logstash/logstash:8.17.0 Up
Verifie Elasticsearch :
bashcurl http://localhost:9200
json{
"name": "es",
"cluster_name": "docker-cluster",
"cluster_uuid": "abc123...",
"version": {
"number": "8.17.0",
"build_flavor": "default",
"build_type": "docker"
},
"tagline": "You Know, for Search"
}
Verifie l'API de monitoring Logstash :
bashcurl http://localhost:9600
json{
"host": "logstash",
"version": "8.17.0",
"http_address": "0.0.0.0:9600",
"id": "...",
"name": "logstash",
"status": "green",
"pipeline": {
"workers": 2,
"batch_size": 125
}
}
Si status est green, Logstash est operationnel.
Ouvre Kibana dans ton navigateur : http://localhost:5601. L'interface met 30 a 60 secondes a se charger au premier démarrage.
Tester le pipeline
Le pipeline actuel lit depuis stdin. Pour envoyer des donnees dans un conteneur Docker, utilise docker exec :
bashecho "hello logstash" | docker exec -i logstash \
/usr/share/logstash/bin/logstash \
-e 'input { stdin {} } output { stdout { codec => rubydebug } }'
Mais cette approche lance une deuxieme instance de Logstash. C'est lent et inutile. On va plutot remplacer le pipeline par un input generator pour tester :
# logstash/pipeline/main.conf
input {
generator {
message => "premier evenement de test"
count => 1
}
}
output {
stdout {
codec => rubydebug
}
}
L'input generator créé des événements artificiels. count => 1 en généré un seul. Sauvegarde le fichier, attends 3 secondes (le reload automatique), et regarde les logs :
bashdocker compose logs logstash --tail 20
Tu verras l'événement :
{
"@timestamp" => 2026-03-31T10:30:00.123Z,
"@version" => "1",
"message" => "premier evenement de test",
"sequence" => 0,
"host" => {
"hostname" => "logstash"
},
"event" => {
"original" => "premier evenement de test",
"sequence" => 0
}
}
Ca marche. Logstash recoit un événement, l'enrichit avec un timestamp et des metadonnees, et l'affiche.
Recharger un pipeline a chaud
Grace a config.reload.automatic: true, tu peux modifier le fichier .conf et Logstash le recharge sans redemarrage.
Modifie le message du generator :
# logstash/pipeline/main.conf
input {
generator {
message => "deuxieme test, rechargement a chaud"
count => 1
}
}
output {
stdout {
codec => rubydebug
}
}
Sauvegarde. Attends 3 secondes. Regarde les logs :
bashdocker compose logs logstash --tail 5
Le nouveau message apparaît. Pas de redemarrage, pas de downtime. C'est pour ca que cette option est activee par défaut dans notre config.
Troubleshooting
Logstash ne démarré pas
Regarde les logs :
bashdocker compose logs logstash
Les erreurs les plus courantes :
"Could not find or load main class" : le JVM opts est mal formate. Verifie que LS_JAVA_OPTS a bien des guillemets dans le compose.yaml : "LS_JAVA_OPTS=-Xms256m -Xmx256m".
"Elasticsearch unreachable" : Logstash a démarré avant qu'Elasticsearch soit pret. Le healthcheck dans le compose.yaml devrait éviter ca. Si ca persiste, relance avec docker compose restart logstash.
"Pipeline aborted due to error" : une erreur de syntaxe dans le fichier .conf. Le message d'erreur indique la ligne. Corrige et Logstash rechargera automatiquement.
Elasticsearch ne démarré pas
"max virtual memory areas vm.max_map_count [65530] is too low" : sur Linux, Elasticsearch a besoin d'un paramétrage noyau. Execute :
bashsudo sysctl -w vm.max_map_count=262144
Pour le rendre permanent, ajoute vm.max_map_count=262144 dans /etc/sysctl.conf.
Sur macOS et Windows avec Docker Desktop, ce n'est pas nécessaire.
Out of memory : Elasticsearch prend trop de RAM. Reduis la heap dans le compose.yaml : -Xms256m -Xmx256m. Ca sera lent, mais ca demarrera.
Kibana affiche "Kibana server is not ready yet"
Normal au premier démarrage. Kibana attend qu'Elasticsearch soit complètement initialise. Attends 30 a 60 secondes et rafraichis la page.
Les fichiers de l'image Docker Logstash
Pour debugger, il est utile de connaître la structure interne de l'image :
/usr/share/logstash/
├── bin/
│ └── logstash # le binaire
├── config/
│ ├── logstash.yml # config globale (on la monte depuis notre volume)
│ ├── pipelines.yml # definition des pipelines (monte aussi)
│ ├── jvm.options # options JVM (heap, GC, etc.)
│ └── log4j2.properties # config des logs Logstash
├── pipeline/
│ └── logstash.conf # pipeline par defaut (remplace par le notre)
├── data/ # donnees internes (sincedb, DLQ, etc.)
├── logs/ # logs du process Logstash
└── vendor/
└── bundle/
└── jruby/ # plugins installes (en JRuby)
Les chemins qu'on monte dans Docker Compose correspondent a cette structure. Quand on écrit ./logstash/pipeline/:/usr/share/logstash/pipeline/, on remplace le dossier pipeline/ de l'image par le notre.
Arreter et nettoyer
bash# Arreter les services
docker compose down
# Arreter et supprimer les donnees Elasticsearch
docker compose down -v
Le flag -v supprime le volume es-data. Utile quand tu veux repartir de zero.
Sur paltemps.fr, je garde un compose.yaml similaire pour chaque projet qui utilise l'Elastic Stack. Le dossier logstash/pipeline/ change selon le projet, mais la structure reste la meme.
Résumé
- L'installation avec Docker Compose prend 3 fichiers :
compose.yaml,logstash.yml,pipelines.yml - Les trois services ont besoin d'au moins 1 Go de RAM combine
config.reload.automatic: truerecharge les pipelines a chaud, sans redemarragepipelines.ymldefinit quels fichiers.confLogstash charge- L'input
generatorest pratique pour tester un pipeline sans source de donnees - Utilise la meme version pour tous les composants de l'Elastic Stack
Precedent : 01 - L'Elastic Stack | Suivant : 03 - Anatomie d'un pipeline