cambios cleanup del registry remoto y tags
This commit is contained in:
@@ -17,9 +17,25 @@ remote Docker daemon. No external registry is required.
|
||||
```
|
||||
|
||||
The script reads `artifactId` and `version` from `pom.xml` for the image name
|
||||
and tag, builds for `linux/amd64`, and verifies the image is present on the
|
||||
remote after pushing. The temporary registry container and SSH tunnel are removed
|
||||
when the script finishes. See `./scripts/build-and-push.sh --help` for all flags.
|
||||
and version tag, builds for `linux/amd64`, and verifies the image is present on
|
||||
the remote after pushing. On the remote (and locally) that push is tagged three
|
||||
ways, all pointing at the same image:
|
||||
|
||||
- `<name>:<version>` — the version from `pom.xml` or `--tag`
|
||||
- `<name>:latest` — moved to this push on every successful deploy
|
||||
- `<name>:sha256-<12 hex chars>` — immutable tag taken from the registry digest
|
||||
|
||||
The temporary registry container and SSH tunnel are removed when the script
|
||||
finishes. See `./scripts/build-and-push.sh --help` for all flags.
|
||||
|
||||
To remove leftover temporary registry containers and `localhost:<port>/...` image
|
||||
tags on the remote (for example after an interrupted push or manual tests):
|
||||
|
||||
```shell script
|
||||
./scripts/build-and-push.sh --remote deploy@prod.example.com --cleanup
|
||||
```
|
||||
|
||||
This does not rebuild or push; it only needs SSH access to the remote host.
|
||||
|
||||
It can be invoked from any directory: by default it resolves the project root
|
||||
from the script's own location. Override with `--project-dir PATH` or the
|
||||
|
||||
+93
-25
@@ -3,9 +3,10 @@
|
||||
# Build the native Quarkus image and push it to a remote Docker host
|
||||
# via a temporary registry:2 on the remote, reached through an SSH tunnel.
|
||||
#
|
||||
# - Image name/tag default to pom.xml properties (quarkus.application.*)
|
||||
# - Image name/tag default to pom.xml properties (artifactId and version)
|
||||
# - Builds for linux/amd64 by default (cross-compile from arm64 hosts)
|
||||
# - Transfers layers over the tunnel (no external registry required)
|
||||
# - On the remote, tags the image as <version>, latest, and sha256-<digest>
|
||||
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
@@ -23,6 +24,7 @@ SSH_CONFIG=""
|
||||
PROJECT_DIR="${PROJECT_DIR:-${SCRIPT_DIR}/..}"
|
||||
SKIP_BUILD=0
|
||||
SKIP_VERIFY=0
|
||||
CLEANUP=0
|
||||
|
||||
# ---------- logging ----------
|
||||
if [[ -t 1 ]]; then
|
||||
@@ -63,7 +65,8 @@ Required:
|
||||
|
||||
Image identity (defaults read from pom.xml):
|
||||
--name NAME Image repository name
|
||||
--tag TAG Image tag
|
||||
--tag TAG Version tag. The remote also receives :latest
|
||||
and a sha256-<digest> tag for this push.
|
||||
|
||||
Working directory (defaults to the parent of the script's directory):
|
||||
--project-dir PATH Project root containing pom.xml
|
||||
@@ -80,6 +83,11 @@ SSH options:
|
||||
Post-push:
|
||||
--no-verify Skip the ssh/docker images verification step
|
||||
|
||||
Maintenance:
|
||||
--cleanup Remove leftover temporary registry containers and
|
||||
localhost:<port>/... image tags on the remote
|
||||
(no build, no push; Docker local not required)
|
||||
|
||||
Other:
|
||||
-h, --help Show this help
|
||||
|
||||
@@ -94,6 +102,7 @@ Examples:
|
||||
$(basename "$0") --remote prod # uses 'Host prod' in ~/.ssh/config
|
||||
$(basename "$0") --remote ubuntu@1.2.3.4 --ssh-key ~/.ssh/deploy_ed25519
|
||||
$(basename "$0") --remote deploy@prod --skip-build --tag 2.0.0
|
||||
$(basename "$0") --remote prod --cleanup
|
||||
/absolute/path/to/test-quarkus/scripts/$(basename "$0") --remote deploy@prod
|
||||
PROJECT_DIR=/srv/proj $(basename "$0") --remote deploy@prod --skip-build
|
||||
EOF
|
||||
@@ -217,13 +226,27 @@ detect_remote_docker() {
|
||||
die "Cannot run docker on ${REMOTE_TARGET}. Ensure Docker is installed and the SSH user may run docker (or passwordless sudo docker)."
|
||||
}
|
||||
|
||||
cleanup_remote_registry() {
|
||||
log "Cleaning temporary registry leftovers on ${REMOTE_TARGET}…"
|
||||
run_remote "${REMOTE_DOCKER} ps -aq --filter name=reg-push- | xargs -r ${REMOTE_DOCKER} rm -f" \
|
||||
>/dev/null 2>&1 || true
|
||||
run_remote "${REMOTE_DOCKER} rm -f regtest" >/dev/null 2>&1 || true
|
||||
run_remote "${REMOTE_DOCKER} images --format '{{.Repository}}:{{.Tag}}' \
|
||||
| grep -E '^localhost:[0-9]+/' | xargs -r ${REMOTE_DOCKER} rmi" \
|
||||
>/dev/null 2>&1 || true
|
||||
ok "Remote cleanup complete."
|
||||
}
|
||||
|
||||
REG_PUSH_CONTAINER=""
|
||||
REG_REMOTE_PORT=""
|
||||
REG_LOCAL_PORT=""
|
||||
TUNNEL_PID=""
|
||||
LOCAL_REGISTRY_REF=""
|
||||
DIGEST_REF=""
|
||||
PUSH_LOG=""
|
||||
|
||||
cleanup_push_resources() {
|
||||
[[ -n "${PUSH_LOG:-}" ]] && rm -f "$PUSH_LOG"
|
||||
[[ -n "${LOCAL_REGISTRY_REF:-}" ]] \
|
||||
&& docker rmi "$LOCAL_REGISTRY_REF" >/dev/null 2>&1 || true
|
||||
if [[ -n "${TUNNEL_PID:-}" ]]; then
|
||||
@@ -280,20 +303,47 @@ start_ssh_tunnel() {
|
||||
die "Failed to establish SSH tunnel to remote registry."
|
||||
}
|
||||
|
||||
digest_tag_from_push_log() {
|
||||
local log_file="$1"
|
||||
local digest hex
|
||||
digest=$(sed -n 's/.*digest: \(sha256:[0-9a-f]\{64\}\).*/\1/p' "$log_file" | tail -1)
|
||||
if [[ -z "$digest" ]]; then
|
||||
digest=$(docker image inspect --format '{{index .RepoDigests 0}}' "$LOCAL_REGISTRY_REF" 2>/dev/null \
|
||||
| sed -n 's/.*@\(sha256:[0-9a-f]\{64\}\)/\1/p')
|
||||
fi
|
||||
[[ -n "$digest" ]] || die "Could not read the image digest after push."
|
||||
hex="${digest#sha256:}"
|
||||
printf 'sha256-%s' "${hex:0:12}"
|
||||
}
|
||||
|
||||
push_via_registry_tunnel() {
|
||||
LOCAL_REGISTRY_REF="localhost:${REG_LOCAL_PORT}/${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
local remote_registry_ref="localhost:${REG_REMOTE_PORT}/${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
local latest_ref="${IMAGE_NAME}:latest"
|
||||
local digest_tag
|
||||
|
||||
log "Tagging ${IMAGE_REF} as ${LOCAL_REGISTRY_REF}…"
|
||||
docker tag "$IMAGE_REF" "$LOCAL_REGISTRY_REF"
|
||||
|
||||
log "Pushing ${LOCAL_REGISTRY_REF} through SSH tunnel…"
|
||||
docker push "$LOCAL_REGISTRY_REF"
|
||||
PUSH_LOG=$(mktemp)
|
||||
docker push "$LOCAL_REGISTRY_REF" | tee "$PUSH_LOG"
|
||||
digest_tag=$(digest_tag_from_push_log "$PUSH_LOG")
|
||||
rm -f "$PUSH_LOG"
|
||||
PUSH_LOG=""
|
||||
DIGEST_REF="${IMAGE_NAME}:${digest_tag}"
|
||||
|
||||
log "Pulling image on remote and retagging as ${IMAGE_REF}…"
|
||||
log "Tagging local image as ${latest_ref} and ${DIGEST_REF}…"
|
||||
docker tag "$IMAGE_REF" "$latest_ref"
|
||||
docker tag "$IMAGE_REF" "$DIGEST_REF"
|
||||
|
||||
log "Pulling image on remote and tagging ${IMAGE_REF}, ${latest_ref}, ${DIGEST_REF}…"
|
||||
run_remote "${REMOTE_DOCKER} pull ${remote_registry_ref}"
|
||||
run_remote "${REMOTE_DOCKER} tag ${remote_registry_ref} ${IMAGE_REF}"
|
||||
run_remote "${REMOTE_DOCKER} tag ${remote_registry_ref} ${latest_ref}"
|
||||
run_remote "${REMOTE_DOCKER} tag ${remote_registry_ref} ${DIGEST_REF}"
|
||||
run_remote "${REMOTE_DOCKER} rmi ${remote_registry_ref}" >/dev/null || true
|
||||
ok "Remote tags: ${IMAGE_REF}, ${latest_ref}, ${DIGEST_REF}."
|
||||
}
|
||||
|
||||
# ---------- arg parsing ----------
|
||||
@@ -307,23 +357,13 @@ while [[ $# -gt 0 ]]; do
|
||||
--project-dir) PROJECT_DIR="$2"; shift 2 ;;
|
||||
--skip-build) SKIP_BUILD=1; shift ;;
|
||||
--no-verify) SKIP_VERIFY=1; shift ;;
|
||||
--cleanup) CLEANUP=1; shift ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) die "Unknown argument: $1 (use --help)" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ---------- resolve project root ----------
|
||||
if ! cd "${PROJECT_DIR}" 2>/dev/null; then
|
||||
die "Invalid --project-dir: ${PROJECT_DIR}"
|
||||
fi
|
||||
PROJECT_DIR="$(pwd)"
|
||||
|
||||
# ---------- defaults ----------
|
||||
[[ -z "$IMAGE_NAME" ]] && IMAGE_NAME=$(read_pom "/*[local-name()='project']/*[local-name()='artifactId']" "test-quarkus" "artifactId")
|
||||
[[ -z "$IMAGE_TAG" ]] && IMAGE_TAG=$(read_pom "/*[local-name()='project']/*[local-name()='version']" "1.0.0-SNAPSHOT" "version")
|
||||
[[ -z "$REMOTE" ]] && die "Missing --remote USER@HOST[:PORT] (use --help)."
|
||||
|
||||
IMAGE_REF="${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
[[ -z "$REMOTE" ]] && die "Missing --remote USER@HOST[:PORT] (use --help)."
|
||||
|
||||
# ---------- resolve SSH target ----------
|
||||
resolved=$(resolve_ssh_alias "$REMOTE")
|
||||
@@ -337,6 +377,29 @@ if [[ -z "$SSH_KEY" && -n "$REMOTE_IDENTITY" ]]; then
|
||||
log "Using IdentityFile from SSH config: ${SSH_KEY}"
|
||||
fi
|
||||
|
||||
# ---------- remote cleanup only ----------
|
||||
if [[ "$CLEANUP" -eq 1 ]]; then
|
||||
log "Remote: ${REMOTE_TARGET}"
|
||||
require ssh
|
||||
parse_ssh_target
|
||||
build_ssh_args
|
||||
detect_remote_docker
|
||||
cleanup_remote_registry
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ---------- resolve project root ----------
|
||||
if ! cd "${PROJECT_DIR}" 2>/dev/null; then
|
||||
die "Invalid --project-dir: ${PROJECT_DIR}"
|
||||
fi
|
||||
PROJECT_DIR="$(pwd)"
|
||||
|
||||
# ---------- defaults ----------
|
||||
[[ -z "$IMAGE_NAME" ]] && IMAGE_NAME=$(read_pom "/*[local-name()='project']/*[local-name()='artifactId']" "test-quarkus" "artifactId")
|
||||
[[ -z "$IMAGE_TAG" ]] && IMAGE_TAG=$(read_pom "/*[local-name()='project']/*[local-name()='version']" "1.0.0-SNAPSHOT" "version")
|
||||
|
||||
IMAGE_REF="${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
|
||||
# ---------- pre-flight ----------
|
||||
log "Image: ${IMAGE_REF}"
|
||||
log "Platform: ${DEFAULT_PLATFORM}"
|
||||
@@ -388,15 +451,20 @@ ok "Push complete."
|
||||
if [[ "$SKIP_VERIFY" -eq 1 ]]; then
|
||||
warn "Skipping post-push verification (--no-verify)."
|
||||
else
|
||||
log "Verifying ${IMAGE_REF} on ${REMOTE_TARGET}…"
|
||||
|
||||
if ! run_remote "${REMOTE_DOCKER} images --format '{{.Repository}}:{{.Tag}} {{.Size}}' | grep -E '^${IMAGE_NAME}:${IMAGE_TAG} '"; then
|
||||
die "Image ${IMAGE_REF} not found on ${REMOTE_TARGET} after push."
|
||||
fi
|
||||
ok "Image present on remote."
|
||||
log "Verifying tags on ${REMOTE_TARGET}…"
|
||||
remote_images=$(run_remote "${REMOTE_DOCKER} images --format '{{.Repository}}:{{.Tag}}'")
|
||||
missing=0
|
||||
for ref in "${IMAGE_REF}" "${IMAGE_NAME}:latest" "${DIGEST_REF}"; do
|
||||
if ! printf '%s\n' "$remote_images" | grep -Fxq "$ref"; then
|
||||
err "Missing on remote: ${ref}"
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
[[ "$missing" -eq 0 ]] || die "Expected tags were not found on ${REMOTE_TARGET} after push."
|
||||
ok "Remote has ${IMAGE_REF}, ${IMAGE_NAME}:latest and ${DIGEST_REF}."
|
||||
fi
|
||||
|
||||
# ---------- next step hint ----------
|
||||
printf '\n%s→ To run on the remote:%s\n' "$C_OK" "$C_RESET"
|
||||
printf ' ssh %s "docker run -d --name %s --restart unless-stopped -p 8080:8080 %s"\n\n' \
|
||||
"$REMOTE_TARGET" "$IMAGE_NAME" "$IMAGE_REF"
|
||||
printf '\n%s→ To run the latest image on the remote:%s\n' "$C_OK" "$C_RESET"
|
||||
printf ' ssh %s "docker run -d --name %s --restart unless-stopped -p 8080:8080 %s:latest"\n\n' \
|
||||
"$REMOTE_TARGET" "$IMAGE_NAME" "$IMAGE_NAME"
|
||||
|
||||
Reference in New Issue
Block a user