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 中创建索引模式:
- 点击左侧菜单 Stack Management → Index Patterns
- 点击 Create index pattern
- 输入索引模式
logs-*,然后选择@timestamp作为时间字段 - 创建完成后,进入 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 可视化仪表盘。





