Skip to content

Add ability to add/set delay between compose files during autostart process #96

@lordraiden

Description

@lordraiden

Summary

Autostart order and delay

Detailed description

I have this script to autostart docker compose files in a specific order and with delays between them.
It would be nice if this would be a built in feature

Image
#!/bin/bash

# Exit on error, unset variables, and pipefail
set -eo pipefail

sleep 30

echo "⏹️ Checking running containers..."
running_containers=$(docker ps -q)

if [ -n "$running_containers" ]; then
  echo "⏹️ Stopping all running containers..."
  docker stop $running_containers
  echo "✅ Containers stopped successfully."
else
  echo "✅ No running containers."
fi

echo ""

sleep 5

# Base path for docker-compose files
base_path="/mnt/services/docker/git/homeserver/docker-compose"

# Path to the global .env file
global_env_file="$base_path/.env"

# Check if global .env exists
if [ ! -f "$global_env_file" ]; then
  echo "⚠️ Global .env file not found at $global_env_file — proceeding anyway."
fi

# Function to parse .env file into an associative array
parse_env_file() {
  local file=$1
  declare -n env_map=$2 # Use -g if you need it globally, but local nameref is good here

  # Read only lines that are not comments and contain an equals sign
  while IFS='=' read -r key value || [[ -n "$key" ]]; do
    # Basic sanitization of key, skip if key is empty after read
    key=$(echo "$key" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
    if [[ -z "$key" ]]; then
      continue
    fi

    # Trim spaces from value
    value=$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')

    # Remove quotes if present (handles simple cases)
    value="${value#\"}"; value="${value%\"}"
    value="${value#\'}"; value="${value%\'}"

    env_map["$key"]="$value"
  done < <(grep -Ev '^[[:space:]]*#|^[[:space:]]*$' "$file" | grep '=')
}

# List of services with their delay in seconds (format: "service:delay")
services_with_delays=(
  "dnsservices:60"
  "administration:0"
  "n8n:0"
  "arcane:0"
  "webproxyint:60"
  "homeautomation:0"
  "media:60"
  "immich:0"
  "safeline:0"
  "webproxydmz:0"
  "monitoring:0"
  "backup:0"
  #"portainer:10"
  #"dockge:10"
)

# List of containers to stop at the end
containers_to_stop=(
  "Netdata"
)

# Start services with delays
for entry in "${services_with_delays[@]}"; do
  IFS=":" read -r service delay <<< "$entry"
  
  compose_file="$base_path/$service/docker-compose.yml"
  local_env_file="$base_path/$service/.env"
  
  echo ""
  echo "🚀 Starting service: $service"

  # Check if the docker-compose file exists
  if [ ! -f "$compose_file" ]; then
    echo "❌ Compose file not found for $service at $compose_file. Skipping."
    continue
  fi

  # Check for env file collisions
  if [ -f "$global_env_file" ] && [ -f "$local_env_file" ]; then
    declare -A global_vars
    declare -A local_vars

    parse_env_file "$global_env_file" global_vars
    parse_env_file "$local_env_file" local_vars

    for key in "${!global_vars[@]}"; do
      if [[ -n "${local_vars[$key]}" ]]; then
        echo "⚠️ Variable override detected for '$key'"
        echo "   🌐 Global value: ${global_vars[$key]}"
        echo "   📁 Local value:  ${local_vars[$key]}"
      fi
    done
  fi

  # Build docker compose command arguments
  compose_cmd_args=("-f" "$compose_file")

  # Add global .env file if it exists
  if [ -f "$global_env_file" ]; then
    compose_cmd_args+=("--env-file" "$global_env_file")
  fi

  # Add local .env file if it exists
  if [ -f "$local_env_file" ]; then
    compose_cmd_args+=("--env-file" "$local_env_file")
  fi

  # Run docker compose with the accumulated arguments
  compose_cmd_args+=("up" "-d")

  echo "🐳 Executing: docker compose ${compose_cmd_args[*]}"
  if docker compose "${compose_cmd_args[@]}"; then
    echo "✅ Service $service started successfully."
  else
    echo "❌ Failed to start service $service. Check output above."
    # Consider 'exit 1' or other error handling if a service fails to start
  fi

  echo "⏳ Waiting $delay seconds..."
  sleep "$delay"
done

echo ""
echo "✅ All services have been started in order."
echo ""

# Stop specific containers at the end of the process
echo "🛑 Stopping specific containers at the end of the process..."
for container in "${containers_to_stop[@]}"; do
  if docker ps -q -f name="^${container}$" > /dev/null; then
    docker stop "$container"
    echo "✅ Container stopped: $container"
  else
    echo "ℹ️ Container not running or not found: $container"
  fi
done

echo ""
echo "🏁 Process completed."

Alternatives considered

No response

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions