7.9 KiB
7.9 KiB
42. Deployment — Update Docker, CI/CD, and Environment Configuration
meta: id: shieldai-unified-restructure-42 feature: shieldai-unified-restructure priority: P0 depends_on: [shieldai-unified-restructure-41] tags: [deployment, docker, ci-cd, infrastructure]
objective:
- Create production-ready deployment configuration for the unified monolith. Update Docker containers, CI/CD pipelines, and environment configuration to support the new single-app architecture plus native mobile builds.
deliverables:
web/Dockerfile— Production container for the web app:- Multi-stage build: Node.js builder → runtime
- Installs pnpm, dependencies, builds app
- Exposes port 3000
- Health check endpoint
- Non-root user for security
docker-compose.yml— Local development orchestration:webservice: builds fromweb/Dockerfile, ports3000:3000postgresservice: PostgreSQL 16 with volume for data persistenceredisservice: Redis 7 for job queues and cachingnginxservice: reverse proxy with SSL termination (optional)- Environment variables from
.envfile
docker-compose.prod.yml— Production orchestration:- Similar to dev but with production-optimized settings
- Volume mounts for uploads/logs
- Restart policies
- Resource limits
.github/workflows/ci.yml— GitHub Actions CI pipeline:- Lint and type check (TypeScript)
- Unit tests for web app
- Build verification
- Dependency audit (
pnpm audit)
.github/workflows/deploy.yml— GitHub Actions CD pipeline:- Build Docker image on release tag
- Push to container registry (GitHub Packages, Docker Hub, or ECR)
- Deploy to staging on push to
main - Deploy to production on release tag
- Run database migrations before deployment
- Health check after deployment
web/.env.example— Complete environment variable documentation:- Database:
DATABASE_URL - Redis:
REDIS_URL - Auth:
JWT_SECRET,NEXTAUTH_SECRET - Stripe:
STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET,STRIPE_PRICE_* - Notifications:
RESEND_API_KEY,FIREBASE_SERVICE_ACCOUNT_PATH,TWILIO_* - External APIs:
HIBP_API_KEY,SECURITYTRAILS_API_KEY, etc. - Monitoring:
SENTRY_DSN,DATADOG_API_KEY(optional) - App:
NODE_ENV,PORT,API_URL,APP_URL
- Database:
scripts/deploy.sh— Deployment helper script:- Database backup before migration
- Migration runner
- Health check verification
- Rollback on failure
scripts/backup.sh— Database backup script:pg_dumpto timestamped file- Upload to S3 or similar storage
steps:
- Create
web/Dockerfile:# Build stage FROM node:20-alpine AS builder WORKDIR /app RUN npm install -g pnpm COPY web/package.json web/pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile COPY web/ . RUN pnpm build # Runtime stage FROM node:20-alpine WORKDIR /app RUN npm install -g pnpm COPY --from=builder /app/package.json /app/pnpm-lock.yaml ./ COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/.output ./.output COPY --from=builder /app/drizzle ./drizzle ENV NODE_ENV=production EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 1 USER node CMD ["node", ".output/server/index.mjs"] - Create
docker-compose.yml:- Define services with appropriate environment variables
- PostgreSQL with
volumes: postgres_data:/var/lib/postgresql/data - Redis with
volumes: redis_data:/data - Network configuration
- Create
docker-compose.prod.yml:- Add restart policies:
unless-stopped - Add resource limits:
mem_limit,cpus - Add logging driver configuration
- Remove port bindings for internal services (postgres, redis)
- Add restart policies:
- Create
.github/workflows/ci.yml:- Trigger: push to any branch, pull requests
- Jobs:
lint:pnpm linttypecheck:tsc --noEmittest:pnpm testbuild:pnpm buildaudit:pnpm audit --audit-level=high
- Create
.github/workflows/deploy.yml:- Trigger: release tags (
v*), manual dispatch - Jobs:
build: build Docker image, tag with versionpush: push to registrymigrate: SSH into server, runpnpm db:migratedeploy: update Docker Compose stackhealthcheck: verify/healthendpoint responds 200
- Use GitHub secrets for SSH keys, registry credentials
- Trigger: release tags (
- Update
web/.env.example:- Document every environment variable used by the app
- Include description, example value, and whether required
- Group by category (Database, Auth, Payments, APIs, etc.)
- Create
scripts/deploy.sh:#!/bin/bashwith error handling (set -euo pipefail)- Backup database:
docker exec postgres pg_dump ... - Run migrations:
docker compose exec web pnpm db:migrate - Deploy:
docker compose -f docker-compose.prod.yml up -d - Health check:
curl -f http://localhost:3000/health - Rollback on failure:
docker compose rollbackor restore backup
- Create
scripts/backup.sh:- Generate timestamped dump
- Compress with gzip
- Upload to S3 using AWS CLI or rclone
- Retain last 30 backups
- Test deployment locally:
docker compose up --build- Verify app accessible at
http://localhost:3000 - Verify database migrations run
- Verify health check passes
- Document deployment process in
docs/DEPLOYMENT.md.
steps:
- Integration:
docker compose up --buildstarts all services successfully - Integration: App is accessible and functional inside Docker
- Integration: CI pipeline passes on GitHub Actions
- Integration: Deployment script completes without errors
- Security: Dockerfile uses non-root user
- Security: No secrets committed to repository
acceptance_criteria:
web/Dockerfilebuilds a production-ready containerdocker-compose.ymlorchestrates web, postgres, and redis for local devdocker-compose.prod.ymlis optimized for production with restart policies and resource limits- CI pipeline runs lint, type check, tests, build, and audit on every PR
- CD pipeline builds and deploys on release tags
- Database migrations run automatically before deployment
- Health check endpoint verifies app is ready
- Rollback script restores previous version on deployment failure
- Backup script creates and stores database dumps
.env.exampledocuments all required environment variables- No secrets are present in repository (verified by
git-secretsor manual audit)
validation:
docker compose up --build -d→ verifydocker psshows all containers runningcurl http://localhost:3000/health→ returns{"status":"ok"}docker logs shieldai-web→ no startup errors- Push to a test branch and verify GitHub Actions CI pipeline runs
- Create a test release tag and verify CD pipeline triggers
- Run
scripts/backup.shand verify dump file created - Run
scripts/deploy.shand verify deployment succeeds
notes:
- The unified monolith simplifies deployment significantly: one container instead of 5+ microservices.
- For high availability, run multiple web container instances behind a load balancer (nginx, AWS ALB, etc.).
- Consider using a managed database (RDS, Supabase, Neon) instead of self-hosted PostgreSQL for production.
- For Redis, consider Upstash or ElastiCache for managed service.
- The web app uses SolidStart with Nitro, which can run as a standalone server. Ensure the
.output/server/index.mjsentry point is correct. - For SSL, use Let's Encrypt with nginx or a managed load balancer. Document certificate renewal.
- Monitor disk space for logs and uploads. Configure log rotation in Docker.
- For mobile app deployment (iOS/Android), set up separate CI workflows for building and signing apps. This is outside the scope of the web deployment but should be documented.
- Consider using Terraform or Pulumi for infrastructure as code if managing cloud resources.