1
0
peddlers-of-ketran/launch.sh

161 lines
4.2 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# launch.sh - helper wrapper around `docker compose` for this repo
#
# Features:
# - sets a stable Compose project name (defaults to peddlers-of-ketran)
# - supports multiple compose files (docker-compose.yml and docker-compose.dev.yml)
# - convenience commands: up, down, restart, ps, logs, build
# - supports --production to switch profiles
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Default values (can be overridden by environment or .env)
PROJECT_NAME="${COMPOSE_PROJECT_NAME:-peddlers-of-ketran}"
COMPOSE_FILES="${COMPOSE_FILE:-docker-compose.yml:docker-compose.dev.yml}"
PRODUCTION=${PRODUCTION:-0}
COMMAND="up"
SERVICE=""
usage() {
cat <<EOF
Usage: $0 [--production] [up|down|restart|ps|logs|build] [service]
Examples:
# Start dev profile (hot-reload)
./launch.sh up
# Start production profile
./launch.sh --production up
# Tail logs for the client service
./launch.sh logs peddlers-client
# List compose services
./launch.sh ps
EOF
}
# Parse args
while [[ $# -gt 0 ]]; do
case "$1" in
--production)
PRODUCTION=1
shift
;;
up|down|restart|ps|logs|build)
COMMAND="$1"
shift
# optional service argument for logs/build
if [[ $# -gt 0 && ! "$1" =~ ^- ]]; then
SERVICE="$1"
shift
fi
;;
-h|--help|help)
usage
exit 0
;;
*)
echo "Unknown argument: $1"
usage
exit 1
;;
esac
done
# Determine profile
if [ "$PRODUCTION" = "1" ]; then
PROFILE="prod"
echo "Launching in PRODUCTION mode (profile: $PROFILE)..."
else
PROFILE="dev"
echo "Launching in DEVELOPMENT mode (profile: $PROFILE)..."
fi
# Build compose file args (-f path/to/file -f path/to/other)
IFS=':' read -r -a FILE_ARR <<< "$COMPOSE_FILES"
FILES_ARGS=()
for f in "${FILE_ARR[@]}"; do
# If path is absolute keep it, otherwise resolve relative to repo dir
if [[ "$f" = /* ]]; then
candidate="$f"
else
candidate="$DIR/$f"
fi
if [[ -f "$candidate" ]]; then
FILES_ARGS+=("-f" "$candidate")
fi
done
# Ensure we have at least one compose file
if [ ${#FILES_ARGS[@]} -eq 0 ]; then
echo "Error: no compose files found (checked: ${FILE_ARR[*]}). Aborting."
exit 1
fi
# Resolve which compose invocation is available on the host. Prefer the
# modern `docker compose` plugin but fall back to `docker-compose` if
# necessary. Store the command as an array so we can insert flags safely.
DOCKER_COMPOSE_CMD=()
if docker compose version >/dev/null 2>&1; then
DOCKER_COMPOSE_CMD=(docker compose)
elif command -v docker-compose >/dev/null 2>&1; then
DOCKER_COMPOSE_CMD=(docker-compose)
else
echo "Error: neither 'docker compose' nor 'docker-compose' is available on PATH."
exit 1
fi
compose_base=("${DOCKER_COMPOSE_CMD[@]}" -p "$PROJECT_NAME" "${FILES_ARGS[@]}")
echo "Using compose project: $PROJECT_NAME"
echo "Compose files: ${FILES_ARGS[*]}"
case "$COMMAND" in
up)
echo "Bringing containers up (detached) with profile '$PROFILE'..."
"${compose_base[@]}" --profile "$PROFILE" up -d
;;
down)
echo "Querying compose-managed containers for project '$PROJECT_NAME'..."
# Show containers that will be affected so users know what's being removed
"${compose_base[@]}" ps --services --quiet || true
echo "Bringing containers down (profile: $PROFILE)..."
"${compose_base[@]}" --profile "$PROFILE" down --remove-orphans
;;
restart)
echo "Restarting containers (down + up -d) with profile '$PROFILE'..."
"${compose_base[@]}" --profile "$PROFILE" down --remove-orphans
"${compose_base[@]}" --profile "$PROFILE" up -d
;;
ps)
echo "Compose ps for project '$PROJECT_NAME'"
"${compose_base[@]}" ps
;;
logs)
echo "Tailing logs for project '$PROJECT_NAME'${SERVICE:+, service: $SERVICE}"
if [ -n "$SERVICE" ]; then
"${compose_base[@]}" logs -f --tail=200 "$SERVICE"
else
"${compose_base[@]}" logs -f --tail=200
fi
;;
build)
echo "Building images for project '$PROJECT_NAME'${SERVICE:+, service: $SERVICE}"
if [ -n "$SERVICE" ]; then
"${compose_base[@]}" build --no-cache "$SERVICE"
else
"${compose_base[@]}" build --no-cache
fi
;;
*)
echo "Unknown command: $COMMAND"
usage
exit 1
;;
esac