非法字符导致spring boot微服务构建在docker镜像创建过程中失败
Posted
技术标签:
【中文标题】非法字符导致spring boot微服务构建在docker镜像创建过程中失败【英文标题】:Illegal character causes spring boot microservice build to fail during creation of docker image 【发布时间】:2020-12-16 11:38:47 【问题描述】:我正在 Spring 启动应用程序中与微服务建立相互通信。响应以 JSON 格式生成,并使用 logback.xml 记录在日志文件中。这在 ELK 端通过 docker-maven 插件得到了进一步的利用。执行 mvn clean install 时,通过 pom.xml 创建 docker 镜像时抛出异常
错误堆栈:
引起:com.spotify.docker.client.exceptions.DockerException: com.spotify.docker.client.shaded.com.fasterxml.jackson.core.JsonParseException: 非法字符((CTRL-CHAR,代码0)):只有常规空格(\r, \n, \t) 允许在标记之间 在 [来源:(文件);行:1,列:2] 在 com.spotify.docker.client.auth.ConfigFileRegistryAuthSupplier.authForBuild (ConfigFileRegistryAuthSupplier.java:108) 在 com.spotify.docker.client.auth.MultiRegistryAuthSupplier.authForBuild (MultiRegistryAuthSupplier.java:77) 在 com.spotify.docker.client.DefaultDockerClient.build (DefaultDockerClient.java:1483) 在 com.spotify.docker.client.DefaultDockerClient.build (DefaultDockerClient.java:1460) 在 com.spotify.plugin.dockerfile.BuildMojo.buildImage (BuildMojo.java:240) 在 com.spotify.plugin.dockerfile.BuildMojo.execute (BuildMojo.java:135) 在 com.spotify.plugin.dockerfile.AbstractDockerMojo.tryExecute (AbstractDockerMojo.java:265) 在 com.spotify.plugin.dockerfile.AbstractDockerMojo.execute (AbstractDockerMojo.java:254) 在 org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137) 在 org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
pom.xml:
<!-- Dockerfile from Spotify -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.11</version>
<configuration>
<repository>$docker.image.prefix/$project.artifactId</repository>
</configuration>
<executions>
<execution>
<id>default</id>
<phase>install</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
我调试了代码,找到了错误的原因。这是在以下突出显示的方法中引起的:
private List<Comment> findCommentsForFeed(Feeds feed)
log.info("Finding comments of feed with id ", feed.getId());
String url = UriComponentsBuilder.fromHttpUrl(commentServiceBaseUrl).path("comments")
.queryParam("feedId", feed.getId()).toUriString();
// ** THIS LINE CAUSES ERROR... **
ResponseEntity<List<Comment>> response = restTemplate.exchange(url, HttpMethod.GET, null,
new ParameterizedTypeReference<List<Comment>>()
);
List<Comment> comments = Objects.isNull(response.getBody()) ? new ArrayList<>() : response.getBody();
log.info("Found comment(s) of feed with id ", comments.size(), feed.getId());
return comments;
我的控制器看起来像:
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/feeds", produces = MediaType.APPLICATION_JSON_VALUE)
public class FeedController
@Autowired
private final FeedService service;
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<Feeds>> getFeeds()
List<Feeds> feeds = service.getFeeds();
return ResponseEntity.ok(feeds);
@GetMapping(path = "/id", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<FeedWithComment> getFeed(@PathVariable Long id)
FeedWithComment feedWithComments = service.getFeed(id).orElseThrow(ResourceNotFoundException::new);
return ResponseEntity.ok(feedWithComments);
我用于 json 输出的 logback.xml 文件如下所示:
<springProfile name="docker">
<appender name="jsonConsoleAppender"
class="ch.qos.logback.core.ConsoleAppender">
<encoder
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
<version />
<logLevel />
<message />
<loggerName />
<threadName />
<context />
<pattern>
<omitEmptyFields>true</omitEmptyFields>
<pattern>
"trace":
"trace_id": "%mdcX-B3-TraceId",
"span_id":
"%mdcX-B3-SpanId",
"parent_span_id": "%mdcX-B3-ParentSpanId",
"exportable": "%mdcX-Span-Export"
</pattern>
</pattern>
<mdc>
<excludeMdcKeyName>traceId</excludeMdcKeyName>
<excludeMdcKeyName>spanId</excludeMdcKeyName>
<excludeMdcKeyName>parentId</excludeMdcKeyName>
<excludeMdcKeyName>spanExportable</excludeMdcKeyName>
<excludeMdcKeyName>X-B3-TraceId</excludeMdcKeyName>
<excludeMdcKeyName>X-B3-SpanId</excludeMdcKeyName>
<excludeMdcKeyName>X-B3-ParentSpanId</excludeMdcKeyName>
<excludeMdcKeyName>X-Span-Export</excludeMdcKeyName>
</mdc>
<stackTrace />
</providers>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="jsonConsoleAppender" />
</root>
</springProfile>
【问题讨论】:
【参考方案1】:我做了一些分析,发现问题是因为 Spring boot 版本。 Springboot 2.3.0 引入后,Spring boot 的目录结构发生了变化。我正在使用 Spring Boot 版本 2.3.3。我在 dockerfile 中做了一些更改,它起作用了。 Maven docker 插件成功创建镜像。 Dockerfile:
FROM adoptopenjdk/openjdk14 as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY $JAR_FILE application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM adoptopenjdk/openjdk14
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "-Dspring.profiles.active=docker", "org.springframework.boot.loader.JarLauncher"]
【讨论】:
以上是关于非法字符导致spring boot微服务构建在docker镜像创建过程中失败的主要内容,如果未能解决你的问题,请参考以下文章
基于Spring Cloud的微服务构建学习-2 Spring Boot
Spring Cloud:构建微服务 - Spring Boot
Spring-Boot:Spring Cloud构建微服务架构