@slamb2k/mad-skills 2.0.14 → 2.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,357 @@
1
+ ---
2
+ name: dock
3
+ description: >-
4
+ Generate container-based release pipelines that build once and promote immutable
5
+ artifacts through environments (dev → staging → prod). Detects your stack, interviews
6
+ for infrastructure choices, then outputs deterministic CI/CD files (Dockerfile,
7
+ workflows, deployment manifests) that run without an LLM. Use when setting up
8
+ deployment pipelines, containerizing an app, creating release workflows, or
9
+ connecting CI to container-friendly infrastructure (Azure Container Apps, AWS Fargate,
10
+ Google Cloud Run, Kubernetes, Dokku, Coolify, CapRover, etc.).
11
+ argument-hint: "--registry-only, --skip-interview, --dry-run"
12
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion, Agent
13
+ ---
14
+
15
+ # Dock - Container Release Pipelines
16
+
17
+ When this skill is invoked, IMMEDIATELY output the banner below before doing anything else.
18
+ Pick ONE tagline at random — vary your choice each time.
19
+ CRITICAL: Reproduce the banner EXACTLY character-for-character. The first line of the art has 4 leading spaces — you MUST preserve them.
20
+
21
+ ```
22
+ {tagline}
23
+
24
+ ⠀ ██╗██████╗ ██████╗ ██████╗██╗ ██╗
25
+ ██╔╝██╔══██╗██╔═══██╗██╔════╝██║ ██╔╝
26
+ ██╔╝ ██║ ██║██║ ██║██║ █████╔╝
27
+ ██╔╝ ██║ ██║██║ ██║██║ ██╔═██╗
28
+ ██╔╝ ██████╔╝╚██████╔╝╚██████╗██║ ██╗
29
+ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝
30
+ ```
31
+
32
+ Taglines:
33
+ - 🐳 Containerize all the things!
34
+ - 📦 Build once, deploy everywhere!
35
+ - 🚀 From code to container in one shot!
36
+ - ⚓ Anchoring your release pipeline!
37
+ - 🏗️ Immutable artifacts, mutable environments!
38
+ - 🔒 Same image, every stage, every time!
39
+ - 🌊 Shipping containers since... just now!
40
+ - 🎯 One build to rule them all!
41
+
42
+ ---
43
+
44
+ Generate container-based release pipelines following the **build-once, promote-everywhere**
45
+ philosophy. Every artifact is built exactly once, tested, tagged with git SHA + semver,
46
+ pushed to a registry, and promoted through environments without rebuilding.
47
+
48
+ All generated files are deterministic — no LLM required at runtime.
49
+
50
+ ## Flags
51
+
52
+ Parse optional flags from the request:
53
+ - `--registry-only`: Only generate Dockerfile, .dockerignore, and registry config (skip deployment)
54
+ - `--skip-interview`: Use detected defaults without interactive prompts
55
+ - `--dry-run`: Show what would be generated without writing files
56
+
57
+ ---
58
+
59
+ ## Pre-flight
60
+
61
+ Before starting, check dependencies:
62
+
63
+ | Dependency | Type | Check | Required | Resolution | Detail |
64
+ |-----------|------|-------|----------|------------|--------|
65
+ | docker | cli | `docker --version` | no | ask | Needed for local build verification; skip verify phase if absent |
66
+ | git | cli | `git --version` | yes | stop | Install from https://git-scm.com |
67
+ | sync | skill | `.claude/skills/sync/SKILL.md` | no | fallback | Repo sync; falls back to manual git pull |
68
+
69
+ For each row:
70
+ 1. Run the Check command
71
+ 2. If found: continue silently
72
+ 3. If missing: apply Resolution strategy
73
+ 4. After all checks: summarize availability
74
+
75
+ ---
76
+
77
+ ## Phase 0: Sync
78
+
79
+ Invoke `/sync` to ensure the working tree is up to date with origin/main before
80
+ scanning. If /sync is unavailable, run `git pull` manually. This prevents
81
+ generating pipelines against stale code.
82
+
83
+ ---
84
+
85
+ ## Phase 1: Detection
86
+
87
+ Launch an **Explore subagent** to scan the codebase and produce a DETECTION_REPORT.
88
+
89
+ ```
90
+ Task(
91
+ subagent_type: "Explore",
92
+ description: "Detect stack and existing infrastructure",
93
+ prompt: <read from references/interview-guide.md#detection-prompt>
94
+ )
95
+ ```
96
+
97
+ The detection prompt scans for:
98
+ - **Language & framework**: package.json, requirements.txt, go.mod, Cargo.toml, Gemfile, pom.xml, etc.
99
+ - **Existing Dockerfile**: Dockerfile, Dockerfile.*, docker-compose.yml
100
+ - **Existing CI**: .github/workflows/, azure-pipelines.yml, .gitlab-ci.yml
101
+ - **Existing deploy config**: Helm charts, Kubernetes manifests, Procfile, app.json, fly.toml, dokku config
102
+ - **Package manager**: npm/yarn/pnpm/bun, pip/uv/poetry, go modules, cargo, bundler, maven/gradle
103
+ - **Entry point**: main file, start scripts, Procfile commands
104
+ - **Port**: exposed ports in existing config or framework defaults
105
+ - **Environment files**: .env, .env.example, .env.* patterns
106
+
107
+ Parse DETECTION_REPORT. This feeds into the interview phase.
108
+
109
+ ---
110
+
111
+ ## Phase 2: Interview
112
+
113
+ Present the detection results to the user and fill in gaps through guided questions.
114
+ Read the full interview flow from `references/interview-guide.md#interview-questions`.
115
+
116
+ The interview covers these topics in order. Skip questions where detection already
117
+ provided a confident answer (but confirm with the user).
118
+
119
+ ### 2.1 — Stack Confirmation
120
+
121
+ Confirm detected language, framework, and entry point. Ask only if detection was
122
+ ambiguous (e.g., monorepo with multiple stacks).
123
+
124
+ ### 2.2 — Container Registry
125
+
126
+ Detect from existing CI config or ask:
127
+ - GitHub Container Registry (ghcr.io) — default for GitHub repos
128
+ - Azure Container Registry
129
+ - AWS ECR
130
+ - Google Artifact Registry
131
+ - Docker Hub
132
+ - Self-hosted registry
133
+
134
+ ### 2.3 — Environment Topology
135
+
136
+ Ask how many deployment stages and the promotion model:
137
+ - **Simple**: dev → prod (2-stage)
138
+ - **Standard**: dev → staging → prod (3-stage, default)
139
+ - **Custom**: user-defined stages
140
+
141
+ For each environment, ask the deployment target:
142
+ - Azure App Service for Containers
143
+ - Azure Container Apps
144
+ - AWS Fargate
145
+ - Google Cloud Run
146
+ - Kubernetes (any distribution)
147
+ - Dokku
148
+ - Coolify
149
+ - CapRover
150
+ - Other (user-specified)
151
+
152
+ Different environments can use different targets (e.g., dev=Dokku, prod=Azure Container Apps).
153
+
154
+ ### 2.4 — Testing Gates
155
+
156
+ For each environment promotion, ask what tests gate the promotion:
157
+ - **Build gate** (before registry push): unit tests, linting, type checks
158
+ - **Dev gate**: smoke tests, health check verification
159
+ - **Staging gate**: integration tests, e2e tests
160
+ - **Prod gate**: final smoke test post-deploy
161
+
162
+ ### 2.5 — Secrets & Configuration
163
+
164
+ How environment-specific config is managed:
165
+ - GitHub Secrets / Variables (default for GitHub Actions)
166
+ - Azure Key Vault
167
+ - AWS Secrets Manager
168
+ - Environment variables in deployment platform
169
+ - Doppler / 1Password / Vault
170
+
171
+ ### 2.6 — Networking & Domains
172
+
173
+ Optional — ask only if deploying to platforms that need this:
174
+ - Custom domain per environment?
175
+ - TLS certificate management (auto via platform, Let's Encrypt, manual)
176
+ - Load balancer or ingress configuration
177
+
178
+ ### 2.7 — Rollback Strategy
179
+
180
+ - **Simple rollback** (default): redeploy previous image tag on failure
181
+ - **Blue-green**: maintain two environments, swap traffic
182
+ - **Canary**: gradual traffic shift with automatic rollback on error thresholds
183
+
184
+ **If `--skip-interview` flag**: Use detected defaults + sensible defaults for
185
+ everything else (ghcr.io, 3-stage, GitHub Secrets, simple rollback).
186
+
187
+ Compile all answers into a DOCK_CONFIG object for Phase 3.
188
+
189
+ ---
190
+
191
+ ## Phase 3: Generate Artifacts
192
+
193
+ Based on DETECTION_REPORT and DOCK_CONFIG, generate all pipeline files.
194
+ Use templates from `references/` as starting points and customize for the
195
+ detected stack and chosen platforms.
196
+
197
+ ### 3.1 — Dockerfile & .dockerignore
198
+
199
+ Read `references/dockerfile-templates.md` for the detected stack.
200
+
201
+ Generate a multi-stage Dockerfile:
202
+ - **Stage 1 — deps**: Install dependencies only (maximizes cache hits)
203
+ - **Stage 2 — build**: Copy source, run build step
204
+ - **Stage 3 — test**: Run unit tests against the build
205
+ - **Stage 4 — production**: Minimal runtime image with built artifacts only
206
+
207
+ Generate `.dockerignore` excluding: `.git`, `node_modules`, `__pycache__`, `.env*`,
208
+ test fixtures, documentation, IDE config.
209
+
210
+ ### 3.2 — docker-compose.yml
211
+
212
+ Generate a local development compose file that mirrors the production image
213
+ with development overrides (volume mounts, hot reload, debug ports).
214
+
215
+ ### 3.3 — CI/CD Workflow
216
+
217
+ Detect CI system from Phase 1 (GitHub Actions / Azure Pipelines / GitLab CI).
218
+ Read the appropriate template from `references/pipeline-templates.md`.
219
+
220
+ Generate a workflow that implements:
221
+
222
+ **On pull request:**
223
+ 1. Build image tagged with `pr-{number}-{sha:7}`
224
+ 2. Run test stage inside the image
225
+ 3. Push to registry (optional — configurable)
226
+ 4. Comment build status on PR
227
+
228
+ **On merge to main (or default branch):**
229
+ 1. Build image tagged with `{sha:7}` and `latest`
230
+ 2. Run full test suite inside the image
231
+ 3. Push to registry
232
+ 4. Deploy to dev environment
233
+ 5. Run dev-gate tests (smoke tests)
234
+
235
+ **On release tag (vX.Y.Z):**
236
+ 1. Retag the existing `{sha:7}` image as `vX.Y.Z` — **do NOT rebuild**
237
+ 2. Deploy to staging
238
+ 3. Run staging-gate tests
239
+ 4. On success: deploy to prod
240
+ 5. Run prod-gate tests (post-deploy smoke)
241
+
242
+ Key principle: the release workflow **never rebuilds**. It promotes the exact
243
+ image that was tested on main.
244
+
245
+ ### 3.4 — Deployment Manifests
246
+
247
+ Based on the chosen platforms per environment, read the appropriate section
248
+ from `references/platform-deploy-guides.md` and generate:
249
+
250
+ - **Kubernetes**: Helm chart or kustomize overlays with per-environment values
251
+ - **Azure Container Apps**: Bicep/ARM template or `az containerapp` commands in workflow
252
+ - **Azure App Service**: App Service deployment slots config
253
+ - **AWS Fargate**: ECS task definition + service config
254
+ - **Google Cloud Run**: Cloud Run service YAML or `gcloud run deploy` commands
255
+ - **Dokku**: Procfile + dokku git push deployment step
256
+ - **Coolify**: API-based deployment step or docker-compose based
257
+ - **CapRover**: captain-definition file + deploy step
258
+
259
+ ### 3.5 — Environment Matrix
260
+
261
+ Generate an environment matrix config file (`deploy/environments.json` or
262
+ `deploy/environments.yml`) defining per-environment settings:
263
+
264
+ ```yaml
265
+ environments:
266
+ dev:
267
+ target: <platform>
268
+ registry_tag_pattern: "{sha:7}"
269
+ auto_deploy: true
270
+ tests: [smoke]
271
+ staging:
272
+ target: <platform>
273
+ registry_tag_pattern: "v{version}"
274
+ auto_deploy: false # requires manual approval or tag
275
+ tests: [integration, e2e]
276
+ prod:
277
+ target: <platform>
278
+ registry_tag_pattern: "v{version}"
279
+ auto_deploy: false
280
+ tests: [smoke-post-deploy]
281
+ ```
282
+
283
+ ### 3.6 — Health Check Endpoint Guidance
284
+
285
+ If the detected framework doesn't already have a health endpoint, add a comment
286
+ in the generated workflow noting that a `/healthz` or `/health` endpoint is
287
+ recommended for deployment readiness probes.
288
+
289
+ ---
290
+
291
+ ## Phase 4: Verify
292
+
293
+ If Docker is available, run a verification step:
294
+
295
+ ```bash
296
+ docker build --target production -t dock-verify:test .
297
+ ```
298
+
299
+ If the build succeeds, report success. If it fails, diagnose and fix the
300
+ Dockerfile. Skip this phase if Docker is not installed (noted in pre-flight).
301
+
302
+ Also validate generated workflow files:
303
+ - GitHub Actions: check YAML syntax
304
+ - Azure Pipelines: check YAML syntax
305
+ - GitLab CI: check YAML syntax
306
+
307
+ Present the user with a summary of all generated files before writing.
308
+
309
+ **If `--dry-run` flag**: Show the file list and content previews without writing.
310
+
311
+ ---
312
+
313
+ ## Final Report
314
+
315
+ After all files are generated and verified, present:
316
+
317
+ ```
318
+ Dock complete
319
+
320
+ Stack: {language} / {framework}
321
+ Registry: {registry}
322
+ Stages: {env1} → {env2} → {env3}
323
+
324
+ Generated files:
325
+ {file list with brief descriptions}
326
+
327
+ Pipeline flow:
328
+ PR → build + test → [push to registry]
329
+ Merge → build + test → push → deploy dev → smoke tests
330
+ Tag → retag (no rebuild) → deploy staging → e2e → deploy prod → smoke
331
+
332
+ Next steps:
333
+ 1. Review generated files
334
+ 2. Configure secrets: {list of required secrets}
335
+ 3. Push to trigger first pipeline run
336
+ ```
337
+
338
+ ---
339
+
340
+ ## Idempotency
341
+
342
+ If /dock detects it has been run before (existing `deploy/` directory, existing
343
+ deployment workflow), it should:
344
+ - **Dockerfile**: Update if stack detection shows changes; preserve custom stages
345
+ - **Workflow**: Merge new steps; never overwrite user customizations without confirmation
346
+ - **Manifests**: Update image references; preserve environment-specific overrides
347
+ - **Always ask** before overwriting existing files
348
+
349
+ ---
350
+
351
+ ## Integration with /rig and /ship
352
+
353
+ - **/rig integration**: When /rig runs after /dock, it should detect `deploy/`
354
+ artifacts and wire the CI workflow to trigger deployment on merge to main.
355
+ - **/ship integration**: /ship's merge step naturally triggers the deployment
356
+ workflow created by /dock. No special coupling needed — the CI/CD workflow
357
+ handles the handoff via branch/tag triggers.
@@ -0,0 +1,358 @@
1
+ # Dockerfile Templates
2
+
3
+ Multi-stage Dockerfile templates by detected stack. Each template follows the
4
+ four-stage pattern: deps → build → test → production.
5
+
6
+ Customize based on DETECTION_REPORT values. These are starting points, not
7
+ rigid templates — adapt to the specific project.
8
+
9
+ ---
10
+
11
+ ## Node.js
12
+
13
+ ### With npm/yarn/pnpm
14
+
15
+ ```dockerfile
16
+ # Stage 1: Dependencies
17
+ FROM node:22-alpine AS deps
18
+ WORKDIR /app
19
+ COPY package.json package-lock.json ./
20
+ RUN npm ci --production=false
21
+
22
+ # Stage 2: Build
23
+ FROM deps AS build
24
+ COPY . .
25
+ RUN npm run build
26
+
27
+ # Stage 3: Test (used in CI, not in final image)
28
+ FROM build AS test
29
+ RUN npm test
30
+
31
+ # Stage 4: Production
32
+ FROM node:22-alpine AS production
33
+ WORKDIR /app
34
+ ENV NODE_ENV=production
35
+ RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 -G appgroup
36
+ COPY --from=deps /app/node_modules ./node_modules
37
+ COPY --from=build /app/dist ./dist
38
+ COPY --from=build /app/package.json ./
39
+ USER appuser
40
+ EXPOSE {PORT}
41
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
42
+ CMD wget --no-verbose --tries=1 --spider http://localhost:{PORT}/healthz || exit 1
43
+ CMD ["node", "dist/index.js"]
44
+ ```
45
+
46
+ ### With bun
47
+
48
+ ```dockerfile
49
+ FROM oven/bun:1-alpine AS deps
50
+ WORKDIR /app
51
+ COPY package.json bun.lockb ./
52
+ RUN bun install --frozen-lockfile
53
+
54
+ FROM deps AS build
55
+ COPY . .
56
+ RUN bun run build
57
+
58
+ FROM build AS test
59
+ RUN bun test
60
+
61
+ FROM oven/bun:1-alpine AS production
62
+ WORKDIR /app
63
+ ENV NODE_ENV=production
64
+ RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 -G appgroup
65
+ COPY --from=deps /app/node_modules ./node_modules
66
+ COPY --from=build /app/dist ./dist
67
+ COPY --from=build /app/package.json ./
68
+ USER appuser
69
+ EXPOSE {PORT}
70
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
71
+ CMD bun --eval "fetch('http://localhost:{PORT}/healthz').then(r => process.exit(r.ok ? 0 : 1))" || exit 1
72
+ CMD ["bun", "run", "dist/index.js"]
73
+ ```
74
+
75
+ ### Next.js (standalone output)
76
+
77
+ ```dockerfile
78
+ FROM node:22-alpine AS deps
79
+ WORKDIR /app
80
+ COPY package.json package-lock.json ./
81
+ RUN npm ci
82
+
83
+ FROM deps AS build
84
+ COPY . .
85
+ ENV NEXT_TELEMETRY_DISABLED=1
86
+ RUN npm run build
87
+
88
+ FROM build AS test
89
+ RUN npm test
90
+
91
+ FROM node:22-alpine AS production
92
+ WORKDIR /app
93
+ ENV NODE_ENV=production NEXT_TELEMETRY_DISABLED=1
94
+ RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001 -G appgroup
95
+ COPY --from=build /app/.next/standalone ./
96
+ COPY --from=build /app/.next/static ./.next/static
97
+ COPY --from=build /app/public ./public
98
+ USER appuser
99
+ EXPOSE 3000
100
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=15s \
101
+ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1
102
+ CMD ["node", "server.js"]
103
+ ```
104
+
105
+ Note: Requires `output: 'standalone'` in next.config.js.
106
+
107
+ ---
108
+
109
+ ## Python
110
+
111
+ ### With pip/uv
112
+
113
+ ```dockerfile
114
+ FROM python:3.12-slim AS deps
115
+ WORKDIR /app
116
+ COPY requirements.txt ./
117
+ RUN pip install --no-cache-dir -r requirements.txt
118
+
119
+ FROM deps AS build
120
+ COPY . .
121
+
122
+ FROM build AS test
123
+ RUN python -m pytest
124
+
125
+ FROM python:3.12-slim AS production
126
+ WORKDIR /app
127
+ RUN groupadd -r appgroup && useradd -r -g appgroup appuser
128
+ COPY --from=deps /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
129
+ COPY --from=deps /usr/local/bin /usr/local/bin
130
+ COPY --from=build /app .
131
+ USER appuser
132
+ EXPOSE {PORT}
133
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
134
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:{PORT}/healthz')" || exit 1
135
+ CMD ["gunicorn", "--bind", "0.0.0.0:{PORT}", "--workers", "4", "app:app"]
136
+ ```
137
+
138
+ ### With uv (faster installs)
139
+
140
+ ```dockerfile
141
+ FROM python:3.12-slim AS deps
142
+ WORKDIR /app
143
+ COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
144
+ COPY pyproject.toml uv.lock ./
145
+ RUN uv sync --frozen --no-dev --no-install-project
146
+
147
+ FROM deps AS build
148
+ COPY . .
149
+ RUN uv sync --frozen --no-install-project
150
+
151
+ FROM build AS test
152
+ RUN uv run pytest
153
+
154
+ FROM python:3.12-slim AS production
155
+ WORKDIR /app
156
+ RUN groupadd -r appgroup && useradd -r -g appgroup appuser
157
+ COPY --from=deps /app/.venv /app/.venv
158
+ COPY --from=build /app .
159
+ ENV PATH="/app/.venv/bin:$PATH"
160
+ USER appuser
161
+ EXPOSE {PORT}
162
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
163
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:{PORT}/healthz')" || exit 1
164
+ CMD ["gunicorn", "--bind", "0.0.0.0:{PORT}", "--workers", "4", "app:app"]
165
+ ```
166
+
167
+ ### Django
168
+
169
+ Replace CMD with:
170
+ ```dockerfile
171
+ CMD ["gunicorn", "--bind", "0.0.0.0:{PORT}", "--workers", "4", "{PROJECT_NAME}.wsgi:application"]
172
+ ```
173
+
174
+ Add collectstatic to build stage:
175
+ ```dockerfile
176
+ RUN python manage.py collectstatic --noinput
177
+ ```
178
+
179
+ ### FastAPI
180
+
181
+ Replace CMD with:
182
+ ```dockerfile
183
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "{PORT}", "--workers", "4"]
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Go
189
+
190
+ ```dockerfile
191
+ FROM golang:1.23-alpine AS deps
192
+ WORKDIR /app
193
+ COPY go.mod go.sum ./
194
+ RUN go mod download
195
+
196
+ FROM deps AS build
197
+ COPY . .
198
+ RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server ./cmd/server
199
+
200
+ FROM build AS test
201
+ RUN go test ./...
202
+
203
+ FROM gcr.io/distroless/static-debian12 AS production
204
+ COPY --from=build /app/server /server
205
+ EXPOSE {PORT}
206
+ USER nonroot:nonroot
207
+ CMD ["/server"]
208
+ ```
209
+
210
+ ---
211
+
212
+ ## Rust
213
+
214
+ ```dockerfile
215
+ FROM rust:1.83-slim AS deps
216
+ WORKDIR /app
217
+ COPY Cargo.toml Cargo.lock ./
218
+ RUN mkdir src && echo "fn main() {}" > src/main.rs
219
+ RUN cargo build --release && rm -rf src
220
+
221
+ FROM deps AS build
222
+ COPY . .
223
+ RUN cargo build --release
224
+
225
+ FROM build AS test
226
+ RUN cargo test --release
227
+
228
+ FROM debian:bookworm-slim AS production
229
+ RUN groupadd -r appgroup && useradd -r -g appgroup appuser
230
+ COPY --from=build /app/target/release/{BINARY_NAME} /usr/local/bin/app
231
+ USER appuser
232
+ EXPOSE {PORT}
233
+ CMD ["app"]
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Ruby / Rails
239
+
240
+ ```dockerfile
241
+ FROM ruby:3.3-slim AS deps
242
+ WORKDIR /app
243
+ RUN apt-get update && apt-get install -y build-essential libpq-dev && rm -rf /var/lib/apt/lists/*
244
+ COPY Gemfile Gemfile.lock ./
245
+ RUN bundle config set --local deployment true && bundle install
246
+
247
+ FROM deps AS build
248
+ COPY . .
249
+ RUN SECRET_KEY_BASE=placeholder bundle exec rails assets:precompile
250
+
251
+ FROM build AS test
252
+ RUN bundle exec rspec
253
+
254
+ FROM ruby:3.3-slim AS production
255
+ WORKDIR /app
256
+ RUN apt-get update && apt-get install -y libpq5 && rm -rf /var/lib/apt/lists/*
257
+ RUN groupadd -r appgroup && useradd -r -g appgroup appuser
258
+ COPY --from=deps /app/vendor/bundle ./vendor/bundle
259
+ COPY --from=build /app .
260
+ ENV RAILS_ENV=production RAILS_SERVE_STATIC_FILES=true
261
+ USER appuser
262
+ EXPOSE {PORT}
263
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=15s \
264
+ CMD ruby -e "require 'net/http'; Net::HTTP.get(URI('http://localhost:{PORT}/up'))" || exit 1
265
+ CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0", "-p", "{PORT}"]
266
+ ```
267
+
268
+ ---
269
+
270
+ ## .NET
271
+
272
+ ```dockerfile
273
+ FROM mcr.microsoft.com/dotnet/sdk:9.0 AS deps
274
+ WORKDIR /app
275
+ COPY *.csproj ./
276
+ RUN dotnet restore
277
+
278
+ FROM deps AS build
279
+ COPY . .
280
+ RUN dotnet publish -c Release -o /app/publish --no-restore
281
+
282
+ FROM build AS test
283
+ RUN dotnet test --no-restore
284
+
285
+ FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS production
286
+ WORKDIR /app
287
+ RUN groupadd -r appgroup && useradd -r -g appgroup appuser
288
+ COPY --from=build /app/publish .
289
+ USER appuser
290
+ EXPOSE {PORT}
291
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
292
+ CMD curl -f http://localhost:{PORT}/healthz || exit 1
293
+ CMD ["dotnet", "{ASSEMBLY_NAME}.dll"]
294
+ ```
295
+
296
+ ---
297
+
298
+ ## Java / Spring Boot
299
+
300
+ ```dockerfile
301
+ FROM eclipse-temurin:21-jdk AS deps
302
+ WORKDIR /app
303
+ COPY pom.xml mvnw .mvn ./
304
+ RUN ./mvnw dependency:resolve
305
+
306
+ FROM deps AS build
307
+ COPY . .
308
+ RUN ./mvnw package -DskipTests
309
+
310
+ FROM build AS test
311
+ RUN ./mvnw test
312
+
313
+ FROM eclipse-temurin:21-jre AS production
314
+ WORKDIR /app
315
+ RUN groupadd -r appgroup && useradd -r -g appgroup appuser
316
+ COPY --from=build /app/target/*.jar app.jar
317
+ USER appuser
318
+ EXPOSE {PORT}
319
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=30s \
320
+ CMD curl -f http://localhost:{PORT}/actuator/health || exit 1
321
+ CMD ["java", "-jar", "app.jar"]
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Generic .dockerignore
327
+
328
+ Adapt based on detected stack. Always include:
329
+
330
+ ```
331
+ .git
332
+ .github
333
+ .gitlab
334
+ .env
335
+ .env.*
336
+ *.md
337
+ LICENSE
338
+ docs/
339
+ tests/
340
+ test/
341
+ __tests__/
342
+ *.test.*
343
+ *.spec.*
344
+ .vscode
345
+ .idea
346
+ .editorconfig
347
+ .eslintrc*
348
+ .prettierrc*
349
+ Makefile
350
+ docker-compose*.yml
351
+ ```
352
+
353
+ Stack-specific additions:
354
+ - Node: `node_modules/`
355
+ - Python: `__pycache__/`, `*.pyc`, `.venv/`, `.mypy_cache/`
356
+ - Go: no additions needed (Go copies only what's needed)
357
+ - Rust: `target/`
358
+ - Ruby: `.bundle/`, `tmp/`, `log/`