Agent Skills: Deployment Skill

Deploy, debug, and maintain services on Render and containerized platforms

UncategorizedID: alexwelcing/copy/deployment

Install this agent skill to your local

pnpm dlx add-skill https://github.com/alexwelcing/copy/tree/HEAD/skills/deployment

Skill Files

Browse the full folder contents for deployment.

Download Skill

Loading file tree…

skills/deployment/SKILL.md

Skill Metadata

Name
deployment
Description
Deploy, debug, and maintain services on Render and containerized platforms

Deployment Skill

You are an expert deployment engineer specializing in containerized web services on Render and similar PaaS platforms. Your goal is to ensure reliable builds, correct service configuration, and zero-downtime deploys.

Core Principles

  1. The build context is king — every Docker COPY failure traces back to a context mismatch
  2. Dashboard overrides config files — platform UI settings often take precedence over repo-checked config (render.yaml, app.yaml)
  3. Test the container locally before pushingdocker build catches 90% of deploy failures
  4. Environment variables must match what the app reads — not what a framework expects (VITE_API_URL vs API_URL)
  5. Services communicate over public URLs on PaaS — not Docker networking hostnames
  6. Fail loud, not silent — log every file read, API call, and config load so deploy issues surface in logs

Render Platform

Service Architecture

  • Each service gets its own container and public URL
  • Inter-service communication uses https://<service-name>.onrender.com
  • NOT Docker Compose networking (http://service:port)
  • Free tier services spin down after inactivity — first request is slow

render.yaml vs Dashboard

  • render.yaml defines infrastructure-as-code for initial setup
  • Dashboard settings can override render.yaml after first deploy
  • When debugging: always check dashboard config, not just the yaml
  • Key fields: dockerContext, dockerfilePath, envVars, buildCommand

Docker Context on Render

# If your service root is a subdirectory:
dockerContext: frontend          # Build context = ./frontend/
dockerfilePath: frontend/Dockerfile  # Dockerfile location from repo root

# Inside the Dockerfile, paths are relative to dockerContext:
COPY go.mod go.sum ./          # Copies frontend/go.mod, frontend/go.sum
COPY . .                       # Copies everything in frontend/

Common trap: Changing dockerContext in render.yaml after initial deploy may not take effect if the dashboard has its own setting locked in. Verify in the Render dashboard under Service > Settings > Build & Deploy.

Environment Variables

  • Set secrets in dashboard (never in render.yaml)
  • Use envVarKey references for shared secrets between services:
- key: API_SECRET
  fromService:
    type: web
    name: other-service
    property: envVar
    envVarKey: API_SECRET

Docker Best Practices

Multi-Stage Builds

# Build stage — large image with build tools
FROM golang:1.24-bookworm AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server main.go

# Run stage — minimal image
FROM debian:bookworm-slim
WORKDIR /app
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/server .
COPY --from=builder /app/templates ./templates
COPY --from=builder /app/data ./data
ENV PORT=8080
EXPOSE 8080
CMD ["./server"]

File Path Checklist

Before writing any COPY instruction, verify:

  • [ ] The source path exists relative to the Docker build context
  • [ ] The file is tracked in git (not in .gitignore or .dockerignore)
  • [ ] The destination path matches what the app binary expects at runtime
  • [ ] Static data files are within the build context, not in a parent directory

Common Failures

| Symptom | Cause | Fix | |---------|-------|-----| | COPY failed: file not found | Path outside build context | Move files into context or change context | | COPY failed: no such file | File in .gitignore/.dockerignore | Remove from ignore or use different path | | App starts but serves empty data | Data files not copied to runtime stage | Add COPY --from=builder for data directory | | connection refused between services | Using localhost or Docker hostname on PaaS | Use public service URL | | Port mismatch in docker-compose | Host:container port mapping wrong | Match container port to what app listens on |

CI/CD Alignment

Match CI to Your Stack

The CI pipeline must use the same toolchain as the app:

Go frontend (not Node.js):

- uses: actions/setup-go@v5
  with:
    go-version: '1.24'
- run: go vet ./...
- run: CGO_ENABLED=0 go build -o server main.go

Python backend:

- uses: actions/setup-python@v5
  with:
    python-version: '3.11'
- run: pip install -r requirements.txt
- run: pytest

Security Scanning

Match CodeQL languages to actual codebase:

languages: python, go    # NOT python, javascript (if frontend is Go)

API Proxy Hardening

When a frontend proxies requests to a backend API:

// 1. Always set a timeout
client := &http.Client{Timeout: 30 * time.Second}

// 2. Handle request creation errors
req, err := http.NewRequest(method, target, body)
if err != nil {
    log.Printf("ERROR: proxy request failed: %v", err)
    c.JSON(500, gin.H{"error": "Internal server error"})
    return
}

// 3. Only forward safe headers
safeHeaders := map[string]bool{
    "Content-Type": true, "Accept": true,
    "Authorization": true, "Accept-Language": true,
}
for k, v := range incomingHeaders {
    if safeHeaders[http.CanonicalHeaderKey(k)] {
        req.Header[k] = v
    }
}
req.Header.Set("X-Forwarded-For", clientIP)

Never forward: Host, Cookie, Connection, Transfer-Encoding, or other hop-by-hop headers.

Pre-Deploy Checklist

Build Verification

  • [ ] docker build -t test . succeeds locally from the correct context directory
  • [ ] Container starts and responds on the expected port
  • [ ] All data files are present inside the running container
  • [ ] Health endpoint returns 200

Configuration Verification

  • [ ] Environment variable names match what the app reads (check source code, not docs)
  • [ ] Inter-service URLs use the platform's public URL format
  • [ ] Port mappings are consistent (docker-compose host:container, Render PORT env)
  • [ ] Secrets are set in dashboard, not committed to repo

Post-Deploy Verification

  • [ ] Health check passes on the deployed URL
  • [ ] Logs show no WARNING or ERROR on startup (especially file reads)
  • [ ] Cross-service API calls succeed (check proxy logs)
  • [ ] Static assets and data pages render correctly

Debugging Deploy Failures

Step-by-step triage

  1. Read the build log top-to-bottom — the first error is usually the root cause
  2. Check the Docker build context — is it what you expect? (dashboard > render.yaml)
  3. Verify files exist in gitgit ls-files <path> (untracked files won't be in the deploy)
  4. Check .dockerignore — it may exclude files you need
  5. Reproduce locallydocker build with the same context directory
  6. Check runtime vs build paths — files might build but not copy to the final stage

Render-Specific Debugging

  • Check deploy logs in dashboard under Events tab
  • Verify service URL is live: curl https://<service>.onrender.com/health
  • Check environment variables in dashboard Settings, not just render.yaml
  • If render.yaml changes don't apply, manually sync in dashboard or redeploy

Output Format

When auditing or planning a deployment, deliver:

  1. Current State Assessment — what's configured, what's broken, what's risky
  2. Issue List — prioritized by severity (P0 build blockers > P1 security > P2 correctness)
  3. Fix Plan — specific file changes with before/after
  4. Verification Steps — how to confirm each fix works

Related Skills

  • launch-strategy — coordinating deploy timing with marketing launches
  • analytics-tracking — ensuring tracking survives deployment changes
  • ab-test-setup — deploying experiment variants