Docker部署Spring Boot应用时Bean创建失败及Cassandra连接问题求助
我是Docker新手,尝试用docker build构建Spring Boot应用镜像,镜像创建成功,但运行时出现Bean创建失败错误。本地运行(包括直接执行jar包)完全正常,仅Docker环境下出问题。数据库是AWS上的Cassandra Keyspace,推测和连接有关。
Dockerfile
FROM openjdk:17-jdk-buster AS build WORKDIR /app COPY build.gradle settings.gradle gradlew /app/ COPY gradle /app/gradle COPY src /app/src RUN chmod +x gradlew RUN ./gradlew build --no-daemon --info FROM openjdk:17-jdk-buster WORKDIR /app COPY --from=build /app/build/libs/*.jar /app/application.jar COPY --from=build /app/build/resources/main/cassandra_truststore.jks /app/cassandra_truststore.jks EXPOSE 8000 ENTRYPOINT ["java", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseContainerSupport", "-Djava.security.egd=file:/dev/./urandom","-jar","/app/application.jar"]
Repository接口
public interface VisitorsRepository extends CassandraRepository<VisitorEntity, String> {}
Service类(手动创建Bean,未使用@Service注解)
@RequiredArgsConstructor @Slf4j public class VisitorService { @Autowired private VisitorsRepository repository; public ApiResponse execute(VisitorDto dto){ return Mono.just(repository.save(VisitorMapper.dtoToEntity(dto))) .map(visitorEntity -> ResponseMapper.buildResponse(true, HttpStatus.CREATED.value(), HttpStatus.CREATED.getReasonPhrase(), HttpStatus.CREATED.value(), HttpStatus.CREATED.getReasonPhrase()) ) .doOnSuccess(m -> log.info("entity saved")) .doOnError(error -> log.error("Error saving entity: " + error.getMessage())) .onErrorResume(error -> Mono.error(new RuntimeException(error.getMessage()))).block(); } }
Bean配置类
@Configuration public class ServiceConfiguration { @Bean public VisitorService getVisitorService(){ return new VisitorService(); } }
Controller类
@RestController @CrossOrigin(origins = "*") @RequestMapping(value = "/api") @AllArgsConstructor @Validated @Slf4j public class VisitorController { private final VisitorService service; @PostMapping("/create-visitor") public ResponseEntity<ApiResponse> execute(@RequestBody @Valid VisitorDto dto){ try{ ApiResponse apiResponse = service.execute(dto); return new ResponseEntity<ApiResponse>(apiResponse,HttpStatus.OK); }catch (Exception e){ e.getStackTrace(); throw new BadRequestException(e.getMessage()); } } }
错误日志
ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'visitorController' defined in URL [jar:nested:/app/application.jar/!BOOT-INF/classes/!/ipservice/controller/VisitorController.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'getVisitorService': Unsatisfied dependency expressed through field 'repository': Error creating bean with name 'visitorsRepository' defined in ipservice.repository.VisitorsRepository defined in @EnableCassandraRepositories declared on CassandraConfig: Cannot resolve reference to bean 'cassandraTemplate' while setting bean property 'cassandraTemplate'
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
ipservice.configuration.CassandraConfig$$SpringCGLIB$$0.session() ~[!/:0.0.1-SNAPSHOT]
Caused by: java.security.KeyManagementException: problem accessing trust store
application.yml配置
cloud: aws: stack: auto: false region: static: "us-east-1" cassandra: username: "cassandra-user-at-466964128512" password: "XXXXXXXXX" trustStoreUrl: "./src/main/resources/cassandra_truststore.jks" trustStorePassword: "XXXXXXX" keySpace: "comparaasegurate" localDatacenter: "us-east-1" resolveContactPoints: true contactPoints: "cassandra.us-east-1.amazonaws.com:9142" requestPageSize: 3500 requestTimeout: 3 requestConsistency: "LOCAL_QUORUM" reconnectOnInit: true sssEngineFactoryClass: "DefaultSslEngineFactory" sslHostnameValidation: true
问题分析
核心错误是java.security.KeyManagementException: problem accessing trust store,说明Docker容器内无法找到Cassandra的信任证书文件:
- Dockerfile中已将
cassandra_truststore.jks复制到容器的/app目录,但application.yml里的trustStoreUrl配置的是本地开发路径./src/main/resources/cassandra_truststore.jks,容器内不存在这个路径,导致SSL连接初始化失败,进而引发后续Cassandra相关Bean(如cassandraTemplate、visitorsRepository)创建失败,最终导致Controller依赖注入异常。 - 次要问题:
VisitorService同时使用@RequiredArgsConstructor和@Autowired注入仓库,手动创建Bean时@Autowired可能无法正常生效,不符合Spring依赖注入最佳实践。
解决方案
1. 修正信任证书路径
修改application.yml中的trustStoreUrl为容器内实际路径:
trustStoreUrl: "file:/app/cassandra_truststore.jks"
或利用容器工作目录/app,简化为:
trustStoreUrl: "./cassandra_truststore.jks"
2. 修复Service的依赖注入
改用构造器注入替代@Autowired,确保手动创建Bean时依赖能正确注入:
- 更新
VisitorService:
@RequiredArgsConstructor @Slf4j public class VisitorService { private final VisitorsRepository repository; public ApiResponse execute(VisitorDto dto){ // 原有业务逻辑保持不变 } }
- 更新
ServiceConfiguration:
@Configuration public class ServiceConfiguration { @Bean public VisitorService getVisitorService(VisitorsRepository repository){ return new VisitorService(repository); } }
3. 验证容器内文件(可选)
若仍有问题,可临时修改Dockerfile的ENTRYPOINT进入容器检查文件:
ENTRYPOINT ["bash"]
运行容器后执行ls /app,确认cassandra_truststore.jks存在,确保复制步骤无误。
内容的提问来源于stack exchange,提问作者Michael Torres Ospina

