changemaker.lite/scripts/mirror-images.sh
bunker-admin be2fa5d80b Fix media-api restart loop and add registry build scripts
- Fix @/utils/logger path alias (tsc doesn't transform @/ in output)
- Add JWT_INVITE_SECRET to media-api compose environment block
- Fix redis-exporter depends_on to use service name not container name
- Fix upgrade.sh: restore tracked files deleted by restore_user_paths
- Add scripts/build-and-push.sh for building + pushing production images
- Add scripts/mirror-images.sh for mirroring third-party images

Bunker Admin
2026-03-22 19:17:10 -06:00

127 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================================
# Changemaker Lite V2 — Mirror Third-Party Images to Gitea Registry
# Pulls infrastructure images from Docker Hub and re-pushes to the Gitea
# container registry, protecting against Docker Hub rate limits.
#
# Usage:
# ./scripts/mirror-images.sh [OPTIONS]
#
# Options:
# --all Also mirror heavy optional images (Rocket.Chat, MongoDB, n8n,
# Gitea, Jitsi x4) in addition to core images
# --dry-run Print commands without executing
# --registry Override registry (default: gitea.bnkops.com/admin)
# --help Show this help
#
# Prerequisites:
# docker login gitea.bnkops.com
# =============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
# --- Defaults ---
REGISTRY="${GITEA_REGISTRY:-gitea.bnkops.com/admin}"
INCLUDE_ALL=false
DRY_RUN=false
# --- Colors ---
if [[ -t 1 ]] && [[ -z "${NO_COLOR:-}" ]]; then
RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m'
BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m'
else
RED='' GREEN='' YELLOW='' BLUE='' CYAN='' BOLD='' NC=''
fi
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
success() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
run() { if [[ "$DRY_RUN" == "true" ]]; then echo -e "${CYAN}[DRY-RUN]${NC} $*"; else eval "$@"; fi; }
# --- Arg parser ---
while [[ $# -gt 0 ]]; do
case "$1" in
--all) INCLUDE_ALL=true; shift ;;
--dry-run) DRY_RUN=true; shift ;;
--registry) REGISTRY="$2"; shift 2 ;;
--help|-h)
sed -n '2,30p' "$0" | grep '^#' | sed 's/^# \?//'
exit 0 ;;
*) error "Unknown option: $1"; exit 1 ;;
esac
done
# --- Core images (always mirrored) ---
CORE_IMAGES=(
"postgres:16-alpine"
"postgres:17-alpine"
"redis:7-alpine"
"nocodb/nocodb:0.301.3"
"listmonk/listmonk:v6.0.0"
"mailhog/mailhog:v1.0.1"
"prom/prometheus:v3.10.0"
"grafana/grafana:12.3.0"
"prom/alertmanager:v0.31.1"
"oliver006/redis_exporter:v1.81.0"
"gcr.io/cadvisor/cadvisor:v0.52.1"
"prom/node-exporter:v1.9.1"
"alpine:3"
)
# --- Heavy optional images (--all flag) ---
OPTIONAL_IMAGES=(
"gitea/gitea:1.23"
"n8nio/n8n:1.83.2"
"rocket.chat:7.4.0"
"mongo:6.0"
"jitsi/web:stable-10168"
"jitsi/prosody:stable-10168"
"jitsi/jicofo:stable-10168"
"jitsi/jvb:stable-10168"
"gotify/server:2.6.1"
)
mirror_image() {
local source="$1"
# Get short name: last path segment + tag
local name_tag="${source##*/}"
local dest="${REGISTRY}/${name_tag}"
info "Mirroring ${source}${dest}..."
run docker pull "${source}"
run docker tag "${source}" "${dest}"
run docker push "${dest}"
success "Mirrored ${name_tag}"
}
echo -e "${BOLD}Changemaker Lite — Mirror Images${NC}"
echo " Registry: $REGISTRY"
echo " All: $INCLUDE_ALL"
echo ""
IMAGES=("${CORE_IMAGES[@]}")
if [[ "$INCLUDE_ALL" == "true" ]]; then
IMAGES+=("${OPTIONAL_IMAGES[@]}")
warn "Including heavy optional images — this will take a while"
fi
FAILED=()
for img in "${IMAGES[@]}"; do
if ! mirror_image "$img"; then
FAILED+=("$img")
warn "Failed to mirror: $img (continuing...)"
fi
done
echo ""
if [[ ${#FAILED[@]} -eq 0 ]]; then
success "All ${#IMAGES[@]} images mirrored to ${REGISTRY}"
else
warn "Mirrored $((${#IMAGES[@]} - ${#FAILED[@]}))/${#IMAGES[@]} images"
error "Failed: ${FAILED[*]}"
exit 1
fi