You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Compose中Spring应用无法连接Cassandra求助

问题:Spring应用通过Docker Compose连接Cassandra失败

问题背景

Spring应用依赖Cassandra数据库,将二者配置在同一个Docker Compose文件中。本地单独用Docker运行时一切正常,但通过Compose部署时,应用始终出现连接错误。

Docker Compose配置

version: "3.9"
services:
  myapplication:
    image: eclipse-temurin:17.0.7_7-jre
    working_dir: /root/app
    restart: on-failure
    command: sh -c "java -jar -Dspring.profiles.active=docker /root/app/app.jar"
    depends_on:
      - db
    volumes:
      - jar:/root/app/
      - ./logs:/root/app/logs
  db:
    image: cassandra:5.0
    restart: always
    container_name: cassandra
    environment:
      CASSANDRA_CLUSTER_NAME: app
    ports:
      - "9042:9042"
      - "9160:9160"
      - "7199:7199"
    volumes:
      - cas_data:/var/lib/cassandra
volumes:
  cas_data:
    driver: local
networks:
  default:
    name: my-application

Spring应用配置

spring.cassandra.schema-action=CREATE_IF_NOT_EXISTS
#spring.cassandra.request.timeout=10s
#spring.cassandra.connection.connect-timeout=10s
#spring.cassandra.connection.init-query-timeout=20s
#spring.cassandra.keyspace-name=app
#spring.data.cassandra.port=9042
spring.data.cassandra.contact-points=cassandra
spring.cassandra.local-datacenter=datacenter1

排查测试

在应用容器内通过nc命令可正常连接cassandra服务的9042端口:

# nc -zv cassandra 9042
Connection to cassandra (192.xxx.xxx.x) 9042 port [tcp/*] succeeded!

错误日志

应用抛出连接错误:

Caused by: com.datastax.oss.driver.api.core.AllNodesFailedException: Could not reach any contact point, make sure you've provided valid addresses (showing first 1 nodes, use getAllErrors() for more): Node(endPoint=/127.0.0.1:9042, hostId=null, hashCode=7b503e49): [com.datastax.oss.driver.api.core.connection.ConnectionInitException: [s0|control|connecting...] Protocol initialization request, step 1 (OPTIONS): failed to send request (io.netty.channel.StacklessClosedChannelException)]
        at com.datastax.oss.driver.api.core.AllNodesFailedException.copy(AllNodesFailedException.java:141) ~[java-driver-core-4.15.0.jar!/:na]

详细错误栈:

Suppressed: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: /127.0.0.1:9042
                Caused by: java.net.ConnectException: Connection refused
                        at java.base/sun.nio.ch.Net.pollConnect(Native Method)
                        at java.base/sun.nio.ch.Net.pollConnectNow(Unknown Source)
                        at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(Unknown Source)
                        at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:337)
                        at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334)
                        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:776)
                        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
                        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
                        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
                        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
                        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
                        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
                        at java.base/java.lang.Thread.run(Unknown Source)
        Caused by: io.netty.channel.StacklessClosedChannelException: null
                at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0()(Unknown Source)

原因分析

  1. 配置未生效:错误日志显示应用尝试连接127.0.0.1:9042,而非配置中的cassandra主机名,说明spring.data.cassandra.contact-points=cassandra配置未被正确加载。可能是Docker Profile配置文件未正确命名/放置,或Spring Boot版本导致属性前缀不兼容(比如Spring Boot 3.x推荐使用spring.cassandra.*前缀,而非spring.data.cassandra.*)。
  2. Cassandra未就绪:Compose的depends_on仅保证容器启动顺序,不保证Cassandra服务完全初始化完成,Spring应用启动时Cassandra可能还未准备好接受连接。

解决方案

1. 确保配置正确加载

  • 确认Docker Profile的配置文件命名为application-docker.properties,且放置在应用的classpath路径下。
  • 根据Spring Boot版本统一配置前缀:Spring Boot 3.x建议使用spring.cassandra.*前缀,修改配置如下:
    spring.cassandra.schema-action=CREATE_IF_NOT_EXISTS
    spring.cassandra.request.timeout=10s
    spring.cassandra.connection.connect-timeout=10s
    spring.cassandra.connection.init-query-timeout=20s
    spring.cassandra.keyspace-name=app
    spring.cassandra.port=9042
    spring.cassandra.contact-points=cassandra
    spring.cassandra.local-datacenter=datacenter1
    

2. 等待Cassandra服务就绪后启动应用

方式一:添加启动前等待脚本

修改Compose中myapplication的command,增加循环检测Cassandra端口的逻辑:

command: sh -c "until nc -zv cassandra 9042; do echo waiting for cassandra; sleep 2; done; java -jar -Dspring.profiles.active=docker /root/app/app.jar"

方式二:使用Compose健康检查

在db服务中添加健康检查,确保Cassandra服务就绪后再启动应用:

db:
  image: cassandra:5.0
  restart: always
  container_name: cassandra
  environment:
    CASSANDRA_CLUSTER_NAME: app
  ports:
    - "9042:9042"
    - "9160:9160"
    - "7199:7199"
  volumes:
    - cas_data:/var/lib/cassandra
  healthcheck:
    test: ["CMD", "cqlsh", "-u", "cassandra", "-p", "cassandra", "-e", "DESCRIBE KEYSPACES;"]
    interval: 10s
    timeout: 5s
    retries: 5

同时修改myapplication的depends_on:

depends_on:
  db:
    condition: service_healthy

3. 配置Cassandra广播地址

在db服务的环境变量中添加广播地址配置,确保Cassandra返回正确的容器主机名给客户端:

environment:
  CASSANDRA_CLUSTER_NAME: app
  CASSANDRA_LISTEN_ADDRESS: cassandra
  CASSANDRA_BROADCAST_ADDRESS: cassandra

内容的提问来源于stack exchange,提问作者Akash Jain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 21:15:03