This commit is contained in:
2026-05-15 22:19:14 -07:00
commit f4f046263c
2058 changed files with 236159 additions and 0 deletions

56
solr/docker/README.md Normal file
View File

@@ -0,0 +1,56 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
Solr Docker
----
This Solr docker module creates both a local Docker image from the source as well as the official Solr Dockerfile.
This allows for local images to be completely compatible with the official Solr images available on DockerHub.
In order to build/test/tag your Docker images using local Solr source code, please refer to `./gradlew helpDocker` in a git checkout or a source-release download.
Please refer to the [Solr Reference Guide](https://solr.apache.org/guide/solr/latest/deployment-guide/solr-in-docker.html) for information on using the Solr Docker image.
Building from the Solr Binary Distribution
----
Officially-compliant Docker images can be built directly from the Solr binary distribution (i.e. `solr-<version>.tgz`).
A Dockerfile is included in the binary distribution, under `solr-<version>/docker/Dockerfile`, and is the same one used when building a docker image via Gradle.
The slim binary distribution can also be used by using `solr-<version>-slim` instead of `solr-<version>`.
To build the Docker image, pass the Solr TGZ as the Docker context and provide the path of the Dockerfile.
Note, that Docker will accept either a URL or a local TGZ file, but each require slightly different syntax.
Therefore custom Solr releases or official releases can be used to create custom Solr images.
```bash
docker build -f solr-X.Y.Z/docker/Dockerfile - < solr-X.Y.Z.tgz
docker build -f solr-X.Y.Z/docker/Dockerfile https://www.apache.org/dyn/closer.lua/solr/X.Y.Z/solr-X.Y.Z.tgz
docker build -f solr-X.Y.Z-slim/docker/Dockerfile https://www.apache.org/dyn/closer.lua/solr/X.Y.Z/solr-X.Y.Z-slim.tgz
```
When building the image, Solr accepts arguments for customization. Currently only one argument is accepted:
- `BASE_IMAGE`: Change the base java image for Solr. This can be used to change java versions, jvms, etc.
```bash
docker build --build-arg BASE_IMAGE=custom/jdk:17-slim -f solr-X.Y.Z/docker/Dockerfile https://www.apache.org/dyn/closer.lua/solr/X.Y.Z/solr-X.Y.Z.tgz
```
Official Image Management
----
Please refer to the `dev-docs` in [apache/solr-docker](https://github.com/apache/solr-docker) for information on how the [Official Solr Dockerfile](https://hub.docker.com/_/solr) is maintained & released.

View File

@@ -0,0 +1,56 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# docker-entrypoint for Solr docker
set -e
#
files=$(find /var/solr -name write.lock)
if [ -n "$files" ]; then
echo "removing files $files"
rm $files
else
echo "No files found."
fi
# Clear some variables that we don't want runtime
unset SOLR_USER SOLR_UID SOLR_GROUP SOLR_GID \
SOLR_CLOSER_URL SOLR_DIST_URL SOLR_ARCHIVE_URL SOLR_DOWNLOAD_URL SOLR_DOWNLOAD_SERVER SOLR_KEYS SOLR_SHA512
if [[ "$VERBOSE" == "yes" ]]; then
set -x
fi
if ! [[ ${SOLR_PORT:-} =~ ^[0-9]+$ ]]; then
SOLR_PORT=8983
export SOLR_PORT
fi
# Essential for running Solr
init-var-solr
# when invoked with e.g.: docker run solr -help
if [ "${1:0:1}" == '-' ]; then
set -- solr-foreground "$@"
fi
# execute command passed in as arguments.
# The Dockerfile has specified the PATH to include
# /opt/solr/bin (for Solr) and /opt/solr/docker (for docker-specific scripts
# like solr-foreground, solr-create, solr-precreate, solr-demo).
# Note: if you specify "solr", you'll typically want to add -f to run it in
# the foreground.
exec "$@"

View File

@@ -0,0 +1,63 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# A helper script to initialise an empty $DIR
# If you use volumes then Docker will copy the $DIR content from the container to the volume.
# If you use bind mounts, that does not happen, so we do it here.
set -e
if [[ "$VERBOSE" == "yes" ]]; then
set -x
fi
if [[ -n "${NO_INIT_VAR_SOLR:-}" ]]; then
exit 0
fi
DIR=${1:-/var/solr}
if [ ! -d "$DIR" ]; then
echo "Missing $DIR"
exit 1
fi
function check_dir_writability {
local dir="$1"
if [ ! -w "$dir" ]; then
echo "Cannot write to $dir as $(id -u):$(id -g)"
ls -ld "$dir"
exit 1
fi
}
if [ ! -d "$DIR/data" ]; then
#echo "Creating $DIR/data"
check_dir_writability "$DIR"
mkdir -m0770 "$DIR/data"
fi
if [ ! -d "$DIR/logs" ]; then
#echo "Creating $DIR/logs"
check_dir_writability "$DIR"
mkdir -m0770 "$DIR/logs"
fi
if [ ! -f "$DIR/log4j2.xml" ]; then
#echo "Copying log4j2.xml"
cp -a /opt/solr/server/resources/log4j2.xml "$DIR/log4j2.xml"
fi

View File

@@ -0,0 +1,54 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Create a core on disk
# arguments are: corename configdir
set -e
echo "Executing $0" "$@"
if [[ "${VERBOSE:-}" == "yes" ]]; then
set -x
fi
CORE=${1:-gettingstarted}
CONFIG_SOURCE="${2:-}"
if [[ -z "$CONFIG_SOURCE" ]]; then
DEFAULT_CONFIGS=(_default data_driven_schema_configs)
for config_dir in "${DEFAULT_CONFIGS[@]}"; do
config_dir="/opt/solr/server/solr/configsets/$config_dir"
if [ -d "$config_dir" ]; then
CONFIG_SOURCE="$config_dir"
break
fi
done
if [[ -z $CONFIG_SOURCE ]]; then
echo "Cannot find default config"
exit 1
fi
fi
coresdir=/var/solr/data
coredir="$coresdir/$CORE"
if [[ ! -d $coredir ]]; then
cp -r "$CONFIG_SOURCE/" "$coredir"
touch "$coredir/core.properties"
echo "Created $CORE"
else
echo "Core $CORE already exists"
fi

42
solr/docker/scripts/run-initdb Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Run the init-solr-home script and source any '.sh' scripts in
# /docker-entrypoint-initdb.d.
# This script is sourced by some of the solr-* commands, so that
# you can run eg:
#
# mkdir initdb; echo "echo hi" > initdb/hi.sh
# docker run -v $PWD/initdb:/docker-entrypoint-initdb.d solr
#
# and have your script execute before Solr starts.
#
# Note: scripts can modify the environment, which will affect
# subsequent scripts and ultimately Solr. That allows you to set
# environment variables from your scripts (though you usually just
# use "docker run -e"). If this is undesirable in your use-case,
# have your scripts execute a sub-shell.
set -e
# execute files in /docker-entrypoint-initdb.d before starting solr
while read -r f; do
case "$f" in
*.sh) echo "$0: running $f"; . "$f" ;;
*) echo "$0: ignoring $f" ;;
esac
echo
done < <(find /docker-entrypoint-initdb.d/ -mindepth 1 -type f | sort -n)

78
solr/docker/scripts/solr-create Executable file
View File

@@ -0,0 +1,78 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This script starts Solr on localhost, creates a core with "solr create",
# stops Solr, and then starts Solr as normal.
# Any arguments are passed to the "solr create".
# To simply create a core:
# docker run -P -d solr solr-create -c mycore
# To create a core from mounted config:
# docker run -P -d -v $PWD/myconfig:/myconfig solr solr-create -c mycore -d /myconfig
set -euo pipefail
echo "Executing $0" "$@"
if [[ "${VERBOSE:-}" == "yes" ]]; then
set -x
fi
# Could set env-variables for solr-fg
source run-initdb
# solr uses "-c corename". Parse the arguments to determine the core name.
CORE_NAME="$(
while (( $# > 0 )); do
if [[ "$1" == '-c' ]]; then
shift
echo "$1"
fi
shift
done
)"
if [[ -z "${CORE_NAME:-}" ]]; then
echo "Could not determine core name"
exit 1
fi
coresdir=/var/solr/data
CORE_DIR="$coresdir/$CORE_NAME"
if [[ -d $CORE_DIR ]]; then
echo "Directory $CORE_DIR exists; skipping core creation"
else
start-local-solr
echo "Creating core with:" "${@:1}"
/opt/solr/bin/solr create "${@:1}"
# See https://github.com/docker-solr/docker-solr/issues/27
echo "Checking core"
if ! wget -O - "http://localhost:${SOLR_PORT:-8983}/solr/admin/cores?action=STATUS" | grep instanceDir >/dev/null; then
echo "Could not find any cores"
exit 1
fi
echo "Created core with:" "${@:1}"
stop-local-solr
# check the core_dir exists; otherwise the detecting above will fail after stop/start
if [ ! -d "$CORE_DIR" ]; then
echo "Missing $CORE_DIR"
exit 1
fi
fi
exec solr-fg

53
solr/docker/scripts/solr-demo Executable file
View File

@@ -0,0 +1,53 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Configure a Solr demo and then run solr in the foreground
set -euo pipefail
if [[ "${VERBOSE:-}" == "yes" ]]; then
set -x
fi
# Could set env-variables for solr-fg
source run-initdb
CORE=demo
coresdir=/var/solr/data
CORE_DIR="$coresdir/demo"
if [ -d "$CORE_DIR" ]; then
echo "$CORE_DIR exists; skipping demo creation"
else
start-local-solr
echo "Creating $CORE"
/opt/solr/bin/solr create -c "$CORE"
echo "Created $CORE"
echo "Loading example data"
/opt/solr/bin/solr post -c $CORE example/exampledocs/*.xml
/opt/solr/bin/solr post -c $CORE example/exampledocs/books.json
/opt/solr/bin/solr post -c $CORE example/exampledocs/books.csv
echo "Loaded example data"
stop-local-solr
# check the core_dir exists; otherwise the detecting above will fail after stop/start
if [ ! -d "$CORE_DIR" ]; then
echo "Missing $CORE_DIR"
exit 1
fi
fi
exec solr-fg

45
solr/docker/scripts/solr-fg Executable file
View File

@@ -0,0 +1,45 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# start solr in the foreground
set -e
if [[ "$VERBOSE" == "yes" ]]; then
set -x
fi
echo "Starting Solr"
# determine TINI default. If it is already set, assume the user knows what they want
if [[ -z "${TINI:-}" ]]; then
if [[ "$$" == 1 ]]; then
# Default to running tini, so we can run with an OOM script and have 'kill -9' work
TINI=yes
else
# Presumably we're already running under tini through 'docker --init', in which case we
# don't need to run it twice.
# It's also possible that we're run from a wrapper script without exec,
# in which case running tini would not be ideal either.
TINI=no
fi
fi
if [[ "$TINI" == yes ]]; then
exec tini -- solr start -f "$@"
elif [[ "$TINI" == no ]]; then
exec solr start -f "$@"
else
echo "invalid value TINI=$TINI"
exit 1
fi

View File

@@ -0,0 +1,35 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Run the initdb, then start solr in the foreground
set -e
if [[ "$VERBOSE" == "yes" ]]; then
set -x
fi
files=$(find /var/solr -name write.lock)
if [ -n "$files" ]; then
echo "removing files $files"
rm $files
else
echo "No files found."
fi
# Could set env-variables for solr-fg
source run-initdb
exec solr-fg "$@"

View File

@@ -0,0 +1,39 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Create a core on disk and then run solr in the foreground
# arguments are: corename configdir
# To simply create a core:
# docker run -P -d solr solr-precreate mycore
# To create a core from mounted config:
# docker run -P -d -v $PWD/myconfig:/myconfig solr solr-precreate mycore /myconfig
# To create a core in a mounted directory:
# mkdir myvarsolr; chown 8983:8983 myvarsolr
# docker run -it --rm -P -v $PWD/myvarsolr://var/solr solr solr-precreate mycore
set -e
echo "Executing $0" "$@"
if [[ "${VERBOSE:-}" == "yes" ]]; then
set -x
fi
# Could set env-variables for solr-fg
source run-initdb
precreate-core "$@"
exec solr-fg

View File

@@ -0,0 +1,36 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# configure Solr to run on the local interface, and start it running in the background
set -euo pipefail
if [[ "${VERBOSE:-}" == "yes" ]]; then
set -x
fi
echo "Running solr in the background. Logs are in /var/solr/logs"
SOLR_OPTS="-Djetty.host=${SOLR_LOCAL_HOST:-localhost}" solr start
max_try=${MAX_TRY:-12}
wait_seconds=${WAIT_SECONDS:-5}
if ! wait-for-solr.sh --max-attempts "$max_try" --wait-seconds "$wait_seconds"; then
echo "Could not start Solr."
if [ -f "/var/solr/logs/solr.log" ]; then
echo "Here is the log:"
cat "/var/solr/logs/solr.log"
fi
exit 1
fi

View File

@@ -0,0 +1,26 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# stop the background Solr, and restore the normal configuration
set -e
if [[ "$VERBOSE" == "yes" ]]; then
set -x
fi
echo "Shutting down the background Solr"
solr stop

View File

@@ -0,0 +1,112 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# A helper script to wait for solr
#
# Usage: wait-for-solr.sh [--max-attempts count] [--wait-seconds seconds] [--solr-url url]
# Deprecated usage: wait-for-solr.sh [ max_attempts [ wait_seconds ] ]
set -euo pipefail
SCRIPT="$0"
if [[ "${VERBOSE:-}" == "yes" ]]; then
set -x
fi
function usage {
echo "$1"
echo "Usage: $SCRIPT [--max-attempts count] [--wait-seconds seconds ] [--solr-url url]"
exit 1
}
max_attempts=12
wait_seconds=5
if ! [[ ${SOLR_PORT:-8983} =~ ^[0-9]+$ ]]; then
echo "Invalid SOLR_PORT=${SOLR_PORT:-} environment variable specified"
exit 1
fi
solr_url="http://localhost:${SOLR_PORT:-8983}"
while (( $# > 0 )); do
case "$1" in
--help)
cat <<EOM
Usage: $SCRIPT [options]
Options:
--max-attempts count: number of attempts to check Solr is up. Default: $max_attempts
--wait-seconds seconds: number of seconds to wait between attempts. Default: $wait_seconds
--solr-url url: URL for Solr server to check. Default: $solr_url
EOM
exit 0
;;
--solr-url)
solr_url="$2";
shift 2
;;
--max-attempts)
max_attempts="$2";
shift 2;
;;
--wait-seconds)
wait_seconds="$2";
shift 2;
;;
* )
# deprecated invocation, kept for backwards compatibility
max_attempts=$1;
wait_seconds=$2;
echo "WARNING: deprecated invocation. Use $SCRIPT [--max-attempts count] [--wait-seconds seconds]"
shift 2;
break;
;;
esac
done
grep -q -E '^[0-9]+$' <<<"$max_attempts" || usage "--max-attempts $max_attempts: not a number"
if (( max_attempts == 0 )); then
echo "The --max-attempts argument should be >0"
exit 1
fi
grep -q -E '^[0-9]+$' <<<"$wait_seconds" || usage "--wait-seconds $wait_seconds: not a number"
grep -q -E '^https?://' <<<"$solr_url" || usage "--solr-url $solr_url: not a URL"
((attempts_left=max_attempts))
while (( attempts_left > 0 )); do
if wget -q -O - "$solr_url" | grep -i solr >/dev/null; then
break
fi
(( attempts_left-- ))
if (( attempts_left == 0 )); then
echo "Solr is still not running; giving up"
exit 1
fi
if (( attempts_left == 1 )); then
attempts=attempt
else
attempts=attempts
fi
echo "Solr is not running yet on $solr_url. $attempts_left $attempts left"
sleep "$wait_seconds"
done
echo "Solr is running on $solr_url"

View File

@@ -0,0 +1,179 @@
#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# A helper script to wait for ZooKeeper
#
# This script waits for a ZooKeeper master to appear.
# It repeatedly looks up the name passed as argument
# in the DNS using getent, and then connects to the
# ZooKeeper admin port and uses the 'srvr' command to
# obtain the server's status.
# You can use this in a Kubernetes init container to
# delay Solr pods starting until the ZooKeeper service
# has settled down. Or you could explicitly run this in
# the Solr container before exec'ing Solr.
#
# Inspired by https://github.com/helm/charts/blob/9eba7b1c80990233a68dce48f4a8fe0baf9b7fa5/incubator/solr/templates/statefulset.yaml#L60
#
# Usage: wait-for-zookeeper.sh [--max-attempts count] [--wait-seconds seconds] zookeeper-service-name
#
# If no argument is provided, but a Solr-style ZK_HOST is set,
# that will be used. If neither is provided, the default
# name is 'solr-zookeeper-headless', to match the helm chart.
set -euo pipefail
SCRIPT="$0"
if [[ "${VERBOSE:-}" == "yes" ]]; then
set -x
fi
function usage {
echo "$1"
echo "Usage: $SCRIPT [--max-attempts count] [--wait-seconds seconds ] zookeeper-service-name"
exit 1
}
TMP_HOSTS="/tmp/hosts.$$"
TMP_STATUS="/tmp/status.$$"
function cleanup {
rm -f $TMP_HOSTS $TMP_STATUS
}
trap cleanup EXIT
function check_zookeeper {
local host=$1
local port="${2:-2181}"
if ! echo srvr | nc "$host" "$port" > $TMP_STATUS; then
echo "Failed to get status from $host"
return
fi
if [ ! -s $TMP_STATUS ]; then
echo "No data from $ip"
return
fi
if grep -q 'not currently serving requests' $TMP_STATUS; then
echo "Node $ip is not currently serving requests"
return
fi
mode=$(grep "Mode: " $TMP_STATUS | sed 's/Mode: //');
if [ -z "$mode" ]; then
echo "Cannot determine mode from:"
cat $TMP_STATUS
return
fi
echo "Node $ip is a $mode"
if [ "$mode" = "leader" ] || [ "$mode" = "standalone" ]; then
echo "Done"
exit 0
fi
}
max_attempts=120
wait_seconds=2
while (( $# > 0 )); do
case "$1" in
--help)
cat <<EOM
Usage: $SCRIPT [options] zookeeper-service-name
Options:
--max-attempts count: number of attempts to check Solr is up. Default: $max_attempts
--wait-seconds seconds: number of seconds to wait between attempts. Default: $wait_seconds
EOM
exit 0
;;
--max-attempts)
max_attempts="$2";
shift 2;
;;
--wait-seconds)
wait_seconds="$2";
shift 2;
;;
*)
if [ -n "${lookup_arg:-}" ]; then
usage "Cannot specify multiple zookeeper service names"
fi
lookup_arg=$1;
shift;
break;
;;
esac
done
grep -q -E '^[0-9]+$' <<<"$max_attempts" || usage "--max-attempts $max_attempts: not a number"
if (( max_attempts == 0 )); then
echo "The --max-attempts argument should be >0"
exit 1
fi
grep -q -E '^[0-9]+$' <<<"$wait_seconds" || usage "--wait-seconds $wait_seconds: not a number"
if [ -z "${lookup_arg:-}" ]; then
if [ -n "$ZK_HOST" ]; then
lookup_arg="$ZK_HOST"
else
lookup_arg=solr-zookeeper-headless
fi
fi
echo "Looking up '$lookup_arg'"
# split on commas, for when a ZK_HOST string like zoo1:2181,zoo2:2181 is used
IFS=',' read -ra lookups <<< "$lookup_arg"
((attempts_left=max_attempts))
while (( attempts_left > 0 )); do
for lookup in "${lookups[@]}"; do
if grep -q -E "^\[[0-9].*\]" <<<"$lookup"; then
# looks like an IPv6 address, eg [2001:DB8::1] or [2001:DB8::1]:2181
# getent does not support the bracket notation, but does support IPv6 addresses
host=$(sed -E 's/\[(.*)\].*/\1/' <<<"$lookup")
port=$(sed -E 's/^\[(.*)\]:?//' <<<"$lookup")
else
# IPv4, just split on :
IFS=: read -ra split <<<"$lookup"
host="${split[0]}"
port="${split[1]:-}"
fi
if [[ "${VERBOSE:-}" == "yes" ]]; then
echo "Parsed host=$host port=${port:-}"
fi
if getent hosts "$host" > $TMP_HOSTS; then
while read -r ip hostname ; do
echo "${hostname:-}">/dev/null # consume for shellcheck
check_zookeeper "$ip" "$port"
done <$TMP_HOSTS
else
echo "Cannot find $lookup yet"
fi
done
(( attempts_left-- ))
if (( attempts_left == 0 )); then echo "Still no master found; giving up"
exit 1
fi
sleep "$wait_seconds"
done
# To test the parsing:
# bash scripts/wait-for-zookeeper.sh foo
# bash scripts/wait-for-zookeeper.sh 'ZK_HOST=[2001:DB8::1]:2181,[2001:DB8::1],127.0.0.1:2181,127.0.0.2'
# ZK_HOST=[2001:DB8::1]:2181,[2001:DB8::1],127.0.0.1:2181,127.0.0.2 bash scripts/wait-for-zookeeper.sh