使用docker-compose的Cassandra初始化脚本

22
我希望在我的Cassandra容器启动时创建keyspaces和列族。
我在docker-compose.yml文件中尝试了以下内容:
# shortened for clarity
cassandra:
    hostname: my-cassandra
    image: my/cassandra:latest
    command: "cqlsh -f init-database.cql"

镜像my/cassandra:latest包含/中的init-database.cql。但是这似乎不起作用。

有没有办法让这个生效?


可能是在Cassandra的Docker容器内自动创建Keyspace的重复问题。 - Oleg Estekhin
3个回答

26
我也在寻找这个问题的解决方案,以下是我实现的方法。
第二个Cassandra实例具有包含schema.cql的卷,并运行CQLSH命令。

我的版本中使用healthcheck以便我们可以摆脱sleep命令。

version: '2.2'

services:
  cassandra:
      image: cassandra:3.11.2
      container_name: cassandra
      ports:
        - "9042:9042"
      environment:
        - "MAX_HEAP_SIZE=256M"
        - "HEAP_NEWSIZE=128M"
      restart: always
      volumes:
        - ./out/cassandra_data:/var/lib/cassandra
      healthcheck:
        test: ["CMD", "cqlsh", "-u cassandra", "-p cassandra" ,"-e describe keyspaces"]
        interval: 15s
        timeout: 10s
        retries: 10

  cassandra-load-keyspace:
      container_name: cassandra-load-keyspace
      image: cassandra:3.11.2
      depends_on:
        cassandra:
          condition: service_healthy
      volumes:
        - ./src/main/resources/cassandra_schema.cql:/schema.cql
      command: /bin/bash -c "echo loading cassandra keyspace && cqlsh cassandra -f /schema.cql"

NetFlix使用sleep函数的版本

version: '3.5'

services:
  cassandra:
      image: cassandra:latest
      container_name: cassandra
      ports:
        - "9042:9042"
      environment:
        - "MAX_HEAP_SIZE=256M"
        - "HEAP_NEWSIZE=128M"
      restart: always
      volumes:
        - ./out/cassandra_data:/var/lib/cassandra

  cassandra-load-keyspace:
      container_name: cassandra-load-keyspace
      image: cassandra:latest
      depends_on:
        - cassandra
      volumes:
        - ./src/main/resources/cassandra_schema.cql:/schema.cql 
      command: /bin/bash -c "sleep 60 && echo loading cassandra keyspace && cqlsh cassandra -f /schema.cql"

P.S.我在Netflix的一个库中找到了这种方式:Netflix Repos


2
提醒一下,Docker Compose的3+版本不再支持您配置文件中使用的条件语法(https://docs.docker.com/compose/compose-file/#depends_on),这就是Netflix使用sleep的原因。 - Alexander Tsepkov
@SachinGiri 基本思路是Cassandra有自己的工具可以执行CQL - CQLSH,因此在Cassandra启动自己的Docker镜像后,镜像的第二个实例运行此工具,您可以在此行中看到 ->command: /bin/bash -c "echo loading cassandra keyspace && cqlsh cassandra -f /schema.cql" - Dias Abdraimov
哇..只是复制粘贴,就省了我一些时间。谢谢你的分享! - Sathesh
1
非常优秀的脚本,结合 Scylla 在 2023 年仍然有用。 - Josh
@Josh,你能分享一下你是如何让Scylla工作的吗?对我来说它无法正常运行,节点始终无法配置成功。 - r3wt
1
@r3wt 我曾经有同样的问题,但最终通过使用Scylla解决了。我将我的文件作为答案发布在这个Stack Overflow链接上:https://dev59.com/LaxapogBymzxlkE8zz2H#76972678 - LogDog23

14
我们最近在Cassandra的参考应用程序KillrVideo中尝试解决类似的问题。我们使用Docker Compose来启动应用程序所需的环境,其中包括DataStax Enterprise(即Cassandra)节点。我们希望该节点在第一次启动时执行一些引导操作,以安装CQL模式(使用cqlsh运行.cql文件中的语句,就像您正在尝试的那样)。基本上,我们采用的方法是为我们的Docker入口点编写一个shell脚本,该脚本:
  1. 正常启动节点,但在后台。
  2. 等待端口9042可用(这是客户端连接以运行CQL语句的地方)。
  3. 使用cqlsh -f运行一些CQL语句并初始化模式。
  4. 停止在后台运行的节点。
  5. 继续通常的Docker图像入口点,以正常启动节点(像Docker期望的前台方式)。
我们只需使用文件的存在来指示节点是否已经引导,并在启动时检查它,以确定我们是否需要执行上述逻辑或者可以正常启动。您可以在GitHub上的killrvideo-dse-docker存储库中查看结果。
这种方法有一个注意事项。这对我们非常有效,因为在我们的参考应用程序中,我们只会启动单个节点(即,我们不会创建具有多个节点的集群)。如果您运行多个节点,则可能需要确保仅有一个节点进行引导以创建模式,因为同时修改模式的多个客户端可能会导致集群出现一些问题。(这是一个已知问题,希望在某个时候能够修复。)

非常好的答案,谢谢。我刚刚尝试了你提出的类似方法,它似乎是满足我的需求的令人满意的解决方案。 - blakelead
不客气!我更新了答案,加入了关于多个节点的警告,请在这种情况下牢记这一点。 - Luke Tillman

5
我通过修补cassandra的docker-entrypoint.sh来解决这个问题,以便在启动时执行位于/docker-entrypoint-initdb.d中的shcql文件。这类似于MySQL docker容器的工作方式。
基本上,我在docker-entrypoint.sh末尾(在最后一行exec "$@"之前)添加了一个小脚本,它将在cassandra启动后运行cql脚本。简化版本如下:
INIT_DIR=docker-entrypoint-initdb.d
# this whole block will execute in the background
(
    cd $INIT_DIR
    # wait for cassandra to be ready
    while ! cqlsh -e 'describe cluster' > /dev/null 2>&1; do sleep 6; done
    echo "$0: Cassandra cluster ready: executing cql scripts found in $INIT_DIR"
    # find and execute cql scripts, in name order
    for f in $(find . -type f -name "*.cql" -print | sort); do
        echo "$0: running $f"
        cqlsh -f "$f"
        echo "$0: $f executed"
    done
) &

这个解决方案适用于所有Cassandra版本(至少在撰写时的3.11版本)。
因此,您只需构建和使用该Cassandra镜像版本,然后使用docker-compose卷向容器添加适当的初始化脚本即可。
完整的gist包含更强大的入口点补丁(以及示例),可以在这里找到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接