diff --git a/5.0/Dockerfile b/5.0/Dockerfile new file mode 100644 index 0000000..d6125fc --- /dev/null +++ b/5.0/Dockerfile @@ -0,0 +1,178 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + +FROM eclipse-temurin:17-jre-focal + +# explicitly set user/group IDs +RUN set -eux; \ + groupadd -r cassandra --gid=999; \ + useradd -r -g cassandra --uid=999 cassandra + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ +# solves warning: "jemalloc shared library could not be preloaded to speed up memory allocations" + libjemalloc2 \ +# "free" is used by cassandra-env.sh + procps \ +# "cqlsh" needs a python interpreter + python3 \ +# "ip" is not required by Cassandra itself, but is commonly used in scripting Cassandra's configuration (since it is so fixated on explicit IP addresses) + iproute2 \ +# Cassandra will automatically use numactl if available +# https://github.com/apache/cassandra/blob/18bcda2d4c2eba7370a0b21f33eed37cb730bbb3/bin/cassandra#L90-L100 +# https://github.com/apache/cassandra/commit/604c0e87dc67fa65f6904ef9a98a029c9f2f865a + numactl \ + ; \ + rm -rf /var/lib/apt/lists/*; \ +# https://issues.apache.org/jira/browse/CASSANDRA-15767 ("bin/cassandra" only looks for "libjemalloc.so" or "libjemalloc.so.1" which doesn't match our "libjemalloc.so.2") + libjemalloc="$(readlink -e /usr/lib/*/libjemalloc.so.2)"; \ + ln -sT "$libjemalloc" /usr/local/lib/libjemalloc.so; \ + ldconfig + +# grab gosu for easy step-down from root +# https://github.com/tianon/gosu/releases +ENV GOSU_VERSION 1.16 +RUN set -eux; \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends ca-certificates gnupg wget; \ + rm -rf /var/lib/apt/lists/*; \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true + +ENV CASSANDRA_HOME /opt/cassandra +ENV CASSANDRA_CONF /etc/cassandra +ENV PATH $CASSANDRA_HOME/bin:$PATH + +# https://cwiki.apache.org/confluence/display/CASSANDRA2/DebianPackaging#DebianPackaging-AddingRepositoryKeys +# $ docker run --rm buildpack-deps:bullseye-curl bash -c 'wget -qO- https://downloads.apache.org/cassandra/KEYS | gpg --batch --import &> /dev/null && gpg --batch --list-keys --with-fingerprint --with-colons' | awk -F: '$1 == "pub" && $2 == "-" { pub = 1 } pub && $1 == "fpr" { fpr = $10 } $1 == "sub" { pub = 0 } pub && fpr && $1 == "uid" && $2 == "-" { print "#", $10; print "\t" fpr " \\"; pub = 0 }' +ENV GPG_KEYS \ +# Eric Evans + CEC86BB4A0BA9D0F90397CAEF8358FA2F2833C93 \ +# Eric Evans + C4965EE9E3015D192CCCF2B6F758CE318D77295D \ +# Sylvain Lebresne (pcmanus) + 5AED1BF378E9A19DADE1BCB34BD736A82B5C1B00 \ +# T Jake Luciani + 514A2AD631A57A16DD0047EC749D6EEC0353B12C \ +# Michael Shuler + A26E528B271F19B9E5D8E19EA278B781FE4B2BDA \ +# Michael Semb Wever + A4C465FEA0C552561A392A61E91335D77E3E87CB \ +# Alex Petrov + 9E66CEC6106D578D0B1EB9BFF1000962B7F6840C \ +# Jordan West + C4009872C59B49561310D966D0062876AF30F054 \ +# Brandon Williams + B7842CDAF36E6A3214FAE35D5E85B9AE0B84C041 \ +# Ekaterina Buryanova Dimitrova (CODE SIGNING KEY) + 3E9C876907A560ACA00964F363E9BAD215BBF5F0 \ +# Sam Tunnicliffe (CODE SIGNING KEY) + F8B7FD00E05C932991A2CD6150EE103D162C5A55 \ +# Stefan Miklosovic + 7464AAD9068241C50BA6A26232F35CB2F546D93E \ +# Berenguer Blasi (Code Signing Key) + CEC5C50B9C629EF0F5AB2706650B72EB14CCD622 + +ENV CASSANDRA_VERSION 5.0-alpha1 +ENV CASSANDRA_SHA512 095aede626067da34fc60c04c528030e3860d7489752a9200cf0bcffd93f18c1158512759bb56b85d65def98cfec3580a9edea9dfa5addfd80bd4ceab8a84ebf + +RUN set -eux; \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends ca-certificates gnupg wget; \ + rm -rf /var/lib/apt/lists/*; \ + \ + ddist() { \ + local f="$1"; shift; \ + local distFile="$1"; shift; \ + local success=; \ + local distUrl=; \ + for distUrl in \ +# https://issues.apache.org/jira/browse/INFRA-8753?focusedCommentId=14735394#comment-14735394 + 'https://www.apache.org/dyn/closer.cgi?action=download&filename=' \ +# if the version is outdated (or we're grabbing the .asc file), we might have to pull from the dist/archive :/ + https://www-us.apache.org/dist/ \ + https://www.apache.org/dist/ \ + https://archive.apache.org/dist/ \ + ; do \ + if wget --progress=dot:giga -O "$f" "$distUrl$distFile" && [ -s "$f" ]; then \ + success=1; \ + break; \ + fi; \ + done; \ + [ -n "$success" ]; \ + }; \ + \ + ddist 'cassandra-bin.tgz' "cassandra/$CASSANDRA_VERSION/apache-cassandra-$CASSANDRA_VERSION-bin.tar.gz"; \ + echo "$CASSANDRA_SHA512 *cassandra-bin.tgz" | sha512sum --check --strict -; \ + \ + ddist 'cassandra-bin.tgz.asc' "cassandra/$CASSANDRA_VERSION/apache-cassandra-$CASSANDRA_VERSION-bin.tar.gz.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + for key in $GPG_KEYS; do \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ + done; \ + gpg --batch --verify cassandra-bin.tgz.asc cassandra-bin.tgz; \ + rm -rf "$GNUPGHOME"; \ + \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ + mkdir -p "$CASSANDRA_HOME"; \ + tar --extract --file cassandra-bin.tgz --directory "$CASSANDRA_HOME" --strip-components 1; \ + rm cassandra-bin.tgz*; \ + \ + [ ! -e "$CASSANDRA_CONF" ]; \ + mv "$CASSANDRA_HOME/conf" "$CASSANDRA_CONF"; \ + ln -sT "$CASSANDRA_CONF" "$CASSANDRA_HOME/conf"; \ + \ + dpkgArch="$(dpkg --print-architecture)"; \ + case "$dpkgArch" in \ + ppc64el) \ +# https://issues.apache.org/jira/browse/CASSANDRA-13345 +# "The stack size specified is too small, Specify at least 328k" + grep -- '^-Xss256k$' "$CASSANDRA_CONF/jvm-server.options"; \ + sed -ri 's/^-Xss256k$/-Xss512k/' "$CASSANDRA_CONF/jvm-server.options"; \ + grep -- '^-Xss512k$' "$CASSANDRA_CONF/jvm-server.options"; \ + ;; \ + esac; \ + \ + mkdir -p "$CASSANDRA_CONF" /var/lib/cassandra /var/log/cassandra; \ + chown -R cassandra:cassandra "$CASSANDRA_CONF" /var/lib/cassandra /var/log/cassandra; \ + chmod 1777 "$CASSANDRA_CONF" /var/lib/cassandra /var/log/cassandra; \ + chmod -R a+rwX "$CASSANDRA_CONF"; \ + ln -sT /var/lib/cassandra "$CASSANDRA_HOME/data"; \ + ln -sT /var/log/cassandra "$CASSANDRA_HOME/logs"; \ + \ +# smoke test + cassandra -v + +VOLUME /var/lib/cassandra + +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +# 7000: intra-node communication +# 7001: TLS intra-node communication +# 7199: JMX +# 9042: CQL +# 9160: thrift service +EXPOSE 7000 7001 7199 9042 9160 +CMD ["cassandra", "-f"] diff --git a/5.0/docker-entrypoint.sh b/5.0/docker-entrypoint.sh new file mode 100755 index 0000000..6549f83 --- /dev/null +++ b/5.0/docker-entrypoint.sh @@ -0,0 +1,94 @@ +#!/bin/bash +set -e + +# first arg is `-f` or `--some-option` +# or there are no args +if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then + set -- cassandra -f "$@" +fi + +# allow the container to be started with `--user` +if [ "$1" = 'cassandra' -a "$(id -u)" = '0' ]; then + find "$CASSANDRA_CONF" /var/lib/cassandra /var/log/cassandra \ + \! -user cassandra -exec chown cassandra '{}' + + exec gosu cassandra "$BASH_SOURCE" "$@" +fi + +_ip_address() { + # scrape the first non-localhost IP address of the container + # in Swarm Mode, we often get two IPs -- the container IP, and the (shared) VIP, and the container IP should always be first + ip address | awk ' + $1 != "inet" { next } # only lines with ip addresses + $NF == "lo" { next } # skip loopback devices + $2 ~ /^127[.]/ { next } # skip loopback addresses + $2 ~ /^169[.]254[.]/ { next } # skip link-local addresses + { + gsub(/\/.+$/, "", $2) + print $2 + exit + } + ' +} + +# "sed -i", but without "mv" (which doesn't work on a bind-mounted file, for example) +_sed-in-place() { + local filename="$1"; shift + local tempFile + tempFile="$(mktemp)" + sed "$@" "$filename" > "$tempFile" + cat "$tempFile" > "$filename" + rm "$tempFile" +} + +if [ "$1" = 'cassandra' ]; then + : ${CASSANDRA_RPC_ADDRESS='0.0.0.0'} + + : ${CASSANDRA_LISTEN_ADDRESS='auto'} + if [ "$CASSANDRA_LISTEN_ADDRESS" = 'auto' ]; then + CASSANDRA_LISTEN_ADDRESS="$(_ip_address)" + fi + + : ${CASSANDRA_BROADCAST_ADDRESS="$CASSANDRA_LISTEN_ADDRESS"} + + if [ "$CASSANDRA_BROADCAST_ADDRESS" = 'auto' ]; then + CASSANDRA_BROADCAST_ADDRESS="$(_ip_address)" + fi + : ${CASSANDRA_BROADCAST_RPC_ADDRESS:=$CASSANDRA_BROADCAST_ADDRESS} + + if [ -n "${CASSANDRA_NAME:+1}" ]; then + : ${CASSANDRA_SEEDS:="cassandra"} + fi + : ${CASSANDRA_SEEDS:="$CASSANDRA_BROADCAST_ADDRESS"} + + _sed-in-place "$CASSANDRA_CONF/cassandra.yaml" \ + -r 's/(- seeds:).*/\1 "'"$CASSANDRA_SEEDS"'"/' + + for yaml in \ + broadcast_address \ + broadcast_rpc_address \ + cluster_name \ + endpoint_snitch \ + listen_address \ + num_tokens \ + rpc_address \ + start_rpc \ + ; do + var="CASSANDRA_${yaml^^}" + val="${!var}" + if [ "$val" ]; then + _sed-in-place "$CASSANDRA_CONF/cassandra.yaml" \ + -r 's/^(# )?('"$yaml"':).*/\2 '"$val"'/' + fi + done + + for rackdc in dc rack; do + var="CASSANDRA_${rackdc^^}" + val="${!var}" + if [ "$val" ]; then + _sed-in-place "$CASSANDRA_CONF/cassandra-rackdc.properties" \ + -r 's/^('"$rackdc"'=).*/\1 '"$val"'/' + fi + done +fi + +exec "$@" diff --git a/versions.json b/versions.json index 547c83e..310ad84 100644 --- a/versions.json +++ b/versions.json @@ -18,5 +18,10 @@ "java": "11", "sha512": "393443a5b9849645362df2f7536e734e1fc6d513aadf440fab8dda3063553394a138805098796d35f9d4d31e2899ecab630a2ec2a44d00d5e63bed549a2e844c", "version": "4.1.3" + }, + "5.0": { + "java": "17", + "sha512": "095aede626067da34fc60c04c528030e3860d7489752a9200cf0bcffd93f18c1158512759bb56b85d65def98cfec3580a9edea9dfa5addfd80bd4ceab8a84ebf", + "version": "5.0-alpha1" } } diff --git a/versions.sh b/versions.sh index 1e4d2aa..766a27c 100755 --- a/versions.sh +++ b/versions.sh @@ -1,10 +1,15 @@ #!/usr/bin/env bash set -Eeuo pipefail -defaultJavaVersion='11' +# https://cassandra.apache.org/doc/5.0/cassandra/installing/installing.html#prerequisites +# https://cassandra.apache.org/doc/4.1/cassandra/getting_started/installing.html#prerequisites +# https://cassandra.apache.org/doc/3.11/cassandra/getting_started/installing.html#prerequisites +defaultJavaVersion='17' declare -A javaVersions=( [3.0]='8' [3.11]='8' + [4.0]='11' + [4.1]='11' ) cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"