主题模式
Are you an LLM? You can read better optimized documentation at /fe/docker/elk-stack-logging.md for this page in Markdown format
Docker 日志管理与 ELK Stack 部署:构建企业级日志平台
随着 Docker 容器越来越多,日志分散在各个容器中,排查问题变得越来越困难。ELK Stack(Elasticsearch + Logstash + Kibana)是目前最流行的日志管理解决方案,可以将所有容器日志集中收集、存储、分析和可视化。
相比直接查看 docker logs,ELK Stack 的优势:
- 集中管理:所有服务日志统一存储,一个界面查看所有日志
- 全文检索:支持关键词搜索,快速定位问题
- 可视化分析:Kibana 图表展示日志趋势和统计
- 告警通知:日志异常时自动触发告警
- 历史追溯:日志持久化存储,随时回溯历史
🛠️ 准备工作
硬件需求
| 配置 | 最低 | 推荐 |
|---|---|---|
| CPU | 4 核 | 8 核+ |
| 内存 | 8GB | 16GB+ |
| 硬盘 | 50GB | 200GB+(SSD 推荐) |
软件环境
- Docker + Docker Compose(必备)
- 至少 4GB 内存(Elasticsearch 对内存要求较高)
🐳 ELK Stack 一键部署
创建目录结构
bash
mkdir -p /root/data/docker_data/elk/{elasticsearch,logstash,kibana}
cd /root/data/docker_data/elkdocker-compose.yml
yaml
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
container_name: elk-es
environment:
- node.name=es01
- cluster.name=docker-cluster
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms4g -Xmx4g
- xpack.security.enabled=false
- xpack.monitoring.enabled=false
ports:
- '9200:9200'
- '9300:9300'
volumes:
- ./elasticsearch/data:/usr/share/elasticsearch/data
restart: unless-stopped
ulimits:
memlock:
soft: -1
hard: -1
logstash:
image: docker.elastic.co/logstash/logstash:8.15.0
container_name: elk-logstash
environment:
- LS_JAVA_OPTS=-Xms2g -Xmx2g
ports:
- '5044:5044'
- '5000:5000/tcp'
- '5000:5000/udp'
- '9600:9600'
volumes:
- ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml
- ./logstash/pipeline:/usr/share/logstash/pipeline
depends_on:
- elasticsearch
restart: unless-stopped
kibana:
image: docker.elastic.co/kibana/kibana:8.15.0
container_name: elk-kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- XPACK_SECURITY_ENABLED=false
ports:
- '5601:5601'
depends_on:
- elasticsearch
restart: unless-stopped
filebeat:
image: docker.elastic.co/beats/filebeat:8.15.0
container_name: elk-filebeat
volumes:
- ./filebeat/config/filebeat.yml:/usr/share/filebeat/filebeat.yml
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- logstash
restart: unless-stopped
user: root配置 Logstash
创建 pipeline 配置文件:
bash
mkdir -p ./logstash/pipeline
nano ./logstash/pipeline/logstash.confruby
input {
beats {
port => 5044
}
tcp {
port => 5000
codec => json_lines
}
udp {
port => 5000
codec => json_lines
}
}
filter {
if [source] =~ /docker/ {
json {
source => "message"
skip_on_invalid_json => true
}
mutate {
add_field => {
"container_id" => "%{[docker][container][id]}"
"container_name" => "%{[docker][container][name]}"
"image_name" => "%{[docker][container][image]}"
"log_source" => "%{[log][file][path]}"
}
}
date {
match => ["@timestamp", "ISO8601"]
target => "@timestamp"
}
}
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:loglevel} %{DATA:logger} - %{GREEDYDATA:message}" }
overwrite => ["message"]
tag_on_failure => ["_grokparsefailure"]
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "docker-logs-%{+YYYY.MM.dd}"
}
stdout {
codec => rubydebug
}
}配置 Filebeat
bash
mkdir -p ./filebeat/config
nano ./filebeat/config/filebeat.ymlyaml
filebeat.autodiscover:
providers:
- type: docker
hints.enabled: true
templates:
- condition:
contains:
docker.container.name: '*'
config:
- type: container
paths:
- '/var/lib/docker/containers/${data.docker.container.id}/*.log'
processors:
- add_docker_metadata: ~
- decode_json_fields:
fields: ['message']
target: ''
overwrite_keys: true
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
output.logstash:
hosts: ['logstash:5044']
logging.level: info
logging.to_files: true
logging.files:
path: /var/log/filebeat
name: filebeat
keepfiles: 7
permissions: 0644启动服务
bash
docker compose up -d验证服务状态:
bash
docker compose ps等待几分钟让服务启动完成,然后访问:
- Kibana:
http://your-server-ip:5601
📊 Kibana 配置
创建索引模式
- 访问 Kibana → Management → Stack Management
- 点击 Index Patterns → Create index pattern
- 输入
docker-logs-* - 选择
@timestamp作为时间字段 - 点击 Create index pattern
查看日志
- 访问 Discover 页面
- 选择刚创建的索引模式
- 即可看到所有 Docker 容器的日志
创建仪表盘
- 点击 Dashboard → Create dashboard
- 添加可视化图表:
- 折线图:日志数量趋势
- 柱状图:按容器名称统计日志数量
- 饼图:按日志级别分布
- 表格:最新日志列表
常用查询
# 搜索特定容器的日志
container_name: "jellyfin"
# 搜索错误日志
loglevel: "ERROR" OR loglevel: "error"
# 搜索包含特定关键词的日志
message: "timeout" OR message: "error"
# 搜索时间范围内的日志
@timestamp >= "now-24h" AND @timestamp <= "now"
# 组合查询
container_name: "nextcloud" AND loglevel: "ERROR" AND @timestamp >= "now-1h"🔔 告警配置
创建告警规则
- 访问 Kibana → Management → Alerting → Rules
- 点击 Create rule → Threshold
- 设置条件:
- 索引:
docker-logs-* - 时间窗口:5 分钟
- 条件:错误日志数量 > 5
- 索引:
- 添加通知:
- Telegram:通过 Webhook 发送通知
- 邮件:配置 SMTP 发送邮件
- Slack:发送到 Slack 频道
测试告警
bash
# 模拟大量错误日志
docker exec your-container bash -c "for i in {1..10}; do echo '[ERROR] Test error message'; done"🔧 进阶配置
日志轮转
防止日志文件占用过多磁盘空间:
bash
# 修改 Docker daemon 配置
nano /etc/docker/daemon.jsonjson
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}bash
systemctl restart dockerElasticsearch 性能优化
yaml
environment:
- ES_JAVA_OPTS=-Xms8g -Xmx8g
- indices.memory.index_buffer_size=30%
- thread_pool.search.size=4
- thread_pool.search.queue_size=1000多节点部署
对于生产环境,建议部署多节点 Elasticsearch 集群:
yaml
services:
elasticsearch1:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
container_name: elk-es1
environment:
- node.name=es01
- cluster.name=docker-cluster
- discovery.seed_hosts=elk-es2,elk-es3
- cluster.initial_master_nodes=elk-es1,elk-es2,elk-es3
- ES_JAVA_OPTS=-Xms4g -Xmx4g
volumes:
- ./es1/data:/usr/share/elasticsearch/data
elasticsearch2:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
container_name: elk-es2
environment:
- node.name=es02
- cluster.name=docker-cluster
- discovery.seed_hosts=elk-es1,elk-es3
- cluster.initial_master_nodes=elk-es1,elk-es2,elk-es3
- ES_JAVA_OPTS=-Xms4g -Xmx4g
volumes:
- ./es2/data:/usr/share/elasticsearch/data
elasticsearch3:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
container_name: elk-es3
environment:
- node.name=es03
- cluster.name=docker-cluster
- discovery.seed_hosts=elk-es1,elk-es2
- cluster.initial_master_nodes=elk-es1,elk-es2,elk-es3
- ES_JAVA_OPTS=-Xms4g -Xmx4g
volumes:
- ./es3/data:/usr/share/elasticsearch/data使用 Fluentd 替代 Logstash
如果对资源占用有要求,可以用 Fluentd 替代 Logstash:
yaml
fluentd:
image: fluent/fluentd:v1.16-debian-1
container_name: fluentd
volumes:
- ./fluentd/conf:/fluentd/etc
- /var/lib/docker/containers:/var/lib/docker/containers:ro
ports:
- '24224:24224'
- '24224:24224/udp'
depends_on:
- elasticsearch
restart: unless-stopped🔒 安全加固
启用 HTTPS
为 Kibana 配置 SSL 证书:
nginx
server {
listen 443 ssl http2;
server_name kibana.your-domain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:5601;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}启用 Elasticsearch 安全认证
yaml
environment:
- xpack.security.enabled=true初始化密码:
bash
docker exec elk-es bin/elasticsearch-setup-passwords auto配置防火墙
bash
# 只允许特定 IP 访问
ufw allow from 192.168.1.0/24 to any port 5601
ufw allow from 192.168.1.0/24 to any port 9200
# 禁止公网访问
ufw deny 5601
ufw deny 9200
ufw enable📈 性能监控
Elasticsearch 监控
bash
# 查看集群状态
curl http://localhost:9200/_cluster/health
# 查看节点信息
curl http://localhost:9200/_nodes/stats
# 查看索引大小
curl http://localhost:9200/_cat/indices?v日志存储清理
定期清理旧日志:
bash
#!/bin/bash
# cleanup-logs.sh
# 删除 30 天前的索引
curl -X DELETE "http://localhost:9200/docker-logs-$(date -d '30 days ago' +%Y.%m.%d)"
# 优化索引
curl -X POST "http://localhost:9200/_forcemerge?max_num_segments=1"添加定时任务:
bash
crontab -e
0 3 * * * /bin/bash /root/scripts/cleanup-logs.sh❓ 常见问题
Q: Elasticsearch 启动失败,报内存不足?
解决方案:
bash
# 修改系统内存限制
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
sysctl -pQ: Kibana 无法连接 Elasticsearch?
排查步骤:
- 检查 Elasticsearch 是否正常运行
- 确认网络连通性:
docker exec elk-kibana ping elk-es - 检查 Elasticsearch 端口:
curl http://elk-es:9200 - 查看 Kibana 日志:
docker logs elk-kibana
Q: 日志没有收集到?
排查步骤:
- 检查 Filebeat 是否正常运行:
docker logs elk-filebeat - 确认日志文件路径权限:
ls -la /var/lib/docker/containers/ - 检查 Logstash 输入端口:
nc -zv localhost 5044 - 查看 Elasticsearch 索引:
curl http://localhost:9200/_cat/indices
Q: 日志太多导致磁盘满?
解决方案:
- 配置 Docker 日志轮转
- 设置 Elasticsearch 索引生命周期策略(ILM)
- 定期清理旧日志索引
📋 配置清单
| 项目 | 推荐配置 |
|---|---|
| 服务器 | N100 小主机 + 16GB 内存 + 512GB SSD |
| Elasticsearch | 4GB JVM 堆内存 |
| Logstash | 2GB JVM 堆内存 |
| Kibana | 2GB 内存 |
| 日志保留 | 30 天 |
| 索引模式 | docker-logs-YYYY.MM.dd |
🔗 相关文章
- Docker Compose 模板库 — 更多 Docker 配置
- Docker 安装教程 — 环境准备
- Docker 镜像源配置 — 拉镜像加速
- Docker 自托管服务部署合集 — 一站式部署
- Uptime Kuma 服务监控 — 服务可用性监控
