@rashidee/co2 1.2.5
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/dist/index.js +25449 -0
- package/drizzle/0000_remarkable_charles_xavier.sql +210 -0
- package/drizzle/0001_wise_wolf_cub.sql +13 -0
- package/drizzle/0002_secret_spyke.sql +16 -0
- package/drizzle/0003_workspace_config_singleton.sql +16 -0
- package/drizzle/0004_terminal_claim_v120.sql +11 -0
- package/drizzle/0005_brainstorm_v124.sql +10 -0
- package/drizzle/0006_project_v140.sql +6 -0
- package/drizzle/0007_prd_wizard_v124.sql +14 -0
- package/drizzle/0008_workflow_artifact_v126.sql +24 -0
- package/drizzle/0009_project_import_v150.sql +7 -0
- package/drizzle/0010_quality_v151.sql +3 -0
- package/drizzle/meta/0000_snapshot.json +1335 -0
- package/drizzle/meta/0001_snapshot.json +1416 -0
- package/drizzle/meta/0002_snapshot.json +1510 -0
- package/drizzle/meta/_journal.json +83 -0
- package/package.json +41 -0
- package/plugin/.claude-plugin/marketplace.json +36 -0
- package/plugin/.claude-plugin/plugin.json +22 -0
- package/plugin/README.md +625 -0
- package/plugin/SKILLS.md +350 -0
- package/plugin/co2.svg +5 -0
- package/plugin/commands/brainstorm-loop.md +129 -0
- package/plugin/skills/conductor-defect/SKILL.md +898 -0
- package/plugin/skills/conductor-feature-develop/SKILL.md +1383 -0
- package/plugin/skills/conductor-feature-develop/references/implementation-domain-template.md +131 -0
- package/plugin/skills/conductor-feature-develop/references/implementation-master-template.md +89 -0
- package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +224 -0
- package/plugin/skills/conductor-feature-prepare/SKILL.md +604 -0
- package/plugin/skills/depgen-k8s/SKILL.md +468 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-laravel.md +197 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-nodejs.md +163 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-spring-boot.md +174 -0
- package/plugin/skills/depgen-k8s/references/k8s-patterns.md +869 -0
- package/plugin/skills/mockgen-shadcn/SKILL.md +1067 -0
- package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +1467 -0
- package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +498 -0
- package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +216 -0
- package/plugin/skills/mockgen-tailwind/SKILL.md +904 -0
- package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +720 -0
- package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +498 -0
- package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -0
- package/plugin/skills/modelgen-nosql/SKILL.md +617 -0
- package/plugin/skills/modelgen-nosql/references/model-extraction-methodology.md +497 -0
- package/plugin/skills/modelgen-nosql/references/nosql-design-guide.md +258 -0
- package/plugin/skills/modelgen-relational/SKILL.md +707 -0
- package/plugin/skills/modelgen-relational/references/model-extraction-methodology.md +499 -0
- package/plugin/skills/specgen-flutter-riverpod/SKILL.md +898 -0
- package/plugin/skills/specgen-flutter-riverpod/references/component-patterns.md +971 -0
- package/plugin/skills/specgen-flutter-riverpod/references/notification-patterns.md +457 -0
- package/plugin/skills/specgen-flutter-riverpod/references/routing-patterns.md +362 -0
- package/plugin/skills/specgen-flutter-riverpod/references/security-patterns.md +709 -0
- package/plugin/skills/specgen-flutter-riverpod/references/spec-template.md +1566 -0
- package/plugin/skills/specgen-flutter-riverpod/references/state-patterns.md +518 -0
- package/plugin/skills/specgen-flutter-riverpod/references/storage-patterns.md +370 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/SKILL.md +984 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/batch-patterns.md +359 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/messaging-patterns.md +468 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/modulith-patterns.md +461 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/reporting-patterns.md +803 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/security-patterns.md +501 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/spec-template.md +1268 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/web-patterns.md +301 -0
- package/plugin/skills/specgen-node-cli-web/SKILL.md +561 -0
- package/plugin/skills/specgen-node-cli-web/references/auth-patterns.md +293 -0
- package/plugin/skills/specgen-node-cli-web/references/cli-packaging-patterns.md +250 -0
- package/plugin/skills/specgen-node-cli-web/references/server-patterns.md +247 -0
- package/plugin/skills/specgen-node-cli-web/references/spec-template.md +401 -0
- package/plugin/skills/specgen-node-cli-web/references/testing-patterns.md +174 -0
- package/plugin/skills/specgen-react-mui/SKILL.md +789 -0
- package/plugin/skills/specgen-react-mui/references/component-patterns.md +1077 -0
- package/plugin/skills/specgen-react-mui/references/reporting-patterns.md +1998 -0
- package/plugin/skills/specgen-react-mui/references/routing-patterns.md +461 -0
- package/plugin/skills/specgen-react-mui/references/security-patterns.md +599 -0
- package/plugin/skills/specgen-react-mui/references/spec-template.md +1030 -0
- package/plugin/skills/specgen-react-mui/references/state-patterns.md +327 -0
- package/plugin/skills/specgen-react-tailwind/SKILL.md +859 -0
- package/plugin/skills/specgen-react-tailwind/references/component-patterns.md +1212 -0
- package/plugin/skills/specgen-react-tailwind/references/reporting-patterns.md +1529 -0
- package/plugin/skills/specgen-react-tailwind/references/routing-patterns.md +669 -0
- package/plugin/skills/specgen-react-tailwind/references/security-patterns.md +656 -0
- package/plugin/skills/specgen-react-tailwind/references/spec-template.md +1237 -0
- package/plugin/skills/specgen-react-tailwind/references/state-patterns.md +327 -0
- package/plugin/skills/specgen-sdk-java/SKILL.md +933 -0
- package/plugin/skills/specgen-sdk-java/references/api-extraction-patterns.md +247 -0
- package/plugin/skills/specgen-sdk-java/references/http-client-patterns.md +495 -0
- package/plugin/skills/specgen-sdk-java/references/packaging-patterns.md +366 -0
- package/plugin/skills/specgen-sdk-java/references/spec-template.md +956 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/SKILL.md +1284 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/batch-patterns.md +1224 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/jasper-patterns.md +1638 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/messaging-patterns.md +512 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/modulith-patterns.md +354 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/security-patterns.md +551 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/spec-template.md +2502 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/web-patterns.md +503 -0
- package/plugin/skills/specgen-spring-jpa-restapi/SKILL.md +990 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/batch-patterns.md +1224 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/messaging-patterns.md +512 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/modulith-patterns.md +279 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/reporting-patterns.md +1536 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/restapi-patterns.md +722 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/security-patterns.md +351 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/spec-template.md +553 -0
- package/plugin/skills/specgen-ts-cli/SKILL.md +861 -0
- package/plugin/skills/specgen-ts-cli/references/async-patterns.md +1101 -0
- package/plugin/skills/specgen-ts-cli/references/command-patterns.md +383 -0
- package/plugin/skills/specgen-ts-cli/references/config-patterns.md +430 -0
- package/plugin/skills/specgen-ts-cli/references/database-patterns.md +750 -0
- package/plugin/skills/specgen-ts-cli/references/packaging-patterns.md +426 -0
- package/plugin/skills/specgen-ts-cli/references/spec-template.md +1391 -0
- package/plugin/skills/specgen-ts-cli/references/testing-patterns.md +909 -0
- package/plugin/skills/testgen-functional/SKILL.md +1381 -0
- package/plugin/skills/tracegen-matrix/SKILL.md +243 -0
- package/plugin/skills/util-preparek8senv/SKILL.md +422 -0
- package/plugin/skills/util-projectinit/SKILL.md +307 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-loop.md +129 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-protocol.md +144 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-setup-guide.md +153 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-template-appdev.md +87 -0
- package/plugin/skills/util-projectinit/reference/co2-context-generation-guide.md +761 -0
- package/plugin/skills/util-projectsync/SKILL.md +501 -0
- package/plugin/skills/util-updprd/SKILL.md +324 -0
- package/plugin/skills/util-usanalyzer/SKILL.md +307 -0
- package/plugin/skills/util-ustagger/SKILL.md +154 -0
- package/static/assets/abnfDiagram-VRR7QNED-DvPuwyCV.js +1 -0
- package/static/assets/arc-DRKw7sjs.js +1 -0
- package/static/assets/architectureDiagram-ZJ3FMSHR-CaNcxUbC.js +36 -0
- package/static/assets/blockDiagram-677ZJIJ3-Demd4AOK.js +132 -0
- package/static/assets/c4Diagram-LMCZKHZV-PVKUfc2x.js +10 -0
- package/static/assets/channel-C2nVbuwv.js +1 -0
- package/static/assets/chunk-2Q5K7J3B-CExf8ww_.js +1 -0
- package/static/assets/chunk-32BRIVSS-CFPaoONF.js +1 -0
- package/static/assets/chunk-5VM5RSS4-DE2esM67.js +15 -0
- package/static/assets/chunk-EX3LRPZG-SON_YdDG.js +231 -0
- package/static/assets/chunk-JWPE2WC7-Qxah8LNr.js +1 -0
- package/static/assets/chunk-MOJQB5TN-BcWGQV3j.js +88 -0
- package/static/assets/chunk-RYQCIY6F-DkDj-OR5.js +1 -0
- package/static/assets/chunk-V7JOEXUC-BlI1Mrah.js +206 -0
- package/static/assets/chunk-VR4S4FIN-Agf__duj.js +1 -0
- package/static/assets/chunk-XXDRQBXY-B5CfAh85.js +1 -0
- package/static/assets/classDiagram-OUVF2IWQ-DXJIljsR.js +1 -0
- package/static/assets/classDiagram-v2-EOCWNBFH-DXJIljsR.js +1 -0
- package/static/assets/cose-bilkent-JH36ORCC-DO0cQkcy.js +1 -0
- package/static/assets/cynefin-VYW2F7L2-CfOnsnXc.js +178 -0
- package/static/assets/cynefinDiagram-TSTJHNR4-BJ8tULAv.js +62 -0
- package/static/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
- package/static/assets/dagre-VKFMJZFB-DfjwzHqP.js +4 -0
- package/static/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/static/assets/diagram-FQU43EPY-CndSOIIM.js +3 -0
- package/static/assets/diagram-G47NLZAW-Czf5hN0Z.js +24 -0
- package/static/assets/diagram-NH7WQ7WH-COAyojGh.js +24 -0
- package/static/assets/diagram-OA4YK3LP-H8PoiN2m.js +30 -0
- package/static/assets/diagram-WEI45ONY-DzcaVzjp.js +41 -0
- package/static/assets/ebnfDiagram-CCIWWBDH-DPazGYLJ.js +1 -0
- package/static/assets/erDiagram-Q63AITRT-Bo-fubgF.js +85 -0
- package/static/assets/flowDiagram-23GEKE2U-CSvxUDwh.js +156 -0
- package/static/assets/ganttDiagram-NO4QXBWP-DnBveWX6.js +292 -0
- package/static/assets/gitGraphDiagram-IHSO6WYX-B3rVL8c-.js +106 -0
- package/static/assets/graph-C9eacEi8.js +1 -0
- package/static/assets/index-LZSQkLE2.css +41 -0
- package/static/assets/index-y7XDSgMG.js +495 -0
- package/static/assets/infoDiagram-FWYZ7A6U-CvWV9yy2.js +2 -0
- package/static/assets/init-Gi6I4Gst.js +1 -0
- package/static/assets/ishikawaDiagram-FXEZZL3T-DF28a1N6.js +70 -0
- package/static/assets/journeyDiagram-5HDEW3XC-CB6CugYk.js +139 -0
- package/static/assets/kanban-definition-HUTT4EX6-ResSLF6d.js +89 -0
- package/static/assets/katex-C5jXJg4s.js +257 -0
- package/static/assets/layout-DEXfKzaS.js +1 -0
- package/static/assets/linear-CLO--ryk.js +1 -0
- package/static/assets/map-Czzmt4hB.js +1 -0
- package/static/assets/mindmap-definition-LN4V7U3C-BvW3EbxX.js +96 -0
- package/static/assets/ordinal-Cboi1Yqb.js +1 -0
- package/static/assets/pegDiagram-2B236MQR-BHCgqrrM.js +1 -0
- package/static/assets/pieDiagram-ENE6RG2P-DVmCQ5FA.js +39 -0
- package/static/assets/quadrantDiagram-ABIIQ3AL-B3e5KR52.js +7 -0
- package/static/assets/railroadDiagram-RFXS5EU6-Csv5ysLc.js +1 -0
- package/static/assets/requirementDiagram-TGXJPOKE-DOMVzvnB.js +84 -0
- package/static/assets/sankeyDiagram-HTMAVEWB-B1dcTOvy.js +40 -0
- package/static/assets/sequenceDiagram-DBY2YBRQ-BY414yeO.js +162 -0
- package/static/assets/sizeCapture-X5ZJPWSS-CuJfrfBN.js +1 -0
- package/static/assets/stateDiagram-2N3HPSRC-FX4rJkzV.js +1 -0
- package/static/assets/stateDiagram-v2-6OUMAXLB-BVufbO_H.js +1 -0
- package/static/assets/swimlanes-5IMT3BWC-Sfy58mmv.js +2 -0
- package/static/assets/swimlanesDiagram-G3AALYLV-wDCDw08H.js +8 -0
- package/static/assets/timeline-definition-FHXFAJF6-CmV7by8p.js +120 -0
- package/static/assets/vennDiagram-L72KCM5P-FqIyFZFt.js +34 -0
- package/static/assets/wardleyDiagram-EHGQE667-BZ06O45i.js +78 -0
- package/static/assets/xychartDiagram-FW5EYKEG-BOkffR06.js +7 -0
- package/static/index.html +24 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: depgen-k8s
|
|
3
|
+
model: claude-sonnet-4-6
|
|
4
|
+
effort: high
|
|
5
|
+
description: >
|
|
6
|
+
Generate a Dockerfile and Kubernetes manifests for an application targeting a single
|
|
7
|
+
environment. Supports Spring Boot (Java), Laravel (PHP), and Node.js application stacks.
|
|
8
|
+
Auto-detects the stack from project files (pom.xml, composer.json, package.json), reads
|
|
9
|
+
CLAUDE.md dependencies, SPECIFICATION.md tech stack, and the application's externalized
|
|
10
|
+
environment variables. Generates a Dockerfile in the application root folder and Kubernetes
|
|
11
|
+
manifest YAML files directly in `<app_folder>/k8s/` (no per-environment subfolders — the
|
|
12
|
+
k8s/ folder is gitignored, each machine maintains its own copy).
|
|
13
|
+
Standardized input: application name (mandatory), environment (optional).
|
|
14
|
+
Use this skill whenever the user asks to create deployment artifacts, Dockerfiles,
|
|
15
|
+
Kubernetes manifests, or containerize an application. Also trigger when the user says
|
|
16
|
+
things like "deploy this app", "containerize this", "create a Dockerfile",
|
|
17
|
+
"generate k8s manifests", or any request for deployment-related artifacts.
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Deployment Artifact Generator — Kubernetes
|
|
21
|
+
|
|
22
|
+
This skill generates deployment artifacts for a custom application:
|
|
23
|
+
|
|
24
|
+
1. **Dockerfile** — A production-ready, multi-stage container build file placed in the
|
|
25
|
+
application root folder.
|
|
26
|
+
2. **Kubernetes manifests** — Manifest files stored directly in the application's own
|
|
27
|
+
`k8s/` folder for a **single target environment**. Since the `k8s/` folder is gitignored,
|
|
28
|
+
each machine maintains its own independent copy of the manifests with environment-specific
|
|
29
|
+
ConfigMap/Secret values (hostnames, credentials, resource limits).
|
|
30
|
+
|
|
31
|
+
**Note:** Only custom applications (from `# Custom Applications` in CLAUDE.md) are processed.
|
|
32
|
+
3rd party supporting applications and external services are NOT containerized by this skill.
|
|
33
|
+
|
|
34
|
+
## Inputs
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
/depgen-k8s <application> [environment]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Argument | Required | Example | Description |
|
|
41
|
+
|----------|----------|---------|-------------|
|
|
42
|
+
| `<application>` | Yes | `hub_middleware` | Application name — must be a custom application from CLAUDE.md |
|
|
43
|
+
| `<environment>` | No | `home_server` | Target environment name — must match a Kubernetes environment in CLAUDE.md |
|
|
44
|
+
|
|
45
|
+
If `<environment>` is omitted:
|
|
46
|
+
- If CLAUDE.md defines exactly **one** Kubernetes environment → auto-select it.
|
|
47
|
+
- If CLAUDE.md defines **multiple** Kubernetes environments → list them and ask the user to specify.
|
|
48
|
+
|
|
49
|
+
The environment name is matched **case-insensitively** against the environment headings in CLAUDE.md, accepting snake_case, kebab-case, or title-case input (e.g., `home_server`, `home-server`, `Home Server`).
|
|
50
|
+
|
|
51
|
+
No `version:` or `module:` arguments — deployment is application-level.
|
|
52
|
+
|
|
53
|
+
### Input Resolution
|
|
54
|
+
|
|
55
|
+
The application name is matched against root-level application folders:
|
|
56
|
+
1. Strip any leading `<number>_` prefix from folder names (e.g., `1_hub_middleware` → `hub_middleware`)
|
|
57
|
+
2. Match case-insensitively against the provided application name
|
|
58
|
+
3. Accept snake_case, kebab-case, or title-case input
|
|
59
|
+
4. Verify the application is listed under `# Custom Applications` in CLAUDE.md — reject if it is a 3rd party application or external service
|
|
60
|
+
5. If no match found, list available custom applications and stop
|
|
61
|
+
|
|
62
|
+
### Auto-Resolved Paths
|
|
63
|
+
|
|
64
|
+
| File | Resolved Path |
|
|
65
|
+
|------|---------------|
|
|
66
|
+
| CLAUDE.md | Project root `CLAUDE.md` |
|
|
67
|
+
| ENVIRONMENT.md | Project root `ENVIRONMENT.md` |
|
|
68
|
+
| SPECIFICATION.md | `<app_folder>/context/specification/SPECIFICATION.md` |
|
|
69
|
+
| Source code | `<app_folder>/` (pom.xml, composer.json, package.json, etc.) |
|
|
70
|
+
| Application config | Stack-dependent (see detection) |
|
|
71
|
+
| K8s manifests output | `<app_folder>/k8s/` (gitignored — each machine maintains its own copy) |
|
|
72
|
+
|
|
73
|
+
## PRD.md Extended Sections
|
|
74
|
+
|
|
75
|
+
Before generating deployment artifacts, check PRD.md for the following extended sections:
|
|
76
|
+
|
|
77
|
+
### Architecture Principle
|
|
78
|
+
|
|
79
|
+
If PRD.md contains an `# Architecture Principle` section, extract patterns that affect deployment:
|
|
80
|
+
|
|
81
|
+
| Pattern | Deployment Impact |
|
|
82
|
+
|---|---|
|
|
83
|
+
| "Stateless" | Deployment uses `RollingUpdate` strategy without sticky sessions; no PVC needed for session storage |
|
|
84
|
+
| "Container based deployment" | Validates this skill's applicability |
|
|
85
|
+
| "Scale out" / "horizontally scalable" | Generate HorizontalPodAutoscaler (HPA) manifest targeting CPU 70% |
|
|
86
|
+
| Specific resource constraints (e.g., "max 256Mi per pod") | Use as default resource limits in K8s manifests |
|
|
87
|
+
| "Message driven" / "message queue" | Readiness probe should verify message queue connectivity |
|
|
88
|
+
|
|
89
|
+
If absent, use defaults from SPECIFICATION.md and CLAUDE.md (existing behavior).
|
|
90
|
+
|
|
91
|
+
### High Level Process Flow
|
|
92
|
+
|
|
93
|
+
If PRD.md contains a `# High Level Process Flow` section:
|
|
94
|
+
- Process flows reveal inter-system dependencies (message queues, external service endpoints)
|
|
95
|
+
- Validate that the environment variable list and ConfigMap/Secret values include all dependencies mentioned in process flows
|
|
96
|
+
- If a flow references an external system not in the `Depends on` list, log a warning
|
|
97
|
+
|
|
98
|
+
If absent, derive dependencies from CLAUDE.md only (existing behavior).
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Pre-Requisites
|
|
103
|
+
|
|
104
|
+
Before running this skill, the following must exist:
|
|
105
|
+
- **Source code** — The application must be implemented (not just context artifacts)
|
|
106
|
+
- **SPECIFICATION.md** — The technical specification must exist (generated by a `specgen-*` skill)
|
|
107
|
+
- **Externalized configuration** — The application config must use environment variables
|
|
108
|
+
(e.g., `${ENV_VAR:default}` in Spring Boot, `env('VAR')` in Laravel, `process.env.VAR` in Node.js)
|
|
109
|
+
|
|
110
|
+
If any are missing, stop and inform the user.
|
|
111
|
+
|
|
112
|
+
## Workflow
|
|
113
|
+
|
|
114
|
+
### Phase 0: Validate Inputs
|
|
115
|
+
|
|
116
|
+
1. Resolve application folder from the provided name
|
|
117
|
+
2. Verify the application is a custom application in CLAUDE.md (not 3rd party or external service)
|
|
118
|
+
3. Verify source code exists (at least one of: `pom.xml`, `composer.json`, `package.json`)
|
|
119
|
+
4. Verify `<app_folder>/context/specification/SPECIFICATION.md` exists
|
|
120
|
+
5. Read `CLAUDE.md` (already in context) for project-level information
|
|
121
|
+
6. **Detect environments** from CLAUDE.md's `# Environment` section:
|
|
122
|
+
- Each `## <Environment Name>` heading under `# Environment` is an environment
|
|
123
|
+
- For each environment, extract:
|
|
124
|
+
- Environment name (e.g., "Home Server")
|
|
125
|
+
- `Domain` field (e.g., `localhost`, `home.server`)
|
|
126
|
+
- `Deployment Type` field (e.g., `Manual`, `Kubernetes`)
|
|
127
|
+
- `IP` field (from SSH Configuration or direct IP field) if present — needed for `hostAliases` generation in Phase 3
|
|
128
|
+
- If no environments are defined, stop with error: "No environments found in CLAUDE.md `# Environment` section."
|
|
129
|
+
|
|
130
|
+
7. **Select target environment** — filter to Kubernetes environments and select one:
|
|
131
|
+
1. Filter environments to those with `Deployment Type: Kubernetes`.
|
|
132
|
+
2. If no environment has `Deployment Type: Kubernetes`, stop with error: "No Kubernetes environments found in CLAUDE.md. This skill only generates K8s manifests for environments with Deployment Type: Kubernetes."
|
|
133
|
+
3. If the user provided an `<environment>` argument, match it against the Kubernetes environments (case-insensitively, accepting snake_case, kebab-case, or title-case).
|
|
134
|
+
- If matched → use it as the target environment.
|
|
135
|
+
- If not matched → list available Kubernetes environments and stop.
|
|
136
|
+
4. If no argument was provided:
|
|
137
|
+
- If exactly **one** Kubernetes environment exists → auto-select it.
|
|
138
|
+
- If **multiple** exist → list them and ask the user to specify.
|
|
139
|
+
5. Record the selected environment's Domain and IP for Phase 3.
|
|
140
|
+
|
|
141
|
+
### Phase 1: Detect Application Stack
|
|
142
|
+
|
|
143
|
+
#### Step 1 — Identify Stack
|
|
144
|
+
|
|
145
|
+
Check the application root for build files:
|
|
146
|
+
|
|
147
|
+
| File Found | Stack | Build Tool |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| `pom.xml` | `spring-boot` | Maven |
|
|
150
|
+
| `composer.json` | `laravel` | Composer |
|
|
151
|
+
| `package.json` (no `pom.xml` or `composer.json`) | `nodejs` | npm / pnpm |
|
|
152
|
+
|
|
153
|
+
If none found, stop with error: "Cannot determine application stack."
|
|
154
|
+
|
|
155
|
+
If multiple found (e.g., `pom.xml` + `package.json`), prioritize: `pom.xml` > `composer.json` > `package.json`
|
|
156
|
+
(the `package.json` is likely for frontend or E2E tests, not the main app).
|
|
157
|
+
|
|
158
|
+
#### Step 2 — Extract Stack-Specific Metadata
|
|
159
|
+
|
|
160
|
+
**If `spring-boot`:**
|
|
161
|
+
- Read `pom.xml`:
|
|
162
|
+
- `<java.version>` → JDK version for base image
|
|
163
|
+
- `<artifactId>` → image name
|
|
164
|
+
- `<version>` → image tag
|
|
165
|
+
- `frontend-maven-plugin` presence → has frontend build step
|
|
166
|
+
- `jte-maven-plugin` presence → has JTE precompilation
|
|
167
|
+
- `spring-boot-maven-plugin` → executable JAR packaging
|
|
168
|
+
- Read `src/main/resources/application.yml`:
|
|
169
|
+
- Extract all `${ENV_VAR:default}` patterns via regex `\$\{([^:}]+)(?::([^}]*))?\}`
|
|
170
|
+
- `server.port` default → exposed container port
|
|
171
|
+
- Read `.env` (if exists) → local dev values for reference
|
|
172
|
+
|
|
173
|
+
**If `laravel`:**
|
|
174
|
+
- Read `composer.json`:
|
|
175
|
+
- `require.php` → PHP version for base image
|
|
176
|
+
- `require.laravel/framework` → Laravel version
|
|
177
|
+
- `name` → image name
|
|
178
|
+
- Read `.env.example` or scan `config/*.php`:
|
|
179
|
+
- Extract all `env('VAR', 'default')` patterns via regex `env\('([^']+)'(?:,\s*'?([^')*]*)'?)?\)`
|
|
180
|
+
- `APP_PORT` or default `8000` → exposed container port
|
|
181
|
+
- Check for `vite.config.js` or `webpack.mix.js` → has frontend build step
|
|
182
|
+
- Check for `package.json` in app root → Node.js needed for frontend build
|
|
183
|
+
|
|
184
|
+
**If `nodejs`:**
|
|
185
|
+
- Read `package.json`:
|
|
186
|
+
- `engines.node` → Node.js version for base image
|
|
187
|
+
- `name` → image name
|
|
188
|
+
- `version` → image tag
|
|
189
|
+
- `scripts.build` → build command (e.g., `tsc`, `tsup`, `vite build`, `next build`)
|
|
190
|
+
- `scripts.start` → start command
|
|
191
|
+
- Scan source files or `.env` for `process.env.VAR` patterns
|
|
192
|
+
- Check for `tsconfig.json` → TypeScript build step
|
|
193
|
+
- Determine framework: Express, Fastify, NestJS, Next.js, etc.
|
|
194
|
+
|
|
195
|
+
#### Step 3 — Common Detection (All Stacks)
|
|
196
|
+
|
|
197
|
+
From `CLAUDE.md` → extract the "Depends on" list for the target application:
|
|
198
|
+
|
|
199
|
+
| Dependency Pattern | External Service |
|
|
200
|
+
|---|---|
|
|
201
|
+
| References MongoDB | MongoDB required |
|
|
202
|
+
| References MySQL / HC Database / SC Database | MySQL required |
|
|
203
|
+
| References PostgreSQL | PostgreSQL required |
|
|
204
|
+
| References Hub Single Sign On / Keycloak | Keycloak required |
|
|
205
|
+
| References RabbitMQ / Message Queue | RabbitMQ required |
|
|
206
|
+
| References Redis / Hub Cache | Redis required |
|
|
207
|
+
| References SMTP / Mailcatcher | SMTP service required |
|
|
208
|
+
| References Meilisearch / Hub Search Engine | Meilisearch required |
|
|
209
|
+
|
|
210
|
+
From `SPECIFICATION.md` → extract:
|
|
211
|
+
- Technology stack table (versions)
|
|
212
|
+
- Environment variable reference table (if present)
|
|
213
|
+
|
|
214
|
+
#### Step 4 — Classify Environment Variables
|
|
215
|
+
|
|
216
|
+
For each detected environment variable, classify as ConfigMap or Secret:
|
|
217
|
+
|
|
218
|
+
**Secret** (sensitive — stored in K8s Secret):
|
|
219
|
+
- Variable name contains `PASSWORD`, `SECRET`, `KEY`, `TOKEN`, `CREDENTIAL`
|
|
220
|
+
- Variable name contains `ADMIN_USERNAME` (admin-level credentials)
|
|
221
|
+
- Variable name is a database connection URI containing credentials
|
|
222
|
+
|
|
223
|
+
**ConfigMap** (non-sensitive — stored in K8s ConfigMap):
|
|
224
|
+
- Everything else: hostnames, ports, log levels, feature flags, queue names, CORS origins
|
|
225
|
+
|
|
226
|
+
#### Step 5 — Determine Health Check
|
|
227
|
+
|
|
228
|
+
| Stack | Default Health Endpoint | Condition |
|
|
229
|
+
|---|---|---|
|
|
230
|
+
| Spring Boot | `/actuator/health` | If `spring-boot-starter-actuator` in pom.xml |
|
|
231
|
+
| Spring Boot | `/` (HTTP 200/302 check) | If no actuator |
|
|
232
|
+
| Laravel | `/health` or `/` | Custom route or root |
|
|
233
|
+
| Node.js | `/health` or `/` | Custom route or root |
|
|
234
|
+
|
|
235
|
+
Check if a health endpoint is explicitly defined in the source code. If not, use the
|
|
236
|
+
default for the stack.
|
|
237
|
+
|
|
238
|
+
#### Step 6 — Present Detection Summary
|
|
239
|
+
|
|
240
|
+
Before generating, present findings to the user for confirmation:
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
Application Stack Detection:
|
|
244
|
+
- Stack: Spring Boot 3.5.7 (Java 21)
|
|
245
|
+
- Artifact: hub-middleware:1.0.3
|
|
246
|
+
- Frontend Build: Yes (Vite via frontend-maven-plugin)
|
|
247
|
+
- JTE Precompile: Yes (jte-maven-plugin)
|
|
248
|
+
- Exposed Port: 8080
|
|
249
|
+
- Health Check: /actuator/health (actuator present)
|
|
250
|
+
|
|
251
|
+
External Services:
|
|
252
|
+
- MongoDB 7.0.6 (Hub Core Database)
|
|
253
|
+
- Keycloak 26.5.3 (Hub Single Sign On)
|
|
254
|
+
- RabbitMQ 3.11.9 (HC + SC Adapter Message Queues)
|
|
255
|
+
- Mailcatcher 0.8.1 (SMTP)
|
|
256
|
+
|
|
257
|
+
Environment Variables: 25 detected
|
|
258
|
+
- ConfigMap: 18 (hostnames, ports, log levels, queue names, flags)
|
|
259
|
+
- Secret: 7 (passwords, admin credentials)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
If the user disagrees, allow overrides before proceeding.
|
|
263
|
+
|
|
264
|
+
### Phase 2: Generate or Update Dockerfile
|
|
265
|
+
|
|
266
|
+
1. Check if `<app_folder>/Dockerfile` already exists
|
|
267
|
+
2. **If it exists** (UPDATE mode):
|
|
268
|
+
- Read the existing Dockerfile
|
|
269
|
+
- Compare detected values against what the Dockerfile currently has:
|
|
270
|
+
- Base image version (e.g., Java version changed in pom.xml)
|
|
271
|
+
- Exposed port (e.g., server.port default changed)
|
|
272
|
+
- Environment variable defaults (e.g., new env vars added)
|
|
273
|
+
- Build commands (e.g., frontend build step added or removed)
|
|
274
|
+
- Preserve any lines marked with `# CUSTOM:` comments — these are manual overrides
|
|
275
|
+
by the user/DevOps that should not be replaced
|
|
276
|
+
- Update only the parts that changed, keeping the overall structure intact
|
|
277
|
+
- Log what was changed (e.g., "Updated Java version from 17 to 21",
|
|
278
|
+
"Added MAIL_HOST env var")
|
|
279
|
+
3. **If it does not exist** (CREATE mode):
|
|
280
|
+
- Select the Dockerfile pattern from `references/dockerfile-<stack>.md`
|
|
281
|
+
- Substitute detected values (Java version, artifact name, port, etc.)
|
|
282
|
+
- Write the Dockerfile to `<app_folder>/Dockerfile`
|
|
283
|
+
|
|
284
|
+
The Dockerfile MUST:
|
|
285
|
+
- Use a **multi-stage build** (build stage + runtime stage)
|
|
286
|
+
- Use **specific version tags** for base images (not `latest`)
|
|
287
|
+
- Run as a **non-root user** in the runtime stage
|
|
288
|
+
- **NOT** copy `.env`, `context/`, `e2e/`, or test files into the image
|
|
289
|
+
- Include a `HEALTHCHECK` instruction if a health endpoint is available
|
|
290
|
+
- Include comments explaining each significant instruction
|
|
291
|
+
- Include a `LABEL version="{version}"` instruction using the application version extracted
|
|
292
|
+
from `pom.xml` (`<version>`), `composer.json` (`version`), or `package.json` (`version`)
|
|
293
|
+
- Include a build argument `ARG APP_VERSION={version}` that can be overridden at build time
|
|
294
|
+
via `docker build --build-arg APP_VERSION=1.0.3`
|
|
295
|
+
|
|
296
|
+
Read `references/dockerfile-spring-boot.md`, `references/dockerfile-laravel.md`, or
|
|
297
|
+
`references/dockerfile-nodejs.md` for the complete Dockerfile template per stack.
|
|
298
|
+
|
|
299
|
+
### Phase 3: Generate or Update Kubernetes Manifests
|
|
300
|
+
|
|
301
|
+
Kubernetes manifests are stored directly in `<app_folder>/k8s/` (no per-environment
|
|
302
|
+
subfolders). Since the `k8s/` folder is gitignored, each machine maintains its own
|
|
303
|
+
independent copy with values specific to the target environment selected in Phase 0.
|
|
304
|
+
|
|
305
|
+
#### 3a. Ensure Folder Structure
|
|
306
|
+
|
|
307
|
+
1. Check if `<app_folder>/k8s/` exists. If not, create it.
|
|
308
|
+
|
|
309
|
+
Example folder structure:
|
|
310
|
+
```
|
|
311
|
+
hub_middleware/
|
|
312
|
+
Dockerfile
|
|
313
|
+
k8s/
|
|
314
|
+
namespace.yaml
|
|
315
|
+
configmap.yaml
|
|
316
|
+
secret.yaml
|
|
317
|
+
deployment.yaml
|
|
318
|
+
service.yaml
|
|
319
|
+
ingress.yaml (optional)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
#### 3b. Generate Manifests
|
|
323
|
+
|
|
324
|
+
Generate individual YAML files inside `<app_folder>/k8s/` using values from the target
|
|
325
|
+
environment selected in Phase 0:
|
|
326
|
+
|
|
327
|
+
1. **`namespace.yaml`** — Namespace resource (use project code from CLAUDE.md in lowercase,
|
|
328
|
+
e.g., `urp`). Shared across all applications — identical content for every environment.
|
|
329
|
+
2. **`configmap.yaml`** — Non-sensitive environment variables (from Step 4 classification).
|
|
330
|
+
Values may differ per environment — use defaults from `.env` for local development;
|
|
331
|
+
use `TODO` placeholders for other environments where values are not known.
|
|
332
|
+
3. **`secret.yaml`** — Sensitive environment variables (from Step 4 classification),
|
|
333
|
+
base64-encoded. Values use `TODO` placeholders for all non-local environments.
|
|
334
|
+
4. **`deployment.yaml`** — Container spec with:
|
|
335
|
+
- Versioned image tag (e.g., `image: hub-middleware:1.0.3`), NOT `latest`
|
|
336
|
+
- `envFrom` referencing ConfigMap and Secret
|
|
337
|
+
- Resource requests/limits (sensible defaults: 256Mi-512Mi memory, 250m-500m CPU)
|
|
338
|
+
- Readiness and liveness probes using the detected health endpoint
|
|
339
|
+
- Non-root `securityContext`
|
|
340
|
+
- `hostAliases` (conditional): If the environment's Domain from CLAUDE.md is referenced
|
|
341
|
+
in ConfigMap values AND is not `localhost`, add `hostAliases` mapping the Domain to
|
|
342
|
+
the environment's IP address. This is needed because K8s pod DNS cannot resolve custom
|
|
343
|
+
domains defined only in the host machine's `/etc/hosts`. See `references/k8s-patterns.md`.
|
|
344
|
+
5. **`service.yaml`** — ClusterIP service exposing the application port
|
|
345
|
+
6. **`ingress.yaml`** (optional) — if the application is a web application or API with
|
|
346
|
+
external access. Only generate if the environment's CLAUDE.md description suggests
|
|
347
|
+
external access (e.g., mentions domain, IP, or ingress).
|
|
348
|
+
|
|
349
|
+
Read `references/k8s-patterns.md` for the complete manifest templates per resource type.
|
|
350
|
+
|
|
351
|
+
#### 3c. Environment-Specific Values
|
|
352
|
+
|
|
353
|
+
When generating manifests for the target environment:
|
|
354
|
+
|
|
355
|
+
- **ConfigMap and Secret values**: Read `ENVIRONMENT.md` from the project root. If ENVIRONMENT.md
|
|
356
|
+
contains environment-specific credentials (organized by environment), use the matching
|
|
357
|
+
values for the target environment. If values are not found, use `TODO` as placeholder.
|
|
358
|
+
- **Resource limits**: Use sensible defaults. If the CLAUDE.md environment description
|
|
359
|
+
mentions resource constraints, adjust accordingly.
|
|
360
|
+
- **Ingress hostnames**: Derive from the target environment description in CLAUDE.md if
|
|
361
|
+
available (e.g., IP address, domain name). Use `TODO` if not specified.
|
|
362
|
+
|
|
363
|
+
#### 3d. Create or Update Logic
|
|
364
|
+
|
|
365
|
+
For the `<app_folder>/k8s/` folder:
|
|
366
|
+
|
|
367
|
+
1. **If a manifest file does not exist** (CREATE mode):
|
|
368
|
+
- Generate the file from the detected values and templates
|
|
369
|
+
- Write to `<app_folder>/k8s/<resource>.yaml`
|
|
370
|
+
|
|
371
|
+
2. **If it already exists** (UPDATE mode):
|
|
372
|
+
- Read the existing manifest
|
|
373
|
+
- Compare detected values against what the manifest currently has:
|
|
374
|
+
- New or removed environment variables → update configmap.yaml and secret.yaml
|
|
375
|
+
- Image version changed → update deployment.yaml image tag
|
|
376
|
+
- Port changed → update service.yaml and deployment.yaml container port
|
|
377
|
+
- Health endpoint changed → update probes in deployment.yaml
|
|
378
|
+
- New dependencies → add init containers or environment variables
|
|
379
|
+
- Preserve any lines or resources marked with `# CUSTOM:` comments
|
|
380
|
+
- Update only the parts that changed
|
|
381
|
+
- Log what was changed
|
|
382
|
+
|
|
383
|
+
#### 3e. Namespace Consistency
|
|
384
|
+
|
|
385
|
+
All manifests use the same namespace (derived from the project code in CLAUDE.md's
|
|
386
|
+
`# Project Detail` → Project Code in lowercase, e.g., `urp`).
|
|
387
|
+
|
|
388
|
+
#### 3f. Docker Build Reference
|
|
389
|
+
|
|
390
|
+
Include a comment block at the top of `deployment.yaml`:
|
|
391
|
+
|
|
392
|
+
```yaml
|
|
393
|
+
# Application: <Application Name>
|
|
394
|
+
# Environment: <Target Environment Name>
|
|
395
|
+
# Build: docker build -t <image-name>:<version> <app_folder>/
|
|
396
|
+
# Tag: docker tag <image-name>:<version> <image-name>:latest
|
|
397
|
+
# Apply: kubectl apply -f <app_folder>/k8s/
|
|
398
|
+
---
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### 3g. Update `.gitignore`
|
|
402
|
+
|
|
403
|
+
The `k8s/` folder contains environment-specific manifests with ConfigMap values,
|
|
404
|
+
base64-encoded Secrets, hostnames, and credentials that MUST NOT be committed to
|
|
405
|
+
version control. After generating or updating the K8s manifests, ensure the
|
|
406
|
+
application's `.gitignore` excludes the `k8s/` folder:
|
|
407
|
+
|
|
408
|
+
1. Read `<app_folder>/.gitignore`. If it does not exist, create it.
|
|
409
|
+
2. Check if `k8s/` (or an equivalent pattern like `k8s/**`) is already listed.
|
|
410
|
+
3. If **not already present**, append the following block:
|
|
411
|
+
|
|
412
|
+
```gitignore
|
|
413
|
+
|
|
414
|
+
# Kubernetes manifests — environment-specific configs and secrets
|
|
415
|
+
k8s/
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
4. If already present, do nothing — do not duplicate the entry.
|
|
419
|
+
5. Do NOT remove or modify any other entries in `.gitignore`.
|
|
420
|
+
|
|
421
|
+
## Constraints
|
|
422
|
+
|
|
423
|
+
These constraints are non-negotiable:
|
|
424
|
+
|
|
425
|
+
1. **Custom applications only** — This skill only processes applications listed under
|
|
426
|
+
`# Custom Applications` in CLAUDE.md. 3rd party applications and external services are
|
|
427
|
+
NOT containerized by this skill.
|
|
428
|
+
|
|
429
|
+
2. **Stack-agnostic output** — The skill must work for Spring Boot, Laravel, and Node.js
|
|
430
|
+
applications. All stack-specific logic is gated behind the detection in Phase 1.
|
|
431
|
+
|
|
432
|
+
3. **Real values from context** — Every manifest and Dockerfile must use the actual
|
|
433
|
+
application name, port, environment variables, and dependency versions from the project's
|
|
434
|
+
context files. No placeholder `<TODO>` values except for legitimately unknown production
|
|
435
|
+
values (registry URL, domain name).
|
|
436
|
+
|
|
437
|
+
4. **ConfigMap/Secret separation** — Sensitive values must NEVER appear in ConfigMaps.
|
|
438
|
+
The classification logic in Phase 1 Step 4 must be applied consistently.
|
|
439
|
+
|
|
440
|
+
5. **Non-root containers** — All Dockerfiles must run the application as a non-root user.
|
|
441
|
+
|
|
442
|
+
6. **Multi-stage builds** — All Dockerfiles must use multi-stage builds to minimize the
|
|
443
|
+
runtime image size. Build tools (Maven, Composer, npm dev dependencies) must NOT be
|
|
444
|
+
in the final image.
|
|
445
|
+
|
|
446
|
+
7. **No `.env` in containers** — The `.env` file is for local development only. Container
|
|
447
|
+
environments receive configuration via K8s ConfigMap + Secret injection.
|
|
448
|
+
|
|
449
|
+
8. **Flat K8s manifest folder** — Kubernetes manifests live directly in `<app_folder>/k8s/`
|
|
450
|
+
with separate YAML files per resource type (no per-environment subfolders). The `k8s/`
|
|
451
|
+
folder is gitignored — each machine maintains its own copy with values specific to
|
|
452
|
+
the target environment. Run the skill once per environment on the target machine.
|
|
453
|
+
|
|
454
|
+
9. **Idempotent — supports both create and update** — If Dockerfile or manifest already
|
|
455
|
+
exists, read it first, detect what changed, and update only the affected parts. Preserve
|
|
456
|
+
any manual customizations marked with `# CUSTOM:`. If the file does not exist, create
|
|
457
|
+
from scratch. Always log what was created or changed.
|
|
458
|
+
|
|
459
|
+
10. **Single-pass execution** — This skill completes in one pass (Dockerfile + manifest).
|
|
460
|
+
No Ralph Loop needed.
|
|
461
|
+
|
|
462
|
+
11. **Production-safe defaults** — Dockerfile and K8s manifests must default to
|
|
463
|
+
production-safe values. Dev-specific settings (JTE dev mode, DevTools, debug logging)
|
|
464
|
+
must be OFF by default in the container, overridden only via explicit environment
|
|
465
|
+
variables.
|
|
466
|
+
|
|
467
|
+
12. **Versioned image tags** — Kubernetes Deployment manifests must reference versioned
|
|
468
|
+
image tags (e.g., `hub-middleware:1.0.3`), never `latest`.
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Dockerfile Pattern — Laravel
|
|
2
|
+
|
|
3
|
+
Multi-stage Dockerfile for Laravel applications with PHP-FPM and Nginx.
|
|
4
|
+
|
|
5
|
+
## Detection Inputs
|
|
6
|
+
|
|
7
|
+
| Input | Source | Used For |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| PHP version | `composer.json` → `require.php` | Base image tag |
|
|
10
|
+
| Laravel version | `composer.json` → `require.laravel/framework` | Compatibility |
|
|
11
|
+
| Has frontend | `vite.config.js` or `webpack.mix.js` present | Include Node build stage |
|
|
12
|
+
| App port | `.env.example` → `APP_PORT` or default `8000` | EXPOSE / Nginx config |
|
|
13
|
+
|
|
14
|
+
## Template — PHP-FPM + Nginx (Production)
|
|
15
|
+
|
|
16
|
+
```dockerfile
|
|
17
|
+
# =============================================================================
|
|
18
|
+
# Stage 1: Frontend Build (if Vite/Mix is used)
|
|
19
|
+
# =============================================================================
|
|
20
|
+
FROM node:22-alpine AS frontend
|
|
21
|
+
|
|
22
|
+
WORKDIR /app
|
|
23
|
+
|
|
24
|
+
# Copy package files for dependency caching
|
|
25
|
+
COPY package.json package-lock.json ./
|
|
26
|
+
RUN npm ci --production=false
|
|
27
|
+
|
|
28
|
+
# Copy frontend source and build
|
|
29
|
+
COPY resources ./resources
|
|
30
|
+
COPY vite.config.js ./
|
|
31
|
+
COPY tailwind.config.js ./
|
|
32
|
+
COPY postcss.config.js ./
|
|
33
|
+
RUN npm run build
|
|
34
|
+
|
|
35
|
+
# =============================================================================
|
|
36
|
+
# Stage 2: Composer Dependencies
|
|
37
|
+
# =============================================================================
|
|
38
|
+
FROM composer:2 AS composer
|
|
39
|
+
|
|
40
|
+
WORKDIR /app
|
|
41
|
+
|
|
42
|
+
COPY composer.json composer.lock ./
|
|
43
|
+
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
|
|
44
|
+
|
|
45
|
+
COPY . .
|
|
46
|
+
RUN composer dump-autoload --optimize --no-dev
|
|
47
|
+
|
|
48
|
+
# =============================================================================
|
|
49
|
+
# Stage 3: Runtime (PHP-FPM + Nginx)
|
|
50
|
+
# =============================================================================
|
|
51
|
+
FROM php:{php_version}-fpm-alpine AS runtime
|
|
52
|
+
|
|
53
|
+
# Install required PHP extensions
|
|
54
|
+
RUN apk add --no-cache \
|
|
55
|
+
nginx \
|
|
56
|
+
supervisor \
|
|
57
|
+
&& docker-php-ext-install pdo pdo_mysql opcache
|
|
58
|
+
|
|
59
|
+
# Configure PHP for production
|
|
60
|
+
COPY docker/php.ini /usr/local/etc/php/conf.d/app.ini
|
|
61
|
+
COPY docker/nginx.conf /etc/nginx/http.d/default.conf
|
|
62
|
+
COPY docker/supervisord.conf /etc/supervisord.conf
|
|
63
|
+
|
|
64
|
+
# Create non-root user
|
|
65
|
+
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
|
|
66
|
+
|
|
67
|
+
WORKDIR /var/www/html
|
|
68
|
+
|
|
69
|
+
# Copy application from composer stage
|
|
70
|
+
COPY --from=composer /app .
|
|
71
|
+
|
|
72
|
+
# Copy built frontend assets from frontend stage
|
|
73
|
+
COPY --from=frontend /app/public/build ./public/build
|
|
74
|
+
|
|
75
|
+
# Set permissions
|
|
76
|
+
RUN chown -R appuser:appgroup /var/www/html \
|
|
77
|
+
&& chmod -R 775 storage bootstrap/cache
|
|
78
|
+
|
|
79
|
+
# Expose port
|
|
80
|
+
EXPOSE {app_port}
|
|
81
|
+
|
|
82
|
+
# Health check
|
|
83
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
|
84
|
+
CMD wget --no-verbose --tries=1 --spider http://localhost:{app_port}/health || exit 1
|
|
85
|
+
|
|
86
|
+
# Production defaults
|
|
87
|
+
ENV APP_ENV=production
|
|
88
|
+
ENV APP_DEBUG=false
|
|
89
|
+
ENV LOG_CHANNEL=stderr
|
|
90
|
+
|
|
91
|
+
ENTRYPOINT ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Supporting Files
|
|
95
|
+
|
|
96
|
+
The Dockerfile references supporting config files that should be documented in
|
|
97
|
+
DEPLOYMENT.md. These are placed in a `docker/` directory in the application root.
|
|
98
|
+
|
|
99
|
+
### docker/php.ini
|
|
100
|
+
|
|
101
|
+
```ini
|
|
102
|
+
[PHP]
|
|
103
|
+
display_errors = Off
|
|
104
|
+
log_errors = On
|
|
105
|
+
error_log = /dev/stderr
|
|
106
|
+
opcache.enable = 1
|
|
107
|
+
opcache.memory_consumption = 256
|
|
108
|
+
opcache.interned_strings_buffer = 16
|
|
109
|
+
opcache.max_accelerated_files = 20000
|
|
110
|
+
opcache.validate_timestamps = 0
|
|
111
|
+
upload_max_filesize = 50M
|
|
112
|
+
post_max_size = 50M
|
|
113
|
+
memory_limit = 512M
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### docker/nginx.conf
|
|
117
|
+
|
|
118
|
+
```nginx
|
|
119
|
+
server {
|
|
120
|
+
listen {app_port};
|
|
121
|
+
root /var/www/html/public;
|
|
122
|
+
index index.php;
|
|
123
|
+
|
|
124
|
+
location / {
|
|
125
|
+
try_files $uri $uri/ /index.php?$query_string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
location ~ \.php$ {
|
|
129
|
+
fastcgi_pass 127.0.0.1:9000;
|
|
130
|
+
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
131
|
+
include fastcgi_params;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
135
|
+
expires 1y;
|
|
136
|
+
add_header Cache-Control "public, immutable";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### docker/supervisord.conf
|
|
142
|
+
|
|
143
|
+
```ini
|
|
144
|
+
[supervisord]
|
|
145
|
+
nodaemon=true
|
|
146
|
+
logfile=/dev/stdout
|
|
147
|
+
logfile_maxbytes=0
|
|
148
|
+
|
|
149
|
+
[program:php-fpm]
|
|
150
|
+
command=/usr/local/sbin/php-fpm --nodaemonize
|
|
151
|
+
autostart=true
|
|
152
|
+
autorestart=true
|
|
153
|
+
stdout_logfile=/dev/stdout
|
|
154
|
+
stdout_logfile_maxbytes=0
|
|
155
|
+
stderr_logfile=/dev/stderr
|
|
156
|
+
stderr_logfile_maxbytes=0
|
|
157
|
+
|
|
158
|
+
[program:nginx]
|
|
159
|
+
command=/usr/sbin/nginx -g "daemon off;"
|
|
160
|
+
autostart=true
|
|
161
|
+
autorestart=true
|
|
162
|
+
stdout_logfile=/dev/stdout
|
|
163
|
+
stdout_logfile_maxbytes=0
|
|
164
|
+
stderr_logfile=/dev/stderr
|
|
165
|
+
stderr_logfile_maxbytes=0
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Template — Artisan Serve (Development/Simple)
|
|
169
|
+
|
|
170
|
+
For simpler setups without Nginx:
|
|
171
|
+
|
|
172
|
+
```dockerfile
|
|
173
|
+
FROM php:{php_version}-cli-alpine AS runtime
|
|
174
|
+
|
|
175
|
+
RUN docker-php-ext-install pdo pdo_mysql
|
|
176
|
+
|
|
177
|
+
WORKDIR /var/www/html
|
|
178
|
+
COPY --from=composer /app .
|
|
179
|
+
COPY --from=frontend /app/public/build ./public/build
|
|
180
|
+
|
|
181
|
+
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
|
|
182
|
+
RUN chown -R appuser:appgroup /var/www/html
|
|
183
|
+
USER appuser
|
|
184
|
+
|
|
185
|
+
EXPOSE {app_port}
|
|
186
|
+
CMD ["php", "artisan", "serve", "--host=0.0.0.0", "--port={app_port}"]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Notes
|
|
190
|
+
|
|
191
|
+
- **Queue workers**: If the application uses Laravel queues (detected by `QUEUE_CONNECTION`
|
|
192
|
+
env var or `app/Jobs/` directory), document a separate Deployment for the queue worker
|
|
193
|
+
container using the same image but `CMD ["php", "artisan", "queue:work"]`.
|
|
194
|
+
- **Scheduler**: If `app/Console/Kernel.php` has scheduled tasks, document a CronJob
|
|
195
|
+
manifest using `CMD ["php", "artisan", "schedule:run"]`.
|
|
196
|
+
- **Storage**: Laravel's `storage/` directory needs a writable volume if file uploads
|
|
197
|
+
are used. Document a PersistentVolumeClaim in DEPLOYMENT.md.
|