我想在 Cassandra 容器的开头创建键空间和列族。
我在
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 的第二个实例有一个带有 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 Repos
找到了这种方式我们最近尝试在 Cassandra 的参考应用程序 KillrVideo 中解决类似问题。我们使用 Docker Compose 来启动应用程序所需的环境,其中包括 DataStax Enterprise(即 Cassandra)节点。我们希望该节点在第一次开始安装 CQL 模式时进行一些引导(使用
cqlsh
运行 .cql
文件中的语句,就像您尝试做的那样)。基本上我们采取的方法是为我们的 Docker 入口点编写一个 shell 脚本:
cqlsh -f
运行一些 CQL 语句并初始化架构。我们只是使用文件的存在来指示节点是否已经被引导,并在启动时检查该文件以确定我们是否需要执行上面的逻辑或者可以正常启动它。您可以在 GitHub 上的 killrvideo-dse-docker 存储库中查看结果。
这种方法有一个警告。这对我们来说非常有用,因为在我们的参考应用程序中,我们只旋转单个节点(即我们不会创建具有多个节点的集群)。如果您正在运行多个节点,您可能需要确保只有“一个”节点进行引导来创建架构,因为多个客户端同时修改架构可能会导致集群出现一些问题。 (这是一个已知问题,希望在某个时候得到解决。)
我通过修补 cassandra 的sh
中的
cql
和
/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
) &
此解决方案适用于所有 cassandra 版本(至少在撰写本文时为 3.11)。因此,您只需构建并使用此 cassandra 映像版本,然后使用 docker-composevolumes 将适当的初始化脚本添加到容器中。
这里
提供了完整的要点以及更强大的入口点补丁(和示例)。 您希望通过在启动期间运行 CQL 脚本,使用 Docker Compose 在 Cassandra 容器中自动创建键空间和列族。然而,问题是 Cassandra 可能无法在容器启动后立即接受查询,从而导致脚本失败。
为了确保 CQL 脚本仅在 Cassandra 完全准备好后执行,我们可以结合使用健康检查和自定义入口点脚本。运行状况检查可确保 Cassandra 运行正常,并且自定义入口点脚本会等待 Cassandra 准备就绪(nodetool 状态将节点报告为“UN”)。 Cassandra 准备就绪后,脚本将执行 CQL 文件。
version: '3.9'
services:
cassandra:
image: cassandra:5.0.0
container_name: cassandra
ports:
- "9042:9042"
volumes:
- ./cassandra_config/cassandra.yaml:/etc/cassandra/cassandra.yaml
- ./init-database.cql:/docker-entrypoint-initdb.d/init-database.cql
healthcheck:
test: ['CMD-SHELL', "nodetool status | grep '^UN' || exit 1"]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
networks:
- services
entrypoint: ["/bin/bash", "-c", "until nodetool status | grep '^UN'; do echo 'Waiting for Cassandra...'; sleep 5; done; cqlsh -f /docker-entrypoint-initdb.d/init-database.cql"]
networks:
services:
name: cassandra_network