Phase 7 of 7
Production Deployment and CI/CD
Deliver a reproducible production release path with automated validation, rolling updates, and a documented rollback procedure.
Overview
Move from a manually managed local stack to a CI/CD-driven release process. Create a production-oriented Compose file with resource limits, restart policies, and deploy settings. Wire a CI workflow that builds, tests, scans, and gates deployment on clean results. Implement a rolling update script that replaces containers one at a time while health checks confirm readiness before traffic shifts. After this phase, every commit goes through validation before it can reach production, and any bad release can be rolled back with a documented command sequence.
What to build
Deliverables
Advance only when these outputs exist in your code or compose definitions.
- docker-compose.prod.yml with resource limits (memory, cpus), restart: unless-stopped, and no bind mounts
- CI workflow (GitHub Actions or equivalent) covering: build, unit tests, docker build, security scan, and push to registry
- Deployment script (scripts/deploy.sh) implementing rolling container replacement with health-check gating
- Rollback script (scripts/rollback.sh) that reverts to the previous image tag
- Backup script (scripts/backup.sh) that dumps Postgres to a timestamped file
- Restore script (scripts/restore.sh) that loads a backup dump into a running database container
- RUNBOOK.md documenting the deployment, rollback, backup, and restore procedures step by step
Done when
Success criteria
These are acceptance indicators, not a checklist to start from.
- Every commit to the main branch triggers the CI workflow and the build must pass before deployment proceeds
- The CI workflow fails and blocks deployment if the security scan finds a CRITICAL or HIGH severity finding
- The rolling update script replaces the API container while health checks on the replacement pass before the old container is removed
- The rollback script successfully reverts to the previous image tag and the API returns HTTP 200 after rollback
- The backup script produces a valid Postgres dump that can be restored with the restore script
- The API stays healthy throughout a rolling update under a low-concurrency load (10 concurrent requests)
Verification
Testing and validation
Run these in order. Confirm each result before moving to the next step.
-
Start the production stack with docker compose -f docker-compose.prod.yml up -d and confirm all services start
-
curl http://localhost:8000/health— expect HTTP 200 with all dependency checks passing
-
Run scripts/deploy.sh with a new image tag and confirm the API remains reachable throughout the replacement
-
curl http://localhost:8000/healthafter deployment — confirm the new version is running
-
Run scripts/rollback.sh and confirm the API returns to the previous version without downtime
-
Run scripts/backup.sh and confirm a .sql dump file is created in the backup directory
-
Run scripts/restore.sh against the dump and confirm the data is present in the database after restore
-
Trigger a low-concurrency load (10 parallel curl requests) during a rolling update and confirm no 5xx responses