3eff38f8d2
Rework the application build/deploy pipeline for scalability, reproducibility, and security: - Build queue: deploys run through a bounded-concurrency Bull queue (BUILD_CONCURRENCY, default 3) so concurrent user deploys can't flood the cluster with Kaniko jobs. Build state (progress / cancel / session) moves from in-memory Maps to Redis, so cancel + live logs work across backend replicas. - Nixpacks + BYO Dockerfile: code runtimes build via Nixpacks (or the user's own Dockerfile when present); the hand-written per-runtime Dockerfile generators and runtime auto-detection are removed. WordPress keeps its templated path. Build-time mirror env (NIXPACKS_BUILD_ENV) supports the Iran network. - Source upload to MinIO: archives stream to in-cluster MinIO; build pods pull via a presigned URL. Removes the PVC + helper pod + kubectl cp upload path. - Report-only Trivy scan after build; per-severity summary stored on the deployment and shown as a badge in the dashboard. Never gates a deploy. - Registry GC: a Redis-locked daily job keeps the newest N image tags per app (REGISTRY_KEEP_VERSIONS, default 3) and reclaims disk via garbage-collect. - Hardening: git tokens are delivered via a per-build Secret + git credential store instead of being embedded in the clone URL / Job manifest; build timeout is configurable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
213 lines
8.6 KiB
YAML
213 lines
8.6 KiB
YAML
# ─────────────────────────────────────────────────────────────────────────────
|
||
# فاز ۰ — Spike ریسک Nixpacks روی شبکهی ایران (abrban / cloudhost-builds)
|
||
#
|
||
# هدف: قبل از مهاجرت سیستم بیلد به Nixpacks (فاز ۲)، مطمئن شویم زنجیرهی
|
||
# nixpacks (تولید Dockerfile) → kaniko (build واقعی + نصب وابستگیها)
|
||
# پشت شبکهی ایران کار میکند و کشف کنیم چه mirror/proxy لازم است.
|
||
#
|
||
# چرا این ساختار: `nixpacks build --out` فقط Dockerfile میسازد و دانلودی ندارد؛
|
||
# دانلود سنگین (nixpkgs + npm/go modules) داخل مرحلهی Docker build اتفاق میافتد.
|
||
# پس برای تست واقعی شبکه باید kaniko همان Dockerfile تولیدی را build کند.
|
||
# با --no-push نیازی به رجیستری/کردنشال نیست — فقط build تست میشود.
|
||
#
|
||
# اجرا:
|
||
# kubectl apply -f nixpacks-spike.yaml
|
||
# kubectl -n cloudhost-builds logs -f job/nixpacks-spike-node
|
||
# kubectl -n cloudhost-builds logs -f job/nixpacks-spike-go
|
||
# # بعد از اتمام:
|
||
# kubectl -n cloudhost-builds delete -f nixpacks-spike.yaml
|
||
#
|
||
# اگر kaniko سرِ `RUN ... npm install` یا fetch nixpkgs گیر کرد → شبکهی ایران
|
||
# مانع است؛ env های mirror را (بخش «نکات mirror» پایین فایل) فعال/تنظیم کنید و
|
||
# دوباره اجرا کنید. نتیجه را برای تصمیم فاز ۲ مستند کنید.
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
---
|
||
apiVersion: v1
|
||
kind: ConfigMap
|
||
metadata:
|
||
name: nixpacks-spike-node-src
|
||
namespace: cloudhost-builds
|
||
data:
|
||
package.json: |
|
||
{
|
||
"name": "nixpacks-spike",
|
||
"version": "1.0.0",
|
||
"private": true,
|
||
"scripts": { "start": "node index.js" },
|
||
"dependencies": { "express": "^4.18.2" }
|
||
}
|
||
index.js: |
|
||
const express = require('express');
|
||
const app = express();
|
||
app.get('/', (_req, res) => res.send('nixpacks spike ok'));
|
||
app.listen(process.env.PORT || 3000, () => console.log('up'));
|
||
---
|
||
apiVersion: batch/v1
|
||
kind: Job
|
||
metadata:
|
||
name: nixpacks-spike-node
|
||
namespace: cloudhost-builds
|
||
spec:
|
||
backoffLimit: 0
|
||
ttlSecondsAfterFinished: 1800
|
||
template:
|
||
spec:
|
||
restartPolicy: Never
|
||
volumes:
|
||
- name: workspace
|
||
emptyDir: {}
|
||
- name: src
|
||
configMap:
|
||
name: nixpacks-spike-node-src
|
||
initContainers:
|
||
# 1) staging سورس نمونه از ConfigMap به workspace
|
||
- name: stage-source
|
||
image: alpine:3.19
|
||
imagePullPolicy: IfNotPresent
|
||
command:
|
||
- sh
|
||
- -c
|
||
- |
|
||
set -e
|
||
mkdir -p /workspace/source
|
||
cp /src/package.json /workspace/source/package.json
|
||
cp /src/index.js /workspace/source/index.js
|
||
echo ">>> staged source:" && ls -la /workspace/source
|
||
volumeMounts:
|
||
- { name: workspace, mountPath: /workspace }
|
||
- { name: src, mountPath: /src }
|
||
# 2) Nixpacks: تولید Dockerfile در /workspace/source/.nixpacks/Dockerfile
|
||
- name: nixpacks-plan
|
||
image: ghcr.io/railwayapp/nixpacks:latest
|
||
imagePullPolicy: IfNotPresent
|
||
# نگاشت همان تنظیماتی که فاز ۲ پاس میدهد (نسخهی Node و PORT)
|
||
env:
|
||
- { name: NIXPACKS_NODE_VERSION, value: "20" }
|
||
# - { name: NPM_CONFIG_REGISTRY, value: "https://registry.npmmirror.com" } # ← در صورت نیاز
|
||
command:
|
||
- nixpacks
|
||
- build
|
||
- /workspace/source
|
||
- --out
|
||
- /workspace/source
|
||
volumeMounts:
|
||
- { name: workspace, mountPath: /workspace }
|
||
containers:
|
||
# 3) Kaniko: build واقعی Dockerfile تولیدی (تست دانلود وابستگیها). بدون push.
|
||
- name: kaniko
|
||
image: gcr.io/kaniko-project/executor:v1.23.2
|
||
imagePullPolicy: IfNotPresent
|
||
args:
|
||
- --dockerfile=/workspace/source/.nixpacks/Dockerfile
|
||
- --context=dir:///workspace/source
|
||
- --no-push
|
||
- --verbosity=info
|
||
volumeMounts:
|
||
- { name: workspace, mountPath: /workspace }
|
||
resources:
|
||
requests: { cpu: "500m", memory: "1Gi" }
|
||
limits: { cpu: "2", memory: "4Gi" }
|
||
---
|
||
apiVersion: v1
|
||
kind: ConfigMap
|
||
metadata:
|
||
name: nixpacks-spike-go-src
|
||
namespace: cloudhost-builds
|
||
data:
|
||
go.mod: |
|
||
module nixpacksspike
|
||
|
||
go 1.22
|
||
main.go: |
|
||
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"net/http"
|
||
"os"
|
||
)
|
||
|
||
func main() {
|
||
http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
|
||
fmt.Fprintln(w, "nixpacks spike ok")
|
||
})
|
||
port := os.Getenv("PORT")
|
||
if port == "" {
|
||
port = "8080"
|
||
}
|
||
http.ListenAndServe(":"+port, nil)
|
||
}
|
||
---
|
||
apiVersion: batch/v1
|
||
kind: Job
|
||
metadata:
|
||
name: nixpacks-spike-go
|
||
namespace: cloudhost-builds
|
||
spec:
|
||
backoffLimit: 0
|
||
ttlSecondsAfterFinished: 1800
|
||
template:
|
||
spec:
|
||
restartPolicy: Never
|
||
volumes:
|
||
- name: workspace
|
||
emptyDir: {}
|
||
- name: src
|
||
configMap:
|
||
name: nixpacks-spike-go-src
|
||
initContainers:
|
||
- name: stage-source
|
||
image: alpine:3.19
|
||
imagePullPolicy: IfNotPresent
|
||
command:
|
||
- sh
|
||
- -c
|
||
- |
|
||
set -e
|
||
mkdir -p /workspace/source
|
||
cp /src/go.mod /workspace/source/go.mod
|
||
cp /src/main.go /workspace/source/main.go
|
||
echo ">>> staged source:" && ls -la /workspace/source
|
||
volumeMounts:
|
||
- { name: workspace, mountPath: /workspace }
|
||
- { name: src, mountPath: /src }
|
||
- name: nixpacks-plan
|
||
image: ghcr.io/railwayapp/nixpacks:latest
|
||
imagePullPolicy: IfNotPresent
|
||
env:
|
||
# - { name: GOPROXY, value: "https://goproxy.cn,direct" } # ← در صورت نیاز (mirror چین)
|
||
command:
|
||
- nixpacks
|
||
- build
|
||
- /workspace/source
|
||
- --out
|
||
- /workspace/source
|
||
volumeMounts:
|
||
- { name: workspace, mountPath: /workspace }
|
||
containers:
|
||
- name: kaniko
|
||
image: gcr.io/kaniko-project/executor:v1.23.2
|
||
imagePullPolicy: IfNotPresent
|
||
args:
|
||
- --dockerfile=/workspace/source/.nixpacks/Dockerfile
|
||
- --context=dir:///workspace/source
|
||
- --no-push
|
||
- --verbosity=info
|
||
volumeMounts:
|
||
- { name: workspace, mountPath: /workspace }
|
||
resources:
|
||
requests: { cpu: "500m", memory: "1Gi" }
|
||
limits: { cpu: "2", memory: "4Gi" }
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
# نکات mirror (اگر build گیر کرد، uncomment/تنظیم و دوباره اجرا کنید):
|
||
# • npm: NPM_CONFIG_REGISTRY=https://registry.npmmirror.com (روی container kaniko
|
||
# اثر ندارد چون Dockerfile تولیدی است؛ بهتر است در فاز ۲ بهصورت ARG/ENV
|
||
# داخل مرحلهی نصب تزریق شود — اینجا فقط برای nixpacks-plan گذاشته شده.)
|
||
# • nix: اگر دانلود nixpkgs (https://github.com/NixOS/...) شکست خورد، احتمال نیاز به
|
||
# HTTP(S)_PROXY روی container kaniko یا آینهسازی nixpkgs. در لاگ kaniko دنبال
|
||
# خطوط fetch tarball بگردید.
|
||
# • go: GOPROXY=https://goproxy.cn,direct یا proxy داخلی.
|
||
# • اگر pull از ghcr.io/gcr.io خود مشکل داشت → image ها را به رجیستری داخلی mirror کنید
|
||
# (همان الگوی LOGGING_*_IMAGE در configuration.ts).
|
||
# ─────────────────────────────────────────────────────────────────────────────
|