85 lines
2.1 KiB
Markdown
85 lines
2.1 KiB
Markdown
## 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/<owner>/<repo>: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}}' <container-id>
|
|
```
|
|
|
|
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/<owner>/<repo>:<known-good-tag>
|
|
docker compose -f deploy/docker-compose.prod.yml up -d --no-build
|
|
```
|
|
|
|
Recommended: record the image digest for each release (`docker inspect <image> --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/<owner>/<repo>: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
|
|
```
|
|
|