deployment-automation

Automate application deployment across Docker, Kubernetes, AWS, and Vercel with CI/CD pipelines. Covers Docker containerization with multi-stage builds, GitHub Actions workflows for testing and image building, and Kubernetes deployment with rolling updates and autoscaling Includes zero-downtime deployment strategies using blue-green deployments and health check validation Provides configuration templates for Vercel/Netlify frontend deployments, environment variable management, and graceful shutdown handling Enforces best practices: immutable infrastructure, secret management, version tagging, and post-deployment monitoring integration

INSTALLATION
npx skills add https://github.com/supercent-io/skills-template --skill deployment-automation
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

Deployment Automation

When to use this skill

  • New Projects: Set up automated deployment from scratch
  • Manual Deployment Improvement: Automate repetitive manual tasks
  • Multi-Environment: Separate dev, staging, and production environments
  • Scaling: Introduce Kubernetes to handle traffic growth

Instructions

Step 1: Docker Containerization

Package the application as a Docker image.

Dockerfile (Node.js app):

# Multi-stage build for smaller image size

FROM node:18-alpine AS builder

WORKDIR /app

# Copy package files and install dependencies

COPY package*.json ./

RUN npm ci --only=production

# Copy source code

COPY . .

# Build application (if needed)

RUN npm run build

# Production stage

FROM node:18-alpine

WORKDIR /app

# Copy only necessary files from builder

COPY --from=builder /app/node_modules ./node_modules

COPY --from=builder /app/dist ./dist

COPY --from=builder /app/package.json ./

# Create non-root user for security

RUN addgroup -g 1001 -S nodejs && \

    adduser -S nodejs -u 1001

USER nodejs

# Expose port

EXPOSE 3000

# Health check

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \

  CMD node healthcheck.js

# Start application

CMD ["node", "dist/index.js"]

.dockerignore:

node_modules

npm-debug.log

.git

.env

.env.local

dist

build

coverage

.DS_Store

Build and Run:

# Build image

docker build -t myapp:latest .

# Run container

docker run -d -p 3000:3000 --name myapp-container myapp:latest

# Check logs

docker logs myapp-container

# Stop and remove

docker stop myapp-container

docker rm myapp-container

Step 2: GitHub Actions CI/CD

Automatically runs tests and deploys on code push.

.github/workflows/deploy.yml:

name: CI/CD Pipeline

on:

  push:

    branches: [main, develop]

  pull_request:

    branches: [main]

env:

  NODE_VERSION: '18'

  REGISTRY: ghcr.io

  IMAGE_NAME: ${{ github.repository }}

jobs:

  test:

    runs-on: ubuntu-latest

    steps:

      - uses: actions/checkout@v4

      - name: Setup Node.js

        uses: actions/setup-node@v4

        with:

          node-version: ${{ env.NODE_VERSION }}

          cache: 'npm'

      - name: Install dependencies

        run: npm ci

      - name: Run linter

        run: npm run lint

      - name: Run tests

        run: npm test -- --coverage

      - name: Upload coverage

        uses: codecov/codecov-action@v3

        with:

          files: ./coverage/coverage-final.json

  build:

    needs: test

    runs-on: ubuntu-latest

    if: github.event_name == 'push' && github.ref == 'refs/heads/main'

    steps:

      - uses: actions/checkout@v4

      - name: Set up Docker Buildx

        uses: docker/setup-buildx-action@v3

      - name: Log in to Container Registry

        uses: docker/login-action@v3

        with:

          registry: ${{ env.REGISTRY }}

          username: ${{ github.actor }}

          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata

        id: meta

        uses: docker/metadata-action@v5

        with:

          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

          tags: |

            type=sha,prefix={{branch}}-

            type=semver,pattern={{version}}

            latest

      - name: Build and push Docker image

        uses: docker/build-push-action@v5

        with:

          context: .

          push: true

          tags: ${{ steps.meta.outputs.tags }}

          labels: ${{ steps.meta.outputs.labels }}

          cache-from: type=gha

          cache-to: type=gha,mode=max

  deploy:

    needs: build

    runs-on: ubuntu-latest

    environment: production

    steps:

      - name: Deploy to production

        uses: appleboy/ssh-action@v1.0.0

        with:

          host: ${{ secrets.PROD_HOST }}

          username: ${{ secrets.PROD_USER }}

          key: ${{ secrets.PROD_SSH_KEY }}

          script: |

            cd /app

            docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest

            docker-compose up -d --no-deps --build web

            docker image prune -f

Step 3: Kubernetes Deployment

Implement scalable container orchestration.

k8s/deployment.yaml:

apiVersion: apps/v1

kind: Deployment

metadata:

  name: myapp

  namespace: production

  labels:

    app: myapp

spec:

  replicas: 3

  strategy:

    type: RollingUpdate

    rollingUpdate:

      maxSurge: 1

      maxUnavailable: 0

  selector:

    matchLabels:

      app: myapp

  template:

    metadata:

      labels:

        app: myapp

    spec:

      containers:

      - name: myapp

        image: ghcr.io/username/myapp:latest

        imagePullPolicy: Always

        ports:

        - containerPort: 3000

        env:

        - name: NODE_ENV

          value: "production"

        - name: DATABASE_URL

          valueFrom:

            secretKeyRef:

              name: myapp-secrets

              key: database-url

        resources:

          requests:

            memory: "128Mi"

            cpu: "100m"

          limits:

            memory: "256Mi"

            cpu: "200m"

        livenessProbe:

          httpGet:

            path: /health

            port: 3000

          initialDelaySeconds: 30

          periodSeconds: 10

        readinessProbe:

          httpGet:

            path: /ready

            port: 3000

          initialDelaySeconds: 5

          periodSeconds: 5

---

apiVersion: v1

kind: Service

metadata:

  name: myapp-service

  namespace: production

spec:

  selector:

    app: myapp

  ports:

  - protocol: TCP

    port: 80

    targetPort: 3000

  type: LoadBalancer

---

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

  name: myapp-hpa

  namespace: production

spec:

  scaleTargetRef:

    apiVersion: apps/v1

    kind: Deployment

    name: myapp

  minReplicas: 2

  maxReplicas: 10

  metrics:

  - type: Resource

    resource:

      name: cpu

      target:

        type: Utilization

        averageUtilization: 70

  - type: Resource

    resource:

      name: memory

      target:

        type: Utilization

        averageUtilization: 80

Deployment Script (deploy.sh):

#!/bin/bash

set -e

# Variables

NAMESPACE="production"

IMAGE_TAG="${1:-latest}"

echo "Deploying myapp:${IMAGE_TAG} to ${NAMESPACE}..."

# Apply Kubernetes manifests

kubectl apply -f k8s/namespace.yaml

kubectl apply -f k8s/secrets.yaml

kubectl apply -f k8s/deployment.yaml

kubectl apply -f k8s/service.yaml

# Update image

kubectl set image deployment/myapp myapp=ghcr.io/username/myapp:${IMAGE_TAG} -n ${NAMESPACE}

# Wait for rollout

kubectl rollout status deployment/myapp -n ${NAMESPACE} --timeout=5m

# Verify

kubectl get pods -n ${NAMESPACE} -l app=myapp

echo "Deployment completed successfully!"

Step 4: Vercel/Netlify (Frontend)

Simply deploy static sites and Next.js apps.

vercel.json:

{

  "version": 2,

  "builds": [

    {

      "src": "package.json",

      "use": "@vercel/next"

    }

  ],

  "env": {

    "DATABASE_URL": "@database-url",

    "API_KEY": "@api-key"

  },

  "regions": ["sin1", "icn1"],

  "headers": [

    {

      "source": "/(.*)",

      "headers": [

        {

          "key": "X-Frame-Options",

          "value": "DENY"

        },

        {

          "key": "X-Content-Type-Options",

          "value": "nosniff"

        }

      ]

    }

  ],

  "redirects": [

    {

      "source": "/old-path",

      "destination": "/new-path",

      "permanent": true

    }

  ]

}

CLI Deployment:

# Install Vercel CLI

npm i -g vercel

# Login

vercel login

# Deploy to preview

vercel

# Deploy to production

vercel --prod

# Set environment variable

vercel env add DATABASE_URL

Step 5: Zero-Downtime Deployment Strategy

Deploy new versions without service interruption.

Blue-Green Deployment (docker-compose):

version: '3.8'

services:

  nginx:

    image: nginx:alpine

    ports:

      - "80:80"

    volumes:

      - ./nginx.conf:/etc/nginx/nginx.conf:ro

    depends_on:

      - app-blue

      - app-green

  app-blue:

    image: myapp:blue

    environment:

      - NODE_ENV=production

      - COLOR=blue

  app-green:

    image: myapp:green

    environment:

      - NODE_ENV=production

      - COLOR=green

switch.sh (Blue/Green Switch):

#!/bin/bash

CURRENT_COLOR=$(cat current_color.txt)

NEW_COLOR=$([[ "$CURRENT_COLOR" == "blue" ]] && echo "green" || echo "blue")

# Deploy new version to inactive environment

docker-compose up -d app-${NEW_COLOR}

# Wait for health check

sleep 10

# Health check

if curl -f http://localhost:8080/health; then

  # Update nginx to point to new environment

  sed -i "s/${CURRENT_COLOR}/${NEW_COLOR}/g" nginx.conf

  docker-compose exec nginx nginx -s reload

  # Update current color

  echo ${NEW_COLOR} > current_color.txt

  # Stop old environment after 5 minutes (rollback window)

  sleep 300

  docker-compose stop app-${CURRENT_COLOR}

  echo "Deployment successful! Switched to ${NEW_COLOR}"

else

  echo "Health check failed! Keeping ${CURRENT_COLOR}"

  docker-compose stop app-${NEW_COLOR}

  exit 1

fi

Output format

Deployment Checklist

## Deployment Checklist

### Pre-Deployment

- [ ] All tests passing (unit, integration, E2E)

- [ ] Code review approved

- [ ] Environment variables configured

- [ ] Database migrations ready

- [ ] Rollback plan documented

### Deployment

- [ ] Docker image built and tagged

- [ ] Image pushed to container registry

- [ ] Kubernetes manifests applied

- [ ] Rolling update started

- [ ] Pods healthy and ready

### Post-Deployment

- [ ] Health check endpoint responding

- [ ] Metrics/logs monitoring active

- [ ] Performance baseline established

- [ ] Old pods terminated (after grace period)

- [ ] Deployment documented in changelog

Constraints

Required Rules (MUST)

-

Health Checks: Health check endpoint for all services

app.get('/health', (req, res) => {

  res.status(200).json({ status: 'ok' });

});

-

Graceful Shutdown: Handle SIGTERM signal

process.on('SIGTERM', async () => {

  console.log('SIGTERM received, shutting down gracefully');

  await server.close();

  await db.close();

  process.exit(0);

});

-

Environment Variable Separation: No hardcoding; use .env files

Prohibited Rules (MUST NOT)

  • No Committing Secrets: Never commit API keys or passwords to Git
  • No Debug Mode in Production: NODE_ENV=production is required
  • Avoid latest tag only: Use version tags (v1.0.0, sha-abc123)

Best practices

  • Multi-stage Docker builds: Minimize image size
  • Immutable infrastructure: Redeploy instead of modifying servers
  • Blue-Green deployment: Zero-downtime deployment and easy rollback
  • Monitoring required: Prometheus, Grafana, Datadog

References

Metadata

Version

  • Current Version: 1.0.0
  • Last Updated: 2025-01-01
  • Compatible Platforms: Claude, ChatGPT, Gemini

Related Skills

Tags

#deployment #CI/CD #Docker #Kubernetes #automation #infrastructure

Examples

Example 1: Basic usage

Example 2: Advanced usage

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card