Skip to content

Instantly share code, notes, and snippets.

@sycomix
Last active July 30, 2025 00:03
Show Gist options
  • Select an option

  • Save sycomix/68f19b2c9504349662ad13e8d1efe855 to your computer and use it in GitHub Desktop.

Select an option

Save sycomix/68f19b2c9504349662ad13e8d1efe855 to your computer and use it in GitHub Desktop.
qdrant-docker-tools
#!/bin/bash
# ==============================================================================
# Unified Qdrant Docker Troubleshooter (v3)
#
# This script combines various diagnostic checks for a Qdrant instance
# running in Docker into a single, easy-to-use tool.
#
# It now includes a comprehensive batch test and report option.
#
# Usage:
# ./qdrant_troubleshooter.sh [command]
#
# If no command is provided, it will display an interactive menu.
# ==============================================================================
# --- Configuration ---
# Please edit these variables to match your environment.
# The name or ID of your primary Qdrant container.
QDRANT_CONTAINER_NAME="qdrant"
# The host and port for the Qdrant API.
QDRANT_HOST="localhost:6333"
# --- End of Configuration ---
# --- Helper Functions ---
# Function to print a colored header
print_header() {
echo
echo "================================================="
echo " $1"
echo "================================================="
echo
}
# Function to dynamically get the list of collections and have the user select one
select_collection() {
print_header "Fetching Collections"
# Fetch collections and parse names. This avoids needing jq.
collections=($(curl -s "http://$QDRANT_HOST/collections" | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"//'))
if [ ${#collections[@]} -eq 0 ]; then
echo "No collections found or could not connect to Qdrant at http://$QDRANT_HOST."
return 1
fi
echo "Please select a collection:"
select col in "${collections[@]}"; do
if [ -n "$col" ]; then
SELECTED_COLLECTION=$col
echo "You selected: $SELECTED_COLLECTION"
return 0
else
echo "Invalid selection. Please try again."
fi
done
return 1
}
# --- Diagnostic Functions ---
# 1. Check the status of all Docker containers.
check_container_status() {
print_header "Docker Container Status"
docker ps -a
}
# 2. View the logs of the Qdrant container.
view_container_logs() {
print_header "Logs for $QDRANT_CONTAINER_NAME"
docker logs "$QDRANT_CONTAINER_NAME"
}
# 3. Check for port conflicts on the host.
check_port_conflicts() {
print_header "Checking for Port Conflicts (6333, 6334)"
echo "--- Checking Port 6333 ---"
lsof -i :6333 || echo "Port 6333 is not in use or lsof is not installed."
echo
echo "--- Checking Port 6334 ---"
lsof -i :6334 || echo "Port 6334 is not in use or lsof is not installed."
}
# 4. Check the Qdrant API health endpoint.
check_health_endpoint() {
print_header "Checking Qdrant API Health Endpoint"
http_code=$(curl -s -o /dev/null -w "%{http_code}" "http://$QDRANT_HOST/healthz")
if [ "$http_code" -eq 200 ]; then
echo "Health check successful (HTTP 200 OK)"
else
echo "Health check failed. Received HTTP status $http_code."
echo "Is Qdrant running and the port correctly mapped?"
fi
echo
}
# 5. Check permissions of the data volume (Dynamically discovered).
check_volume_permissions() {
print_header "Checking Data Volume Permissions"
# Dynamically find the host path mapped to /qdrant/storage in the container
local volume_path
volume_path=$(docker inspect -f '{{range .Mounts}}{{if eq .Destination "/qdrant/storage"}}{{.Source}}{{end}}{{end}}' "$QDRANT_CONTAINER_NAME")
if [ -z "$volume_path" ]; then
echo "Could not find a volume mounted to /qdrant/storage for container '$QDRANT_CONTAINER_NAME'."
return 1
fi
echo "Discovered data volume path: $volume_path"
if [ ! -d "$volume_path" ]; then
echo "Error: Directory not found: $volume_path"
return 1
fi
echo "--- Permissions for $volume_path ---"
ls -ld "$volume_path"
}
# 6. Create a snapshot for a user-selected collection.
create_snapshot() {
if ! select_collection; then return 1; fi
print_header "Creating Snapshot for '$SELECTED_COLLECTION'"
curl -X POST "http://$QDRANT_HOST/collections/$SELECTED_COLLECTION/snapshots"
echo
}
# 7. List all snapshots for a user-selected collection.
list_snapshots() {
if ! select_collection; then return 1; fi
print_header "Listing Snapshots for '$SELECTED_COLLECTION'"
curl "http://$QDRANT_HOST/collections/$SELECTED_COLLECTION/snapshots"
echo
}
# 8. Restore a collection from a user-selected snapshot.
restore_snapshot() {
if ! select_collection; then return 1; fi
local collection_to_restore=$SELECTED_COLLECTION
print_header "Fetching Snapshots for '$collection_to_restore'"
# Fetch snapshots for the selected collection
snapshots=($(curl -s "http://$QDRANT_HOST/collections/$collection_to_restore/snapshots" | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"//'))
if [ ${#snapshots[@]} -eq 0 ]; then
echo "No snapshots found for collection '$collection_to_restore'."
return 1
fi
echo "Please select a snapshot to restore:"
select snap in "${snapshots[@]}"; do
if [ -n "$snap" ]; then
local snapshot_to_restore=$snap
break
else
echo "Invalid selection. Please try again."
fi
done
if [ -z "$snapshot_to_restore" ]; then
echo "No snapshot selected. Aborting."
return 1
fi
# Construct the snapshot location URI inside the container
local snapshot_uri="file:///qdrant/storage/snapshots/$collection_to_restore/$snapshot_to_restore"
print_header "Restoring '$collection_to_restore' from Snapshot"
echo "Attempting to restore from: $snapshot_uri"
curl -X PUT "http://$QDRANT_HOST/collections/$collection_to_restore/snapshots/recover" \
-H "Content-Type: application/json" \
-d "{\"location\": \"$snapshot_uri\"}"
echo
}
# 9. Check the container's resource usage.
check_resource_usage() {
print_header "Resource Usage for $QDRANT_CONTAINER_NAME"
docker stats "$QDRANT_CONTAINER_NAME" --no-stream
}
# 10. Inspect the container's environment variables.
inspect_env_vars() {
print_header "Environment Variables for $QDRANT_CONTAINER_NAME"
docker inspect "$QDRANT_CONTAINER_NAME" --format '{{range .Config.Env}}{{println .}}{{end}}'
}
# 11. Check the status of the Qdrant cluster.
check_cluster_status() {
print_header "Qdrant Cluster Status"
curl "http://$QDRANT_HOST/cluster"
echo
}
# 12. Run a comprehensive batch test and generate a report.
run_comprehensive_check() {
print_header "Comprehensive System Report"
echo "Running all key diagnostic checks..."
check_container_status
check_health_endpoint
check_port_conflicts
check_volume_permissions
check_resource_usage
check_cluster_status
echo
echo "--- Comprehensive Report End ---"
echo
}
# --- Main Logic ---
# Function to display the main menu.
show_menu() {
echo
echo "=============================================="
echo " Qdrant Docker Troubleshooter Menu"
echo "=============================================="
echo " 0) Run Comprehensive Health Report"
echo "----------------------------------------------"
echo " Container Health:"
echo " 1) Check Container Status"
echo " 2) View Container Logs"
echo " API & Connectivity:"
echo " 3) Check for Port Conflicts"
echo " 4) Check API Health Endpoint"
echo " Data & Persistence:"
echo " 5) Check Data Volume Permissions (Dynamic)"
echo " 6) Create Collection Snapshot (Interactive)"
echo " 7) List Collection Snapshots (Interactive)"
echo " 8) Restore Collection from Snapshot (Interactive)"
echo " Performance & Configuration:"
echo " 9) Check Container Resource Usage"
echo " 10) Inspect Environment Variables"
echo " Clustering:"
echo " 11) Check Cluster Status"
echo
echo " q) Quit"
echo "=============================================="
echo
}
# Function to read user choice and execute the corresponding command.
read_choice() {
local choice
read -p "Enter your choice [0-11 or q]: " choice
case $choice in
0) run_comprehensive_check ;;
1) check_container_status ;;
2) view_container_logs ;;
3) check_port_conflicts ;;
4) check_health_endpoint ;;
5) check_volume_permissions ;;
6) create_snapshot ;;
7) list_snapshots ;;
8) restore_snapshot ;;
9) check_resource_usage ;;
10) inspect_env_vars ;;
11) check_cluster_status ;;
q|Q) echo "Exiting."; exit 0 ;;
*) echo "Invalid option. Please try again." ;;
esac
}
# --- Script Execution ---
# If a command is passed as an argument, run it directly.
# Note: Snapshot commands will now be interactive.
if [ -n "$1" ]; then
case $1 in
report|all) run_comprehensive_check ;;
status) check_container_status ;;
logs) view_container_logs ;;
ports) check_port_conflicts ;;
health) check_health_endpoint ;;
permissions) check_volume_permissions ;;
create_snapshot) create_snapshot ;;
list_snapshots) list_snapshots ;;
restore_snapshot) restore_snapshot ;;
resources) check_resource_usage ;;
env) inspect_env_vars ;;
cluster) check_cluster_status ;;
*) echo "Invalid command: $1" >&2; exit 1 ;;
esac
exit 0
fi
# If no command is passed, show the interactive menu.
while true
do
show_menu
read_choice
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment