Docker中Spring Boot应用无法连接Redis容器(连接被拒绝)
错误信息
ERROR 1 --- [ElasticSearch_books] [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis] with root cause java.net.ConnectException: Connection refused
环境与观察
- Spring Boot版本:3.3.5
- Redis和Spring Boot应用均已容器化运行
场景对比
- 正常场景:Spring Boot应用在本地(Docker外)运行,可正常连接Docker中的Redis
- 异常场景:两者都在Docker容器中运行时,出现连接拒绝错误
配置详情
application-docker.properties
spring.cache.type=redis spring.redis.host=redis spring.redis.port=6379
Docker Compose配置
应用与Redis处于同一自定义网络book-network,已配置Redis健康检查和depends_on依赖条件,确保Redis就绪后再启动应用。完整配置如下:
networks: book-network: driver: bridge services: app: image: elasticsearchbook:latest # 应用镜像 build: context: . dockerfile: Dockerfile ports: - "8080:8080" # 端口映射到宿主机 depends_on: elasticsearch: condition: service_healthy redis: condition: service_healthy prometheus: condition: service_healthy environment: - SPRING_PROFILES_ACTIVE=docker - SPRING_DATA_ELASTICSEARCH_HOST=elasticsearch - SPRING_DATA_ELASTICSEARCH_PORT=9200 - SPRING_REDIS_HOST=redis - SPRING_REDIS_PORT=6379 networks: - book-network restart: always redis: image: redis:alpine ports: - "6379:6379" # Redis默认端口映射 healthcheck: test: [ "CMD", "redis-cli", "ping" ] interval: 10s timeout: 5s retries: 10 networks: - book-network restart: always
已验证内容
- 网络连通性:应用容器可ping通Redis容器,且在应用容器内用
redis-cli -h redis能正常连接Redis - 环境变量:已设置
SPRING_PROFILES_ACTIVE=docker,确认应用加载了application-docker.properties
尽管完成以上检查,容器化的Spring Boot应用仍无法连接Redis,求排查方向,是否有Spring Boot 3.3.5或Docker网络相关的细节被遗漏?
1. 检查Spring Boot配置优先级冲突
你同时在application-docker.properties和Docker环境变量里配置了Redis连接参数,Spring Boot 3.x的配置优先级中,环境变量优先级高于properties文件。虽然两者配置内容一致,但如果构建镜像时不小心打包了其他环境的配置(比如application.properties里写了spring.redis.host=localhost),或者环境变量未正确覆盖,可能导致应用实际使用错误的连接地址。
可以进入应用容器,执行以下命令查看Spring Boot实际加载的配置:
java -jar your-app.jar --debug | grep redis
或者在应用启动日志里搜索RedisProperties相关内容,确认最终生效的host和port是否正确。
2. 检查Redis绑定地址
默认情况下,部分Redis镜像的配置可能绑定127.0.0.1,这会限制仅容器内部可访问。虽然你已经能从应用容器用redis-cli连接,但仍建议确认Redis的监听地址:
进入Redis容器,执行命令:
redis-cli CONFIG GET bind
如果返回结果是127.0.0.1,需要修改Redis配置,让它绑定0.0.0.0以允许外部容器访问。可以在docker-compose的redis服务中添加启动命令:
redis: image: redis:alpine command: redis-server --bind 0.0.0.0 # 其余配置保持不变
3. 切换Redis客户端测试
Spring Boot 3.3.x默认使用Lettuce作为Redis客户端,可能存在初始化时的网络延迟或DNS解析问题。可以尝试切换为Jedis客户端,排查是否为客户端兼容性问题:
在pom.xml(Maven)中添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
4. 优化容器启动顺序的健康检查
虽然配置了depends_on的service_healthy,但Redis的ping检查通过时,可能服务还未完全就绪(比如加载数据或完成初始化)。可以修改健康检查命令为更严格的测试:
redis: healthcheck: test: [ "CMD", "redis-cli", "info", "server" ] interval: 10s timeout: 5s retries: 10
或者在应用的启动脚本中添加延迟,给Redis更多初始化时间:
sleep 10 && java -jar your-app.jar
5. 检查Docker网络DNS解析
虽然能ping通Redis,但Spring Boot应用启动时可能出现DNS解析延迟或缓存问题。可以在应用容器中手动测试DNS解析:
nslookup redis
如果解析正常,可尝试在应用的JVM参数中禁用DNS缓存,确保每次连接都重新解析地址:
-Dsun.net.inetaddr.ttl=0
内容的提问来源于stack exchange,提问作者Aenbiarshy

