#!/bin/bash # # CodeXchange AI Docker Wrapper Script # This script simplifies running the CodeXchange AI application using Docker. # set -e # Color codes for terminal output GREEN='\033[0;32m' YELLOW='\033[0;33m' RED='\033[0;31m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Script version VERSION="1.0.0" # Default values ENV_FILE=".env" PORT=7860 BUILD_ONLY=false DETACHED=false FOLLOW_LOGS=false STOP=false RESTART=false DOWN=false API_KEY_REMIND=false # Display script banner display_banner() { echo -e "${BLUE}" echo "╔═══════════════════════════════════════════════════╗" echo "║ CodeXchange AI - Docker Launcher ║" echo "╚═══════════════════════════════════════════════════╝" echo -e "${NC}" } # Display help message display_help() { echo -e "Usage: $0 [OPTIONS]" echo echo "Options:" echo " -b, --build Build the Docker image without running the container" echo " -d, --detach Run container in detached mode (background)" echo " -e, --env FILE Specify an environment file (default: .env)" echo " -p, --port PORT Specify the port to expose (default: 7860)" echo " -l, --logs Follow the container logs after starting" echo " -s, --stop Stop the running container" echo " -r, --restart Restart the container" echo " -D, --down Stop and remove the container" echo " -k, --keys Check for API keys and show setup instructions if missing" echo " -h, --help Display this help message" echo " -v, --version Display script version" echo echo "Examples:" echo " $0 Build and run the container" echo " $0 -d -p 8080 Run in detached mode on port 8080" echo " $0 -b Build the image only" echo " $0 -s Stop the running container" echo } # Check prerequisites check_prerequisites() { echo -e "${BLUE}Checking prerequisites...${NC}" # Check for Docker if ! command -v docker &> /dev/null; then echo -e "${RED}Error: Docker is not installed or not in PATH.${NC}" echo "Please install Docker to continue: https://docs.docker.com/get-docker/" exit 1 fi # Check for docker-compose if ! command -v docker-compose &> /dev/null; then echo -e "${YELLOW}Warning: docker-compose not found. Checking for Docker Compose V2...${NC}" if ! docker compose version &> /dev/null; then echo -e "${RED}Error: Docker Compose not found.${NC}" echo "Please install Docker Compose to continue: https://docs.docker.com/compose/install/" exit 1 else echo -e "${GREEN}Docker Compose V2 found.${NC}" COMPOSE_CMD="docker compose" fi else COMPOSE_CMD="docker-compose" fi echo -e "${GREEN}Prerequisites satisfied.${NC}" } # Check for environment variables check_env_file() { # Check if the specified .env file exists if [ ! -f "$ENV_FILE" ]; then echo -e "${YELLOW}Warning: $ENV_FILE file not found.${NC}" # If it's the default .env and .env.example exists, offer to copy it if [ "$ENV_FILE" = ".env" ] && [ -f ".env.example" ]; then echo -e "Would you like to create a .env file from .env.example? (y/n)" read -r response if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then cp .env.example .env echo -e "${GREEN}.env file created from .env.example. Please edit it to add your API keys.${NC}" API_KEY_REMIND=true fi else echo -e "${YELLOW}Please create an environment file with your API keys.${NC}" API_KEY_REMIND=true fi fi } # Check for required API keys check_api_keys() { if [ "$API_KEY_REMIND" = true ] || [ "$1" = true ]; then echo -e "${YELLOW}API Key Requirements:${NC}" echo "The CodeXchange AI requires API keys for the following services:" echo " - OPENAI_API_KEY (Required for OpenAI GPT models)" echo " - ANTHROPIC_API_KEY (Required for Claude models)" echo " - GOOGLE_API_KEY (Required for Google Gemini models)" echo " - DEEPSEEK_API_KEY (Required for DeepSeek models)" echo " - GROQ_API_KEY (Required for GROQ models)" echo echo -e "Please ensure these keys are set in your ${BLUE}$ENV_FILE${NC} file." echo "You only need keys for the models you plan to use." fi } # Parse command line arguments parse_arguments() { while [[ $# -gt 0 ]]; do case $1 in -b|--build) BUILD_ONLY=true shift ;; -d|--detach) DETACHED=true shift ;; -e|--env) ENV_FILE="$2" shift 2 ;; -p|--port) PORT="$2" shift 2 ;; -l|--logs) FOLLOW_LOGS=true shift ;; -s|--stop) STOP=true shift ;; -r|--restart) RESTART=true shift ;; -D|--down) DOWN=true shift ;; -k|--keys) check_api_keys true exit 0 ;; -h|--help) display_banner display_help exit 0 ;; -v|--version) echo "CodeXchange AI Docker Wrapper v$VERSION" exit 0 ;; *) echo -e "${RED}Error: Unknown option $1${NC}" display_help exit 1 ;; esac done } # Build the Docker image build_image() { echo -e "${BLUE}Building the Docker image...${NC}" # Export PORT from the environment for docker-compose export PORT=$PORT if [ -f "$ENV_FILE" ]; then echo -e "${GREEN}Using environment file: $ENV_FILE${NC}" OPTS="--env-file $ENV_FILE" else OPTS="" fi # Build the image $COMPOSE_CMD $OPTS build echo -e "${GREEN}Docker image built successfully.${NC}" } # Run the container run_container() { echo -e "${BLUE}Starting the CodeXchange AI...${NC}" # Export PORT from the environment for docker-compose export PORT=$PORT if [ -f "$ENV_FILE" ]; then OPTS="--env-file $ENV_FILE" else OPTS="" fi # Add detach flag if specified if [ "$DETACHED" = true ]; then OPTS="$OPTS -d" fi # Run the container $COMPOSE_CMD $OPTS up # Follow logs if detached and requested if [ "$DETACHED" = true ] && [ "$FOLLOW_LOGS" = true ]; then $COMPOSE_CMD logs -f fi } # Stop the container stop_container() { echo -e "${BLUE}Stopping the CodeXchange AI...${NC}" $COMPOSE_CMD stop echo -e "${GREEN}Container stopped.${NC}" } # Restart the container restart_container() { echo -e "${BLUE}Restarting the CodeXchange AI...${NC}" $COMPOSE_CMD restart echo -e "${GREEN}Container restarted.${NC}" if [ "$FOLLOW_LOGS" = true ]; then $COMPOSE_CMD logs -f fi } # Bring down the container down_container() { echo -e "${BLUE}Stopping and removing the CodeXchange AI container...${NC}" $COMPOSE_CMD down echo -e "${GREEN}Container stopped and removed.${NC}" } # Display access information display_access_info() { echo -e "${GREEN}The CodeXchange AI is running!${NC}" echo -e "Access the application at: ${BLUE}http://localhost:$PORT${NC}" # Check if port is custom and update info if [ "$PORT" != "7860" ]; then echo -e "Running on custom port: ${BLUE}$PORT${NC}" fi # If running detached, provide instructions for logs if [ "$DETACHED" = true ]; then echo -e "Running in detached mode. Use ${YELLOW}$0 --logs${NC} to follow logs." fi echo -e "To stop the application, press ${YELLOW}Ctrl+C${NC} or run ${YELLOW}$0 --stop${NC}" } # Main function main() { display_banner check_prerequisites parse_arguments "$@" if [ "$DOWN" = true ]; then down_container exit 0 fi if [ "$STOP" = true ]; then stop_container exit 0 fi if [ "$RESTART" = true ]; then restart_container exit 0 fi check_env_file check_api_keys build_image if [ "$BUILD_ONLY" = false ]; then run_container # Only display access info if not in detached mode or if following logs if [ "$DETACHED" = false ] || [ "$FOLLOW_LOGS" = true ]; then display_access_info fi else echo -e "${GREEN}Build completed successfully. Use $0 to run the application.${NC}" fi } # Run main function with all arguments main "$@"