agent-notes 2.0.4__py3-none-any.whl
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.
- agent_notes/VERSION +1 -0
- agent_notes/__init__.py +1 -0
- agent_notes/__main__.py +4 -0
- agent_notes/cli.py +348 -0
- agent_notes/commands/__init__.py +27 -0
- agent_notes/commands/_install_helpers.py +262 -0
- agent_notes/commands/build.py +170 -0
- agent_notes/commands/doctor.py +112 -0
- agent_notes/commands/info.py +95 -0
- agent_notes/commands/install.py +99 -0
- agent_notes/commands/list.py +169 -0
- agent_notes/commands/memory.py +430 -0
- agent_notes/commands/regenerate.py +152 -0
- agent_notes/commands/set_role.py +143 -0
- agent_notes/commands/uninstall.py +26 -0
- agent_notes/commands/update.py +169 -0
- agent_notes/commands/validate.py +199 -0
- agent_notes/commands/wizard.py +720 -0
- agent_notes/config.py +154 -0
- agent_notes/data/agents/agents.yaml +352 -0
- agent_notes/data/agents/analyst.md +45 -0
- agent_notes/data/agents/api-reviewer.md +47 -0
- agent_notes/data/agents/architect.md +46 -0
- agent_notes/data/agents/coder.md +28 -0
- agent_notes/data/agents/database-specialist.md +45 -0
- agent_notes/data/agents/debugger.md +47 -0
- agent_notes/data/agents/devil.md +47 -0
- agent_notes/data/agents/devops.md +38 -0
- agent_notes/data/agents/explorer.md +23 -0
- agent_notes/data/agents/integrations.md +44 -0
- agent_notes/data/agents/lead.md +216 -0
- agent_notes/data/agents/performance-profiler.md +44 -0
- agent_notes/data/agents/refactorer.md +48 -0
- agent_notes/data/agents/reviewer.md +44 -0
- agent_notes/data/agents/security-auditor.md +44 -0
- agent_notes/data/agents/system-auditor.md +38 -0
- agent_notes/data/agents/tech-writer.md +32 -0
- agent_notes/data/agents/test-runner.md +36 -0
- agent_notes/data/agents/test-writer.md +39 -0
- agent_notes/data/cli/claude.yaml +25 -0
- agent_notes/data/cli/copilot.yaml +18 -0
- agent_notes/data/cli/opencode.yaml +22 -0
- agent_notes/data/commands/brainstorm.md +8 -0
- agent_notes/data/commands/debug.md +9 -0
- agent_notes/data/commands/review.md +10 -0
- agent_notes/data/global-claude.md +290 -0
- agent_notes/data/global-copilot.md +27 -0
- agent_notes/data/global-opencode.md +40 -0
- agent_notes/data/hooks/session-context.md.tpl +19 -0
- agent_notes/data/models/claude-haiku-4-5.yaml +15 -0
- agent_notes/data/models/claude-opus-4-1.yaml +16 -0
- agent_notes/data/models/claude-opus-4-5.yaml +16 -0
- agent_notes/data/models/claude-opus-4-6.yaml +16 -0
- agent_notes/data/models/claude-opus-4-7.yaml +15 -0
- agent_notes/data/models/claude-sonnet-4-5.yaml +16 -0
- agent_notes/data/models/claude-sonnet-4-6.yaml +15 -0
- agent_notes/data/models/claude-sonnet-4.yaml +16 -0
- agent_notes/data/pricing.yaml +33 -0
- agent_notes/data/roles/orchestrator.yaml +5 -0
- agent_notes/data/roles/reasoner.yaml +5 -0
- agent_notes/data/roles/scout.yaml +5 -0
- agent_notes/data/roles/worker.yaml +5 -0
- agent_notes/data/rules/code-quality.md +9 -0
- agent_notes/data/rules/safety.md +10 -0
- agent_notes/data/scripts/cost-report +211 -0
- agent_notes/data/skills/brainstorming/SKILL.md +57 -0
- agent_notes/data/skills/code-review/SKILL.md +64 -0
- agent_notes/data/skills/debugging-protocol/SKILL.md +51 -0
- agent_notes/data/skills/docker-compose/SKILL.md +318 -0
- agent_notes/data/skills/docker-compose-advanced/SKILL.md +575 -0
- agent_notes/data/skills/docker-dockerfile/SKILL.md +385 -0
- agent_notes/data/skills/docker-dockerfile-languages/SKILL.md +293 -0
- agent_notes/data/skills/git/SKILL.md +87 -0
- agent_notes/data/skills/rails-active-storage/SKILL.md +321 -0
- agent_notes/data/skills/rails-broadcasting/SKILL.md +374 -0
- agent_notes/data/skills/rails-concerns/SKILL.md +806 -0
- agent_notes/data/skills/rails-controllers/SKILL.md +510 -0
- agent_notes/data/skills/rails-controllers-advanced/SKILL.md +441 -0
- agent_notes/data/skills/rails-helpers/SKILL.md +677 -0
- agent_notes/data/skills/rails-initializers/SKILL.md +79 -0
- agent_notes/data/skills/rails-javascript/SKILL.md +567 -0
- agent_notes/data/skills/rails-jobs/SKILL.md +700 -0
- agent_notes/data/skills/rails-kamal/SKILL.md +483 -0
- agent_notes/data/skills/rails-lib/SKILL.md +101 -0
- agent_notes/data/skills/rails-mailers/SKILL.md +321 -0
- agent_notes/data/skills/rails-migrations/SKILL.md +268 -0
- agent_notes/data/skills/rails-models/SKILL.md +459 -0
- agent_notes/data/skills/rails-models-advanced/SKILL.md +398 -0
- agent_notes/data/skills/rails-routes/SKILL.md +804 -0
- agent_notes/data/skills/rails-style/SKILL.md +538 -0
- agent_notes/data/skills/rails-testing-controllers/SKILL.md +343 -0
- agent_notes/data/skills/rails-testing-models/SKILL.md +296 -0
- agent_notes/data/skills/rails-testing-system/SKILL.md +375 -0
- agent_notes/data/skills/rails-validations/SKILL.md +108 -0
- agent_notes/data/skills/rails-view-components/SKILL.md +511 -0
- agent_notes/data/skills/rails-view-components-advanced/SKILL.md +376 -0
- agent_notes/data/skills/rails-views/SKILL.md +413 -0
- agent_notes/data/skills/rails-views-advanced/SKILL.md +450 -0
- agent_notes/data/skills/refactoring-protocol/SKILL.md +64 -0
- agent_notes/data/skills/tdd/SKILL.md +57 -0
- agent_notes/data/templates/__init__.py +1 -0
- agent_notes/data/templates/__pycache__/__init__.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/__init__.py +1 -0
- agent_notes/data/templates/frontmatter/__pycache__/__init__.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/__pycache__/claude.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/__pycache__/cursor.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/__pycache__/opencode.cpython-314.pyc +0 -0
- agent_notes/data/templates/frontmatter/claude.py +44 -0
- agent_notes/data/templates/frontmatter/opencode.py +104 -0
- agent_notes/doctor_checks.py +189 -0
- agent_notes/domain/__init__.py +17 -0
- agent_notes/domain/agent.py +34 -0
- agent_notes/domain/cli_backend.py +40 -0
- agent_notes/domain/diagnostics.py +29 -0
- agent_notes/domain/diff.py +44 -0
- agent_notes/domain/model.py +27 -0
- agent_notes/domain/role.py +13 -0
- agent_notes/domain/rule.py +13 -0
- agent_notes/domain/skill.py +15 -0
- agent_notes/domain/state.py +46 -0
- agent_notes/install_state.py +11 -0
- agent_notes/registries/__init__.py +16 -0
- agent_notes/registries/_base.py +46 -0
- agent_notes/registries/agent_registry.py +107 -0
- agent_notes/registries/cli_registry.py +89 -0
- agent_notes/registries/model_registry.py +85 -0
- agent_notes/registries/role_registry.py +64 -0
- agent_notes/registries/rule_registry.py +80 -0
- agent_notes/registries/skill_registry.py +141 -0
- agent_notes/services/__init__.py +8 -0
- agent_notes/services/diagnostics/__init__.py +47 -0
- agent_notes/services/diagnostics/_checks.py +272 -0
- agent_notes/services/diagnostics/_display.py +346 -0
- agent_notes/services/diagnostics/_fix.py +169 -0
- agent_notes/services/diff.py +349 -0
- agent_notes/services/fs.py +195 -0
- agent_notes/services/install_state_builder.py +210 -0
- agent_notes/services/installer.py +293 -0
- agent_notes/services/memory_backend.py +155 -0
- agent_notes/services/rendering.py +329 -0
- agent_notes/services/session_context.py +23 -0
- agent_notes/services/settings_writer.py +79 -0
- agent_notes/services/state_store.py +249 -0
- agent_notes/services/ui.py +419 -0
- agent_notes/services/user_config.py +62 -0
- agent_notes/services/validation.py +67 -0
- agent_notes/state.py +21 -0
- agent_notes-2.0.4.dist-info/METADATA +14 -0
- agent_notes-2.0.4.dist-info/RECORD +162 -0
- agent_notes-2.0.4.dist-info/WHEEL +5 -0
- agent_notes-2.0.4.dist-info/entry_points.txt +2 -0
- agent_notes-2.0.4.dist-info/licenses/LICENSE +21 -0
- agent_notes-2.0.4.dist-info/top_level.txt +2 -0
- tests/conftest.py +20 -0
- tests/functional/__init__.py +0 -0
- tests/functional/test_build_commands.py +88 -0
- tests/functional/test_registries.py +128 -0
- tests/integration/__init__.py +0 -0
- tests/integration/test_build_output.py +129 -0
- tests/plugins/__init__.py +0 -0
- tests/plugins/test_agents.py +93 -0
- tests/plugins/test_skills.py +77 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docker-dockerfile
|
|
3
|
+
description: "Dockerfile patterns: structure, base images, multi-stage builds, layer optimization, security, and health checks"
|
|
4
|
+
group: docker
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Dockerfile Patterns
|
|
8
|
+
|
|
9
|
+
Best practices and patterns for writing production-ready Dockerfiles based on official Docker documentation and industry standards.
|
|
10
|
+
|
|
11
|
+
> **Sources**: This guide is based on [Docker Official Documentation](https://docs.docker.com/build/building/best-practices/), [Docker Multi-stage Builds](https://docs.docker.com/build/building/multi-stage/), and current security best practices as of 2025.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Dockerfile Structure Template
|
|
16
|
+
|
|
17
|
+
```dockerfile
|
|
18
|
+
# syntax=docker/dockerfile:1
|
|
19
|
+
|
|
20
|
+
# Build stage
|
|
21
|
+
FROM node:20.11.0-alpine AS builder
|
|
22
|
+
|
|
23
|
+
# Metadata
|
|
24
|
+
LABEL maintainer="team@example.com"
|
|
25
|
+
LABEL version="1.0"
|
|
26
|
+
|
|
27
|
+
# Set working directory
|
|
28
|
+
WORKDIR /app
|
|
29
|
+
|
|
30
|
+
# Install dependencies first (better caching)
|
|
31
|
+
COPY package*.json ./
|
|
32
|
+
RUN npm ci
|
|
33
|
+
|
|
34
|
+
# Copy application code
|
|
35
|
+
COPY . .
|
|
36
|
+
|
|
37
|
+
# Build application
|
|
38
|
+
RUN npm run build
|
|
39
|
+
|
|
40
|
+
# Production stage
|
|
41
|
+
FROM node:20.11.0-alpine AS production
|
|
42
|
+
|
|
43
|
+
# Install security updates
|
|
44
|
+
RUN apk update && apk upgrade && rm -rf /var/cache/apk/*
|
|
45
|
+
|
|
46
|
+
# Create non-root user (UID > 10000 for security)
|
|
47
|
+
RUN addgroup -g 10001 -S nodejs && \
|
|
48
|
+
adduser -S nodejs -u 10001
|
|
49
|
+
|
|
50
|
+
WORKDIR /app
|
|
51
|
+
|
|
52
|
+
# Copy built assets from builder
|
|
53
|
+
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
|
|
54
|
+
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
|
|
55
|
+
COPY --chown=nodejs:nodejs package*.json ./
|
|
56
|
+
|
|
57
|
+
# Switch to non-root user
|
|
58
|
+
USER nodejs
|
|
59
|
+
|
|
60
|
+
# Expose port
|
|
61
|
+
EXPOSE 3000
|
|
62
|
+
|
|
63
|
+
# Health check (production-necessary, not optional)
|
|
64
|
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
|
65
|
+
CMD node healthcheck.js || exit 1
|
|
66
|
+
|
|
67
|
+
# Start application
|
|
68
|
+
CMD ["node", "dist/server.js"]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Base Image Selection
|
|
74
|
+
|
|
75
|
+
### Choose from Trusted Sources
|
|
76
|
+
|
|
77
|
+
Docker recommends using images from:
|
|
78
|
+
- **Docker Official Images**: Curated collection with clear documentation
|
|
79
|
+
- **Verified Publisher images**: Authenticated by Docker
|
|
80
|
+
- **Docker-Sponsored Open Source**: Maintained projects
|
|
81
|
+
|
|
82
|
+
**Source**: [Docker Best Practices - Base Images](https://docs.docker.com/build/building/best-practices/)
|
|
83
|
+
|
|
84
|
+
### Alpine Linux (Minimal)
|
|
85
|
+
|
|
86
|
+
Alpine is recommended as a minimal starting point, currently **under 6 MB** while providing a full Linux distribution.
|
|
87
|
+
|
|
88
|
+
```dockerfile
|
|
89
|
+
# Smallest size, minimal attack surface
|
|
90
|
+
FROM node:20.11.0-alpine
|
|
91
|
+
FROM python:3.12-alpine
|
|
92
|
+
FROM ruby:3.3-alpine
|
|
93
|
+
|
|
94
|
+
# Install common dependencies on Alpine
|
|
95
|
+
RUN apk add --no-cache \
|
|
96
|
+
bash \
|
|
97
|
+
curl \
|
|
98
|
+
git \
|
|
99
|
+
postgresql-dev
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Pin to Specific Digests for Supply Chain Security
|
|
103
|
+
|
|
104
|
+
```dockerfile
|
|
105
|
+
# Pin to specific digest for guaranteed immutability
|
|
106
|
+
FROM node:20.11.0-alpine@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c
|
|
107
|
+
|
|
108
|
+
# Note: Requires active maintenance for security updates
|
|
109
|
+
# Use Docker Scout for automated remediation workflows
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Source**: [Docker Best Practices - Supply Chain Security](https://docs.docker.com/build/building/best-practices/)
|
|
113
|
+
|
|
114
|
+
### Debian Slim (Balanced)
|
|
115
|
+
|
|
116
|
+
```dockerfile
|
|
117
|
+
# Good balance of size and compatibility
|
|
118
|
+
FROM node:20-slim
|
|
119
|
+
FROM python:3.12-slim
|
|
120
|
+
FROM ruby:3.3-slim
|
|
121
|
+
|
|
122
|
+
# CRITICAL: Always combine apt-get update with install
|
|
123
|
+
# Prevents cache issues that could install outdated packages
|
|
124
|
+
RUN apt-get update && \
|
|
125
|
+
apt-get install -y --no-install-recommends \
|
|
126
|
+
curl \
|
|
127
|
+
git \
|
|
128
|
+
postgresql-client && \
|
|
129
|
+
rm -rf /var/lib/apt/lists/*
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Distroless (Maximum Security)
|
|
133
|
+
|
|
134
|
+
```dockerfile
|
|
135
|
+
# Google's distroless images - no shell, minimal attack surface
|
|
136
|
+
FROM gcr.io/distroless/nodejs20-debian12
|
|
137
|
+
FROM gcr.io/distroless/python3-debian12
|
|
138
|
+
FROM gcr.io/distroless/java17-debian12
|
|
139
|
+
|
|
140
|
+
# Note: No shell available, debugging is harder
|
|
141
|
+
# Best for production security
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Multi-Stage Builds (Security Critical)
|
|
147
|
+
|
|
148
|
+
Multi-stage builds are **foundational for production security**. They allow you to "selectively copy artifacts from one stage to another, leaving behind everything you don't want in the final image."
|
|
149
|
+
|
|
150
|
+
### Security Benefits
|
|
151
|
+
|
|
152
|
+
1. **Reduced Attack Surface**: Excludes build tools, compilers, and development dependencies
|
|
153
|
+
2. **Smaller Image Size**: Final image contains only runtime necessities
|
|
154
|
+
3. **No Build Tools in Production**: Eliminates unnecessary security risks
|
|
155
|
+
|
|
156
|
+
**Source**: [Docker Multi-stage Builds Official Documentation](https://docs.docker.com/build/building/multi-stage/)
|
|
157
|
+
|
|
158
|
+
### Basic Multi-Stage Pattern
|
|
159
|
+
|
|
160
|
+
```dockerfile
|
|
161
|
+
# Build stage
|
|
162
|
+
FROM golang:1.24 AS build
|
|
163
|
+
|
|
164
|
+
WORKDIR /app
|
|
165
|
+
COPY . .
|
|
166
|
+
RUN go build -o /bin/hello ./main.go
|
|
167
|
+
|
|
168
|
+
# Production stage - minimal runtime
|
|
169
|
+
FROM scratch
|
|
170
|
+
COPY --from=build /bin/hello /bin/hello
|
|
171
|
+
CMD ["/bin/hello"]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Copy from External Images
|
|
175
|
+
|
|
176
|
+
```dockerfile
|
|
177
|
+
# Copy from any image, not just previous stages
|
|
178
|
+
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Named Stages for Maintainability
|
|
182
|
+
|
|
183
|
+
```dockerfile
|
|
184
|
+
FROM node:20-alpine AS dependencies
|
|
185
|
+
RUN npm ci --only=production
|
|
186
|
+
|
|
187
|
+
FROM node:20-alpine AS builder
|
|
188
|
+
COPY --from=dependencies /app/node_modules ./node_modules
|
|
189
|
+
RUN npm run build
|
|
190
|
+
|
|
191
|
+
FROM node:20-alpine AS production
|
|
192
|
+
COPY --from=builder /app/dist ./dist
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Use `AS <NAME>` to reference stages by name rather than numeric index—improves maintainability when reordering instructions.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Layer Optimization
|
|
200
|
+
|
|
201
|
+
### Order by Change Frequency (Critical for Caching)
|
|
202
|
+
|
|
203
|
+
```dockerfile
|
|
204
|
+
# ❌ BAD - Changes frequently, invalidates cache
|
|
205
|
+
COPY . .
|
|
206
|
+
RUN npm install
|
|
207
|
+
|
|
208
|
+
# ✅ GOOD - Dependencies change less often
|
|
209
|
+
COPY package*.json ./
|
|
210
|
+
RUN npm ci
|
|
211
|
+
COPY . .
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Understanding cache invalidation is critical for efficient builds.
|
|
215
|
+
|
|
216
|
+
### Combine RUN Commands
|
|
217
|
+
|
|
218
|
+
```dockerfile
|
|
219
|
+
# ❌ BAD - Creates multiple layers
|
|
220
|
+
RUN apt-get update
|
|
221
|
+
RUN apt-get install -y curl
|
|
222
|
+
RUN apt-get install -y git
|
|
223
|
+
RUN rm -rf /var/lib/apt/lists/*
|
|
224
|
+
|
|
225
|
+
# ✅ GOOD - Single layer, smaller image
|
|
226
|
+
# CRITICAL: Combine apt-get update with install in same RUN
|
|
227
|
+
RUN apt-get update && \
|
|
228
|
+
apt-get install -y --no-install-recommends \
|
|
229
|
+
curl \
|
|
230
|
+
git && \
|
|
231
|
+
rm -rf /var/lib/apt/lists/*
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Sort arguments alphanumerically for maintainability.
|
|
235
|
+
|
|
236
|
+
### Use Pipefail for Error Detection
|
|
237
|
+
|
|
238
|
+
```dockerfile
|
|
239
|
+
# IMPORTANT: Prepend set -o pipefail to catch errors at any stage
|
|
240
|
+
RUN set -o pipefail && \
|
|
241
|
+
curl -sL https://example.com/install.sh | bash
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Without pipefail, errors in piped commands may be silently ignored.
|
|
245
|
+
|
|
246
|
+
**Source**: [Docker Best Practices - RUN Instructions](https://docs.docker.com/build/building/best-practices/)
|
|
247
|
+
|
|
248
|
+
### Use .dockerignore (Essential)
|
|
249
|
+
|
|
250
|
+
Including unnecessary files like `.git`, `node_modules`, and `.env` increases image size and exposes secrets. The `.dockerignore` file excludes files and directories from the build context.
|
|
251
|
+
|
|
252
|
+
```dockerignore
|
|
253
|
+
# .dockerignore
|
|
254
|
+
node_modules
|
|
255
|
+
npm-debug.log
|
|
256
|
+
.git
|
|
257
|
+
.env
|
|
258
|
+
.env.local
|
|
259
|
+
.env.*.local
|
|
260
|
+
*.md
|
|
261
|
+
.DS_Store
|
|
262
|
+
coverage
|
|
263
|
+
.next
|
|
264
|
+
dist
|
|
265
|
+
build
|
|
266
|
+
*.log
|
|
267
|
+
.vscode
|
|
268
|
+
.idea
|
|
269
|
+
Dockerfile
|
|
270
|
+
docker-compose*.yml
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**Source**: [Docker Best Practices - Build Context](https://docs.docker.com/build/building/best-practices/)
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Security Best Practices
|
|
278
|
+
|
|
279
|
+
### Run as Non-Root User (Critical)
|
|
280
|
+
|
|
281
|
+
By default, Docker containers run as UID 0 (root). If the container is compromised, the attacker will have host-level root access to all resources allocated to the container.
|
|
282
|
+
|
|
283
|
+
**UIDs below 10,000 are a security risk** on several systems. If someone manages to escalate privileges outside the Docker container, their Docker container UID may overlap with a more privileged system user's UID, granting them additional permissions.
|
|
284
|
+
|
|
285
|
+
**Best Practice**: Always run processes as a **UID above 10,000**.
|
|
286
|
+
|
|
287
|
+
```dockerfile
|
|
288
|
+
# Alpine - Use UID > 10000 for security
|
|
289
|
+
RUN addgroup -g 10001 -S appuser && \
|
|
290
|
+
adduser -S appuser -u 10001
|
|
291
|
+
|
|
292
|
+
# Debian/Ubuntu - Use UID > 10000
|
|
293
|
+
RUN useradd -m -u 10001 appuser
|
|
294
|
+
|
|
295
|
+
# Switch to non-root user
|
|
296
|
+
USER appuser
|
|
297
|
+
|
|
298
|
+
# Set proper ownership when copying
|
|
299
|
+
COPY --chown=appuser:appuser . .
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Source**: [Docker USER Instruction Best Practices](https://www.docker.com/blog/understanding-the-docker-user-instruction/)
|
|
303
|
+
|
|
304
|
+
### Scan for Vulnerabilities
|
|
305
|
+
|
|
306
|
+
```dockerfile
|
|
307
|
+
# Use specific versions, never :latest
|
|
308
|
+
FROM node:20.11.0-alpine
|
|
309
|
+
|
|
310
|
+
# Keep base image updated
|
|
311
|
+
RUN apk update && apk upgrade && rm -rf /var/cache/apk/*
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Scan images regularly:
|
|
315
|
+
```bash
|
|
316
|
+
docker scout cves my-image:latest
|
|
317
|
+
# or
|
|
318
|
+
trivy image my-image:latest
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Secrets Management
|
|
322
|
+
|
|
323
|
+
```dockerfile
|
|
324
|
+
# ❌ BAD - Never hardcode secrets
|
|
325
|
+
ENV API_KEY=secret123
|
|
326
|
+
|
|
327
|
+
# ✅ GOOD - Use build args with cleanup
|
|
328
|
+
ARG NPM_TOKEN
|
|
329
|
+
RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc && \
|
|
330
|
+
npm install && \
|
|
331
|
+
rm -f .npmrc
|
|
332
|
+
|
|
333
|
+
# ✅ BETTER - Pass at runtime
|
|
334
|
+
# docker run -e API_KEY=$API_KEY my-image
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Health Checks (Production-Necessary)
|
|
340
|
+
|
|
341
|
+
According to Docker best practices, "adding a HEALTHCHECK to your Dockerfile is not a nice-to-have—**it's a production necessity**." Without health checks, Docker cannot detect if a containerized service is unhealthy, preventing automatic restarts or recovery.
|
|
342
|
+
|
|
343
|
+
### HEALTHCHECK Syntax
|
|
344
|
+
|
|
345
|
+
```dockerfile
|
|
346
|
+
HEALTHCHECK [OPTIONS] CMD command
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Options**:
|
|
350
|
+
- `--interval=DURATION` (default: 30s)
|
|
351
|
+
- `--timeout=DURATION` (default: 30s)
|
|
352
|
+
- `--start-period=DURATION` (default: 0s) - Grace period for slow-starting apps
|
|
353
|
+
- `--start-interval=DURATION` (default: 5s)
|
|
354
|
+
- `--retries=N` (default: 3)
|
|
355
|
+
|
|
356
|
+
**Exit Codes**:
|
|
357
|
+
- `0`: success - container is healthy
|
|
358
|
+
- `1`: unhealthy - container isn't working correctly
|
|
359
|
+
|
|
360
|
+
### Examples
|
|
361
|
+
|
|
362
|
+
```dockerfile
|
|
363
|
+
# Web server check
|
|
364
|
+
HEALTHCHECK --interval=5m --timeout=3s \
|
|
365
|
+
CMD curl -f http://localhost/ || exit 1
|
|
366
|
+
|
|
367
|
+
# Database check
|
|
368
|
+
HEALTHCHECK --interval=10s --timeout=5s --retries=5 \
|
|
369
|
+
CMD pg_isready -U postgres || exit 1
|
|
370
|
+
|
|
371
|
+
# With start-period for slow-starting apps
|
|
372
|
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=120s --retries=3 \
|
|
373
|
+
CMD node healthcheck.js || exit 1
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Best Practices
|
|
377
|
+
|
|
378
|
+
1. **Use appropriate health checks** - Don't use shallow checks (e.g., ping when you need connection tests)
|
|
379
|
+
2. **Use `start-period` for slow apps** - Gives containers grace period before failures count
|
|
380
|
+
3. **Verify tool availability** - Tools like `curl` may not be in slim/alpine images
|
|
381
|
+
4. **Lightweight checks** - Use `wget --spider` or native commands when possible
|
|
382
|
+
|
|
383
|
+
**Source**: [Docker HEALTHCHECK Reference](https://docs.docker.com/reference/dockerfile/#healthcheck)
|
|
384
|
+
|
|
385
|
+
---
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docker-dockerfile-languages
|
|
3
|
+
description: "Dockerfile language patterns: Node.js, Python, Ruby builds, dev/prod targets, and CI/CD integration"
|
|
4
|
+
group: docker
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Dockerfile Language Patterns
|
|
8
|
+
|
|
9
|
+
## Language-Specific Patterns
|
|
10
|
+
|
|
11
|
+
### Node.js with Multi-Stage Build
|
|
12
|
+
|
|
13
|
+
```dockerfile
|
|
14
|
+
FROM node:20.11.0-alpine AS builder
|
|
15
|
+
|
|
16
|
+
WORKDIR /app
|
|
17
|
+
|
|
18
|
+
# Install all dependencies (including devDependencies)
|
|
19
|
+
COPY package*.json ./
|
|
20
|
+
RUN npm ci
|
|
21
|
+
|
|
22
|
+
# Build the application
|
|
23
|
+
COPY . .
|
|
24
|
+
RUN npm run build
|
|
25
|
+
|
|
26
|
+
# Production stage - only production dependencies
|
|
27
|
+
FROM node:20.11.0-alpine AS production
|
|
28
|
+
|
|
29
|
+
RUN addgroup -g 10001 -S nodejs && \
|
|
30
|
+
adduser -S nodejs -u 10001
|
|
31
|
+
|
|
32
|
+
WORKDIR /app
|
|
33
|
+
|
|
34
|
+
COPY package*.json ./
|
|
35
|
+
RUN npm ci --only=production && \
|
|
36
|
+
npm cache clean --force
|
|
37
|
+
|
|
38
|
+
# Copy built assets
|
|
39
|
+
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
|
|
40
|
+
|
|
41
|
+
USER nodejs
|
|
42
|
+
|
|
43
|
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
|
44
|
+
CMD node healthcheck.js || exit 1
|
|
45
|
+
|
|
46
|
+
CMD ["node", "dist/server.js"]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Python with Virtual Environment
|
|
50
|
+
|
|
51
|
+
```dockerfile
|
|
52
|
+
FROM python:3.12-slim AS builder
|
|
53
|
+
|
|
54
|
+
WORKDIR /app
|
|
55
|
+
|
|
56
|
+
COPY requirements.txt .
|
|
57
|
+
RUN python -m venv /opt/venv && \
|
|
58
|
+
/opt/venv/bin/pip install --no-cache-dir -r requirements.txt
|
|
59
|
+
|
|
60
|
+
# Production
|
|
61
|
+
FROM python:3.12-slim
|
|
62
|
+
|
|
63
|
+
# Create non-root user (UID > 10000)
|
|
64
|
+
RUN useradd -m -u 10001 python
|
|
65
|
+
|
|
66
|
+
WORKDIR /app
|
|
67
|
+
|
|
68
|
+
# Copy virtual environment from builder
|
|
69
|
+
COPY --from=builder /opt/venv /opt/venv
|
|
70
|
+
|
|
71
|
+
# Copy application
|
|
72
|
+
COPY --chown=python:python . .
|
|
73
|
+
|
|
74
|
+
USER python
|
|
75
|
+
|
|
76
|
+
ENV PATH="/opt/venv/bin:$PATH"
|
|
77
|
+
|
|
78
|
+
CMD ["python", "app.py"]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Ruby/Rails Application
|
|
82
|
+
|
|
83
|
+
```dockerfile
|
|
84
|
+
FROM ruby:3.3-alpine AS builder
|
|
85
|
+
|
|
86
|
+
# Install build dependencies
|
|
87
|
+
RUN apk add --no-cache \
|
|
88
|
+
build-base \
|
|
89
|
+
postgresql-dev \
|
|
90
|
+
nodejs \
|
|
91
|
+
yarn
|
|
92
|
+
|
|
93
|
+
WORKDIR /app
|
|
94
|
+
|
|
95
|
+
# Install gems
|
|
96
|
+
COPY Gemfile Gemfile.lock ./
|
|
97
|
+
RUN bundle config set --local deployment 'true' && \
|
|
98
|
+
bundle config set --local without 'development test' && \
|
|
99
|
+
bundle install
|
|
100
|
+
|
|
101
|
+
# Install node packages and build assets
|
|
102
|
+
COPY package.json yarn.lock ./
|
|
103
|
+
RUN yarn install --frozen-lockfile
|
|
104
|
+
|
|
105
|
+
COPY . .
|
|
106
|
+
|
|
107
|
+
# Precompile assets
|
|
108
|
+
RUN SECRET_KEY_BASE=dummy bundle exec rails assets:precompile
|
|
109
|
+
|
|
110
|
+
# Production
|
|
111
|
+
FROM ruby:3.3-alpine
|
|
112
|
+
|
|
113
|
+
# Install runtime dependencies only
|
|
114
|
+
RUN apk add --no-cache \
|
|
115
|
+
postgresql-client \
|
|
116
|
+
nodejs \
|
|
117
|
+
tzdata
|
|
118
|
+
|
|
119
|
+
RUN addgroup -g 10001 -S rails && \
|
|
120
|
+
adduser -S rails -u 10001
|
|
121
|
+
|
|
122
|
+
WORKDIR /app
|
|
123
|
+
|
|
124
|
+
# Copy gems and application
|
|
125
|
+
COPY --from=builder /usr/local/bundle /usr/local/bundle
|
|
126
|
+
COPY --from=builder --chown=rails:rails /app /app
|
|
127
|
+
|
|
128
|
+
USER rails
|
|
129
|
+
|
|
130
|
+
EXPOSE 3000
|
|
131
|
+
|
|
132
|
+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
|
133
|
+
CMD wget --quiet --tries=1 --spider http://localhost:3000/health || exit 1
|
|
134
|
+
|
|
135
|
+
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Build Arguments and Environment
|
|
141
|
+
|
|
142
|
+
### Build Arguments
|
|
143
|
+
|
|
144
|
+
```dockerfile
|
|
145
|
+
ARG NODE_ENV=production
|
|
146
|
+
ARG BUILD_DATE
|
|
147
|
+
ARG VERSION
|
|
148
|
+
|
|
149
|
+
RUN if [ "$NODE_ENV" = "production" ]; then \
|
|
150
|
+
npm ci --only=production; \
|
|
151
|
+
else \
|
|
152
|
+
npm ci; \
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
# Build with:
|
|
156
|
+
# docker build --build-arg NODE_ENV=development -t my-app .
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Environment Variables
|
|
160
|
+
|
|
161
|
+
```dockerfile
|
|
162
|
+
ENV NODE_ENV=production \
|
|
163
|
+
PORT=3000 \
|
|
164
|
+
LOG_LEVEL=info
|
|
165
|
+
|
|
166
|
+
# Can be overridden at runtime:
|
|
167
|
+
# docker run -e LOG_LEVEL=debug my-app
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Development vs Production Targets
|
|
173
|
+
|
|
174
|
+
```dockerfile
|
|
175
|
+
# Development stage
|
|
176
|
+
FROM node:20-alpine AS development
|
|
177
|
+
|
|
178
|
+
WORKDIR /app
|
|
179
|
+
|
|
180
|
+
COPY package*.json ./
|
|
181
|
+
RUN npm install
|
|
182
|
+
|
|
183
|
+
COPY . .
|
|
184
|
+
|
|
185
|
+
CMD ["npm", "run", "dev"]
|
|
186
|
+
|
|
187
|
+
# Production stage
|
|
188
|
+
FROM node:20-alpine AS production
|
|
189
|
+
|
|
190
|
+
RUN addgroup -g 10001 -S nodejs && \
|
|
191
|
+
adduser -S nodejs -u 10001
|
|
192
|
+
|
|
193
|
+
WORKDIR /app
|
|
194
|
+
|
|
195
|
+
COPY package*.json ./
|
|
196
|
+
RUN npm ci --only=production
|
|
197
|
+
|
|
198
|
+
COPY --chown=nodejs:nodejs . .
|
|
199
|
+
|
|
200
|
+
USER nodejs
|
|
201
|
+
|
|
202
|
+
CMD ["npm", "start"]
|
|
203
|
+
|
|
204
|
+
# Build with: docker build --target development
|
|
205
|
+
# Or: docker build --target production (default)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
BuildKit optimizes by only processing stages your target depends on.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Best Practices Summary
|
|
213
|
+
|
|
214
|
+
### ✅ DO
|
|
215
|
+
|
|
216
|
+
1. **Use specific versions** - `FROM node:20.11.0-alpine`, never `:latest`
|
|
217
|
+
2. **Use multi-stage builds** - Reduces attack surface, smaller images
|
|
218
|
+
3. **Run as non-root user** - UID > 10,000 for security
|
|
219
|
+
4. **Order layers by change frequency** - Better caching
|
|
220
|
+
5. **Use .dockerignore** - Essential for security and size
|
|
221
|
+
6. **Combine apt-get update with install** - Prevents cache issues
|
|
222
|
+
7. **Use `set -o pipefail`** - Catch errors in piped commands
|
|
223
|
+
8. **Add HEALTHCHECK** - Production-necessary for orchestration
|
|
224
|
+
9. **Scan for vulnerabilities** - Use Docker Scout or Trivy
|
|
225
|
+
10. **Pin to digests for critical apps** - Supply chain security
|
|
226
|
+
|
|
227
|
+
### ❌ DON'T
|
|
228
|
+
|
|
229
|
+
1. **Use :latest tag** - Unpredictable, unreproducible builds
|
|
230
|
+
2. **Run as root** - Security risk, use UID > 10,000
|
|
231
|
+
3. **Store secrets in image** - Use runtime environment variables
|
|
232
|
+
4. **Install unnecessary packages** - Increases attack surface
|
|
233
|
+
5. **Use ADD when COPY works** - ADD has unexpected behaviors
|
|
234
|
+
6. **Forget .dockerignore** - 87% of images have vulnerabilities
|
|
235
|
+
7. **Skip HEALTHCHECK** - Orchestration cannot detect failures
|
|
236
|
+
8. **Separate apt-get update from install** - Cache inconsistency risk
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## CI/CD Integration
|
|
241
|
+
|
|
242
|
+
Rebuild images frequently with `--no-cache` to obtain security patches. Integrate automated building and testing through GitHub Actions or equivalent pipelines.
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Build without cache for security updates
|
|
246
|
+
docker build --no-cache -t my-app:latest .
|
|
247
|
+
|
|
248
|
+
# Scan in CI pipeline
|
|
249
|
+
docker scout cves my-app:latest --exit-code
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Testing Dockerfiles
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
# Build
|
|
258
|
+
docker build -t my-app:latest .
|
|
259
|
+
|
|
260
|
+
# Run
|
|
261
|
+
docker run -p 3000:3000 my-app:latest
|
|
262
|
+
|
|
263
|
+
# Check size
|
|
264
|
+
docker images my-app:latest
|
|
265
|
+
|
|
266
|
+
# Scan for vulnerabilities
|
|
267
|
+
docker scout cves my-app:latest
|
|
268
|
+
trivy image my-app:latest
|
|
269
|
+
|
|
270
|
+
# Inspect layers
|
|
271
|
+
docker history my-app:latest
|
|
272
|
+
|
|
273
|
+
# Test as non-root (should work)
|
|
274
|
+
docker run --user 10001:10001 my-app:latest
|
|
275
|
+
|
|
276
|
+
# Test read-only filesystem
|
|
277
|
+
docker run --read-only --tmpfs /tmp my-app:latest
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## References and Sources
|
|
283
|
+
|
|
284
|
+
This guide is based on official Docker documentation:
|
|
285
|
+
|
|
286
|
+
- [Docker Best Practices Official Documentation](https://docs.docker.com/build/building/best-practices/)
|
|
287
|
+
- [Docker Multi-stage Builds](https://docs.docker.com/build/building/multi-stage/)
|
|
288
|
+
- [Docker USER Instruction Best Practices](https://www.docker.com/blog/understanding-the-docker-user-instruction/)
|
|
289
|
+
- [Docker HEALTHCHECK Reference](https://docs.docker.com/reference/dockerfile/#healthcheck)
|
|
290
|
+
- [Dockerfile Reference](https://docs.docker.com/reference/dockerfile/)
|
|
291
|
+
- [Docker Security Documentation](https://docs.docker.com/engine/security/)
|
|
292
|
+
|
|
293
|
+
Last updated: December 2025
|