2
respostas

Erro de Dependência com Apache Cassandra Vector Store - Só que agora, com Docker Compose

Olá, tive um problema de dependência com "chatService" e "'vectorStore" do SpringAI neste mesmo caso, só que rodando o projeto localmente na minha máquina. A Rafaela Petelin Silvério, me ajudou a descobrir que o problema era a versão antiga do Cassandra.

Aí, após atualizar a versão do Cassandra e incluir o parâmetro de configuração "spring.ai.vectorstore.cassandra.initialize-schema=true" no application.properties, o projeto funcionou normalmente. Esse parâmetro é o que faz o SpringBoot carregar as dependências do SpringAI e permitir que o keyspace e a tabela padrão sejam criados no Cassandra Vector.

Agora, estou com problemas em executar este mesmo projeto em Containers Docker através do Docker Compose.

Estou criando um container para o MySQL, outro para o Cassandra e outro para a Aplicação, conforme os arquivos mais abaixo.

Os três containers "sobem" normalmente e consigo interagir através do docker tanto com o MySQL quanto com o Cassandra.

Novamente: o projeto funciona corretamente localmente. Porém quando executo "docker compose up --build" aparece o erro de dependência:

Error creating bean with name 'chatService': Unsatisfied dependency expressed through field 'reader': e UnsatisfiedDependencyException: Error creating bean with name 'vectorStore'

Acredito que o problema seja de algum parâmetro/variável de configuração. Desde já, Obrigado!

*** Arquivos:

docker-compose.yml

services: cassandra: image: cassandra:5.0 container_name: cassandra ports:

  • "9042:9042" networks:
  • apv-bridge volumes:
  • cassandra-data:/var/lib/cassandra

mysql: image: mysql:8.0.36 container_name: mysql #env_file: ./env/mysql.env environment: MYSQL_ALLOW_EMPTY_PASSWORD: 1 MYSQL_DATABASE: assistente

MYSQL_USER: usr

MYSQL_PASSWORD: pwd

networks:

  • apv-bridge volumes: - ./mysql-data:/var/lib/mysql restart: always depends_on:
  • cassandra

app: container_name: app build: context: . env_file: ./env/app.env restart: always ports:

  • 8080:8080 environment: SPRING_AI_CASSANDRA_VECTOR_INITIALIZE_SCHEMA: true SPRING_DATA_CASSANDRA_KEYSPACE_NAME: springframework SPRING_AI_VECTORSTORE_CASSANDRA_TABLE: ai_vector_store SPRING_CASSANDRA_LOCAL_DATACENTER: datacenter1 SPRING_DATA_CASSANDRA_CONTACT_POINTS: cassandra SPRING_DATA_CASSANDRA_PORT: 9042

depends_on:

  • cassandra networks:
  • apv-bridge

volumes: mysql-data: cassandra-data:

networks: apv-bridge: driver: bridge

Arquivo app.env:

SPRING_PROFILES_ACTIVE=prod SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/assistente?createDatabaseIfNotExist=true SPRING_DATASOURCE_USERNAME=root SPRING_DATASOURCE_PASSWORD=

SPRING_CASSANDRA_CONTACT_POINTS: cassandra SPRING_CASSANDRA_LOCAL_DATACENTER: datacenter1 SPRING_AI_CASSANDRA_VECTOR_INITIALIZE_SCHEMA: true

Arquivo application-prod.properties:

spring.application.name=apv

spring.datasource.url=${DATASOURCE_URL} spring.datasource.username=${DATASOURCE_USERNAME} spring.datasource.password=${DATASOURCE_PASSWORD} spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.show-sql: false spring.jpa.hibernate.ddl-auto=update

spring.ai.vectorstore.cassandra.initialize-schema=true spring.cassandra.local-datacenter=datacenter1 spring.cassandra.contact-points=cassandra

spring.ai.openai.api-key=${OPENAI_API_KEY} spring.ai.openai.chat.api-key=${OPENAI_API_KEY} spring.ai.openai.chat.options.temperature=0.4

2 respostas

Bom dia. Esse erro de dependência no container da aplicação (UnsatisfiedDependencyException com chatService e vectorStore) geralmente acontece porque a aplicação sobe antes do Cassandra estar totalmente pronto para aceitar conexões — mesmo com o depends_on, o Docker não espera o serviço estar "saudável", apenas que ele tenha iniciado.

Soluções possíveis

1. Adicione um healthcheck ao Cassandra no docker-compose Isso garante que o Spring Boot só inicie quando o Cassandra estiver realmente disponível.

cassandra:
  image: cassandra:5.0
  container_name: cassandra
  ports:
    - "9042:9042"
  networks:
    - apv-bridge
  volumes:
    - cassandra-data:/var/lib/cassandra
  healthcheck:
    test: ["CMD", "cqlsh", "-e", "describe keyspaces"]
    interval: 30s
    timeout: 10s
    retries: 5

Depois, na aplicação:

app:
  ...
  depends_on:
    cassandra:
      condition: service_healthy

2. Adicione um wait-for-it.sh ou wait-for-cassandra.sh* Adicione esse script ao container da aplicação para aguardar o Cassandra estar pronto:

Exemplo simples de wait-for-cassandra.sh:

#!/bin/bash

until cqlsh cassandra 9042 -e "describe keyspaces"; do
  echo "Cassandra não está pronta ainda. Aguardando..."
  sleep 5
done

echo "Cassandra está pronta. Iniciando a aplicação..."
exec java -jar app.jar

Altere o CMD do Dockerfile da aplicação para rodar esse script.

3. Verifique as variáveis do application-prod.properties

No seu application-prod.properties, você está usando variáveis como ${DATASOURCE_URL}, mas seu .env está usando SPRING_DATASOURCE_URL.

Ajuste para usar a mesma chave:

spring.datasource.url=${SPRING_DATASOURCE_URL}

Faça o mesmo com as demais, como SPRING_AI_CASSANDRA_VECTOR_INITIALIZE_SCHEMA, se quiser que venham do .env.

Olá Felipe Teixeira, obrigado pela ajuda. Estou começando com Docker agora e estou ainda meio perdido!

Alterei o arquivo Dockerfile da aplicação para o seguinte:

Estágio de construção

FROM eclipse-temurin:21-alpine AS builder

Instala o Maven para compilar a aplicação

RUN apk add --no-cache maven

WORKDIR /app

Copia o arquivo pom.xml e baixa as dependências

COPY pom.xml . RUN mvn dependency:go-offline

Copia o código-fonte e compila a aplicação

COPY src ./src RUN mvn package -DskipTests

Estágio de execução

FROM eclipse-temurin:21-alpine

WORKDIR /app

COPY wait-for-cassandra.sh . RUN chmod +x wait-for-cassandra.sh

Copia o arquivo JAR compilado do estágio de construção

COPY --from=builder /app/target/*.jar apv.jar

Expõe a porta 8080

EXPOSE 8080

Comando para executar a aplicação

#ENTRYPOINT ["java", "-jar", "apv.jar"]

CMD wait-for-cassandra.sh

No entanto, quando executo "docker compose up --build" ele informa que o arquivo wait-for-cassandra.sh não foi encontrado.

=> CACHED [app stage-1 2/5] WORKDIR /app 0.0s => CACHED [app stage-1 3/5] COPY wait-for-cassandra.sh . 0.0s => CACHED [app stage-1 4/5] RUN chmod +x wait-for-cassandra.sh app | /bin/sh: wait-for-cassandra.sh: not found

No CMD, já tentei: CMD ["wait-for-cassandra.sh"] CMD ["./wait-for-cassandra.sh"] CMD wait-for-cassandra CMD wait-for-cassandra.sh CMD ./wait-for-cassandra CMD /app/wait-for-cassandra.sh

Enfim, várias combinações e nada. Aparentemente, o arquivo de script está sendo copiado.