From 33e3963fcf6fe4c7a9a954e12487d2e423b64475 Mon Sep 17 00:00:00 2001 From: "T. Narantuya" Date: Thu, 4 Sep 2025 10:51:44 +0900 Subject: [PATCH] Enhance manage.sh for flexible compose file selection - Introduced logic to select the compose file based on the DEV_STACK environment variable, allowing for options: full, services, or auto. - Updated preflight checks to provide clearer error messages regarding compose file requirements. - Added logging to indicate which compose file is being used during service startup and status checks. --- scripts/dev/manage.sh | 40 +++++++++- scripts/plesk/build-images.sh | 146 ++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 4 deletions(-) create mode 100755 scripts/plesk/build-images.sh diff --git a/scripts/dev/manage.sh b/scripts/dev/manage.sh index 791dcb91..958283e7 100755 --- a/scripts/dev/manage.sh +++ b/scripts/dev/manage.sh @@ -10,7 +10,33 @@ IFS=$'\n\t' ######################################## SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="${PROJECT_ROOT:-"$(cd "$SCRIPT_DIR/../.." && pwd)"}" -COMPOSE_FILE="${COMPOSE_FILE:-"$PROJECT_ROOT/docker/dev/docker-compose.yml"}" + +# Compose file selection +# Priority: explicit COMPOSE_FILE > DEV_STACK (full|services|auto) > default (full if present) +DEFAULT_COMPOSE_SERVICES="$PROJECT_ROOT/docker/dev/docker-compose.yml" +DEFAULT_COMPOSE_FULL="$PROJECT_ROOT/docker/dev/docker-compose.full.yml" + +if [ -z "${COMPOSE_FILE:-}" ]; then + case "${DEV_STACK:-services}" in + full) + COMPOSE_FILE="$DEFAULT_COMPOSE_FULL" + ;; + services) + COMPOSE_FILE="$DEFAULT_COMPOSE_SERVICES" + ;; + auto) + if [ -f "$DEFAULT_COMPOSE_FULL" ]; then + COMPOSE_FILE="$DEFAULT_COMPOSE_FULL" + else + COMPOSE_FILE="$DEFAULT_COMPOSE_SERVICES" + fi + ;; + *) + COMPOSE_FILE="$DEFAULT_COMPOSE_FULL" + ;; + esac +fi + ENV_FILE="${ENV_FILE:-"$PROJECT_ROOT/.env"}" ENV_EXAMPLE_FILE="${ENV_EXAMPLE_FILE:-"$PROJECT_ROOT/.env.example"}" PROJECT_NAME="${PROJECT_NAME:-portal-dev}" @@ -67,7 +93,7 @@ compose() { ######################################## preflight() { command -v docker >/dev/null 2>&1 || fail "Docker is required." - [ -f "$COMPOSE_FILE" ] || fail "Compose file not found: $COMPOSE_FILE" + [ -f "$COMPOSE_FILE" ] || fail "Compose file not found: $COMPOSE_FILE (set DEV_STACK=services or COMPOSE_FILE to override)" # Suggest Docker running if ps fails if ! docker info >/dev/null 2>&1; then @@ -159,6 +185,7 @@ start_services() { load_env_exported log "🚀 Starting development services..." + log "🧩 Using compose: $COMPOSE_FILE" compose up -d postgres redis wait_for_postgres @@ -178,7 +205,9 @@ start_with_tools() { load_env_exported log "🛠️ Starting development services with admin tools..." - compose --profile tools up -d + log "🧩 Using compose: $COMPOSE_FILE" + # Explicitly start only services + admin tools to avoid building app containers in the full compose + compose --profile tools up -d postgres redis adminer redis-commander mailhog wait_for_postgres log "🔗 Database Admin: http://localhost:8080" log "🔗 Redis Commander: http://localhost:8081" @@ -196,6 +225,7 @@ show_status() { preflight "status" cd "$PROJECT_ROOT" log "📊 Development Services Status:" + log "🧩 Using compose: $COMPOSE_FILE" compose ps } @@ -204,6 +234,7 @@ show_logs() { cd "$PROJECT_ROOT" # Pass-through any service names after "logs" # e.g. ./dev.sh logs postgres redis + log "🧩 Using compose: $COMPOSE_FILE" compose logs -f --tail=100 "${@:2}" } @@ -310,6 +341,7 @@ Commands: Environment overrides: PROJECT_ROOT, COMPOSE_FILE, ENV_FILE, ENV_EXAMPLE_FILE, PROJECT_NAME + DEV_STACK (full|services|auto) # default: full POSTGRES_USER, POSTGRES_DB, POSTGRES_PASSWORD, DB_WAIT_SECS NEXT_PORT, BFF_PORT EOF @@ -331,4 +363,4 @@ case "$cmd" in migrate) migrate_db ;; reset) reset_env ;; help|*) usage; exit 0 ;; -esac \ No newline at end of file +esac diff --git a/scripts/plesk/build-images.sh b/scripts/plesk/build-images.sh new file mode 100755 index 00000000..64e1d003 --- /dev/null +++ b/scripts/plesk/build-images.sh @@ -0,0 +1,146 @@ +#!/usr/bin/env bash + +# 🐳 Build production images for Plesk and save as .tar +# - Builds apps/portal (frontend) and apps/bff (backend) +# - Tags both with :latest and optional version/sha tag +# - Saves tarballs in project root for easy Plesk upload + +set -Eeuo pipefail +IFS=$'\n\t' + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +IMAGE_FRONTEND_NAME="${IMAGE_FRONTEND_NAME:-portal-frontend}" +IMAGE_BACKEND_NAME="${IMAGE_BACKEND_NAME:-portal-backend}" + +# Optional explicit tag via env or flag; defaults to git short sha + date +IMAGE_TAG="${IMAGE_TAG:-}" +OUTPUT_DIR="${OUTPUT_DIR:-$PROJECT_ROOT}" +PUSH_REMOTE="${PUSH_REMOTE:-}" # e.g. ghcr.io/ + +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +log() { echo -e "${GREEN}[PLESK-BUILD] $*${NC}"; } +warn() { echo -e "${YELLOW}[PLESK-BUILD] $*${NC}"; } +fail() { echo -e "${RED}[PLESK-BUILD] ERROR: $*${NC}"; exit 1; } + +usage() { + cat <] [--output ] [--push ] [--no-save] + +Options: + --tag Tag to add in addition to 'latest' (e.g. v1.2.3 or abc123) + --output Directory to write tar files (default: project root) + --push Also tag and push to registry (e.g. ghcr.io/org or docker.io/user) + --no-save Build and tag images but do not write tar files + +Env vars: + IMAGE_FRONTEND_NAME, IMAGE_BACKEND_NAME, IMAGE_TAG, OUTPUT_DIR, PUSH_REMOTE + +Examples: + $0 --tag $(date +%Y%m%d)-$(git -C "$PROJECT_ROOT" rev-parse --short HEAD) + PUSH_REMOTE=ghcr.io/acme $0 --tag v1.0.0 +EOF +} + +SAVE_TARS=1 +while [[ $# -gt 0 ]]; do + case "$1" in + --tag) + IMAGE_TAG="${2:-}"; shift 2 ;; + --output) + OUTPUT_DIR="${2:-}"; shift 2 ;; + --push) + PUSH_REMOTE="${2:-}"; shift 2 ;; + --no-save) + SAVE_TARS=0; shift ;; + -h|--help) + usage; exit 0 ;; + *) + warn "Unknown option: $1"; usage; exit 1 ;; + esac +done + +command -v docker >/dev/null 2>&1 || fail "Docker is required." + +cd "$PROJECT_ROOT" + +[[ -f apps/portal/Dockerfile ]] || fail "Missing apps/portal/Dockerfile" +[[ -f apps/bff/Dockerfile ]] || fail "Missing apps/bff/Dockerfile" + +if [[ -z "${IMAGE_TAG}" ]]; then + if git -C "$PROJECT_ROOT" rev-parse --short HEAD >/dev/null 2>&1; then + GIT_SHA="$(git -C "$PROJECT_ROOT" rev-parse --short HEAD)" + IMAGE_TAG="$(date +%Y%m%d)-$GIT_SHA" + else + IMAGE_TAG="$(date +%Y%m%d)" + fi +fi + +log "🔨 Building frontend image (${IMAGE_FRONTEND_NAME}:latest, ${IMAGE_FRONTEND_NAME}:${IMAGE_TAG})" +docker build \ + --file apps/portal/Dockerfile \ + --tag "${IMAGE_FRONTEND_NAME}:latest" \ + --tag "${IMAGE_FRONTEND_NAME}:${IMAGE_TAG}" \ + --label "org.opencontainers.image.title=Customer Portal Frontend" \ + --label "org.opencontainers.image.version=${IMAGE_TAG}" \ + --label "org.opencontainers.image.source=$(git -C "$PROJECT_ROOT" config --get remote.origin.url 2>/dev/null || echo unknown)" \ + . + +log "🔨 Building backend image (${IMAGE_BACKEND_NAME}:latest, ${IMAGE_BACKEND_NAME}:${IMAGE_TAG})" +docker build \ + --file apps/bff/Dockerfile \ + --tag "${IMAGE_BACKEND_NAME}:latest" \ + --tag "${IMAGE_BACKEND_NAME}:${IMAGE_TAG}" \ + --label "org.opencontainers.image.title=Customer Portal Backend" \ + --label "org.opencontainers.image.version=${IMAGE_TAG}" \ + --label "org.opencontainers.image.source=$(git -C "$PROJECT_ROOT" config --get remote.origin.url 2>/dev/null || echo unknown)" \ + . + +if [[ "${SAVE_TARS}" -eq 1 ]]; then + mkdir -p "$OUTPUT_DIR" + FRONT_TAR_LATEST="$OUTPUT_DIR/${IMAGE_FRONTEND_NAME}.latest.tar" + BACK_TAR_LATEST="$OUTPUT_DIR/${IMAGE_BACKEND_NAME}.latest.tar" + FRONT_TAR_TAGGED="$OUTPUT_DIR/${IMAGE_FRONTEND_NAME}.${IMAGE_TAG}.tar" + BACK_TAR_TAGGED="$OUTPUT_DIR/${IMAGE_BACKEND_NAME}.${IMAGE_TAG}.tar" + + log "💾 Saving tarballs to $OUTPUT_DIR ..." + docker save -o "$FRONT_TAR_LATEST" "${IMAGE_FRONTEND_NAME}:latest" + docker save -o "$BACK_TAR_LATEST" "${IMAGE_BACKEND_NAME}:latest" + docker save -o "$FRONT_TAR_TAGGED" "${IMAGE_FRONTEND_NAME}:${IMAGE_TAG}" + docker save -o "$BACK_TAR_TAGGED" "${IMAGE_BACKEND_NAME}:${IMAGE_TAG}" + + log "✅ Wrote:" + echo " - $FRONT_TAR_LATEST" + echo " - $BACK_TAR_LATEST" + echo " - $FRONT_TAR_TAGGED" + echo " - $BACK_TAR_TAGGED" +fi + +if [[ -n "${PUSH_REMOTE}" ]]; then + FE_REMOTE_LATEST="${PUSH_REMOTE%/}/${IMAGE_FRONTEND_NAME}:latest" + FE_REMOTE_TAGGED="${PUSH_REMOTE%/}/${IMAGE_FRONTEND_NAME}:${IMAGE_TAG}" + BE_REMOTE_LATEST="${PUSH_REMOTE%/}/${IMAGE_BACKEND_NAME}:latest" + BE_REMOTE_TAGGED="${PUSH_REMOTE%/}/${IMAGE_BACKEND_NAME}:${IMAGE_TAG}" + + log "📤 Tagging for remote: ${PUSH_REMOTE}" + docker tag "${IMAGE_FRONTEND_NAME}:latest" "$FE_REMOTE_LATEST" + docker tag "${IMAGE_FRONTEND_NAME}:${IMAGE_TAG}" "$FE_REMOTE_TAGGED" + docker tag "${IMAGE_BACKEND_NAME}:latest" "$BE_REMOTE_LATEST" + docker tag "${IMAGE_BACKEND_NAME}:${IMAGE_TAG}" "$BE_REMOTE_TAGGED" + + log "🚀 Pushing to remote registry (ensure you are logged in)" + docker push "$FE_REMOTE_LATEST" + docker push "$FE_REMOTE_TAGGED" + docker push "$BE_REMOTE_LATEST" + docker push "$BE_REMOTE_TAGGED" +fi + +log "🎉 Done. Use compose-plesk.yaml in Plesk and upload the .tar files." +