引言在微服务和分布式架构盛行的今天应用的日志不再集中在一台服务器上而是散落在各个容器、主机中。排查问题时若仍使用tail -f逐台登录查看日志效率极低且容易遗漏关键信息。ELKElasticsearch、Logstash、Kibana是业界最为成熟的开源日志解决方案能够方便地完成日志的采集、传输、存储、搜索和可视化。本文将带你从零开始用 Docker Compose 快速搭建一套 ELK 系统并实战采集 Nginx 访问日志在 Kibana 中生成实时可视化看板。所有代码均可直接复制运行让你在十分钟内拥有自己的日志中心。核心概念与架构实际的日志流水线通常由四部分组成Filebeat轻量级采集器部署在产生日志的服务器上监控日志文件并将日志推送到 Logstash 或直接到 Elasticsearch。它资源消耗极小适合做日志的“搬运工”。Logstash数据处理管道负责接收、过滤、转换日志。可以用 Grok 解析非结构化日志还可以丰富字段如添加地理位置信息。Elasticsearch存储与搜索引擎存储索引后的日志数据提供近乎实时的搜索和分析能力。Kibana可视化界面通过图表、仪表盘展示 Elasticsearch 中的数据支持交互式搜索。一个典型的架构如下Nginx(容器) → Filebeat → Logstash → Elasticsearch → Kibana本文示例中所有组件都运行在 Docker 中方便快速搭建和复现。实战搭建 ELK Filebeat 采集 Nginx 日志1. 环境准备确保你的机器已安装 Docker 和 Docker Compose版本 ≥ 1.29。建议给 Docker 分配至少 4GB 内存因为 Elasticsearch 比较占内存。创建项目目录mkdir elk-stack cd elk-stack2. 编写 Docker Compose 编排文件在docker-compose.yml中定义 Elasticsearch、Logstash、Kibana、Nginx 和 Filebeat 服务。我们采用桥接网络elk-net让容器间互通。version: 3.7 services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.17.12 container_name: elasticsearch environment: - discovery.typesingle-node # 单节点模式 - ES_JAVA_OPTS-Xms512m -Xmx512m # 限制堆内存 ulimits: memlock: soft: -1 hard: -1 volumes: - esdata:/usr/share/elasticsearch/data ports: - 9200:9200 networks: - elk-net logstash: image: docker.elastic.co/logstash/logstash:7.17.12 container_name: logstash volumes: - ./logstash/pipeline:/usr/share/logstash/pipeline # 自定义管道配置 ports: - 5044:5044 # 接收 Filebeat 输入 depends_on: - elasticsearch networks: - elk-net kibana: image: docker.elastic.co/kibana/kibana:7.17.12 container_name: kibana environment: - ELASTICSEARCH_HOSTShttp://elasticsearch:9200 ports: - 5601:5601 depends_on: - elasticsearch networks: - elk-net nginx: image: nginx:1.21 container_name: nginx volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro # 自定义 Nginx 日志格式 - nginx_logs:/var/log/nginx ports: - 8080:80 networks: - elk-net filebeat: image: docker.elastic.co/beats/filebeat:7.17.12 container_name: filebeat user: root # 需要 root 读取 Nginx 日志 volumes: - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro - nginx_logs:/var/log/nginx:ro # 挂载同一个日志卷 command: filebeat -e -strict.permsfalse depends_on: - logstash - nginx networks: - elk-net volumes: esdata: nginx_logs: networks: elk-net: driver: bridge3. 配置各组件Nginx 日志格式为了让日志包含更丰富的字段如请求时间、状态码、响应时间等我们自定义 JSON 格式的日志。创建nginx/nginx.confuser nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format json_combined escapejson { time_local:$time_iso8601, remote_addr:$remote_addr, remote_user:$remote_user, request:$request, status: $status, body_bytes_sent:$body_bytes_sent, request_time:$request_time, http_referrer:$http_referer, http_user_agent:$http_user_agent }; access_log /var/log/nginx/access.log json_combined; sendfile on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; }重启 Nginx 后访问日志将是 JSON 格式非常便于 Logstash 解析。Logstash 管道创建logstash/pipeline/nginx.confinput { beats { port 5044 } } filter { # 如果日志是 JSON 格式Nginx 访问日志直接解析 if [log][file][path] ~ access { json { source message target nginx # 解析后的字段放入 nginx 对象 } # 将常用字段提升到顶级 mutate { copy { [nginx][remote_addr] client_ip [nginx][status] status_code [nginx][request_time] response_time [nginx][request] request_url } convert { status_code integer response_time float } } # 移除原始 message 和 nginx 大对象可选 # mutate { remove_field [message, nginx] } } } output { elasticsearch { hosts [http://elasticsearch:9200] index nginx-%{YYYY.MM.dd} user elastic password changeme # 如有安全设置需配置这里暂不启用 manage_template false } # stdout { codec rubydebug } # 调试时可开启 }此配置将 Filebeat 传来的日志按 JSON 解析提取出 Nginx 的关键字段最终存入以日期分片的索引中。Filebeat 配置创建filebeat/filebeat.ymlfilebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/access.log # 多行合并如果需要 # multiline.pattern: ^\{ # multiline.negate: true # multiline.match: after output.logstash: hosts: [logstash:5044]Filebeat 监控 Nginx 日志文件并发送给 Logstash。4. 启动服务在项目根目录下执行docker-compose up -d首次启动会拉取镜像稍等片刻。待所有容器状态为Up后用浏览器访问http://localhost:8080多次产生一些 Nginx 日志。5. 在 Kibana 中查看与分析打开浏览器访问http://localhost:5601。进入Management → Stack Management → Index Patterns创建索引模式。- Index pattern name 填写nginx-*- 选择时间字段timestamp由 Filebeat 自动添加。创建成功后进入Discover页面选择nginx-*索引即可看到 Nginx 日志数据。可以使用 KQL 查询例如status_code:404查找 404 请求。制作可视化看板- 点击Create new选择Lens或Visualization。- 以柱状图展示每分钟请求量x 轴为timestampy 轴为Count。- 将status_code作为分桶维度统计各状态码分布。- 保存图表并添加到 Dashboard最终生成实时监控仪表盘。这样一个基础但完整的日志中心便搭建完成。常见问题与注意事项Elasticsearch 内存不足导致启动失败现象elasticsearch容器反复退出。解决方案增加 Docker 可用内存或调整ES_JAVA_OPTS的-Xms和-Xmx参数但最小不低于 512m。生产环境建议分配 2G 以上。Filebeat 无权读取日志文件日志卷权限默认为 root需要使用user: root运行 Filebeat 容器并为配置文件设置-strict.permsfalse。生产环境建议用chmod或组授权更安全的方式处理。Logstash 管道语法错误如果 Logstash 启动后自动退出可能是配置文件有误。可以通过docker logs logstash查看错误信息。调试时可开启stdout { codec rubydebug }输出将日志打印在控制台确认数据流转正常。索引模式未匹配到数据检查时间字段选择确认日志中确实有timestamp且是有效的日期类型。若使用自定义解析确保date过滤器正确转换了时间字段。磁盘空间增长过快Elasticsearch 索引默认每天创建一个长期运行会占用大量磁盘。建议设置 ILM索引生命周期管理策略定期删除或归档老旧索引。安全性本文示例未开启安全认证仅适合演示环境。生产环境中务必启用 X-Pack 认证、加密、用户角色等安全功能。总结本文详细介绍了如何使用 Docker Compose 快速部署一套 ELK Filebeat 日志收集系统并实战采集 Nginx 的 JSON 格式日志在 Kibana 中实现了搜索和可视化。通过这套组合无论是开发环境排错还是生产环境监控都能大幅提升日志处理效率。从本文你可以学到- ELK 各个组件的作用和数据流向- Docker 化部署 ELK 的 YAML 编排技巧- Nginx 日志格式定制与 Filebeat、Logstash 的配置联动- Kibana 索引模式与可视化图表的基本操作希望这篇实战指南能帮助你在项目中轻松落地日志中心。下一步你可以尝试加入 Grafana、告警规则或扩展到 Kubernetes 日志采集打造企业级可观测性平台。