#!/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."