Advanced rule set for writing secure, performant Dockerfiles and composing & orchestrating containers in production-grade environments.
Your containers are running in production, but are they truly production-ready? If you're dealing with bloated images, security vulnerabilities, mysterious crashes, or deployment inconsistencies, these Cursor Rules will transform how you build and deploy containers.
Every Docker setup starts simple, but production reality hits hard:
Sound familiar? You're not alone. Most Docker implementations start with FROM ubuntu:latest and evolve into maintenance nightmares.
These Cursor Rules implement battle-tested patterns that eliminate common containerization pitfalls. Instead of learning painful lessons in production, you get enterprise-grade practices built into every Dockerfile and Compose configuration you create.
What you get:
# Instead of this security nightmare:
FROM node:latest
COPY . .
RUN npm install
USER root
CMD ["node", "app.js"]
# You get this hardened container:
FROM node:20-alpine3.19 AS base
RUN addgroup -S app && adduser -S -G app app
WORKDIR /srv
COPY --from=builder /dist .
USER app
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
Impact: Zero critical vulnerabilities in your images, automated security scanning in CI/CD, and compliance-ready containers.
Multi-stage builds eliminate build tools from runtime images:
# Build stage with all development dependencies
FROM node:20-alpine3.19 AS builder
WORKDIR /build
COPY package*.json ./
RUN npm ci --only=production
# Runtime stage with only production artifacts
FROM node:20-alpine3.19 AS runtime
WORKDIR /srv
COPY --from=builder /build/node_modules ./node_modules
COPY --from=builder /build/dist ./dist
USER app
Impact: 500MB+ images become 50MB, deployments are 10x faster, and your registry costs plummet.
# Docker Compose with production-grade reliability
services:
api:
build: .
user: "10001:10001"
read_only: true
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 3s
retries: 3
deploy:
resources:
limits:
cpus: "0.50"
memory: "512M"
worker:
depends_on:
api:
condition: service_healthy
Impact: Kubernetes and orchestrators can properly manage your containers, rolling deployments work reliably, and resource exhaustion becomes impossible.
# Your typical debugging session
docker build . -t myapp
docker run myapp
# Container exits silently
docker logs container_id
# No useful output
docker exec -it container_id /bin/sh
# Permission denied or container already stopped
FROM python:3.11-alpine3.19 AS base
LABEL org.opencontainers.image.source="https://github.com/company/api"
# Health check that actually works
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD python -c "import requests; requests.get('http://localhost:5000/health')"
# Proper entrypoint with validation
COPY entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
Result: Containers that fail fast with clear error messages, health endpoints that orchestrators understand, and proper logging from day one.
Your app works locally but fails in staging because of environment differences, missing dependencies, or configuration drift.
# docker-compose.dev.yml
services:
app:
build:
context: .
target: development
volumes:
- .:/app:ro
environment:
- NODE_ENV=development
ports:
- "3000:3000"
# docker-compose.prod.yml
services:
app:
build:
context: .
target: production
read_only: true
deploy:
replicas: 3
resources:
limits:
memory: 512M
Result: Zero environment drift, consistent behavior across all stages, and deployments that work the first time.
Copy the complete rule set into your Cursor IDE. These rules will automatically guide you toward production-grade practices every time you create Docker files.
Run this quick security check on your current images:
# Check for vulnerabilities
trivy image --exit-code 1 --severity CRITICAL,HIGH your-image:tag
# Verify non-root user
docker run --rm your-image:tag whoami
# Should NOT return "root"
# Check image size
docker images your-image:tag
Convert your existing Dockerfiles to use the multi-stage pattern:
# Development stage
FROM node:20-alpine3.19 AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]
# Build stage
FROM development AS builder
RUN npm run build
RUN npm ci --only=production
# Production stage
FROM node:20-alpine3.19 AS production
RUN addgroup -S app && adduser -S -G app app
WORKDIR /srv
COPY --from=builder /app/dist ./
COPY --from=builder /app/node_modules ./node_modules
USER app
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:3000/health
CMD ["node", "server.js"]
Every service needs a health endpoint and corresponding Docker health check:
# Flask health endpoint
@app.route('/health')
def health_check():
try:
# Check database connectivity
db.session.execute('SELECT 1')
# Check external dependencies
requests.get('https://api.external-service.com/health', timeout=5)
return {'status': 'healthy'}, 200
except Exception as e:
return {'status': 'unhealthy', 'error': str(e)}, 503
Update your Docker Compose configurations with proper security and resource controls:
version: "3.9"
services:
web:
build: .
user: "10001:10001"
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=100m
deploy:
resources:
limits:
cpus: "1.0"
memory: "1G"
reservations:
cpus: "0.5"
memory: "512M"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
These rules don't just improve your containers—they transform your entire deployment pipeline into a reliable, secure, and efficient system. Your future self (and your production alerts) will thank you.
Stop fighting with Docker and start shipping with confidence. Your production workloads deserve better than trial-and-error containerization.
You are an expert in Docker, Dockerfile, Docker Compose, Kubernetes, Podman, OCI-compatible runtimes, Trivy, and GitHub Actions.
Key Principles
- Prefer minimal, official, and **pinned** base images (e.g. `alpine:3.19`) to reduce size and avoid unexpected upgrades.
- Use **multi-stage builds** to eliminate build-time dependencies from the final runtime image.
- Never run as root; create a non-privileged user and drop capabilities (`USER app`).
- Apply **principle of least privilege**: read-only root filesystem, scoped volumes, and limited capabilities.
- Always include a `.dockerignore` to exclude node_modules, tests, docs, build output, and secrets.
- Encode one concern per container; rely on composition for multi-service solutions.
- Enable deterministic builds: pin package versions, disable cache busting, and set `ENV` for reproducibility.
- Validate containers continuously (HEALTHCHECK, vulnerability scans, integration tests).
Dockerfile Rules
- Start with an explicit `FROM` and label the image:
```dockerfile
FROM node:20-alpine3.19 AS base
LABEL org.opencontainers.image.source="https://github.com/acme/api" \
org.opencontainers.image.licenses="Apache-2.0"
```
- Prefer `COPY` over `ADD` unless extracting a remote archive is required.
- Group package installation in a single `RUN` layer and clean caches:
```dockerfile
RUN apk add --no-cache bash curl && \
addgroup -S app && adduser -S -G app app
```
- Explicitly set `WORKDIR` before copying code.
- Copy *only* production artefacts during the final stage:
```dockerfile
FROM base AS runtime
WORKDIR /srv
COPY --from=builder /dist .
USER app
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD curl -f http://localhost:3000/health || exit 1
CMD ["node","server.js"]
```
- Use `ARG` for build-time parameters; convert to `ENV` only when the value is needed at runtime.
- Declare a default `SHELL` for Windows images where PowerShell is required.
- Keep layers ordered from least to most volatile to maximise cache usage (e.g. dependencies before source).
Compose (docker-compose.yml) Rules
- Use compose spec `version: "3.9"` or omit when using v2 CLI.
- Always specify `image` **or** `build`, never both in production.
- Define an explicit `healthcheck` and reference it in `depends_on`:
```yaml
services:
api:
build: .
user: "10001:10001"
read_only: true
healthcheck:
test: ["CMD","curl","-f","http://localhost:3000/health"]
interval: 30s
timeout: 3s
retries: 3
worker:
build: ./worker
depends_on:
api:
condition: service_healthy
```
- Declare resource limits for every service:
```yaml
deploy:
resources:
limits:
cpus: "0.50"
memory: "512M"
```
- Isolate networks (`networks:`) for internal traffic; expose only necessary ports via `ports:`.
- Use externally defined volumes with `driver_opts: o=bind, type=none, device=<path>` and mount them as read-only when possible.
Error Handling & Validation
- Add `HEALTHCHECK` to every runtime image; fail fast if critical dependencies are unreachable.
- Application entrypoint scripts must `set -euo pipefail` (bash) and propagate non-zero exit codes.
- Catch early misconfiguration by validating required `ENV` variables at container start.
- Use **early exit** in shell scripts to avoid deep nesting; keep the happy path last.
- Configure restart policies (`on-failure`, `unless-stopped`) instead of blindly using `always`.
Framework-Specific Rules
Kubernetes
- Always set both `requests` and `limits` for CPU & memory to enable scheduling and OOM protection.
- Include `securityContext` in pods:
```yaml
securityContext:
runAsNonRoot: true
runAsUser: 10001
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
```
- Use `readinessProbe` + `livenessProbe` mirroring the image’s `HEALTHCHECK` implementation.
- Pin image digests (`image: api@sha256:...`) for immutability; automate with cosign for signed digests.
- Configure PodDisruptionBudgets and HPA to guarantee availability and auto-scaling.
Docker Swarm (or Compose `deploy:`)
- Use replicated mode with minimum 3 replicas for stateless services.
- Employ rolling updates (`update_config`) and healthcheck-based rollback.
Podman
- Run containers **rootless**: `podman run --userns keep-id ...`.
- Mirror Docker CLI flags but prefer `--security-opt=no-new-privileges` by default.
Testing & CI/CD
- Build images in CI with BuildKit (`DOCKER_BUILDKIT=1`), then run `docker run --rm image:tag npm test`.
- Integrate vulnerability scanning in every pipeline stage:
```bash
trivy image --exit-code 1 --severity CRITICAL,HIGH image:tag
```
- Use ephemeral compose stacks for integration tests in CI, destroyed after test completion.
- Push only signed images to registries: `cosign sign --key k8s://cluster/... image:tag`.
Performance & Optimisation
- Enable BuildKit caching mounts to speed up package managers (`RUN --mount=type=cache,target=/root/.cache pip install -r requirements.txt`).
- Combine commands to limit layer count but stay under 120 characters per line for readability.
- Prefer `COPY --link` (requires BuildKit) to reduce duplicate data in layers.
Security Hardening
- Scan base images weekly; rebuild even without application changes to pick up patches.
- Never bake secrets into images. Use runtime secrets (`docker secret`, `kubectl create secret`).
- Restrict outbound traffic via firewalls where required; use minimal group of network policies in Kubernetes.
Local Development
- Use `docker compose up --build --mount=type=bind,src=.,target=/app,readonly=false` for rapid code iterations.
- Prefer `rancher-desktop` or `colima` for macOS to match the containerd runtime used in production.
Directory & File Naming
- Store Docker artefacts in `infrastructure/docker/`.
- Name compose files by context: `docker-compose.dev.yml`, `docker-compose.ci.yml`.
- Keep versioned manifests under `k8s/` with `deployment.yaml`, `service.yaml`, `hpa.yaml`.
Common Pitfalls & Guards
- ❌ Don’t install build tools (e.g. gcc) in the final image.
- ❌ Don’t leave default credentials in environment variables.
- ❌ Don’t assume `/tmp` is writable when root filesystem is read-only.
- ✅ Verify manifests with `kubeval` and `conftest` as a CI gate.
---
Following these rules ensures images are **small**, **secure**, and **reproducible**, while deployments remain observable, predictable, and easy to debug.