Create keyspace automatically inside docker container with cassandra
Asked Answered
H

6

18

I was wondering if someone has tried to build a cassandra docker image with default keyspace, I've tried to do it on BUILD time but it doesn't work because cassandra is not running in that phase. It was something similar to this:

FROM cassandra:2.0
COPY ../somewhere/keyspace_definition.txt /src/keyspace_definition.txt
RUN /usr/bin/cqlsh -f /src/keyspace_definition.txt

My new approach will be to do it from the entrypoint script, but, I wanted to now if someone else has a better idea.

Happy shipping :D

Heterodyne answered 27/8, 2015 at 16:8 Comment(0)
P
21

Base on answers from @jan-oudrincky and @alexander-morozov, I build a new docker image which has a wrapper of original docker-entrypoint.sh to create keyspace when environment variable CASSANDRA_KEYSPACE is set. It will be useful in dev/test environment.

It doesn't modify docker-entrypoint.sh so even if cassandra base image has any modification you just need a rebuild.

Dockerfile

FROM cassandra

COPY entrypoint-wrap.sh /entrypoint-wrap.sh
ENTRYPOINT ["/entrypoint-wrap.sh"]
CMD ["cassandra", "-f"]

entrypoint-wrap.sh

#!/bin/bash

if [[ ! -z "$CASSANDRA_KEYSPACE" && $1 = 'cassandra' ]]; then
  # Create default keyspace for single node cluster
  CQL="CREATE KEYSPACE $CASSANDRA_KEYSPACE WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};"
  until echo $CQL | cqlsh; do
    echo "cqlsh: Cassandra is unavailable - retry later"
    sleep 2
  done &
fi

exec /docker-entrypoint.sh "$@"
Pinder answered 4/9, 2017 at 12:44 Comment(0)
T
9

Tackled this issue today. Build image, which overwrites default Cassandra docker-entrypoint.sh with one modified, appended, right before exec "$@"

for f in docker-entrypoint-initdb.d/*; do
    case "$f" in
        *.sh)     echo "$0: running $f"; . "$f" ;;
        *.cql)    echo "$0: running $f" && until cqlsh -f "$f"; do >&2 echo "Cassandra is unavailable - sleeping"; sleep 2; done & ;;
        *)        echo "$0: ignoring $f" ;;
    esac
    echo
done

Put the desired *.cql in image in docker-entrypoint-initdb.d/.

Image will start, boot up the cassandra, and retries inserting to the database unless it succeeds. Just make sure your scripts are IF NOT EXISTS otherwise the script will run indefinitely.

Tennant answered 9/3, 2017 at 15:10 Comment(3)
That's a clever solution! I'd like to add that months after I posted this question I found another way to do it, by starting the database at build time followed by a huge sleep time, then run the migrations after it and finally stop the database at the end.Heterodyne
I couldn't really follow what you are saying. How did you integrate this script into your docker container? Can you show a code example?Oneway
Append it to docker-entrypoint.sh before exec "$@" line from github.com/docker-library/cassandra for your desired version and put your cql scripts into docker-entrypoint-initdb.d and you are done. Build your own cassandra image based on that and you're done.Tennant
K
3

I'm using a Spring-Boot docker container to access my cassandra container. Everything is orchestrated by a dockr-compose. this tutorial in combination with the following code worked for me.

@Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
    CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(KEYSPACE);

    return Arrays.asList(specification);
}
Kurrajong answered 30/7, 2018 at 13:8 Comment(0)
P
0

I find it interesting that nobody responded to this yet. You can follow that they did with MySQL running in a container I supposed.

Refer to this link: http://www.luiselizondo.net/a-tutorial-on-how-to-use-mysql-with-docker/

Any script you put in that directory will be executed through the /entrypoint.sh script. Looks like Cassandra's entrypoint.sh script does not support this yet. However! It could!

Peale answered 13/4, 2016 at 22:17 Comment(0)
C
0

I used this decisions. I deleted last line from file docker-entrypoint.sh and inserted in the end those lines:

exec "$@" > /dev/null &
sleep 30 && echo "CREATE KEYSPACE <YOUR_KEYSAPCE> WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};" | cqlsh > /dev/null && tail -n 10000 -f /var/log/cassandra/system.log

Then it's necessary to rebuild docker image.

Crowns answered 1/12, 2016 at 6:39 Comment(0)
P
0

When the container is executed for the first time, it will execute the files with extensions .sh, .cql or .cql.gz located at /docker-entrypoint-initdb.d in sort'ed order by filename. This behavior can be skipped by setting the environment variable CASSANDRA_IGNORE_INITDB_SCRIPTS to a value other than yes or true.

In order to have your custom files inside the docker image you can mount them as a volume.

$ docker run --name cassandra \
  -v /path/to/init-scripts:/docker-entrypoint-initdb.d \
  -v /path/to/cassandra-persistence:/bitnami
  bitnami/cassandra:latest

Or with docker-compose

cassandra:
  image: bitnami/cassandra:latest
  volumes:
    - /path/to/init-scripts:/docker-entrypoint-initdb.d
    - /path/to/cassandra-persistence:/bitnami

Ref: https://hub.docker.com/r/bitnami/cassandra/

Paladin answered 6/8, 2022 at 8:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.