15、Docker Compose 安装ELK + Filebeat单机版

📘 CentOS 9 使用 Docker Compose 部署 ELK + Filebeat 单机版(详细流程+架构图)

📑 目录

  • 📝 前言
  • 🔧 环境准备
  • 📘 组件介绍
  • 📥 安装 Docker 与 Docker Compose
  • 🛠️ 拉取 ELK 镜像
  • ⚙️ 编写 Docker Compose 配置文件
  • 🚀 启动 ELK
  • ⚠️ 重启es后,kibana登录失效问题
  • 🔍 验证 ELK 部署
  • 🖼️ ELK + Filebeat 架构图(Mermaid)
  • 📊 优缺点分析
  • 🏁 总结

📝 前言

ELK(Elasticsearch、Logstash、Kibana)是一套日志采集、存储和可视化解决方案。

Filebeat 是轻量级日志采集器,用于将日志发送到 Logstash 或 Elasticsearch。

本文将介绍如何在 CentOS 9 系统 使用 Docker Compose 部署 ELK + Filebeat 单机版


🔧 环境准备

  • 操作系统:CentOS 9 Stream
  • 推荐配置:CPU ≥ 2 核、内存 ≥ 8GB、磁盘 ≥ 50GB
  • 网络:可访问 Docker Hub 或国内镜像源

📘 组件介绍

在单机环境下使用 Docker Compose 安装 ELK + Filebeat ,其实是搭建了一个完整的 日志收集、存储、分析和可视化平台,主要用途和能做的事情如下:

1️⃣ 组件作用

组件 功能
Elasticsearch 核心存储和搜索引擎,用于存储日志数据、提供搜索和聚合功能。
Logstash 可选组件,用于日志收集、解析和处理(例如:JSON 解析、字段提取、正则处理)。
Kibana 可视化界面,可对日志进行搜索、分析和可视化(图表、仪表盘、告警等)。
Filebeat 轻量级日志采集器,安装在应用服务器上,将日志实时推送到 Elasticsearch 或 Logstash。

2️⃣ 能做什么

  1. 日志集中化
    • 收集不同应用、系统、服务的日志,统一发送到 Elasticsearch 存储。
    • 通过 Filebeat 可以采集:
      • Linux 系统日志(/var/log/messages/var/log/syslog
      • Nginx/Apache 日志
      • Java 应用日志(Spring Boot 等)
      • 自定义业务日志
  2. 日志搜索与查询
    • 可以按时间、级别、关键字搜索日志。
    • 支持多字段组合查询,例如:某服务 + 某用户 + 某时间段。
  3. 日志可视化
    • Kibana 提供丰富图表:
      • 折线图:请求量、错误数随时间变化
      • 饼图:按日志级别统计
      • 条形图:按模块/服务统计
    • 可以生成仪表盘,将关键指标一目了然展示。
  4. 告警与监控
    • 可以通过 Watcher 或 Kibana Alerts 配置告警:
      • 当错误日志超过阈值
      • 某指标异常波动
    • 可发送邮件、Slack、Webhook 等通知。
  5. 日志处理与解析
    • Logstash 可对日志做:
      • 正则提取字段
      • JSON、CSV、XML 解析
      • 数据脱敏和格式转换
  6. 快速实验与开发
    • 单机版可快速搭建环境:
      • 学习 ELK 技术栈
      • 调试日志采集配置
      • 构建仪表盘
    • 适合个人开发、测试或 PoC(Proof of Concept)

3️⃣ 优势

  • 部署简单,Docker Compose 一条命令即可启动
  • 环境隔离好,不影响主机系统
  • 支持快速修改配置和版本升级
  • 可直接和业务应用日志打通,形成可视化监控平台

4️⃣ 限制

  • 单机性能有限:
    • Elasticsearch 存储量有限
    • 并发查询量大时性能下降
  • 没有高可用性,单点故障风险高
  • 不适合生产环境大量日志存储

📥 安装 Docker 与 Docker Compose

Docker Compose 实战


🛠️ 拉取 ELK 镜像

bash 复制代码
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.15.0
docker pull docker.elastic.co/logstash/logstash:8.15.0
docker pull docker.elastic.co/kibana/kibana:8.15.0
docker pull docker.elastic.co/beats/filebeat:8.15.0

⚙️ 编写 Docker Compose 配置文件

/etc/docker/docker-elk 创建 docker-compose.yml

yaml 复制代码
version: '3.9'  # 使用新版本 Compose 文件格式

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms1g -Xmx1g
      - xpack.security.enabled=false
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./es_data:/usr/share/elasticsearch/data  # 数据持久化
      - ./elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro  # 可选 ES 配置
    ports:
      - "9200:9200"

  logstash:
    image: docker.elastic.co/logstash/logstash:8.15.0
    container_name: logstash
    volumes:
      - ./pipeline/:/usr/share/logstash/pipeline/:ro  # 挂载目录而不是单文件
    ports:
      - "5044:5044"  # Beats input 默认端口
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:8.15.0
    container_name: kibana
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
      - SERVER_NAME=kibana
      - I18N_LOCALE=zh-CN    # 设置中文界面
      - ELASTICSEARCH_USERNAME=elastic  # 可配置安全认证
      - ELASTICSEARCH_PASSWORD=changeme
    ports:
      - "5601:5601"
    volumes:
      - ./kibana/data:/usr/share/kibana/data
    depends_on:
      - elasticsearch

  filebeat:
    image: docker.elastic.co/beats/filebeat:8.15.0
    container_name: filebeat
    user: root
    volumes:
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro  # 映射修改后的配置文件
      - /var/log:/var/log:ro                # 采集宿主机日志
    depends_on:
      - logstash
    command: ["/usr/share/filebeat/filebeat", "-e", "-d", "*"]  # 显式指定文件路径和命令

1️⃣ 创建目录结构

bash 复制代码
cd /etc/docker/docker-elk

# Elasticsearch 数据卷
mkdir -p es_data

# Kibana 目录
mkdir -p ./kibana/data

# Logstash pipeline 目录
mkdir -p pipeline

# Filebeat 配置目录
mkdir -p filebeat

2️⃣ 创建文件并写入内容

(1) Elasticsearch 配置

bash 复制代码
cat > elasticsearch.yml <<'EOF'
cluster.name: "docker-cluster"
network.host: 0.0.0.0
http.port: 9200
discovery.type: single-node
bootstrap.memory_lock: true

# 启用安全
xpack.security.enabled: true
xpack.monitoring.collection.enabled: true

# ❗ 禁用 https(否则 Kibana 配 http:// 会连不上)
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false

EOF

(2) Logstash 配置

bash 复制代码
cat > pipeline/logstash.conf <<'EOF'
input {
  beats {
    port => 5044
  }
}

filter {
  #
  # 通用字段:根据 log.file.path 添加 appname
  #
  if "dnf.log" in [log][file][path] {
    mutate { add_field => { "appname" => "dnf" } }
  } else if "messages" in [log][file][path] {
    mutate { add_field => { "appname" => "system" } }
  } else {
    mutate { add_field => { "appname" => "app" } }
  }

  #
  # 1. 解析 dnf.log 格式
  # 示例: 2025-09-28T08:53:19+0800 DDEBUG Plugins were unloaded.
  #
  if [appname] == "dnf" {
    grok {
      match => {
        "message" => "%{TIMESTAMP_ISO8601:logtime}\s+%{WORD:log.level}\s+%{GREEDYDATA:msg}"
      }
    }
    date {
      match => ["logtime", "yyyy-MM-dd'T'HH:mm:ssZ"]
      target => "@timestamp"
    }
  }

  #
  # 2. 解析 syslog 格式 (/var/log/messages)
  # 示例: Sep 28 09:02:08 localhost NetworkManager[753]: <info> ...
  #
  else if [appname] == "system" {
    grok {
      match => {
        "message" => "%{SYSLOGTIMESTAMP:logtime} %{HOSTNAME:host} %{DATA:program}(?:\[%{POSINT:pid}\])?: %{GREEDYDATA:msg}"
      }
    }
    date {
      match => ["logtime", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss"]
      target => "@timestamp"
      timezone => "Asia/Shanghai"
    }

    # 提取 <info>/<err>/<warn> 为 log.level
    if [msg] =~ /<info>/ {
      mutate { add_field => { "log.level" => "INFO" } }
    } else if [msg] =~ /<err>/ {
      mutate { add_field => { "log.level" => "ERROR" } }
    } else if [msg] =~ /<warn>/ {
      mutate { add_field => { "log.level" => "WARN" } }
    } else {
      mutate { add_field => { "log.level" => "INFO" } }  # 默认
    }
  }

  #
  # 3. 解析 应用日志 格式
  # 示例: [ERROR] something bad happened
  #
  else if [appname] == "app" {
    grok {
      match => {
        "message" => "\[%{LOGLEVEL:log.level}\]\s+%{GREEDYDATA:msg}"
      }
      overwrite => [ "log.level" ]
    }
  }

  #
  # 清理无用字段
  #
  mutate {
    remove_field => ["logtime", "ecs", "agent", "host"]
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    user => "elastic"           # 默认管理员用户名
    password => "changeme"      # 你的密码
    index => "filebeat-logs-%{+YYYY.MM.dd}"
  }
  stdout { codec => rubydebug }
}

(3) Filebeat 配置

bash 复制代码
cat > filebeat/filebeat.yml <<'EOF'
filebeat.inputs:
  # 系统日志(syslog/messages)
  - type: log
    paths:
      - /var/log/messages
    fields:
      appname: system
    fields_under_root: true

  # dnf.log
  - type: log
    paths:
      - /var/log/dnf.log
    fields:
      appname: dnf
    fields_under_root: true

  # 业务应用日志(假设放在 /var/log/myapp/)
  - type: log
    paths:
      - /var/log/myapp/*.log
    fields:
      appname: myapp
    fields_under_root: true

# 输出到 Logstash
output.logstash:
  hosts: ["logstash:5044"]

3️⃣ 设置文件权限

Docker 容器内通常以非 root 用户运行,为了避免挂载报错,可以把文件和目录权限设置成 用户可读

bash 复制代码
# 所有配置文件可读写
chmod -R 644 elasticsearch.yml
chmod -R 644 pipeline/logstash.conf
chmod go-w filebeat/filebeat.yml

# 确保目录可进入
# 给所有用户读写权限(单机测试可用)
chmod -R 777 es_data pipeline kibana

说明:

  • 644 → 文件所有者可读写,其他用户可读
  • 777 → 目录所有用户可读写执行

🚀 启动 ELK

bash 复制代码
cd /etc/docker/docker-elk
docker compose up -d
docker ps

过一会,查看发现 kibana没有启动,报错了。

查询日志:docker logs kibana

复制代码
Error: [config validation of [elasticsearch].username]: value of "elastic" is forbidden. This is a superuser account that cannot write to system indices that Kibana needs to function. Use a service account token instead. Learn more: https://www.elastic.co/guide/en/elasticsearch/reference/8.0/service-accounts.html
    at ensureValidConfiguration (/usr/share/kibana/node_modules/@kbn/core-config-server-internal/src/ensure_valid_configuration.js:43:11)
    at Server.preboot (/usr/share/kibana/node_modules/@kbn/core-root-server-internal/src/server.js:174:7)
    at Root.preboot (/usr/share/kibana/node_modules/@kbn/core-root-server-internal/src/root/index.js:47:14)
    at bootstrap (/usr/share/kibana/node_modules/@kbn/core-root-server-internal/src/bootstrap.js:95:29)
    at Command.<anonymous> (/usr/share/kibana/src/cli/serve/serve.js:233:5)

 FATAL  Error: [config validation of [elasticsearch].username]: value of "elastic" is forbidden. This is a superuser account that cannot write to system indices that Kibana needs to function. Use a service account token instead. Learn more: https://www.elastic.co/guide/en/elasticsearch/reference/8.0/service-accounts.html

这个报错其实很关键:

从 8.x 开始,Kibana 不允许用 elastic 超级用户账号直接连接 ES。

因为 Kibana 需要写 .kibana 系统索引,而官方禁止超级用户执行这种写入。


🔑 正确做法:使用 Kibana 的 Service Account Token(官网推荐,但是有生命周期)

1. 在 ES 容器里创建 Token

进入 ES 容器:

bash 复制代码
docker exec -it elasticsearch bash

运行:

bash 复制代码
bin/elasticsearch-service-tokens create elastic/kibana kibana-token

输出类似:

复制代码
eyJ2ZXIiOiIxLjAiLCJhbGciOiJIUzI1NiJ9.xxxxx

这个就是 Kibana 的 service token


2. 修改 docker-compose.yml 中的 Kibana 配置

ELASTICSEARCH_USERNAME / ELASTICSEARCH_PASSWORD 删除,改为:

yaml 复制代码
kibana:
  image: docker.elastic.co/kibana/kibana:8.15.0
  container_name: kibana
  environment:
    - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    - SERVER_NAME=kibana
    - ELASTICSEARCH_SERVICEACCOUNTTOKEN=eyJ2ZXIiOiIxLjAiLCJhbGciOiJIUzI1NiJ9.xxxxx
  ports:
    - "5601:5601"
  depends_on:
    - elasticsearch

注意:这里的 ELASTICSEARCH_SERVICEACCOUNTTOKEN 就是上一步生成的 token。


3. 重启 Kibana
bash 复制代码
docker compose restart kibana

现在 Kibana 就能正常连接 Elasticsearch,不会再报
value of "elastic" is forbidden


⚠️ 总结

  • elastic 超级用户只能用来做初始化管理(比如改密码)。
  • Kibana 必须用 service account token 连接 ES。
  • 这也是 8.x 安全体系的一大变化。

⚠️ 重启es后,kibana登录失效问题

Kibana 使用的 Service Account Token 在 Elasticsearch 重启后可能会失效,原因如下:

1️⃣ Token 的生命周期

  • Elasticsearch 的 Service Account Token 是短期有效的密钥,用于 Kibana 或其他服务访问 Elasticsearch 系统索引
  • 默认不是永久有效,如果 ES 重启、集群重新初始化或 Token 被删除,Kibana 就无法用旧 Token 连接

2️⃣ 实际影响

  • 如果你在 docker-compose 中用 ELASTICSEARCH_SERVICEACCOUNTTOKEN=<token> 启动 Kibana

  • ES 容器重启后,这个 token 很可能不再有效

  • Kibana 会报错,类似:

    FATAL Error: unable to authenticate with Elasticsearch using service account token


3️⃣ 解决方案

方案 A:使用普通用户替代 Token(推荐)
  1. 在 ES 中创建一个 普通用户,授予 Kibana 系统索引权限:
bash 复制代码
# 创建角色
curl -u elastic:changeme -X PUT "http://localhost:9200/_security/role/kibana_user_role" -H 'Content-Type: application/json' -d '{
  "cluster": ["monitor"],
  "indices": [{"names": [".kibana*"], "privileges": ["all"]}]
}'

# 创建用户
curl -u elastic:changeme -X POST "http://localhost:9200/_security/user/kibana_user" -H 'Content-Type: application/json' -d '{
  "password":"kibanapwd",
  "roles":["kibana_user_role"],
  "full_name":"Kibana User"
}'
  1. Docker Compose 配置:
yaml 复制代码
kibana:
  environment:
    - ELASTICSEARCH_USERNAME=kibana_user
    - ELASTICSEARCH_PASSWORD=kibanapwd
  • 优点:不会随 ES 重启失效,稳定可靠
  • 浏览器访问也用 kibana_user / kibanapwd 登录

方案 B:每次重启都生成新 Token
  • 在每次 ES 启动后,用命令生成新的 Service Account Token,再更新 Kibana 配置
  • 缺点:需要额外脚本维护,复杂且不稳定

✅ 总结

方法 是否受重启影响 是否推荐
Service Account Token 会失效 不推荐用于 Docker Compose 长期部署
普通用户(kibana_user) 不会失效 推荐

🔍 验证 ELK 部署

注意:首次访问页面需要提供用户名,密码登录。用户名:elastic,密码:changeme ,密码是docker-compose.yml 中配置的


🖼️ ELK + Filebeat 架构图(Mermaid)

ELK 核心服务 - CentOS 9 服务器 日志采集 - Filebeat 日志来源 - CentOS 9 服务器 读取日志文件 读取日志文件 Beats协议
5044端口 过滤/转换后
写入索引 提供REST API
查询数据 Web界面
http://IP:5601 Logstash
日志处理 Elasticsearch
数据存储/检索 Kibana
可视化分析 Filebeat
采集器 系统日志
/var/log/* 应用日志
/opt/app/logs 用户/运维人员


📊 优缺点分析

✅ 优点

  • 快速部署,环境隔离,适合开发/测试
  • Filebeat 轻量高效,适合日志采集
  • Docker Compose 配置灵活,可一键启停

❌ 缺点

  • 单机性能有限,不适合大规模生产环境
  • 数据持久化需注意卷配置
  • 默认关闭安全认证,不适合公网生产部署

🏁 总结

本文完整介绍了 CentOS 9 + Docker Compose 部署 ELK + Filebeat 单机版 的方法:

  • 搭建 ELK 平台
  • 配置 Filebeat 日志采集
相关推荐
Gss7774 小时前
Docker 公有仓库使用、Docker 私有仓库(Registry)使用总结
docker·容器
暴富奥利奥5 小时前
完成docker方式的ros环境配置
linux·学习·docker·容器
海海思思6 小时前
解决Docker "exec format error":架构不匹配问题分析
docker·容器
帅帅梓8 小时前
docker网络
网络·docker·php
Lv-D-J9 小时前
mac下Docker安装nacos
docker
菜鸟plus+9 小时前
ElasticSearch
运维·jenkins
西瓜er10 小时前
Docker 一键部署指南:GitLab、Nacos、Redis、MySQL 与 MinIO 全解析
redis·docker·gitlab
要站在顶端11 小时前
Jenkins 使用容器运行自动化任务详细文档
docker·自动化·jenkins