Never deploy blind
Stopping the old version before checking the new one is how outages happen. A safer pattern: start the new version next to the old one, health-check it, and only then switch — otherwise throw it away and keep serving the old version. That's the core of blue-green and rolling deployments.
A deploy script
#!/usr/bin/env bash
set -euo pipefail
TAG="${1:?usage: deploy.sh TAG}"
IMAGE="ghcr.io/learner/cafe-api:$TAG"
docker pull "$IMAGE"
docker rm -f api-next 2>/dev/null || true
docker run -d --name api-next -p 3001:3000 "$IMAGE"
if curl -fs localhost:3001/health > /dev/null; then
docker rm -f api-next
docker rm -f api
docker run -d --name api -p 3000:3000 "$IMAGE"
echo "deployed $TAG"
else
docker rm -f api-next
echo "rollback: $TAG is unhealthy, keeping the current version" >&2
exit 1
fi
Real setups put a reverse proxy in front so the switch has zero downtime, and keep the previous image tag handy for instant rollbacks.