带有docker-compose的Cassandra初始化脚本

bla*_*ead 8 cassandra cqlsh docker-compose

我想在我的Cassandra容器的开头创建键空间和列族.

我在docker-compose.yml文件中尝试了以下内容:

# shortened for clarity
cassandra:
    hostname: my-cassandra
    image: my/cassandra:latest
    command: "cqlsh -f init-database.cql"
Run Code Online (Sandbox Code Playgroud)

图像my/cassandra:latest包含init-database.cql/.但这似乎不起作用.

有没有办法让这种情况发生?

Luk*_*man 9

我们最近尝试在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存储库中看到结果.

这种方法有一点需要注意.这对我们很有用,因为在我们的参考应用程序中,我们只是在单个节点上旋转(即我们没有创建具有多个节点的集群).如果您正在运行多个节点,您可能希望确保只有一个节点执行引导以创建架构,因为同时修改架构的多个客户端可能会导致群集出现问题.(这是一个已知问题,希望在某些时候得到解决.)


小智 6

我也在寻找该问题的解决方案,这就是我完成该问题的方式。
这里,Cassandra的第二个实例具有一个带有schema.cql的卷,并运行CQLSH命令

我的版本带有健康检查,因此我们可以摆脱睡眠命令

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"
Run Code Online (Sandbox Code Playgroud)

NetFlix版本使用睡眠

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"
Run Code Online (Sandbox Code Playgroud)

PS我在Netflix Repos之一中发现了这种方式

  • 请注意,docker-compose 的 3+ 版本不再允许在配置中使用条件语法(https://docs.docker.com/compose/compose-file/#depends_on),这就是 Netflix 使用睡觉。 (2认同)

Der*_*lin 5

我通过修补 cassandra 解决了这个问题,docker-entrypoint.sh以便它将在启动时执行shcql定位文件/docker-entrypoint-initdb.d。这与 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
) &
Run Code Online (Sandbox Code Playgroud)

该解决方案适用于所有 cassandra 版本(至少在撰写本文时为 3.11)。

因此,您只需构建并使用此 cassandra 映像版本,然后使用 docker-composevolumes 将适当的初始化脚本添加到容器中。

此处提供了具有更强大的入口点补丁(和示例)的完整要点。