news 2026/6/24 8:04:56

Ubuntu26.04下Loki与Spring Boot集成实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu26.04下Loki与Spring Boot集成实战指南

本文基于实际踩坑经历,详细记录在Ubuntu系统上部署Loki+Grafana,并通过Spring Boot应用将日志直接推送至Loki的全过程。文中包含完整的配置示例、常见错误及解决方案,以及如何在Grafana中利用上下文功能快速定位问题。


1. 为什么选择Loki?

相比传统的ELK(Elasticsearch+Logstash+Kibana)栈,Loki采用标签索引而非全文索引,存储成本更低,查询速度更快,尤其适合Kubernetes环境和微服务架构。配合Grafana的可视化能力,可以轻松实现日志的聚合、检索和监控。

本文方案特点

  • 使用Loki4j作为Logback Appender,Spring Boot应用直接推送日志,无需额外部署Promtail。

  • 所有组件(Loki、Grafana)通过Docker Compose一键启动

  • 覆盖从部署到排错的全流程,尤其针对权限、配置文件等常见坑点给出明确解决办法。


2. 环境准备

  • 操作系统:Ubuntu 26.04(其他版本同理)

  • DockerDocker Compose(已安装)

  • Spring Boot项目(推荐3.x, 2/3/4均可)

  • JDK 8+

检查Docker版本:

docker --version docker compose version

若未安装,可参考官方文档安装Docker Engine和Compose。


3. 部署Loki和Grafana

3.1 创建项目目录

mkdir -p ~/loki-stack cd ~/loki-stack

3.2 编写docker-compose.yml

经过多次调整,最终使用不含配置文件挂载的简洁版本,避免因配置文件缺失或权限问题导致容器无法启动。关键点:数据目录权限必须正确。

创建docker-compose.yml

nanodocker-compose.yml

(ctrl+o save, press enter comfirm , ctrl+x exit)

networks: loki-network: services: loki: image: grafana/loki:latest container_name: loki ports: - "3100:3100" volumes: - ./loki/data:/loki # 数据持久化目录 networks: - loki-network # 不指定command,使用镜像默认配置 grafana: image: grafana/grafana:latest container_name: grafana ports: - "3000:3000" environment: - GF_SECURITY_ADMIN_PASSWORD=admin - GF_AUTH_ANONYMOUS_ENABLED=false volumes: - ./grafana/data:/var/lib/grafana networks: - loki-network depends_on: - loki

注意:此处去掉了version字段(避免警告),并未挂载loki/conf,让Loki使用内置默认配置。数据目录./loki/data./grafana/data需提前创建并赋予正确权限。

3.3 准备数据目录并解决权限问题

Loki和Grafana容器内均以非root用户运行(Loki用户uid约为10001,Grafana用户uid为472),需要宿主机目录具有写权限。

快速解决(测试环境)

# 创建目录 mkdir -p ./loki/data ./grafana/data # 赋予所有用户读写执行权限(777) chmod 777 ./loki/data ./grafana/data

更安全的做法(生产推荐)

# 为Loki目录设置uid 10001(可通过docker run --rm grafana/loki id -u确认) sudo chown -R 10001:10001 ./loki/data # 为Grafana目录设置uid 472 sudo chown -R 472:472 ./grafana/data

3.4 启动服务

docker compose up -d

检查容器状态:

docker ps

验证Loki是否就绪:

curl http://localhost:3100/ready

返回ready表示成功。也可查看日志:

docker logs loki docker logs grafana

若遇到权限错误(如mkdir /loki/rules: permission deniedGF_PATHS_DATA is not writable),请按上述权限调整步骤重新执行。

4. Spring Boot集成Loki4j

4.1 添加Maven依赖

pom.xml中加入:

<dependency> <groupId>com.github.loki4j</groupId> <artifactId>loki-logback-appender</artifactId> <version>1.4.1</version> </dependency>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.5.0</version> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>springboot-loki</artifactId> <version>1.0.0</version> <name>Spring Boot Loki Integration</name> <description>Spring Boot 3.5 project with Loki4j integration</description> <properties> <java.version>17</java.version> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- Spring Boot Web Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Loki4j Logback Appender --> <dependency> <groupId>com.github.loki4j</groupId> <artifactId>loki-logback-appender</artifactId> <version>2.0.3</version> <scope>compile</scope> </dependency> <!-- Lombok (可选,简化代码) --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>

4.2 配置Logback

src/main/resources下创建或修改logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 控制台输出配置 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> <charset>UTF-8</charset> </encoder> </appender> <!-- Loki4j Appender 配置 --> <appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender"> <http> <url>http://localhost:3100/loki/api/v1/push</url> <connectionTimeoutMs>5000</connectionTimeoutMs> <requestTimeoutMs>10000</requestTimeoutMs> </http> <format> <label> <pattern>app=springboot-loki,env=local</pattern> <readMarkers>true</readMarkers> </label> <message> <pattern>${FILE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n}</pattern> </message> <sortByTime>true</sortByTime> </format> <batch> <maxItems>1000</maxItems> <maxWaitMs>5000</maxWaitMs> <maxBytes>10485760</maxBytes> </batch> <send> <minLevel>INFO</minLevel> <retry> <maxRetries>3</maxRetries> <backoffMs>1000</backoffMs> </retry> </send> </appender> <!-- 异步Loki Appender --> <appender name="ASYNC_LOKI" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="LOKI"/> <queueSize>512</queueSize> <discardingThreshold>0</discardingThreshold> <neverBlock>true</neverBlock> </appender> <!-- 根日志配置 --> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="ASYNC_LOKI"/> </root> <!-- 应用特定日志配置 --> <logger name="com.example.springbootloki" level="DEBUG" additivity="false"> <appender-ref ref="CONSOLE"/> <appender-ref ref="ASYNC_LOKI"/> </logger> </configuration>

配置要点

  • <url>指向Loki的推送端点,若Loki不在本机,替换为实际IP。

  • 标签(applicationlevel)是查询的核心,建议包含应用名、环境等。

  • 消息体可包含自定义字段,便于后续解析。

application.properties中定义应用名:

spring: application: name: springboot-loki

4.3 编写测试接口

创建测试Controller,验证日志推送:

package com.example.springbootloki.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Map; @RestController @RequestMapping("/api/logs") public class LogTestController { //https://zhengkai.blog.csdn.net/ private static final Logger logger = LoggerFactory.getLogger(LogTestController.class); /** * 基本日志测试接口 */ @GetMapping("/test") public Map<String, String> testLogs() { logger.info("这是一条INFO级别日志 - 测试Loki集成"); logger.debug("这是一条DEBUG级别日志 - 调试信息"); logger.warn("这是一条WARN级别日志 - 警告信息"); logger.error("这是一条ERROR级别日志 - 错误信息"); return Map.of( "status", "success", "message", "日志已写入Loki", "timestamp", String.valueOf(System.currentTimeMillis()) ); } }

启动Spring Boot应用,访问/test,日志便会推送至Loki。

http://localhost:8080/api/logs/test


5. 在Grafana中配置Loki数据源

  1. 浏览器访问http://<你的Ubuntu IP>:3000,登录(admin/admin)。

  2. 点击左侧齿轮图标(Configuration)→Data SourcesAdd data source

  3. 选择Loki

  4. URL 填写http://loki:3100(因为Grafana与Loki在同一Docker网络,可使用服务名)。

  5. 点击Save & Test,显示成功即可。


6. 查询日志与查看上下文

6.1 基本查询

进入Explore页面,选择Loki数据源。使用标签过滤器,例如:

  • {app="default"}查看该应用所有日志。

  • 加上level="WARN"过滤警告级别。

  • 使用|= "警告信息"进行文本搜索。

6.2 查看某条日志的上下文(关键功能)

当你在日志列表中发现一条感兴趣的日志(如WARN),想查看它之前之后的日志以了解触发背景时,可以使用Grafana的上下文功能:

  1. 鼠标悬停在目标日志行上,右侧会出现操作图标。

  2. 点击显示上下文按钮(两条横线带箭头,英文版是Content)。

  3. 默认会展示该条日志前后各10行日志,你可以调整行数(例如20行),点击加载。

这样就能快速分析出WARN发生前的DEBUG或INFO日志,从而定位问题根源。

原理:上下文查询基于相同标签流时间顺序,因此务必确保标签组合能唯一标识一个日志流(例如包含applicationhostcontainer等)。


7. 常见问题与排错

7.1 Loki容器启动失败,日志显示config file not found

  • 原因:未正确挂载配置文件或镜像默认路径不存在。

  • 解决:移除volumes中挂载配置目录的行,让容器使用内置默认配置。

7.2 权限错误permission denied

  • 原因:宿主机数据目录权限不足。

  • 解决chmod 777chown为容器内用户uid(Loki uid≈10001,Grafana uid=472)。

7.3 Spring Boot日志未出现在Loki

  • 检查Loki URL是否正确,确保网络可达。

  • 查看Spring Boot日志中是否有连接异常。

  • 检查Loki容器是否正常运行(docker logs loki)。

7.4 Grafana无法连接Loki数据源

  • 确保Grafana和Loki在同一网络,URL使用服务名http://loki:3100

  • 检查Loki端口是否暴露,可用curl http://localhost:3100/ready测试。


8. 总结

通过本文的实战步骤,你已成功在Ubuntu上部署Loki+Grafana,并让Spring Boot应用通过Loki4j直接将结构化日志推送至Loki。整个过程解决了配置文件缺失、权限不足等典型问题,并掌握了利用Grafana上下文功能快速回溯日志的技巧。

这套轻量级日志方案适合开发和测试环境,也可平滑迁移至生产(配合Promtail收集文件日志、使用对象存储等)。希望本文能帮助你高效构建日志系统,提升问题排查效率。


附录:清理所有容器和数据

cd ~/loki-stack docker compose down #只是shutdown docker compose down -v # -v 会删除数据卷,谨慎使用

扩展阅读

  • Loki官方文档

  • Loki4j GitHub


​ # ----------------------------------------------------- # - 🚀 Powered by Moshow郑锴 # - 🌟 Might the holy code be with you! # ----------------------------------------------------- # 🔍 公众号 👉 软件开发大百科 # 💻 CSDN 👉 https://zhengkai.blog.csdn.net # 📂 Github 👉 https://github.com/moshowgame

本文基于Ubuntu 26.04实践,其他Linux发行版类似。如有问题,欢迎留言交流。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/24 8:03:47

列车-轨道-桥梁交互仿真研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码及仿真咨询…

作者头像 李华
网站建设 2026/6/24 7:59:06

VSCode 插件推荐:让你编码效率翻倍

VSCode 插件推荐&#xff1a;让你编码效率翻倍 作为一款轻量级且功能强大的代码编辑器&#xff0c;Visual Studio Code&#xff08;简称VSCode&#xff09;凭借其丰富的插件生态&#xff0c;成为众多开发者的首选工具。通过安装合适的插件&#xff0c;你可以大幅提升编码效率&…

作者头像 李华
网站建设 2026/6/24 7:41:00

CTF实战:从流量分析到AES解密的Misc综合解题思路

1. 项目概述与核心思路拆解 最近在复盘攻防世界的一道Misc进阶题&#xff0c;题目本身融合了网络流量分析、图片隐写和密码学解密&#xff0c;非常典型&#xff0c;也很有意思。很多朋友卡在某个环节就进行不下去了&#xff0c;其实关键在于理解出题人的“串联”思路。这道题不…

作者头像 李华
网站建设 2026/6/24 7:40:18

MPC860 SCC以太网控制器:CSMA/CD协议实现与CAM接口应用

1. MPC860 SCC以太网模式&#xff1a;从协议到硬件的深度解析在嵌入式网络开发领域&#xff0c;尤其是工业控制和通信设备中&#xff0c;飞思卡尔&#xff08;现恩智浦&#xff09;的MPC860 PowerQUICC系列处理器是一个绕不开的经典。它集成的SCC&#xff08;串行通信控制器&am…

作者头像 李华
网站建设 2026/6/24 7:38:28

Metasploit实战:SSH弱口令爆破原理、自动化检测与防御策略

1. 项目概述&#xff1a;为什么SSH弱口令依然是“低垂的果实”&#xff1f; 在网络安全领域&#xff0c;SSH&#xff08;Secure Shell&#xff09;协议是远程管理服务器、传输文件最核心、最广泛使用的加密通道。它设计之初就是为了替代不安全的Telnet和FTP&#xff0c;其安全性…

作者头像 李华
网站建设 2026/6/24 7:36:14

Cursor AI原生编辑器深度配置指南:从安装陷阱到中文工作流

1. 为什么是 Cursor 而不是 VS Code&#xff1f;一个真实项目场景下的选型逻辑上周我帮团队重构一个遗留的 Python 数据清洗脚本&#xff0c;原脚本跑一次要 47 分钟&#xff0c;核心逻辑散落在 3 个文件里&#xff0c;变量命名全是df1,temp_df,final_result。我打开 VS Code&a…

作者头像 李华