Docker Compose 快速搭建 ELK Stack 日志平台

Docker Compose 快速搭建 ELK Stack 日志平台

ELK Stack 是由 Elasticsearch、Logstash 和 Kibana 三个开源工具组成的日志管理解决方案,广泛应用于系统日志收集、分析与可视化。本文将详细介绍如何使用 Docker Compose 快速搭建一套完整的 ELK Stack 日志平台,包含环境准备、配置文件编写、启动验证以及常见问题排查。

一、环境准备

在开始搭建之前,确保你的服务器已经安装以下软件:

  • Docker:版本 20.10 及以上,推荐使用最新稳定版
  • Docker Compose:版本 2.x 及以上
  • 建议宿主机内存不低于 4GB,磁盘剩余空间不低于 20GB

检查 Docker 安装情况:

docker --version
docker-compose --version  # 或 docker compose version

如果没有安装 Docker,可参考以下命令快速安装(以 Ubuntu/Debian 为例):

# 安装 Docker
curl -fsSL https://get.docker.com | bash -s docker

# 安装 Docker Compose 插件
sudo apt-get update
sudo apt-get install -y docker-compose-plugin

# 启动 Docker 并设置为开机自启
sudo systemctl enable docker
sudo systemctl start docker

对于 CentOS/RHEL 系统,同样使用官方安装脚本:

curl -fsSL https://get.docker.com | bash -s docker
sudo systemctl enable --now docker

二、项目目录结构

建议按以下目录结构组织 ELK 配置文件:

elk-stack/
├── docker-compose.yml
├── elasticsearch/
│   ├── config/
│   │   └── elasticsearch.yml
│   └── data/             # 数据持久化目录
├── logstash/
│   ├── config/
│   │   └── logstash.yml
│   └── pipeline/
│       └── logstash.conf
└── kibana/
    └── config/
        └── kibana.yml

创建目录:

mkdir -p elk-stack/{elasticsearch/{config,data},logstash/{config,pipeline},kibana/config}

三、docker-compose.yml 完整配置

以下是一个生产级别的 docker-compose.yml 配置,同时包含 Elasticsearch、Logstash 和 Kibana 三个服务:

version: "3.8"

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    container_name: elk-elasticsearch
    restart: always
    environment:
      - cluster.name=elk-cluster
      - node.name=elk-node-1
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
      - xpack.security.enabled=false
      - xpack.security.enrollment.enabled=false
      - xpack.security.http.ssl.enabled=false
      - xpack.security.transport.ssl.enabled=false
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - ./elasticsearch/data:/usr/share/elasticsearch/data
    networks:
      - elk-net

  logstash:
    image: docker.elastic.co/logstash/logstash:8.12.0
    container_name: elk-logstash
    restart: always
    environment:
      - "LS_JAVA_OPTS=-Xms512m -Xmx512m"
    ports:
      - "5044:5044"
      - "5000:5000/tcp"
      - "5000:5000/udp"
      - "9600:9600"
    volumes:
      - ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml
      - ./logstash/pipeline/logstash.conf:/usr/share/logstash/pipeline/logstash.conf
    depends_on:
      - elasticsearch
    networks:
      - elk-net

  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    container_name: elk-kibana
    restart: always
    environment:
      - SERVER_NAME=kibana
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    ports:
      - "5601:5601"
    volumes:
      - ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml
    depends_on:
      - elasticsearch
    networks:
      - elk-net

networks:
  elk-net:
    driver: bridge

四、配置文件详解

4.1 elasticsearch.yml

Elasticsearch 是核心搜索引擎,负责数据的存储、索引和检索。以下为推荐配置:

# elasticsearch/config/elasticsearch.yml
cluster.name: "elk-cluster"
node.name: "elk-node-1"
path.data: /usr/share/elasticsearch/data
path.logs: /usr/share/elasticsearch/logs

network.host: 0.0.0.0
http.port: 9200
transport.port: 9300

discovery.type: single-node

# 关闭安全特性(开发环境)
xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false

# 索引分片和副本配置
index.number_of_shards: 1
index.number_of_replicas: 0

# 内存锁配置(防止交换分区)
bootstrap.memory_lock: true

# 允许所有来源的跨域请求(用于开发调试)
http.cors.enabled: true
http.cors.allow-origin: "*"

# 集群节点发现
discovery.seed_hosts: []
cluster.initial_master_nodes: ["elk-node-1"]

关键参数说明:

  • discovery.type: single-node:单节点模式,适合测试和开发环境
  • bootstrap.memory_lock: true:锁定内存,防止 Elasticsearch 被交换到磁盘,可显著提升性能
  • xpack.security.enabled: false:关闭 X-Pack 安全认证,简化开发环境配置。生产环境建议开启

4.2 logstash.conf

Logstash 是数据处理管道,负责从多种来源采集数据,进行转换后发送到 Elasticsearch。以下为常见的 Beats 输入配置:

# logstash/pipeline/logstash.conf
input {
  beats {
    port => 5044
    codec => plain
  }

  tcp {
    port => 5000
    codec => json_lines
  }

  udp {
    port => 5000
    codec => json_lines
  }
}

filter {
  # 解析 JSON 格式日志
  if [message] =~ /^{.*}$/ {
    json {
      source => "message"
      target => "parsed_json"
    }
  }

  # 添加时间戳和主机信息
  mutate {
    add_field => {
      "[@metadata][index_prefix]" => "logs"
    }
  }

  # 移除不必要的字段
  mutate {
    remove_field => ["beat", "tags", "@version"]
  }

  # 如果存在 @timestamp,使用日志时间替代接收时间
  date {
    match => ["timestamp", "ISO8601"]
    target => "@timestamp"
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "%{[@metadata][index_prefix]}-%{+YYYY.MM.dd}"
    user => ""
    password => ""
  }

  # 同时输出到控制台便于调试
  stdout {
    codec => rubydebug
  }
}

管道说明:

  • input:定义了三个输入源——Beats 协议(Filebeat 等)、TCP 和 UDP
  • filter:自动解析 JSON 格式日志、添加字段、移除冗余信息
  • output:将处理后的数据写入 Elasticsearch,按日期自动创建索引

4.3 kibana.yml

Kibana 提供 Web 可视化界面,配置相对简单:

# kibana/config/kibana.yml
server.name: "kibana"
server.host: "0.0.0.0"
server.port: 5601

# Elasticsearch 连接地址(容器内使用服务名)
elasticsearch.hosts: ["http://elasticsearch:9200"]

# Kibana 索引(用于保存仪表盘、可视化等配置)
kibana.index: ".kibana"

# 语言设置
i18n.locale: "zh-CN"

# 关闭安全特性
xpack.security.enabled: false

# 监控相关
monitoring.ui.container.elasticsearch.enabled: true

# 日志级别
logging.root.level: info

# 历史记录数量限制
history.limit: 100

配置要点:

  • elasticsearch.hosts:使用 Docker 网络中的服务名 elasticsearch,无需写 IP 地址
  • i18n.locale: "zh-CN":将 Kibana 界面设置为中文
  • server.host: "0.0.0.0":监听所有网络接口,确保外部可访问

4.4 logstash.yml

Logstash 自身配置文件:

# logstash/config/logstash.yml
http.host: "0.0.0.0"
http.port: 9600

# 管道配置
pipeline.workers: 2
pipeline.batch.size: 125
pipeline.batch.delay: 50

# 日志级别
log.level: info

# 关闭 X-Pack 监控
xpack.monitoring.enabled: false

五、启动和验证步骤

5.1 启动服务

在 elk-stack 目录下执行以下命令启动所有服务:

cd elk-stack
docker compose up -d

首次启动会拉取三个镜像(约 2GB),请耐心等待。可以通过以下命令查看启动日志:

docker compose logs -f

5.2 验证服务状态

验证 Elasticsearch:

curl http://localhost:9200

# 预期返回
{
  "name" : "elk-node-1",
  "cluster_name" : "elk-cluster",
  "cluster_uuid" : "...",
  "version" : {
    "number" : "8.12.0",
    ...
  },
  "tagline" : "You Know, for Search"
}

检查 Elasticsearch 集群健康状态:

curl http://localhost:9200/_cluster/health?pretty

# 预期返回 status: "green" 或 "yellow"
{
  "cluster_name" : "elk-cluster",
  "status" : "green",
  ...
}

验证 Logstash:

curl http://localhost:9600/

# 预期返回 Logstash 节点信息,包含 pipeline 状态

验证 Kibana:

打开浏览器访问 http://服务器IP:5601,如果看到 Kibana 的欢迎页面则说明启动成功。

5.3 测试日志采集

发送一条测试日志到 Logstash 的 TCP 输入端口:

echo '{"message":"Hello ELK Stack","timestamp":"2025-06-08T12:00:00+08:00","level":"INFO","service":"test"}' | nc localhost 5000

在 Kibana 中创建索引模式:

  1. 点击左侧菜单 Stack Management → Index Patterns
  2. 点击 Create index pattern
  3. 输入索引模式 logs-*,然后选择 @timestamp 作为时间字段
  4. 创建完成后,进入 Discover 页面即可看到刚才发送的测试日志

六、数据持久化配置

ELK Stack 中最重要的持久化数据是 Elasticsearch 的索引数据。在 docker-compose.yml 中我们已经挂载了数据卷:

volumes:
  - ./elasticsearch/data:/usr/share/elasticsearch/data

这意味着所有索引数据都会保存在宿主机的 ./elasticsearch/data 目录中。即使容器被删除和重建,数据不会丢失。

数据备份建议:

  • 定期将 elasticsearch/data 目录备份到远程存储
  • 使用 Elasticsearch 的快照 API 进行增量备份:
    # 注册快照仓库
    PUT _snapshot/elk_backup
    {
      "type": "fs",
      "settings": {
        "location": "/usr/share/elasticsearch/backup"
      }
    }
    
    # 创建快照
    PUT _snapshot/elk_backup/snapshot_1
  • 对于生产环境,建议使用命名卷(named volumes)而非绑定挂载,以便于迁移:
    volumes:
      elasticsearch-data:
        driver: local
    
    services:
      elasticsearch:
        volumes:
          - elasticsearch-data:/usr/share/elasticsearch/data

七、常见问题排查

7.1 内存配置问题

Elasticsearch 默认使用 1GB 堆内存,Logstash 默认 512MB。如果服务器内存不足,容器可能在启动后不久就 OOM(内存溢出)被杀死。

解决方案:

  • 降低 JVM 堆内存:
    # Elasticsearch
    ES_JAVA_OPTS="-Xms512m -Xmx512m"
    
    # Logstash
    LS_JAVA_OPTS="-Xms256m -Xmx256m"
  • 检查容器内存使用情况:
    docker stats
  • 查看 OOM 日志:
    docker compose logs elasticsearch | grep -i "out of memory\|killed\|OOM"

重要提示:Elasticsearch 官方建议堆内存不超过系统总内存的 50%。例如 4GB 内存的服务器,ES 堆内存最高设为 2GB。

7.2 端口冲突

如果宿主机上已有服务占用 9200、5601 等端口,容器将无法启动。常见冲突源包括已存在的 Elasticsearch 或其他 Java 应用。

解决方案:

  • 查看端口占用:
    sudo lsof -i :9200
    sudo netstat -tlnp | grep 9200
  • 在 docker-compose.yml 中修改映射端口,例如:
    ports:
      - "19200:9200"   # 宿主机 19200 映射到容器 9200
  • 或者停止占用端口的服务:
    sudo systemctl stop elasticsearch

7.3 权限问题(Permission Denied)

Elasticsearch 容器默认以 uid 1000 运行,挂载的数据目录如果权限不正确会导致启动失败。

错误示例:

ElasticsearchException: failed to obtain lock on /usr/share/elasticsearch/data

解决方案:

# 修改数据目录权限
sudo chown -R 1000:1000 ./elasticsearch/data
chmod -R 755 ./elasticsearch/data

如果使用 SELinux,可能需要设置上下文:

sudo chcon -Rt svirt_sandbox_file_t ./elasticsearch/data

7.4 max virtual memory areas 限制

Elasticsearch 需要较大的 vm.max_map_count 值,否则会报错:

max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

解决方案(临时生效):

sudo sysctl -w vm.max_map_count=262144

永久生效:

echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

7.5 Logstash 无法连接 Elasticsearch

如果 Logstash 日志显示连接 Elasticsearch 失败,通常是网络配置或认证问题:

排查步骤:

  • 检查 Elasticsearch 是否正常运行:
    docker compose ps
    docker compose logs elasticsearch | tail
  • 确认 Logstash 配置文件中的 hosts 使用了服务名而非 IP:
    elasticsearch { hosts => ["http://elasticsearch:9200"] }
  • 测试容器间网络连通性:
    docker exec -it elk-logstash curl http://elasticsearch:9200

八、完整启动命令汇总

以下为完整的快速启动命令序列,适用于全新的服务器:

# 1. 创建项目目录
mkdir -p /opt/elk-stack/{elasticsearch/{config,data},logstash/{config,pipeline},kibana/config}
cd /opt/elk-stack

# 2. 创建所有配置文件(使用上面提供的配置内容)
# 依次创建:docker-compose.yml、elasticsearch.yml、logstash.conf、logstash.yml、kibana.yml

# 3. 设置数据目录权限
sudo chown -R 1000:1000 elasticsearch/data

# 4. 调整系统参数
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# 5. 启动 ELK Stack
docker compose up -d

# 6. 查看启动日志
docker compose logs -f

# 7. 验证服务
curl http://localhost:9200
curl http://localhost:9200/_cluster/health?pretty
curl http://localhost:9600/

# 8. 打开浏览器访问 http://服务器IP:5601

九、总结

通过 Docker Compose,我们可以在几分钟内快速搭建一套完整的 ELK Stack 日志平台。本文提供了从环境准备到生产级配置的完整指南,覆盖了 Elasticsearch、Logstash 和 Kibana 三大组件。在实际部署中,建议根据服务器规格调整 JVM 堆内存大小,并做好数据持久化和备份策略。对于生产环境,还应考虑开启 X-Pack 安全认证、配置多节点集群以及使用 Filebeat 等轻量级日志采集器。

ELK Stack 是日志分析领域的事实标准,掌握其 Docker 化部署方式,能够极大提升日志管理的效率和灵活性。后续文章将深入介绍如何使用 Filebeat 采集应用日志、自定义 Logstash 过滤规则以及构建 Kibana 可视化仪表盘。

发表回复

后才能评论