Docker网络中Spring Boot自动配置Elasticsearch失败问题
Docker网络中Spring Boot自动配置Elasticsearch无法解析容器DNS的问题及解决
问题背景
在Docker网络中部署了spring_app、hosting_db(MySQL)、elastic_search三个容器:
- 直接用curl可正常连接
elastic_search容器 - 禁用Spring自动配置、手动编写
RestHighLevelClientBean时,spring_app能成功连接Elasticsearch - 但启用自动配置、在
application.yml中指定elastic_search:9200时,Spring会忽略该配置,转而使用localhost,无法解析Elasticsearch的容器DNS名称
使用的依赖:org.springframework.boot:spring-boot-starter-data-elasticsearch
初始无效配置
spring: data: elasticsearch: cluster-nodes: elastic_search:9200 repositories: enabled: true conversions: enabled: true
后续尝试
发现使用IP地址时配置可正常工作:
spring: elasticsearch: uris: http://172.16.255.2:${ELASTIC_PORT}, http://172.16.255.3:${ELASTIC_PORT}, http://172.16.255.4:${ELASTIC_PORT} connection-timeout: 5s socket-timeout: 10s sniff: false
但MySQL配置使用容器DNS名称hosting_db完全正常:
spring: datasource: username: ${MYSQL_USER} password: ${MYSQL_PASSWORD} url: jdbc:mysql://hosting_db:3306/${MYSQL_DATABASE}
Docker Compose配置
version: '3.8' services: mysql: image: mysql:8.0 container_name: hosting_db environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} ports: - "3307:3306" volumes: - "mysql_volume:/var/lib/mysql" networks: - spring_boot_network spring: build: context: . dockerfile: Dockerfile container_name: spring_app env_file: - .env depends_on: - mysql - elastic volumes: - "${HOSTING_APP_LOCATION}/spring_conf:/app/spring_conf" - "spring_storage:/app/spring_storage" ports: - "${HOSTING_PORT}:${HOSTING_PORT}" environment: SPRING_CONFIG_LOCATION: "file:/app/spring_conf/application.yml" networks: - spring_boot_network elastic: container_name: elastic_search image: elasticsearch:8.16.2 ports: - "${ELASTIC_PORT}:${ELASTIC_PORT}" volumes: - "elastic_volume:/usr/share/elasticsearch/data" environment: - "discovery.type=single-node" - "xpack.security.enabled=false" - "ES_JAVA_OPTS=-Xms512m -Xmx512m" networks: - spring_boot_network volumes: mysql_volume: spring_storage: elastic_volume: networks: spring_boot_network: driver: bridge ipam: driver: default config: - subnet: "172.16.255.0/24" gateway: "172.16.255.1"
解决方法
问题根源在于Spring Boot版本与Elasticsearch自动配置属性的匹配问题:
- 旧属性
spring.data.elasticsearch.cluster-nodes是针对已废弃的TransportClient设计的,而当前使用的Elasticsearch 8.x对应的Spring Boot自动配置已切换为基于RestClient的实现,需使用spring.elasticsearch.uris属性 - 使用容器DNS名称时,必须加上协议前缀(
http://或https://),否则自动配置会识别为无效配置, fallback到默认的localhost:9200
正确的自动配置配置如下:
spring: elasticsearch: uris: http://elastic_search:${ELASTIC_PORT} connection-timeout: 5s socket-timeout: 10s sniff: false data: elasticsearch: repositories: enabled: true conversions: enabled: true
至于MySQL配置可直接用容器名的原因:JDBC URL本身要求带协议前缀(jdbc:mysql://),Spring数据源解析时会直接将hosting_db作为主机名解析,Docker网络内部的DNS服务可正常解析该容器名,因此无问题。
内容的提问来源于stack exchange,提问作者theoutstandingme
相关产品推荐
相关产品推荐

