一、准备条件
-
已安装:Docker ≥ 20.x、Docker Compose 插件 (
docker compose命令) -
本机一个日志目录(示例:
/abs/path/to/logs)。里边有你的 Logback JSON 文件,如:
logback-demo.json.log(行级 JSON,包含message/level/timestamp/traceId/...字段)
如果你用的是我上一条给的 Spring Boot + Logback 配置,只要确定它的 JSON 日志落在这个目录即可。
二、目录结构(复制即可)
在任意空文件夹(例如 elk-stack/)里创建如下结构与文件:
elk-stack/
├─ docker-compose.yml
├─ .env
├─ logstash/
│ └─ pipeline/
│ └─ logstash.conf
└─ filebeat/
└─ filebeat.yml
三、.env(版本与路径)
把
HOST_LOG_DIR改成你 日志目录的绝对路径(很重要)
# Elasticsearch / Kibana / Logstash 统一版本
STACK_VERSION=8.12.2
# ES 堆大小(本机内存够可以调大)
ES_JAVA_OPTS=-Xms1g -Xmx1g
# Kibana 映射的端口
KIBANA_PORT=5601
# Logstash 映射的端口(Beats 输入)
LOGSTASH_BEATS_PORT=5044
# 你的日志目录(绝对路径)
HOST_LOG_DIR=/abs/path/to/logs
四、docker-compose.yml(核心编排,一键启动)
version: "3.9"
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
container_name: es
environment:
- discovery.type=single-node
- xpack.security.enabled=false # 本地演示禁用安全,生产请开启
- ES_JAVA_OPTS=${ES_JAVA_OPTS}
ulimits:
memlock:
soft: -1
hard: -1
ports:
- "9200:9200"
volumes:
- esdata:/usr/share/elasticsearch/data
kibana:
image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
container_name: kibana
depends_on:
- elasticsearch
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- XPACK_SECURITY_ENABLED=false
ports:
- "${KIBANA_PORT}:5601"
logstash:
image: docker.elastic.co/logstash/logstash:${STACK_VERSION}
container_name: logstash
depends_on:
- elasticsearch
ports:
- "${LOGSTASH_BEATS_PORT}:5044"
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline:ro
filebeat:
image: docker.elastic.co/beats/filebeat:${STACK_VERSION}
container_name: filebeat
user: root
depends_on:
- logstash
volumes:
# 你的日志目录挂载到容器内 /logs
- ${HOST_LOG_DIR}:/logs:ro
# Filebeat 配置
- ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
# 容器读取宿主机文件需要访问 docker 的 meta(可选)
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
command: ["--strict.perms=false"]
volumes:
esdata:
五、Logstash Pipeline(解析 JSON 并写 ES)
html
input {
beats {
port => 5044
codec => "json" # Filebeat 已经传 JSON,这里再保险
}
}
filter {
# 如果你的 JSON 在 message 字段里而不是最外层,请用 json 过滤器解开:
# json { source => "message" }
# 规范化时间戳(如果有 @timestamp 就跳过)
if !("@timestamp" in [@metadata]) and [timestamp] {
date {
match => ["timestamp", "ISO8601", "yyyy-MM-dd HH:mm:ss,SSS", "UNIX_MS"]
target => "@timestamp"
remove_field => ["timestamp"]
}
}
# 统一字段名与类型(可按你的日志做适配)
mutate {
rename => { "level" => "log.level" }
rename => { "logger" => "log.logger" }
rename => { "thread" => "process.thread.name" }
# 保留示例字段:traceId/spanId/app/env/message
}
# 简单去除无用字段示例
mutate {
remove_field => ["host", "agent", "ecs", "log.flags"]
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
# 模板/ILM 可后续加,这里先简单跑通
}
# 便于调试
stdout { codec => rubydebug }
}
六、Filebeat(采集你的 JSON 文件并输送到 Logstash)
html
filebeat.inputs:
- type: filestream
id: app-json-logs
enabled: true
paths:
- /logs/*.json.log
- /logs/**/*.json.log
parsers:
- ndjson:
# 如果你的日志每行就是 JSON(logback JSON Encoder),开启 ndjson
overwrite_keys: true
add_error_key: true
# 如果你的 JSON 行里 time 字段叫 "timestamp",这里可以映射到 @timestamp
# 但我们在 Logstash 里做了统一处理,这里可以不配
ignore_older: 72h
close_inactive: 5m
output.logstash:
hosts: ["logstash:5044"]
# 关闭 elastic-agent 管理
features:
# 禁用云、k8s自动发现等高级特性(本地演示用)
monitoring.enabled: false
说明
-
如果你的日志不是每行一个 JSON(比如普通文本),也能采,不过建议把 Logback 输出改为 JSON,更利于结构化检索。
-
如果你已有 Filebeat 生产配置,可直接把
output指到本 Logstash。
七、启动(一步到位)
cd elk-stack
docker compose pull
docker compose up -d
健康检查:
html
# ES
curl http://localhost:9200
# Kibana(浏览器打开)
# http://localhost:5601
确认 Filebeat、Logstash 日志:
docker logs -f filebeat
docker logs -f logstash
看到 Filebeat 发现文件、Logstash 输出“elasticsearch output succeeded”之类即 OK。
八、产生日志(两种方式)
-
你的应用 :确保它把 JSON 日志写到
.env里的HOST_LOG_DIR目录。例如 Spring Boot 示例,执行后访问接口触发日志:
curl "http://localhost:8080/api/hello?name=Alice"
curl "http://localhost:8080/api/hello?name=oops"
2.快速模拟器(可选):临时生成一些 JSON 行用来验证采集。
在 HOST_LOG_DIR 下生成文件并持续写入
html
mkdir -p /abs/path/to/logs
bash -c 'while true; do \
echo "{\"level\":\"INFO\",\"logger\":\"demo.producer\",\"thread\":\"main\",\"message\":\"hello\",\"app\":\"demo\",\"traceId\":\""$(uuidgen | tr -d - | cut -c1-16)"\",\"env\":\"dev\",\"timestamp\":\""$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")"\"}"; \
sleep 1; \
done >> /abs/path/to/logs/demo.json.log'
九、在 Kibana 里看日志
-
打开浏览器:
http://localhost:5601 -
左侧 Discover → 创建 Data View:
-
Name :
app-logs -
Index pattern :
app-logs-* -
Timestamp field :选择
@timestamp
-
-
保存后即可看到实时入库的日志。
-
常用查询(KQL)示例:
-
log.level: "ERROR" -
app: "logback-demo" -
traceId: "abcd1234*"
-
十、常见问题排查
-
Kibana 看不到索引 :确认 Logstash 是否在往
app-logs-*写入(看容器日志 / curl 索引)curl "http://localhost:9200/_cat/indices?v" -
Filebeat 无法读取 :确认本机日志目录是绝对路径 并已挂载到容器
/logs,文件权限可读。 -
时间乱序 :确保你的 JSON 带有正确的 UTC 时间,或让 Logstash
date过滤器按格式解析。