## Deploy Runbook (Docker-Only Host) This runbook is for a minimal production host where **Docker is installed** and **Node.js is not**. The deployment model is: - CI builds and publishes a Docker image containing the built static site - the server updates by pulling that image and restarting the service ### Prerequisites - Docker + Docker Compose plugin available on the host - Registry access (e.g., logged in to GHCR if the image is private) - A `WEB_IMAGE` value pointing at the image to deploy (tag or digest) Example: ```bash export WEB_IMAGE=ghcr.io//:latest ``` ### First-Time Start ```bash docker compose -f deploy/docker-compose.prod.yml up -d ``` ### Refresh (Pull + Restart) Pull first (safe; does not affect the running container): ```bash docker compose -f deploy/docker-compose.prod.yml pull ``` Then restart the service on the newly pulled image: ```bash docker compose -f deploy/docker-compose.prod.yml up -d --no-build ``` ### Verify Deployed Version 1. Check the container's image reference (tag/digest): ```bash docker compose -f deploy/docker-compose.prod.yml ps docker inspect --format '{{.Image}} {{.Config.Image}}' ``` 2. Check build metadata served by the site: ```bash curl -fsS http://localhost:8080/build.json ``` ### Rollback Re-deploy a known-good version by pinning a previous tag or digest: ```bash export WEB_IMAGE=ghcr.io//: docker compose -f deploy/docker-compose.prod.yml up -d --no-build ``` Recommended: record the image digest for each release (`docker inspect --format '{{.Id}}'`), and use a digest pin for true immutability. ### Failure Mode Validation (Pull Failure) If `docker compose pull` fails, **do not run** the restart step. The running site will continue serving the existing container. To simulate a pull failure safely: ```bash export WEB_IMAGE=ghcr.io//:this-tag-does-not-exist docker compose -f deploy/docker-compose.prod.yml pull ``` The pull should fail, but the current service should still be running: ```bash docker compose -f deploy/docker-compose.prod.yml ps curl -fsS http://localhost:8080/ > /dev/null ```