Community Edition using Docker
This page describes how to install Community Edition (CE) using Docker, to run on your x86_64 machine, laptop or server.
Prerequisites
- Docker must be installed on your machine or server (version 4.32.0 or later). Please download it from the Docker page.
- Minimum free memory: 16GB.
- Minimum storage for docker: 100GB.
- K9S installed on your machine (optional but recommended).
Special Steps needed to start WSL for Windows Machines
Windows machines require WSL to run the CE container. Please follow the steps given below to setup WSL:
Step 1: Install WSL
Open PowerShell as Administrator and run the following command to install WSL:
wsl --install
Step 2: Choose a Distribution
After installing WSL, choose a Linux distribution from the Microsoft Store. Some popular choices are Ubuntu, Debian, and Kali Linux. For example, to install Ubuntu, run:
wsl --install -d Ubuntu
Step 3: Set WSL2 as default
wsl --set-default-version 2
Step 4: Start the WSL shell in your local machine
wsl
There is a possibility you may encounter kernel issues with WSL, which can be resolved by updating the kernel using the installer listed on the Official Microsoft page for WSL 2 kernel update.
Try running the ./ybdce start script mentioned below.
YBDCE
ybdce script
#!/bin/bash
K8SVER="1.29.2"
DATA_DIR="`pwd`/local_data"
NODE_NAME="ybd-ce"
KUBECTL="docker exec $NODE_NAME k0s kubectl"
DOCKER_ON_MAC="false"
UPGRADE_MODE=false
# will help in upgrade if we do not want to check the OS again
ACTION=start
VERBOSE="false"
VOLUME_NAME_LFS_ALT="local_data"
VOLUME_NAME="ybd-storage"
VOLUME_NAME_RFS="ybd-storage_rfs"
VOLUME_NAME_LFS="ybd-storage_lfs"
RESTART='false'
POD_NAME='ybinst-i0-0'
NAMESPACE='ybdcens'
CE_VERSION=1.0
PASSWORD=""
# Determine the OS and CPU variant
cpu_arch=$(uname -m)
if [ "$cpu_arch" == "arm64" ]; then
arch="arm64"
elif [ "$cpu_arch" == "x86_64" ]; then
arch="amd64"
fi
IMAGE_NAME="yellowbrickdata/ybd-ce-k0s-$arch:stable"
# Detect the operating system and set DOCKER_ON_MAC
case "$OSTYPE" in
darwin*)
DOCKER_ON_MAC=true
;; # macOS
msys*)
DOCKER_ON_MAC=true
;; # Windows
linux*)
DOCKER_ON_MAC=false
;; # Linux
*)
echo "Unknown OS type: $OSTYPE"
DOCKER_ON_MAC=false
;;
esac
# Function to display general help message
ybdce_usage() {
echo "Usage: $0 [COMMAND] [OPTIONS]"
echo
echo "COMMAND:"
echo " start Start ybd ce."
echo " stop Stop ybd ce."
echo " upgrade Upgrade ybd ce."
echo " diags Get the logs from the docker container."
echo " help Display this help message."
echo " logs Collect logs from ybdce."
}
# Function to display start command help message
ybdce_start_usage() {
echo "Usage: $0 start [-d true|false] [-i image_name] [-v] [-h|--help]"
echo
echo "Options:"
echo " -d Set Docker on Mac to true or false"
echo " -i Specify the image name"
echo " -v Enable verbose mode"
echo " -p Specify a password for ybdce initial user"
echo " -h, --help Display this help message and exit"
}
# Function to display stop command help message
ybdce_stop_usage() {
echo "Usage: $0 stop [-f|--full-clean] [-r|--remove-container] [-h|--help]"
echo
echo "Options:"
echo " -f, --full-clean Delete container and the Docker volumes"
echo " -r, --remove-container Delete container"
echo " -h, --help Display this help message"
}
ybdce_upgrade_usage() {
echo "Usage: $0 upgrade [-d true|false] [-i image_name] [-v] [-h|--help]"
echo
echo "Options:"
echo " -d Set Docker on Mac to true or false"
echo " -i Specify the image name"
echo " -v Enable verbose mode"
echo " -h, --help Display this help message and exit"
}
ybdce_logs_usage() {
echo "Collect logs for ybdce."
echo "Options:"
echo " -n Specify a name for this logs. The package will be ybdce-logs-<name>.tgz"
}
# Function to print verbose logs and append to a file with a date timestamp
vlog() {
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local message="[$timestamp] $1"
if [ "$VERBOSE" = true ]; then
echo "$message"
fi
echo "$message" >> "ybdce-diags.txt"
}
container_resume(){
while true; do
# if the container is up and running
if [ $(docker ps --filter "name=^/${NODE_NAME}$" --format '{{.Names}}') ]; then
vlog "Container is up and running"
return 1
else
echo "Container is still waiting to spin up. Restarting it now"
docker start ${NODE_NAME}
fi
sleep 5
done
}
node_ready() {
local node_name node_ready
node_name=$1
# making sure the container has not errored out
container_resume
sleep 5
if [ -z ${node_name} ]; then
vlog "A node name must be specified to check if it's ready" >&2
return 1
fi
k0s_ready=$(docker exec $NODE_NAME k0s status)
node_ready=$(${KUBECTL} get node ${node_name} -o jsonpath='{.status.conditions[3].status}')
if [ $? != 0 ]; then
return 3
fi
if [ ${node_ready} == True ]; then
vlog "node ${node_name} is ready."
return 0
else
return 1
fi
}
create_volumes(){
# Check if Docker volume exists and create it if it doesn't
VOLUME_NAME="ybd-storage"
VOLUME_NAME_RFS="ybd-storage_rfs"
VOLUME_NAME_LFS="ybd-storage_lfs"
if ! docker volume ls --format '{{ .Name }}' | grep -qw $VOLUME_NAME; then
vlog "Docker volume $VOLUME_NAME does not exist. Creating..."
docker volume create $VOLUME_NAME
docker volume create $VOLUME_NAME_RFS
if [[ ${DOCKER_ON_MAC} == "true" ]]; then
MNT_DIR=/host_mnt$DATA_DIR
docker volume create --driver local -o o=bind -o type=none -o device=$MNT_DIR $VOLUME_NAME_LFS 2>&1
else
VOLUME_NAME_LFS=$DATA_DIR
fi
else
vlog "Docker volume $VOLUME_NAME already exists."
fi
}
create_container(){
# creating the container
docker run -d --name $NODE_NAME --hostname $NODE_NAME --privileged -v $VOLUME_NAME_RFS:/var/lib/k0s --cgroupns=host -v $VOLUME_NAME:/mnt/ \
-e PASSWORD="$PASSWORD" \
-v $VOLUME_NAME_LFS:/local_data/ -v /sys/fs/cgroup:/sys/fs/cgroup:rw -p 7443:6443 -p 5432:5432 -p 8443:443 $IMAGE_NAME 2>&1
if [ $? -ne 0 ]; then
vlog "Failed to run the Docker container. Please check the docker image."
exit 1
else
vlog "Docker container started successfully."
fi
}
start_controlplane() {
# call the function to create volumes
create_volumes
# if we are in upgrade mode
if [[ $UPGRADE_MODE == true ]]; then
# checking if container exists
if [ $(docker ps -a --filter "name=^/${NODE_NAME}$" --format '{{.Names}}') ]; then
echo "Container ${NODE_NAME} exists."
echo "Do you want to stop the container and conitnue upgrading (y/n)?"
read -r REPLY
if [[ $REPLY == y ]]; then
ybdce_stop -r
echo "Proceeding with the upgrade"
else
UPGRADE_MODE=false
echo "Nothing will be done. Exiting upgrade."
exit 0
fi
else
vlog "Container ${NODE_NAME} does not exist. Proceeding to create it now."
fi
create_container
else
# Check if container exists
if [ $(docker ps -a --filter "name=^/${NODE_NAME}$" --format '{{.Names}}') ]; then
vlog "Container ${NODE_NAME} exists."
# Check if container is not running
if [ $(docker ps --filter "name=^/${NODE_NAME}$" --format '{{.Names}}') ]; then
vlog "Container ${NODE_NAME} is running. Please use the upgrade option to upgrade your image."
exit 1
else
vlog "Container ${NODE_NAME} is not running. Restarting it now."
container_resume
RESTART=true
fi
else
vlog "Container ${NODE_NAME} does not exist. Creating it now."
create_container
fi
fi
}
# progress bar in green
show_progress() {
local duration=$1
local pid=$2
local elapsed=0
local bar_length=50
local max_elapsed=45 # Maximum duration before restarting the bar if duration is zero
local green=$(tput setaf 2) # Set text color to green
local reset=$(tput sgr0) # Reset text color
while true; do
if [[ $duration -ne 0 ]]; then
while [ $elapsed -le $duration ]; do
local progress=$(( ($elapsed * $bar_length) / $duration ))
local remainder=$(( $bar_length - $progress ))
printf "\r["
for ((i = 0; i < $progress; i++)); do printf "${green}-"; done
for ((i = 0; i < $remainder; i++)); do printf " "; done
printf "] %d%%" $(( ($elapsed * 100) / $duration ))
sleep 1
elapsed=$(( elapsed + 1 ))
done
break
else
# Progress bar that restarts if duration is zero
local effective_elapsed=$((elapsed % max_elapsed))
local progress=$(( (effective_elapsed * bar_length) / max_elapsed ))
local remainder=$(( bar_length - progress ))
printf "\r["
for ((i = 0; i < progress; i++)); do printf "${green}-"; done
for ((i = 0; i < remainder; i++)); do printf " "; done
printf "] %d seconds elapsed" $elapsed
fi
sleep 1
elapsed=$(( elapsed + 1 ))
if [[ -n "$pid" ]]; then
if ! ps -p $pid > /dev/null 2>&1; then
break
fi
fi
done
printf "${reset}\n"
}
ybdce_start(){
echo ""
vlog "Running in Verbose Mode..."
vlog "DOCKER ON MAC = $DOCKER_ON_MAC"
vlog "Upgrade Mode = $UPGRADE_MODE"
vlog "IMAGE = $IMAGE_NAME"
mkdir -p ${DATA_DIR}
# Start the controplane with the configuration provided
echo "Starting install of Yellowbrick Community Edition v$CE_VERSION"
echo "------------------------------------------------------"
echo ""
echo "Executing Step 1/4: Infrastructure"
start_controlplane
vlog "Waiting for Infrastructure to Initailize"
# wait for control plane to start before moving ahead
echo "Executing Step 2/4: System Intialization"
duration=30 # Total time for the progress bar (in seconds)
echo "-- This can take multiple minutes to complete --"
show_progress $duration
while true; do
if node_ready $NODE_NAME; then
break
else
vlog "Waiting for System to become Ready"
fi
sleep 5 # Wait for 5 seconds before checking again
done
while [ "$RESTART" = true ]; do
status=$(docker exec "$NODE_NAME" k0s kubectl get pod "$POD_NAME" -n "$NAMESPACE" | grep "$POD_NAME" | awk '{print $3}')
if [ "$status" = "Unknown" ]; then
break
fi
sleep 0.1
done
echo "Executing Step 3/4: Pod Status Check"
vlog "Checking if the pod is up and running"
# Loop untill we can make sure the pod ybinst-i0-0 is up and running
while [ "$RESTART" = true ]; do
# Check if the status of each container in the pod
READY_STATUS=$(docker exec $NODE_NAME k0s kubectl get pod $POD_NAME -n $NAMESPACE -o custom-columns="READY:.status.containerStatuses[*].ready" --no-headers)
vlog "Running status of each container = $READY_STATUS"
# Count the number of "true" values in the READY_STATUS to get the number of running containers
RUNNING_CONTAINERS=$(echo $READY_STATUS | grep -o "true" | wc -l | xargs)
# Check if the status is "Running"
if [ "$RUNNING_CONTAINERS" = "3" ]; then
break
else
vlog "Pod $POD_NAME is not fully running. Waiting..."
fi
sleep 10
done
vlog "Pod $POD_NAME is running."
# Export the kubeconfig to allow local access for the pods
docker exec $NODE_NAME cat /var/lib/k0s/pki/admin.conf > ybd_ce_config
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' 's|localhost:6443|localhost:7443|g' ybd_ce_config
else
sed -i 's|localhost:6443|localhost:7443|g' ybd_ce_config
fi
chmod 0600 ybd_ce_config
vlog "kubeconfig is saved as ybd_ce_config"
echo "Executing Step 4/4: Service and Cluster Check"
vlog "------Checking if the Service is Up. This will take a few minutes initially------"
if [ "$VERBOSE" == true ]; then
docker exec $NODE_NAME /opt/community_edition/check_service.sh -v
vlog "------YBD service is up. Configuring the worker------"
docker exec $NODE_NAME /opt/community_edition/check_cluster_availability.sh -v
else
(docker exec $NODE_NAME /opt/community_edition/check_service.sh) &
pid=$!
show_progress 0 $pid
wait $pid
vlog "------YBD service is up. Configuring the worker------"
docker exec $NODE_NAME /opt/community_edition/check_cluster_availability.sh
fi
echo ""
echo "The Cluster is up and running with the following settings:"
echo ""
get_password
echo ""
ybdce_get_diags ybdce_install_diags
docker cp $NODE_NAME:/opt/community_edition/ybdce-diags.txt temp_1.txt && cat temp_1.txt >> ybdce-diags.txt && rm -f temp_1.txt
}
# Function to get the password from the logs
get_password() {
logs=$(docker logs ybd-ce 2>&1)
# URL and link text
URL="https://localhost:8443/"
LINK_TEXT="Yellowbrick UI:"
# Print Markdown link
echo "$LINK_TEXT ($URL)"
# Echo the username for the instance
echo "Username : 'ybdadmin'"
# Filter the logs for the desired string
password=$(echo "$logs" | grep "YB instance generated password:")
echo "Password : $password"
}
# Function to display a warning message
display_warning() {
echo "Warning: This would delete Docker volumes: $VOLUME_NAME $VOLUME_NAME_RFS $VOLUME_NAME_LFS $VOLUME_NAME_LFS_ALT"
}
# Function to display a warning message
delete_container() {
echo "Deleting Docker container: $NODE_NAME"
docker rm -f $NODE_NAME
rm -f ybd_ce_config
}
# Function to delete the Docker volume
delete_volume() {
echo "Deleting Docker volume: $VOLUME_NAME"
docker volume rm -f $VOLUME_NAME $VOLUME_NAME_RFS $VOLUME_NAME_LFS $VOLUME_NAME_LFS_ALT
}
ybdce_stop(){
# stopping the container
docker stop $NODE_NAME
# Check if any argument is passed
if [ "$#" -eq 1 ]; then
case $1 in
-f|--full-clean)
display_warning
delete_container
delete_volume
;;
-r|--remove-container)
delete_container
;;
-h|--help)
ybdce_stop_usage
exit 0
;;
*)
echo "Invalid option: $1"
ybdce_stop_usage
exit 1
;;
esac
else
echo "Not deleting the container."
echo "Not deleting the volumes."
fi
}
ybdce_upgrade(){
vlog "Running upgrade script"
UPGRADE_MODE=true
ybdce_start
ybdce_get_diags ybdce_upgrade_diags
docker cp $NODE_NAME:/opt/community_edition/ybdce-diags.txt temp_1.txt && cat temp_1.txt >> ybdce-diags.txt && rm -f temp_1.txt
}
ybdce_get_diags(){
diags_name=$1
local timestamp=$(date '+%Y-%m-%d_%H-%M-%S')
echo "Creating full diagnostics"
docker logs -t $NODE_NAME >> ${diags_name}-${timestamp}.txt 2>&1
echo "The diags are stored in the current directory with the name '${diags_name}-${timestamp}.txt'"
}
# Main function call logic
ACTION=$1
shift || true
case $ACTION in
diags)
ybdce_get_diags ybdce_diags
exit 0
;;
start)
for arg in "$@"; do
case $arg in
--help)
ybdce_start_usage
exit 0
;;
esac
done
while getopts ":d:i:p:hv" opt; do
case ${opt} in
d)
DOCKER_ON_MAC="$OPTARG"
;;
i)
IMAGE_NAME="$OPTARG"
;;
h)
ybdce_start_usage
exit 0
;;
p)
PASSWORD="$OPTARG"
;;
v)
VERBOSE=true
;;
:)
echo "Option -$OPTARG requires an argument." >&2
ybdce_start_usage
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" >&2
ybdce_start_usage
exit 1
;;
esac
done
ybdce_start
exit 0
;;
stop)
for arg in "$@"; do
case $arg in
--help)
ybdce_stop_usage
exit 0
;;
--full-clean)
ybdce_stop -f
exit 0
;;
--remove-container)
ybdce_stop -f
exit 0
;;
esac
done
while getopts ":frh" opt; do
case ${opt} in
f)
ybdce_stop -f
exit 0
;;
r)
ybdce_stop -r
exit 0
;;
h)
ybdce_stop_usage
exit 0
;;
:)
echo "Option -$OPTARG requires an argument." >&2
ybdce_stop_usage
exit 1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
ybdce_stop_usage
exit 1
;;
esac
done
ybdce_stop
exit 0
;;
upgrade)
for arg in "$@"; do
case $arg in
--help)
ybdce_upgrade_usage
exit 0
;;
esac
done
while getopts ":d:i:hv" opt; do
case ${opt} in
d)
DOCKER_ON_MAC="$OPTARG"
;;
i)
IMAGE_NAME="$OPTARG"
;;
h)
ybdce_upgrade_usage
exit 0
;;
v)
VERBOSE=true
;;
:)
echo "Option -$OPTARG requires an argument." >&2
ybdce_upgrade_usage
exit 0
;;
\?)
echo "Invalid option: -$OPTARG" >&2
ybdce_upgrade_usage
exit 1
;;
esac
done
ybdce_upgrade
exit 0
;;
logs)
for arg in "$@"; do
case $arg in
--help)
ybdce_logs_usage
exit 0
;;
esac
done
while getopts ":n:" opt; do
case ${opt} in
n)
NAME="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
ybdce_logs_usage
exit 1
;;
esac
done
if ! docker container inspect ybd-ce &>/dev/null; then
echo "YBD CE doesn't exist. Use `$0 start` to start." >&2
fi
NAME=${NAME:-$(date +%Y%m%d%H%M%S%3N)}
docker exec ybd-ce bash /collect_logs.sh -o /tmp -p -n $NAME && docker cp ybd-ce:/tmp/ybdce-logs-$NAME.tgz ./
echo "ybdce-logs-$NAME.tgz is created."
exit 0
;;
config)
get_password
exit 0
;;
help|-h|--help)
ybdce_usage
exit 0
;;
"")
ybdce_usage
exit 0
;;
*)
echo "Unsupported action. '$ACTION'"
exit 1
;;
esac
If you encounter issues with the formatting of the ./ybdce script, you can convert it to an acceptable format and then re-run it as follows:
sudo apt-get install dos2unix
dos2unix ./ybdce
Instructions for YBDCE script
The CE image can be pulled automatically for your OS, so there is no need to provide images explicitly. However, if you want to work with a specific image, you can pass it as an option with -i
.
The Community Edition Images can be found at the yellowbrickdata dockerhub page.
Access all available commands for ybdce by running the following command:
% ./ybdce
Usage: ./ybdce [COMMAND] [OPTIONS]
COMMAND:
start Start ybd ce.
stop Stop ybd ce.
upgrade Upgrade ybd ce.
help Display this help message.
To start CE and install the container, use the following command:
% ./ybdce start -h
Usage: ./ybdce start [-d true|false] [-i image_name] [-v] [-h|--help]
Options:
-d Set Docker on Mac to true or false
-i Specify the image name
-v Enable verbose mode
-h, --help Display this help message and exit
For example, to start a simple CE installation, use the following command:
./ybdce start
You do not need to explicitely pass the -d option as the script auto detects the OS and sets the -d value accordingly. By default, -d is set to off.
The start script performs the following tasks:
Creates volumes, sets up the pods, and the ybd-ce container.
Auto detects the available memory and switches between a medium-v1 and a large-v1 configuration with appropriate WLM Resource Pools. The switch occurs at 16GB of memory.
Checks if the service endpoint is up.
Ensures that the cluster is running.
Outputs the password for the UI, which can be accessed at localhost:8443 with the username ybadmin.
Note: Other options supported for the start script are stop and upgrade. Their syntax and usage can be found by running:
./ybdce stop -h
or ./ybdce upgrade -h
To monitor the state of kubernetes cluster being spun up in the backend, you can use K9S with the following command:
k9s --kubeconfig ./ybd_ce_config
You can access YBSQL using the following command or by using the tools container and pointing it to the CE instance running on your machine by passing -h localhost
docker exec -it ybd-ce k0s kubectl exec -it -n ybdcens ybinst-i0-0 -c ybinst-pg -- ybsql yellowbrick
The instructions for using the tools container can be found on the YBTools Docker Installation Page.
You can also try using local LOAD TABLE
by placing files in the local_data directory. A default location called default_mount_loc has been created for you to use.
For details on Advanced Docker Usage, click here.