Docker环境下Spring Boot与Elasticsearch通信失败问题排查
问题描述
在Docker环境中搭建Spring Boot应用与Elasticsearch通信时,遇到以下问题:
- 程序运行时抛出警告:
AbstractElasticsearchRepository : Cannot create index: Connection refused; nested exception is java.lang.RuntimeException: Connection refused - 浏览器访问
http://localhost:9200/article/_search?pretty=true提示索引不存在 - 手动运行程序(非Docker容器化)时功能正常
- 已尝试调整docker-compose和Spring配置,但问题未解决
现有配置文件
docker-compose.yml
version: '3' services: demo: container_name: demo image: demo-elastic build: . ports: - "8080:8080" depends_on: - es networks: - demo-network es: image: elasticsearch:7.6.2 environment: - discovery.type=single-node ports: - "9200:9200" networks: - demo-network networks: demo-network: driver: bridge
Dockerfile
# For Java 11 FROM adoptopenjdk/openjdk11:alpine-jre ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} demo.jar ENTRYPOINT ["java","-jar","/demo.jar"]
Config.java
@Configuration @EnableElasticsearchRepositories(basePackages = "com.example.demo.repository") public class Config extends AbstractElasticsearchConfiguration { @Value("${elasticsearch.url}") public String elasticsearchUrl; @Bean @Override public RestHighLevelClient elasticsearchClient() { final ClientConfiguration config = ClientConfiguration.builder() .connectedTo(elasticsearchUrl) .build(); return RestClients.create(config).rest(); } }
application.properties
elasticsearch.url=localhost:9200 spring.data.elasticsearch.cluster-nodes=localhost:9200
pom.xml(核心依赖)
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch --> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.6.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.6.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-elasticsearch --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>4.0.0.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> </dependencies>
解决方案
1. 修正容器间通信地址
Docker容器内的localhost指向容器自身,而非宿主机。Spring应用容器尝试连接localhost:9200时,实际是在容器内部寻找Elasticsearch,导致连接失败。
修改application.properties,改用Docker Compose中Elasticsearch的服务名es作为主机:
elasticsearch.url=es:9200 spring.data.elasticsearch.cluster-nodes=es:9200
Docker Compose会在自定义网络demo-network中自动解析服务名到对应容器的IP,确保Spring应用能正确找到Elasticsearch容器。
2. 确保Elasticsearch完全启动
depends_on仅保证容器启动顺序,不确保Elasticsearch服务就绪。添加健康检查避免Spring应用在Elasticsearch未就绪时发起连接:
修改docker-compose.yml的es服务:
es: image: elasticsearch:7.6.2 environment: - discovery.type=single-node ports: - "9200:9200" networks: - demo-network healthcheck: test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health | grep -q '\"status\":\"green\"'"] interval: 10s timeout: 10s retries: 5
修改demo服务的依赖条件:
demo: container_name: demo image: demo-elastic build: . ports: - "8080:8080" depends_on: es: condition: service_healthy networks: - demo-network
3. 统一依赖版本兼容性
Spring Boot 2.7.5对应的Spring Data Elasticsearch版本应为4.4.x,手动指定4.0.0.RELEASE可能导致版本不兼容。建议使用Spring Boot依赖管理自动控制版本:
修改pom.xml,替换Elasticsearch相关依赖:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 依赖Spring Boot自动管理版本 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> </dependencies>
Spring Boot 2.7.5默认适配Elasticsearch 7.17.x,若继续使用7.6.2需确保版本兼容,或升级Elasticsearch容器版本到7.17.x。
4. 重新构建启动服务
执行以下命令更新镜像并启动容器:
docker-compose down docker-compose build docker-compose up -d
内容的提问来源于stack exchange,提问作者Александр Гладун

