Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- """
- Docker Compose Startup Helper (Python Version)
- This script automatically finds and runs Docker Compose files with
- proper error handling and status reporting.
- Features:
- - Automatically detects common Docker Compose filenames
- - Provides clear visual feedback with colored output
- - Handles errors gracefully with descriptive messages
- - Cross-platform support (Windows, macOS, Linux)
- - Displays running containers after successful startup
- Usage:
- python docker_compose_helper.py
- Returns:
- 0: Success - Docker Compose started successfully
- 1: Error - No valid Docker Compose file found
- 2: Error - Docker Compose command failed
- 3: Error - Docker daemon not running
- 4: Error - Docker Compose not available
- 130: Error - Script interrupted by user
- """
- import os
- import sys
- import subprocess
- from pathlib import Path
- from typing import List, Optional, Tuple
- # ANSI color codes for terminal output
- class Colors:
- """ANSI color codes for terminal output formatting."""
- GREEN = "\033[0;32m" # Success messages
- RED = "\033[0;31m" # Error messages
- YELLOW = "\033[0;33m" # Warning or information messages
- BLUE = "\033[0;34m" # Status or processing messages
- CYAN = "\033[0;36m" # Additional highlighting
- BOLD = "\033[1m" # Bold text
- NC = "\033[0m" # No Color (reset)
- # Status icons for visual feedback
- class Icons:
- """Unicode icons for visual status indication."""
- SUCCESS = "â " # Success indicator
- ERROR = "â" # Error indicator
- INFO = "âšī¸" # Information indicator
- ROCKET = "đ" # Process starting indicator
- FOLDER = "đ" # Directory/location indicator
- SEARCH = "đ" # Search/check indicator
- TIP = "đĄ" # Suggestion/tip indicator
- DOCKER = "đŗ" # Docker-related indicator
- LIST = "đ" # List/display indicator
- WARNING = "â ī¸" # Warning indicator
- CHECK = "â" # Check/verification indicator
- def print_status(icon: str, message: str, color: str) -> None:
- """
- Print a colored status message with an icon.
- Args:
- icon (str): The icon to display before the message.
- message (str): The message to display.
- color (str): The ANSI color code to use.
- """
- print(f"{color}{icon} {message}{Colors.NC}")
- def print_header(title: str) -> None:
- """
- Print a formatted header with title.
- Args:
- title (str): The title text for the header.
- """
- border = "=" * (len(title) + 10)
- print(f"\n{Colors.BOLD}{Colors.BLUE}{border}")
- print(f" {title}")
- print(f"{border}{Colors.NC}\n")
- def check_command_exists(command: str) -> bool:
- """
- Check if a command exists and is executable in the system path.
- Args:
- command (str): The command to check.
- Returns:
- bool: True if the command exists and is executable, False otherwise.
- """
- try:
- # Use 'which' on Unix-like systems and 'where' on Windows
- check_cmd = "which" if sys.platform != "win32" else "where"
- result = subprocess.run(
- [check_cmd, command],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- text=True,
- check=False
- )
- return result.returncode == 0
- except Exception:
- return False
- def run_command(command: List[str]) -> Tuple[int, str, str]:
- """
- Run a system command and return its results.
- Args:
- command (List[str]): The command to run as a list of strings.
- Returns:
- Tuple[int, str, str]: A tuple containing:
- - Exit code (int)
- - Standard output (str)
- - Standard error (str)
- """
- try:
- process = subprocess.Popen(
- command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- text=True,
- universal_newlines=True
- )
- stdout, stderr = process.communicate()
- return process.returncode, stdout, stderr
- except Exception as e:
- return 1, "", str(e)
- def check_docker() -> bool:
- """
- Check if Docker daemon is running.
- Returns:
- bool: True if Docker daemon is running, False otherwise.
- """
- print_status(Icons.SEARCH, "Checking if Docker daemon is running...", Colors.YELLOW)
- # First check if docker command is available
- if not check_command_exists("docker"):
- print_status(Icons.ERROR, "Docker command not found! Please install Docker first.", Colors.RED)
- return False
- # Then check if docker daemon is running
- exit_code, _, stderr = run_command(["docker", "info"])
- if exit_code != 0:
- print_status(Icons.ERROR, "Docker daemon is not running! Please start Docker first.", Colors.RED)
- if stderr:
- print(f"{Colors.RED}Error details: {stderr.strip()}{Colors.NC}")
- return False
- print_status(Icons.SUCCESS, "Docker daemon is running.", Colors.GREEN)
- return True
- def check_docker_compose() -> bool:
- """
- Check if Docker Compose is available.
- Returns:
- bool: True if Docker Compose is available, False otherwise.
- """
- print_status(Icons.SEARCH, "Checking if Docker Compose is available...", Colors.YELLOW)
- exit_code, stdout, _ = run_command(["docker", "compose", "version"])
- if exit_code != 0:
- print_status(Icons.ERROR, "Docker Compose is not available. Please install it first.", Colors.RED)
- return False
- # Extract and display version for informational purposes
- if stdout:
- version_line = stdout.strip().split('\n')[0]
- print_status(Icons.SUCCESS, f"Docker Compose is available: {version_line}", Colors.GREEN)
- else:
- print_status(Icons.SUCCESS, "Docker Compose is available.", Colors.GREEN)
- return True
- def find_compose_file(current_dir: Path) -> Optional[str]:
- """
- Find a Docker Compose file in the current directory.
- Args:
- current_dir (Path): The directory to search in.
- Returns:
- Optional[str]: The name of the found compose file, or None if not found.
- """
- # Standard Docker Compose filenames in order of preference
- compose_files = [
- "compose.yaml",
- "compose.yml",
- "docker-compose.yaml",
- "docker-compose.yml"
- ]
- print_status(Icons.SEARCH, "Searching for Docker Compose files:", Colors.YELLOW)
- for file in compose_files:
- file_path = current_dir / file
- if file_path.exists():
- print_status(Icons.SUCCESS, f"Found: {file}", Colors.GREEN)
- return file
- else:
- print_status(Icons.INFO, f"Not found: {file}", Colors.YELLOW)
- return None
- def display_running_containers(compose_file: str) -> None:
- """
- Display currently running containers from the Docker Compose setup.
- Args:
- compose_file (str): The Docker Compose file name.
- """
- print()
- print_status(Icons.LIST, "Currently running containers:", Colors.BLUE)
- # Get running containers
- exit_code, stdout, stderr = run_command(["docker", "compose", "-f", compose_file, "ps"])
- if stdout:
- print(f"{Colors.CYAN}{stdout}{Colors.NC}")
- elif exit_code != 0:
- print_status(Icons.WARNING, "Could not list containers.", Colors.YELLOW)
- if stderr:
- print(f"{Colors.RED}{stderr}{Colors.NC}")
- def main() -> int:
- """
- Main function to run the Docker Compose startup script.
- This function:
- 1. Checks prerequisites (Docker daemon, Docker Compose)
- 2. Finds a Docker Compose file in the current directory
- 3. Starts the Docker Compose services
- 4. Displays running containers on success
- Returns:
- int: Exit code indicating success (0) or specific failure (1-4, 130)
- """
- try:
- # Display script header
- print_header("Docker Compose Startup Helper")
- # Check prerequisites
- print_status(Icons.INFO, "Checking prerequisites...", Colors.BLUE)
- if not check_docker():
- return 3
- if not check_docker_compose():
- return 4
- # Get current directory
- current_dir = Path.cwd()
- print()
- print_status(Icons.FOLDER, f"Working directory: {current_dir}", Colors.BLUE)
- # Find Docker Compose file
- compose_file = find_compose_file(current_dir)
- if not compose_file:
- print()
- print_status(Icons.ERROR, f"Error: No valid Docker Compose file found in {current_dir}!", Colors.RED)
- print()
- print_status(Icons.TIP, "Tip: Create one of these files:", Colors.YELLOW)
- print(f"{Colors.YELLOW} - compose.yaml (recommended)")
- print(f" - compose.yml")
- print(f" - docker-compose.yaml")
- print(f" - docker-compose.yml{Colors.NC}")
- return 1
- # Run Docker Compose
- print()
- print_status(Icons.ROCKET, f"Starting services from {compose_file}...", Colors.BLUE)
- print()
- exit_code, stdout, stderr = run_command(["docker", "compose", "-f", compose_file, "up", "-d"])
- if stdout:
- print(f"{Colors.CYAN}{stdout}{Colors.NC}")
- if exit_code == 0:
- print()
- print_status(Icons.SUCCESS, "Services started successfully!", Colors.GREEN)
- # Display running containers
- display_running_containers(compose_file)
- else:
- print()
- print_status(Icons.ERROR, f"Docker Compose failed with exit code: {exit_code}", Colors.RED)
- if stderr:
- print(f"{Colors.RED}{stderr}{Colors.NC}")
- print_status(Icons.SEARCH, "Possible issues:", Colors.YELLOW)
- print(f"{Colors.YELLOW} - Check the syntax in {compose_file}")
- print(" - Ensure Docker daemon is running properly")
- print(" - Verify network connectivity for image pulling")
- print(" - Check for port conflicts with existing services")
- print(f" - Verify environment variables referenced in {compose_file}{Colors.NC}")
- return 2
- # Success message with instructions
- print()
- print_status(Icons.TIP, "Useful commands:", Colors.CYAN)
- print(f"{Colors.CYAN} - View logs: docker compose -f {compose_file} logs")
- print(f" - Stop services: docker compose -f {compose_file} down")
- print(f" - Restart services: docker compose -f {compose_file} restart{Colors.NC}")
- # Optional pause to view results
- print()
- input(f"{Colors.BOLD}Press Enter to exit...{Colors.NC}")
- return 0
- except KeyboardInterrupt:
- print("\n")
- print_status(Icons.INFO, "Script interrupted by user.", Colors.YELLOW)
- return 130
- if __name__ == "__main__":
- try:
- sys.exit(main())
- except KeyboardInterrupt:
- print("\n")
- print_status(Icons.INFO, "Script interrupted by user.", Colors.YELLOW)
- sys.exit(130)
- except Exception as e:
- print("\n")
- print_status(Icons.ERROR, f"Unexpected error occurred:", Colors.RED)
- print(f"{Colors.RED}{str(e)}{Colors.NC}")
- # Print stack trace in development environments
- if os.environ.get("DEBUG", "").lower() in ("1", "true", "yes"):
- import traceback
- print(f"{Colors.RED}{traceback.format_exc()}{Colors.NC}")
- sys.exit(1)
Advertisement
Add Comment
Please, Sign In to add comment