This commit is contained in:
tema 2025-09-04 14:17:14 +09:00
commit f2b34d9949
3 changed files with 196 additions and 5 deletions

View File

@ -93,7 +93,20 @@ customer-portal/
### Image Build and Upload
You can build locally and upload images to Plesk:
Option A — Use the helper script (recommended):
```bash
# Build both images, tag :latest and a date+sha tag, and write tarballs
scripts/plesk/build-images.sh
# Custom tag and output directory
scripts/plesk/build-images.sh --tag v1.0.0 --output ./dist
# Also push to a registry (e.g., GHCR)
scripts/plesk/build-images.sh --tag v1.0.0 --push ghcr.io/<org>
```
Option B — Manual build commands:
```bash
# Frontend

View File

@ -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
esac

146
scripts/plesk/build-images.sh Executable file
View File

@ -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/<org>
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 <<EOF
Build production Docker images and save tarballs for Plesk.
Usage: $0 [--tag <tag>] [--output <dir>] [--push <registry>] [--no-save]
Options:
--tag <tag> Tag to add in addition to 'latest' (e.g. v1.2.3 or abc123)
--output <dir> Directory to write tar files (default: project root)
--push <registry> 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."