refactor(compose): centralize external compose file handling

add build_compose_files_array() and getter functions for n8n-workers,
supabase, dify compose files in utils.sh. simplifies restart.sh and
apply_update.sh by using shared function. now checks both profile
activation AND file existence before including external compose files.
This commit is contained in:
Yury Kossakovsky
2025-12-29 13:06:03 -07:00
parent c5d5925986
commit 58799d9ae1
5 changed files with 114 additions and 39 deletions

View File

@@ -633,20 +633,51 @@ fi
---
## STEP 11: scripts/apply_update.sh (for complex services)
## STEP 11: External Compose Files (for complex services like Supabase/Dify)
**File:** `scripts/apply_update.sh`
**Files:** `scripts/utils.sh`, `scripts/restart.sh`, `scripts/apply_update.sh`, `start_services.py`
For services with external docker-compose files:
For services with their own external docker-compose files (cloned from upstream repos):
### 11.1 Add getter function to utils.sh
```bash
if is_profile_active "$ARGUMENTS"; then
log_info "Updating $ARGUMENTS..."
docker compose -f docker-compose.$ARGUMENTS.yml pull
fi
# Get $ARGUMENTS compose file path if profile is active and file exists
# Usage: path=$(get_${SERVICE_SLUG_UNDERSCORE}_compose) && COMPOSE_FILES+=("-f" "$path")
get_${SERVICE_SLUG_UNDERSCORE}_compose() {
local compose_file="$PROJECT_ROOT/$ARGUMENTS/docker/docker-compose.yml"
if [ -f "$compose_file" ] && is_profile_active "$ARGUMENTS"; then
echo "$compose_file"
return 0
fi
return 1
}
```
Most services don't need this.
### 11.2 Add to build_compose_files_array() in utils.sh
```bash
build_compose_files_array() {
COMPOSE_FILES=("-f" "$PROJECT_ROOT/docker-compose.yml")
# ... existing ...
if path=$(get_${SERVICE_SLUG_UNDERSCORE}_compose); then
COMPOSE_FILES+=("-f" "$path")
fi
}
```
### 11.3 Add to start_services.py
Add functions similar to Supabase/Dify:
- `is_${SERVICE_SLUG_UNDERSCORE}_enabled()` - Check if profile is in COMPOSE_PROFILES
- `clone_${SERVICE_SLUG_UNDERSCORE}_repo()` - Clone upstream repo with sparse checkout
- `prepare_${SERVICE_SLUG_UNDERSCORE}_env()` - Copy/transform .env file
- `start_${SERVICE_SLUG_UNDERSCORE}()` - Start services if enabled
- Update `stop_all_services()` - Include compose file in down command (by file existence, not profile)
**Important:** `stop_all_services()` checks file existence only (not profile) to ensure cleanup when profile is removed.
Most services don't need this - only use for services that maintain their own docker-compose.yml upstream.
---
@@ -713,3 +744,9 @@ bash -n scripts/07_final_report.sh
### If Hardware Variants (CPU/GPU)
- [ ] Mutually exclusive profiles (cpu, gpu-nvidia, gpu-amd)
- [ ] GPU resource reservations
### If External Compose File (Supabase/Dify style)
- [ ] `scripts/utils.sh`: `get_*_compose()` function added
- [ ] `scripts/utils.sh`: `build_compose_files_array()` updated
- [ ] `start_services.py`: `is_*_enabled()`, `clone_*_repo()`, `prepare_*_env()`, `start_*()` functions
- [ ] `start_services.py`: `stop_all_services()` includes compose file (by existence, not profile)

View File

@@ -155,6 +155,8 @@ Key functions:
- `get_real_user` / `get_real_user_home` - Get actual user even under sudo
- `backup_preserved_dirs` / `restore_preserved_dirs` - Directory preservation for git updates
- `cleanup_legacy_n8n_workers` - Remove old n8n worker containers from previous naming convention
- `get_n8n_workers_compose` / `get_supabase_compose` / `get_dify_compose` - Get compose file path if profile active AND file exists
- `build_compose_files_array` - Build global `COMPOSE_FILES` array with all active compose files (main + external)
### Service Profiles

View File

@@ -77,31 +77,16 @@ cleanup_legacy_postgresus
# Pull latest versions of selected containers based on updated .env
set_telemetry_stage "update_docker_pull"
log_info "Pulling latest versions of selected containers..."
COMPOSE_FILES_FOR_PULL=("-f" "$PROJECT_ROOT/docker-compose.yml")
# Check if n8n workers file exists (generated by 05_configure_services.sh)
N8N_WORKERS_COMPOSE_FILE="$PROJECT_ROOT/docker-compose.n8n-workers.yml"
if [ -f "$N8N_WORKERS_COMPOSE_FILE" ]; then
COMPOSE_FILES_FOR_PULL+=("-f" "$N8N_WORKERS_COMPOSE_FILE")
fi
# Load environment to check active profiles (wizard may have updated them)
load_env
# Check if Supabase directory and its docker-compose.yml exist
SUPABASE_DOCKER_DIR="$PROJECT_ROOT/supabase/docker"
SUPABASE_COMPOSE_FILE_PATH="$SUPABASE_DOCKER_DIR/docker-compose.yml"
if [ -d "$SUPABASE_DOCKER_DIR" ] && [ -f "$SUPABASE_COMPOSE_FILE_PATH" ]; then
COMPOSE_FILES_FOR_PULL+=("-f" "$SUPABASE_COMPOSE_FILE_PATH")
fi
# Check if Dify directory and its docker-compose.yaml exist
DIFY_DOCKER_DIR="$PROJECT_ROOT/dify/docker"
DIFY_COMPOSE_FILE_PATH="$DIFY_DOCKER_DIR/docker-compose.yaml"
if [ -d "$DIFY_DOCKER_DIR" ] && [ -f "$DIFY_COMPOSE_FILE_PATH" ]; then
COMPOSE_FILES_FOR_PULL+=("-f" "$DIFY_COMPOSE_FILE_PATH")
fi
# Build compose files array using shared function (checks profile + file existence)
build_compose_files_array
# Use the project name "localai" for consistency.
# This command WILL respect COMPOSE_PROFILES from the .env file (updated by the wizard above).
$COMPOSE_CMD -p "localai" "${COMPOSE_FILES_FOR_PULL[@]}" pull --ignore-buildable || {
$COMPOSE_CMD -p "localai" "${COMPOSE_FILES[@]}" pull --ignore-buildable || {
log_error "Failed to pull Docker images for selected services. Check network connection and Docker Hub status."
exit 1
}

View File

@@ -3,11 +3,13 @@
# restart.sh - Restart all services
# =============================================================================
# Restarts all Docker Compose services including dynamically generated
# worker/runner compose files.
# worker/runner compose files and external service stacks.
#
# Handles compose files:
# Handles compose files via build_compose_files_array() from utils.sh:
# - docker-compose.yml (main)
# - docker-compose.n8n-workers.yml (if exists)
# - docker-compose.n8n-workers.yml (if exists and n8n profile active)
# - supabase/docker/docker-compose.yml (if exists and supabase profile active)
# - dify/docker/docker-compose.yaml (if exists and dify profile active)
#
# Usage: bash scripts/restart.sh
# =============================================================================
@@ -20,16 +22,13 @@ init_paths
cd "$PROJECT_ROOT"
# Load environment to check active profiles
load_env
PROJECT_NAME="localai"
# Build compose files array
COMPOSE_FILES=("-f" "docker-compose.yml")
# Add n8n workers compose file if exists
N8N_WORKERS_COMPOSE="docker-compose.n8n-workers.yml"
if [ -f "$N8N_WORKERS_COMPOSE" ]; then
COMPOSE_FILES+=("-f" "$N8N_WORKERS_COMPOSE")
fi
# Build compose files array (sets global COMPOSE_FILES)
build_compose_files_array
log_info "Restarting services..."
log_info "Using compose files: ${COMPOSE_FILES[*]}"

View File

@@ -319,6 +319,58 @@ is_profile_active() {
[[ -n "$COMPOSE_PROFILES" && ",$COMPOSE_PROFILES," == *",$profile,"* ]]
}
# Get n8n workers compose file path if profile is active and file exists
# Usage: path=$(get_n8n_workers_compose) && COMPOSE_FILES+=("-f" "$path")
get_n8n_workers_compose() {
local compose_file="$PROJECT_ROOT/docker-compose.n8n-workers.yml"
if [ -f "$compose_file" ] && is_profile_active "n8n"; then
echo "$compose_file"
return 0
fi
return 1
}
# Get Supabase compose file path if profile is active and file exists
# Usage: path=$(get_supabase_compose) && COMPOSE_FILES+=("-f" "$path")
get_supabase_compose() {
local compose_file="$PROJECT_ROOT/supabase/docker/docker-compose.yml"
if [ -f "$compose_file" ] && is_profile_active "supabase"; then
echo "$compose_file"
return 0
fi
return 1
}
# Get Dify compose file path if profile is active and file exists
# Usage: path=$(get_dify_compose) && COMPOSE_FILES+=("-f" "$path")
get_dify_compose() {
local compose_file="$PROJECT_ROOT/dify/docker/docker-compose.yaml"
if [ -f "$compose_file" ] && is_profile_active "dify"; then
echo "$compose_file"
return 0
fi
return 1
}
# Build array of all active compose files (main + external services)
# IMPORTANT: Requires COMPOSE_PROFILES to be set before calling (via load_env)
# Usage: build_compose_files_array; docker compose "${COMPOSE_FILES[@]}" up -d
# Result is stored in global COMPOSE_FILES array
build_compose_files_array() {
COMPOSE_FILES=("-f" "$PROJECT_ROOT/docker-compose.yml")
local path
if path=$(get_n8n_workers_compose); then
COMPOSE_FILES+=("-f" "$path")
fi
if path=$(get_supabase_compose); then
COMPOSE_FILES+=("-f" "$path")
fi
if path=$(get_dify_compose); then
COMPOSE_FILES+=("-f" "$path")
fi
}
#=============================================================================
# UTILITIES
#=============================================================================