@plazmodium/odin 0.3.3-beta → 0.3.5-beta
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.
- package/README.md +25 -10
- package/builtin/ODIN.md +1067 -0
- package/builtin/agent-definitions/README.md +170 -0
- package/builtin/agent-definitions/_shared-context.md +377 -0
- package/builtin/agent-definitions/architect.md +627 -0
- package/builtin/agent-definitions/builder.md +713 -0
- package/builtin/agent-definitions/discovery.md +293 -0
- package/builtin/agent-definitions/documenter.md +238 -0
- package/builtin/agent-definitions/guardian.md +1049 -0
- package/builtin/agent-definitions/integrator.md +189 -0
- package/builtin/agent-definitions/planning.md +236 -0
- package/builtin/agent-definitions/product.md +405 -0
- package/builtin/agent-definitions/release.md +205 -0
- package/builtin/agent-definitions/reviewer.md +447 -0
- package/builtin/agent-definitions/watcher.md +402 -0
- package/builtin/skills/api/graphql/SKILL.md +548 -0
- package/builtin/skills/api/grpc/SKILL.md +554 -0
- package/builtin/skills/api/rest-api/SKILL.md +469 -0
- package/builtin/skills/api/trpc/SKILL.md +503 -0
- package/builtin/skills/architecture/clean-architecture/SKILL.md +141 -0
- package/builtin/skills/architecture/domain-driven-design/SKILL.md +129 -0
- package/builtin/skills/architecture/event-driven/SKILL.md +145 -0
- package/builtin/skills/architecture/microservices/SKILL.md +143 -0
- package/builtin/skills/architecture/tla-precheck/SKILL.md +171 -0
- package/builtin/skills/backend/golang-gin/SKILL.md +141 -0
- package/builtin/skills/backend/nodejs-express/SKILL.md +277 -0
- package/builtin/skills/backend/nodejs-fastify/SKILL.md +152 -0
- package/builtin/skills/backend/python-django/SKILL.md +128 -0
- package/builtin/skills/backend/python-fastapi/SKILL.md +140 -0
- package/builtin/skills/database/mongodb/SKILL.md +132 -0
- package/builtin/skills/database/postgresql/SKILL.md +120 -0
- package/builtin/skills/database/prisma-orm/SKILL.md +366 -0
- package/builtin/skills/database/redis/SKILL.md +140 -0
- package/builtin/skills/database/supabase/SKILL.md +416 -0
- package/builtin/skills/devops/aws/SKILL.md +382 -0
- package/builtin/skills/devops/docker/SKILL.md +359 -0
- package/builtin/skills/devops/github-actions/SKILL.md +435 -0
- package/builtin/skills/devops/kubernetes/SKILL.md +459 -0
- package/builtin/skills/devops/terraform/SKILL.md +453 -0
- package/builtin/skills/frontend/alpine-dev/SKILL.md +27 -0
- package/builtin/skills/frontend/angular-dev/SKILL.md +28 -0
- package/builtin/skills/frontend/astro-dev/SKILL.md +28 -0
- package/builtin/skills/frontend/htmx-dev/SKILL.md +28 -0
- package/builtin/skills/frontend/nextjs-dev/SKILL.md +470 -0
- package/builtin/skills/frontend/react-patterns/SKILL.md +166 -0
- package/builtin/skills/frontend/svelte-dev/SKILL.md +28 -0
- package/builtin/skills/frontend/tailwindcss/SKILL.md +131 -0
- package/builtin/skills/frontend/vuejs-dev/SKILL.md +28 -0
- package/builtin/skills/generic-dev/SKILL.md +307 -0
- package/builtin/skills/testing/cypress/SKILL.md +372 -0
- package/builtin/skills/testing/jest/SKILL.md +176 -0
- package/builtin/skills/testing/playwright/SKILL.md +341 -0
- package/builtin/skills/testing/unit-tests-eval-sdd/SKILL.md +73 -0
- package/builtin/skills/testing/unit-tests-sdd/SKILL.md +83 -0
- package/builtin/skills/testing/vitest/SKILL.md +249 -0
- package/dist/adapters/skills/filesystem.d.ts +1 -0
- package/dist/adapters/skills/filesystem.d.ts.map +1 -1
- package/dist/adapters/skills/filesystem.js +6 -18
- package/dist/adapters/skills/filesystem.js.map +1 -1
- package/dist/adapters/skills/types.d.ts +1 -0
- package/dist/adapters/skills/types.d.ts.map +1 -1
- package/dist/adapters/workflow-state/in-memory.d.ts +10 -2
- package/dist/adapters/workflow-state/in-memory.d.ts.map +1 -1
- package/dist/adapters/workflow-state/in-memory.js +98 -5
- package/dist/adapters/workflow-state/in-memory.js.map +1 -1
- package/dist/adapters/workflow-state/supabase.d.ts +8 -2
- package/dist/adapters/workflow-state/supabase.d.ts.map +1 -1
- package/dist/adapters/workflow-state/supabase.js +204 -0
- package/dist/adapters/workflow-state/supabase.js.map +1 -1
- package/dist/adapters/workflow-state/types.d.ts +15 -1
- package/dist/adapters/workflow-state/types.d.ts.map +1 -1
- package/dist/builtin-assets.d.ts +8 -0
- package/dist/builtin-assets.d.ts.map +1 -0
- package/dist/builtin-assets.js +90 -0
- package/dist/builtin-assets.js.map +1 -0
- package/dist/domain/skill-draft-validation.d.ts +18 -0
- package/dist/domain/skill-draft-validation.d.ts.map +1 -0
- package/dist/domain/skill-draft-validation.js +100 -0
- package/dist/domain/skill-draft-validation.js.map +1 -0
- package/dist/domain/skill-proposals.d.ts +11 -0
- package/dist/domain/skill-proposals.d.ts.map +1 -0
- package/dist/domain/skill-proposals.js +103 -0
- package/dist/domain/skill-proposals.js.map +1 -0
- package/dist/init.js +69 -11
- package/dist/init.js.map +1 -1
- package/dist/schemas.d.ts +39 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +30 -1
- package/dist/schemas.js.map +1 -1
- package/dist/server.js +38 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/apply-migrations.d.ts +10 -0
- package/dist/tools/apply-migrations.d.ts.map +1 -1
- package/dist/tools/apply-migrations.js +10 -26
- package/dist/tools/apply-migrations.js.map +1 -1
- package/dist/tools/capture-learning.d.ts.map +1 -1
- package/dist/tools/capture-learning.js +14 -1
- package/dist/tools/capture-learning.js.map +1 -1
- package/dist/tools/get-skill-proposal-queue.d.ts +5 -0
- package/dist/tools/get-skill-proposal-queue.d.ts.map +1 -0
- package/dist/tools/get-skill-proposal-queue.js +21 -0
- package/dist/tools/get-skill-proposal-queue.js.map +1 -0
- package/dist/tools/get-skill-proposals.d.ts +4 -0
- package/dist/tools/get-skill-proposals.d.ts.map +1 -0
- package/dist/tools/get-skill-proposals.js +11 -0
- package/dist/tools/get-skill-proposals.js.map +1 -0
- package/dist/tools/prepare-phase-context.d.ts.map +1 -1
- package/dist/tools/prepare-phase-context.js +5 -0
- package/dist/tools/prepare-phase-context.js.map +1 -1
- package/dist/tools/publish-skill-proposal.d.ts +5 -0
- package/dist/tools/publish-skill-proposal.d.ts.map +1 -0
- package/dist/tools/publish-skill-proposal.js +57 -0
- package/dist/tools/publish-skill-proposal.js.map +1 -0
- package/dist/tools/record-skill-proposal-decision.d.ts +4 -0
- package/dist/tools/record-skill-proposal-decision.d.ts.map +1 -0
- package/dist/tools/record-skill-proposal-decision.js +22 -0
- package/dist/tools/record-skill-proposal-decision.js.map +1 -0
- package/dist/tools/record-skill-proposal-draft.d.ts +5 -0
- package/dist/tools/record-skill-proposal-draft.d.ts.map +1 -0
- package/dist/tools/record-skill-proposal-draft.js +65 -0
- package/dist/tools/record-skill-proposal-draft.js.map +1 -0
- package/dist/tools/sync-skill-proposal-candidates.d.ts +5 -0
- package/dist/tools/sync-skill-proposal-candidates.d.ts.map +1 -0
- package/dist/tools/sync-skill-proposal-candidates.js +20 -0
- package/dist/tools/sync-skill-proposal-candidates.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/migrations/009_skill_proposal_candidates.sql +124 -0
- package/migrations/010_skill_proposals.sql +36 -0
- package/migrations/README.md +6 -0
- package/package.json +5 -3
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docker
|
|
3
|
+
description: Docker containerization expertise for building, running, and orchestrating containers. Covers Dockerfiles, multi-stage builds, Docker Compose, networking, and production best practices.
|
|
4
|
+
category: devops
|
|
5
|
+
compatible_with:
|
|
6
|
+
- kubernetes
|
|
7
|
+
- github-actions
|
|
8
|
+
- terraform
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Docker Containerization
|
|
12
|
+
|
|
13
|
+
## Instructions
|
|
14
|
+
|
|
15
|
+
1. **Assess the containerization need**: Determine if it's single container, multi-container, or production deployment.
|
|
16
|
+
2. **Follow Docker best practices**:
|
|
17
|
+
- Use official base images
|
|
18
|
+
- Minimize layers and image size
|
|
19
|
+
- Don't run as root
|
|
20
|
+
- Use multi-stage builds for compiled languages
|
|
21
|
+
3. **Provide complete examples**: Include Dockerfiles, compose files, and commands.
|
|
22
|
+
4. **Guide on security**: Image scanning, secrets management, least privilege.
|
|
23
|
+
|
|
24
|
+
## Dockerfile Basics
|
|
25
|
+
|
|
26
|
+
```dockerfile
|
|
27
|
+
# Use specific version tags, not 'latest'
|
|
28
|
+
FROM node:20-alpine
|
|
29
|
+
|
|
30
|
+
# Set working directory
|
|
31
|
+
WORKDIR /app
|
|
32
|
+
|
|
33
|
+
# Copy package files first (layer caching)
|
|
34
|
+
COPY package*.json ./
|
|
35
|
+
|
|
36
|
+
# Install dependencies
|
|
37
|
+
RUN npm ci --only=production
|
|
38
|
+
|
|
39
|
+
# Copy application code
|
|
40
|
+
COPY . .
|
|
41
|
+
|
|
42
|
+
# Create non-root user
|
|
43
|
+
RUN addgroup -g 1001 -S nodejs && \
|
|
44
|
+
adduser -S nodejs -u 1001
|
|
45
|
+
USER nodejs
|
|
46
|
+
|
|
47
|
+
# Expose port (documentation)
|
|
48
|
+
EXPOSE 3000
|
|
49
|
+
|
|
50
|
+
# Health check
|
|
51
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
52
|
+
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
|
|
53
|
+
|
|
54
|
+
# Start command
|
|
55
|
+
CMD ["node", "server.js"]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Multi-Stage Builds
|
|
59
|
+
|
|
60
|
+
### Node.js Application
|
|
61
|
+
|
|
62
|
+
```dockerfile
|
|
63
|
+
# Build stage
|
|
64
|
+
FROM node:20-alpine AS builder
|
|
65
|
+
WORKDIR /app
|
|
66
|
+
COPY package*.json ./
|
|
67
|
+
RUN npm ci
|
|
68
|
+
COPY . .
|
|
69
|
+
RUN npm run build
|
|
70
|
+
|
|
71
|
+
# Production stage
|
|
72
|
+
FROM node:20-alpine AS production
|
|
73
|
+
WORKDIR /app
|
|
74
|
+
COPY --from=builder /app/dist ./dist
|
|
75
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
76
|
+
COPY package*.json ./
|
|
77
|
+
|
|
78
|
+
USER node
|
|
79
|
+
EXPOSE 3000
|
|
80
|
+
CMD ["node", "dist/server.js"]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Go Application
|
|
84
|
+
|
|
85
|
+
```dockerfile
|
|
86
|
+
# Build stage
|
|
87
|
+
FROM golang:1.21-alpine AS builder
|
|
88
|
+
WORKDIR /app
|
|
89
|
+
COPY go.mod go.sum ./
|
|
90
|
+
RUN go mod download
|
|
91
|
+
COPY . .
|
|
92
|
+
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/main .
|
|
93
|
+
|
|
94
|
+
# Production stage (scratch for minimal image)
|
|
95
|
+
FROM scratch
|
|
96
|
+
COPY --from=builder /app/main /main
|
|
97
|
+
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
|
98
|
+
EXPOSE 8080
|
|
99
|
+
ENTRYPOINT ["/main"]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Rust Application
|
|
103
|
+
|
|
104
|
+
```dockerfile
|
|
105
|
+
FROM rust:1.75 AS builder
|
|
106
|
+
WORKDIR /app
|
|
107
|
+
COPY Cargo.toml Cargo.lock ./
|
|
108
|
+
COPY src ./src
|
|
109
|
+
RUN cargo build --release
|
|
110
|
+
|
|
111
|
+
FROM debian:bookworm-slim
|
|
112
|
+
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
|
|
113
|
+
COPY --from=builder /app/target/release/myapp /usr/local/bin/
|
|
114
|
+
EXPOSE 8080
|
|
115
|
+
CMD ["myapp"]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Docker Compose
|
|
119
|
+
|
|
120
|
+
### Development Setup
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
# docker-compose.yml
|
|
124
|
+
version: '3.8'
|
|
125
|
+
|
|
126
|
+
services:
|
|
127
|
+
app:
|
|
128
|
+
build:
|
|
129
|
+
context: .
|
|
130
|
+
dockerfile: Dockerfile.dev
|
|
131
|
+
ports:
|
|
132
|
+
- "3000:3000"
|
|
133
|
+
volumes:
|
|
134
|
+
- .:/app
|
|
135
|
+
- /app/node_modules # Anonymous volume for node_modules
|
|
136
|
+
environment:
|
|
137
|
+
- NODE_ENV=development
|
|
138
|
+
- DATABASE_URL=postgres://user:pass@db:5432/mydb
|
|
139
|
+
depends_on:
|
|
140
|
+
db:
|
|
141
|
+
condition: service_healthy
|
|
142
|
+
|
|
143
|
+
db:
|
|
144
|
+
image: postgres:16-alpine
|
|
145
|
+
environment:
|
|
146
|
+
POSTGRES_USER: user
|
|
147
|
+
POSTGRES_PASSWORD: pass
|
|
148
|
+
POSTGRES_DB: mydb
|
|
149
|
+
volumes:
|
|
150
|
+
- postgres_data:/var/lib/postgresql/data
|
|
151
|
+
healthcheck:
|
|
152
|
+
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
|
|
153
|
+
interval: 5s
|
|
154
|
+
timeout: 5s
|
|
155
|
+
retries: 5
|
|
156
|
+
|
|
157
|
+
redis:
|
|
158
|
+
image: redis:7-alpine
|
|
159
|
+
ports:
|
|
160
|
+
- "6379:6379"
|
|
161
|
+
|
|
162
|
+
volumes:
|
|
163
|
+
postgres_data:
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Production Setup
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
# docker-compose.prod.yml
|
|
170
|
+
version: '3.8'
|
|
171
|
+
|
|
172
|
+
services:
|
|
173
|
+
app:
|
|
174
|
+
image: myregistry/myapp:${VERSION:-latest}
|
|
175
|
+
deploy:
|
|
176
|
+
replicas: 3
|
|
177
|
+
resources:
|
|
178
|
+
limits:
|
|
179
|
+
cpus: '0.5'
|
|
180
|
+
memory: 512M
|
|
181
|
+
reservations:
|
|
182
|
+
cpus: '0.25'
|
|
183
|
+
memory: 256M
|
|
184
|
+
restart_policy:
|
|
185
|
+
condition: on-failure
|
|
186
|
+
delay: 5s
|
|
187
|
+
max_attempts: 3
|
|
188
|
+
environment:
|
|
189
|
+
- NODE_ENV=production
|
|
190
|
+
secrets:
|
|
191
|
+
- db_password
|
|
192
|
+
healthcheck:
|
|
193
|
+
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
|
194
|
+
interval: 30s
|
|
195
|
+
timeout: 10s
|
|
196
|
+
retries: 3
|
|
197
|
+
|
|
198
|
+
secrets:
|
|
199
|
+
db_password:
|
|
200
|
+
external: true
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Common Commands
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Build
|
|
207
|
+
docker build -t myapp:latest .
|
|
208
|
+
docker build -t myapp:latest --no-cache .
|
|
209
|
+
docker build -t myapp:latest --target builder . # Multi-stage target
|
|
210
|
+
|
|
211
|
+
# Run
|
|
212
|
+
docker run -d --name myapp -p 3000:3000 myapp:latest
|
|
213
|
+
docker run -it --rm myapp:latest sh # Interactive shell
|
|
214
|
+
docker run --env-file .env myapp:latest # With env file
|
|
215
|
+
|
|
216
|
+
# Compose
|
|
217
|
+
docker compose up -d
|
|
218
|
+
docker compose up -d --build # Rebuild
|
|
219
|
+
docker compose down -v # Remove volumes
|
|
220
|
+
docker compose logs -f app # Follow logs
|
|
221
|
+
docker compose exec app sh # Shell into running container
|
|
222
|
+
|
|
223
|
+
# Inspect
|
|
224
|
+
docker ps -a
|
|
225
|
+
docker logs myapp
|
|
226
|
+
docker inspect myapp
|
|
227
|
+
docker stats # Resource usage
|
|
228
|
+
|
|
229
|
+
# Cleanup
|
|
230
|
+
docker system prune -a # Remove all unused
|
|
231
|
+
docker volume prune # Remove unused volumes
|
|
232
|
+
docker image prune -a # Remove unused images
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Networking
|
|
236
|
+
|
|
237
|
+
```yaml
|
|
238
|
+
# Custom networks for isolation
|
|
239
|
+
version: '3.8'
|
|
240
|
+
|
|
241
|
+
services:
|
|
242
|
+
frontend:
|
|
243
|
+
networks:
|
|
244
|
+
- frontend
|
|
245
|
+
|
|
246
|
+
api:
|
|
247
|
+
networks:
|
|
248
|
+
- frontend
|
|
249
|
+
- backend
|
|
250
|
+
|
|
251
|
+
db:
|
|
252
|
+
networks:
|
|
253
|
+
- backend
|
|
254
|
+
|
|
255
|
+
networks:
|
|
256
|
+
frontend:
|
|
257
|
+
driver: bridge
|
|
258
|
+
backend:
|
|
259
|
+
driver: bridge
|
|
260
|
+
internal: true # No external access
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Best Practices
|
|
264
|
+
|
|
265
|
+
### Image Size Optimization
|
|
266
|
+
|
|
267
|
+
```dockerfile
|
|
268
|
+
# Use alpine base images
|
|
269
|
+
FROM node:20-alpine # ~180MB vs node:20 ~1GB
|
|
270
|
+
|
|
271
|
+
# Combine RUN commands
|
|
272
|
+
RUN apt-get update && \
|
|
273
|
+
apt-get install -y --no-install-recommends curl && \
|
|
274
|
+
rm -rf /var/lib/apt/lists/*
|
|
275
|
+
|
|
276
|
+
# Use .dockerignore
|
|
277
|
+
# .dockerignore
|
|
278
|
+
node_modules
|
|
279
|
+
.git
|
|
280
|
+
*.md
|
|
281
|
+
.env*
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Security
|
|
285
|
+
|
|
286
|
+
```dockerfile
|
|
287
|
+
# Don't run as root
|
|
288
|
+
USER node
|
|
289
|
+
|
|
290
|
+
# Use specific versions
|
|
291
|
+
FROM node:20.10.0-alpine3.19
|
|
292
|
+
|
|
293
|
+
# Scan images
|
|
294
|
+
# docker scout cves myapp:latest
|
|
295
|
+
|
|
296
|
+
# Don't store secrets in images
|
|
297
|
+
# Use Docker secrets or environment variables at runtime
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Layer Caching
|
|
301
|
+
|
|
302
|
+
```dockerfile
|
|
303
|
+
# Order from least to most frequently changed
|
|
304
|
+
COPY package*.json ./
|
|
305
|
+
RUN npm ci
|
|
306
|
+
COPY . . # Application code last
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Development vs Production
|
|
310
|
+
|
|
311
|
+
```dockerfile
|
|
312
|
+
# Dockerfile.dev
|
|
313
|
+
FROM node:20-alpine
|
|
314
|
+
WORKDIR /app
|
|
315
|
+
COPY package*.json ./
|
|
316
|
+
RUN npm install # Include devDependencies
|
|
317
|
+
COPY . .
|
|
318
|
+
CMD ["npm", "run", "dev"]
|
|
319
|
+
|
|
320
|
+
# Dockerfile (production)
|
|
321
|
+
FROM node:20-alpine AS builder
|
|
322
|
+
WORKDIR /app
|
|
323
|
+
COPY package*.json ./
|
|
324
|
+
RUN npm ci
|
|
325
|
+
COPY . .
|
|
326
|
+
RUN npm run build
|
|
327
|
+
|
|
328
|
+
FROM node:20-alpine
|
|
329
|
+
WORKDIR /app
|
|
330
|
+
COPY --from=builder /app/dist ./dist
|
|
331
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
332
|
+
USER node
|
|
333
|
+
CMD ["node", "dist/server.js"]
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Debugging
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
# Shell into running container
|
|
340
|
+
docker exec -it myapp sh
|
|
341
|
+
|
|
342
|
+
# Shell into stopped container
|
|
343
|
+
docker run -it --entrypoint sh myapp:latest
|
|
344
|
+
|
|
345
|
+
# Copy files from container
|
|
346
|
+
docker cp myapp:/app/logs ./logs
|
|
347
|
+
|
|
348
|
+
# View container processes
|
|
349
|
+
docker top myapp
|
|
350
|
+
|
|
351
|
+
# Inspect layers
|
|
352
|
+
docker history myapp:latest
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## References
|
|
356
|
+
|
|
357
|
+
- Docker Documentation: https://docs.docker.com/
|
|
358
|
+
- Dockerfile Best Practices: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
|
|
359
|
+
- Docker Compose: https://docs.docker.com/compose/
|