fix(deploy): install.sh always docker-loads so stale wrong-arch images can't hide the shipped tarball
Previously install.sh short-circuited with "Image ... already present - skipping load" whenever a tag with the same version already existed in Docker. That optimization was actively harmful: if an earlier deploy attempt had loaded a wrong-arch (e.g. arm64) image at the same tag, we'd never load the corrected tarball in the current ZIP and the arch check would keep failing against the stale image forever. docker load reassigns the tag atomically to whatever is in the tarball and is a fast no-op when the layers are already present, so unconditional load is both safe and self-healing. install.sh now also prints the loaded image id + arch and, on mismatch, tells the operator to `git pull` on the build host before re-running package.sh so they pick up the buildx/binfmt fixes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
74b3a9fcb6
commit
0506f39bf3
2 changed files with 40 additions and 14 deletions
|
|
@ -106,12 +106,18 @@ it — handy if you need to roll back quickly.
|
|||
does not match this host"** — the ZIP was built for the wrong CPU
|
||||
architecture (typically an Apple Silicon Mac produced an `arm64` image
|
||||
for an `x86_64` Linux host). `install.sh` catches this and prints the
|
||||
exact rebuild command; ask your build operator to run:
|
||||
exact rebuild command; ask your build operator to `git pull` first
|
||||
(to pick up the fixed cross-arch build) and then run:
|
||||
```
|
||||
./docker/remote-agent/package.sh --platform linux/amd64
|
||||
```
|
||||
(or `linux/arm64` if this host is ARM — run `uname -m` to check:
|
||||
`x86_64` → `linux/amd64`, `aarch64` → `linux/arm64`.)
|
||||
|
||||
Note that `install.sh` **always** re-runs `docker load` on the bundled
|
||||
tarball, so a stale image left from an earlier wrong-arch attempt at the
|
||||
same version tag will be transparently replaced when you install a
|
||||
corrected bundle — no need to `docker rmi` by hand.
|
||||
- **Agent connects, then disconnects immediately** — `WS_TOKEN` doesn't
|
||||
match the server. Fix in `.env`, then `docker compose restart`.
|
||||
- **Agent never connects** — check `WS_URL` (correct hostname, correct
|
||||
|
|
|
|||
|
|
@ -65,21 +65,29 @@ else
|
|||
fi
|
||||
|
||||
# --- 3. Load the image -----------------------------------------------------
|
||||
# ALWAYS docker load, unconditionally. `docker load` reassigns the tag to
|
||||
# whatever's in the tarball and is a fast no-op when the layers are already
|
||||
# present, so this is safe to re-run. We intentionally do NOT "skip if the
|
||||
# tag already exists" — a stale image left over from a previous wrong-arch
|
||||
# attempt has this exact tag, and skipping the load would hide the correct
|
||||
# image in the tarball we're actually holding.
|
||||
|
||||
IMAGE_TAG="sha-remote-agent:${VERSION}"
|
||||
if docker image inspect "$IMAGE_TAG" >/dev/null 2>&1; then
|
||||
log "Image $IMAGE_TAG already present — skipping load."
|
||||
else
|
||||
log "Loading Docker image from $IMAGE_TARBALL..."
|
||||
|
||||
log "Loading Docker image from ${IMAGE_TARBALL}..."
|
||||
docker load -i "$IMAGE_TARBALL"
|
||||
fi
|
||||
|
||||
# --- 3a. Platform sanity check --------------------------------------------
|
||||
# If the image was built for a different CPU architecture than this host,
|
||||
# Docker will let it "run" but tini (and node) fail with cryptic errors
|
||||
# like "exec format error". Catch that up front with a clear message.
|
||||
# Inspect the image we just (re)loaded — this is the ground truth for what
|
||||
# was actually shipped in this ZIP, independent of anything that was on the
|
||||
# host before. If the tarball was built for a different CPU architecture
|
||||
# than this host, Docker will let it "run" but tini (and node) fail with
|
||||
# cryptic errors like "exec format error". Catch that up front with a
|
||||
# clear message.
|
||||
|
||||
IMAGE_ARCH="$(docker image inspect --format '{{.Architecture}}' "$IMAGE_TAG" 2>/dev/null || true)"
|
||||
IMAGE_ID_SHORT="$(docker image inspect --format '{{.Id}}' "$IMAGE_TAG" 2>/dev/null | sed 's|^sha256:||' | cut -c1-12)"
|
||||
|
||||
HOST_ARCH_RAW="$(uname -m)"
|
||||
case "$HOST_ARCH_RAW" in
|
||||
x86_64|amd64) HOST_ARCH="amd64" ;;
|
||||
|
|
@ -88,10 +96,22 @@ case "$HOST_ARCH_RAW" in
|
|||
*) HOST_ARCH="$HOST_ARCH_RAW" ;;
|
||||
esac
|
||||
|
||||
if [[ -n "$IMAGE_ARCH" && "$IMAGE_ARCH" != "$HOST_ARCH" ]]; then
|
||||
warn "Image architecture ($IMAGE_ARCH) does not match this host ($HOST_ARCH)."
|
||||
warn "The container will fail to start with 'exec format error'."
|
||||
die "Rebuild on the dev host with: ./docker/remote-agent/package.sh --platform linux/${HOST_ARCH}"
|
||||
log "Loaded ${IMAGE_TAG} (id: ${IMAGE_ID_SHORT:-unknown}, arch: ${IMAGE_ARCH:-unknown}); host arch: ${HOST_ARCH}."
|
||||
|
||||
if [[ -z "$IMAGE_ARCH" ]]; then
|
||||
die "Could not read image architecture from Docker — is the image really loaded?"
|
||||
fi
|
||||
|
||||
if [[ "$IMAGE_ARCH" != "$HOST_ARCH" ]]; then
|
||||
warn "Image architecture (${IMAGE_ARCH}) does not match this host (${HOST_ARCH})."
|
||||
warn "The container would fail to start with 'exec /sbin/tini: exec format error'."
|
||||
warn ""
|
||||
warn "This means the ZIP was built for the wrong CPU. On the build host:"
|
||||
warn " 1. git pull # make sure you have the fixed package.sh"
|
||||
warn " 2. ./docker/remote-agent/package.sh --platform linux/${HOST_ARCH}"
|
||||
warn "The updated package.sh verifies the architecture during build and"
|
||||
warn "refuses to produce a ZIP that would fail this check."
|
||||
die "Aborting install. Ship a linux/${HOST_ARCH} bundle and re-run this script."
|
||||
fi
|
||||
|
||||
# --- 4. Bootstrap .env -----------------------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in a new issue