26 KiB
🔧 راهنمای CI/CD Pipeline — Gitea Actions + K3s
آخرین بروزرسانی: February 17, 2026
📐 معماری کلی
┌─────────────────────────────────────────────────────────┐
│ K3s Cluster (194.5.195.53) │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ gitea-runner Pod (2 containers) │ │
│ │ │ │
│ │ ┌──────────────────┐ ┌──────────────────────┐ │ │
│ │ │ docker (DinD) │ │ runner (act_runner) │ │ │
│ │ │ docker:dind │ │ gitea/act_runner │ │ │
│ │ │ privileged: true │ │ DOCKER_HOST= │ │ │
│ │ │ port: 2375 │ │ tcp://localhost:2375│ │ │
│ │ └──────────────────┘ └──────────────────────┘ │ │
│ │ ▲ shared volumes: docker-storage │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌───────────┐ ┌────────────────┐ │
│ │ Gitea │ │ Nexus │ │ Docker Reg. │ │
│ │ :3000 │ │ :32081 │ │ :32082 (pull) │ │
│ │ │ │ (NuGet) │ │ :30080 (push) │ │
│ └─────────────┘ └───────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────────┘
سه لایه Docker-in-Docker:
K3s containerd (لایه ۱)
└── gitea-runner Pod → docker container (DinD daemon) (لایه ۲)
└── workflow: docker run / docker build (لایه ۳)
📁 فایلهای Workflow
🐳 K8s Pipelines (Docker + K3s) — آفلاین
| سرویس | فایل | Branch | Image | Deploy |
|---|---|---|---|---|
| CMS | kub-deploy.yml |
kub-stage |
admin/cms |
SSH → kubectl |
| BackOffice | kub-deploy.yml |
kub-stage |
admin/backoffice |
SSH → kubectl |
| FrontOffice | kub-deploy.yml |
kub-stage |
admin/frontoffice |
SSH → kubectl |
| CMS | prod-deploy.yml |
production |
admin/cms:prod |
SSH → kubectl |
| BackOffice | prod-deploy.yml |
production |
admin/backoffice:prod |
SSH → kubectl |
| FrontOffice | prod-deploy.yml |
production |
admin/frontoffice:prod |
SSH → kubectl |
🪟 Windows/IIS Pipelines (Legacy) — آنلاین
| سرویس | فایل | Branch | Target |
|---|---|---|---|
| CMS | cms-stage.yml |
stage_new |
IIS → cms.kbs1.ir |
| BackOffice | bo-stage.yml |
stage-new |
IIS → admin.kbs1.ir |
| FrontOffice | fo-stage.yml |
stage-new |
IIS → kbs1.ir |
⚠️ Stage pipeline ها از Windows runner + IIS استفاده میکنن و Docker ندارن.
ساختار مشترک Pipeline:
1. Start Docker daemon (DinD)
2. Checkout code (git clone)
3. Login to Docker registries (32082 + 30080)
4. [CMS only] Publish Protobuf packages
5. Build Docker Image
6. Push to Registry
7. Deploy to Kubernetes (SSH → kubectl rollout restart)
🐛 مشکلات حلشده و راهحلها
مشکل ۱: iptables failed: Permission denied
خطا:
iptables v1.8.10 (nf_tables): Could not fetch rule set generation id: Permission denied
علت: K3s containerd به Docker daemon اجازه تغییر iptables نمیده.
راهحل: غیرفعال کردن networking در dockerd:
dockerd --iptables=false --ip6tables=false --bridge=none --storage-driver=vfs &
⚠️ با
--bridge=noneنیاز به شبکهسازی Docker نیست چون فقط build و push انجام میشه.
مشکل ۲: failed to unmount overlayfs: operation not permitted
خطا:
failed to register layer: unshare: operation not permitted
علت: overlay2 storage driver نیاز به mount namespace داره که داخل K3s مجاز نیست.
راهحل: استفاده از vfs storage driver:
dockerd --storage-driver=vfs &
⚠️
vfsکندتره ولی هیچ mount syscall خاصی نیاز نداره. برای CI/CD کافیه.
مشکل ۳: no basic auth credentials هنگام pull ایمیج
خطا:
Error response from daemon: Head "https://194.5.195.53:32082/v2/dotnet/sdk/manifests/9.0":
no basic auth credentials
علت: docker login فقط قبل از push انجام میشد، ولی docker build (یا docker run) هم از 32082 ایمیج pull میکنه.
راهحل: اضافه کردن step "Login to Docker registries" بلافاصله بعد از Checkout:
- name: Login to Docker registries
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login 194.5.195.53:32082 -u admin --password-stdin
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin
مشکل ۴: unshare: operation not permitted هنگام extract لایهها
خطا:
docker: failed to register layer: unshare: operation not permitted
علت اصلی (دو بخش):
بخش ۱: Gitea act_runner دیفالت container.privileged: false داره. یعنی job container ها بدون privileged ساخته میشن — حتی اگه workflow بنویسه options: --privileged.
بخش ۲: env var CONFIG_FILE در runner container ست نبود → run.sh فلگ --config رو به act_runner daemon پاس نمیداد → config.yaml اصلاً لود نمیشد!
راهحل (سمت سرور):
۱. ساخت ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: runner-config
namespace: default
data:
config.yaml: |
log:
level: info
runner:
file: .runner
capacity: 1
timeout: 3h
container:
privileged: true
options: "--security-opt seccomp=unconfined --security-opt apparmor=unconfined"
valid_volumes:
- "**"
۲. Mount کردن در Deployment + env var:
kubectl patch deployment gitea-runner --type=json -p='[
{"op":"add","path":"/spec/template/spec/containers/1/env/-",
"value":{"name":"CONFIG_FILE","value":"/data/config.yaml"}},
{"op":"add","path":"/spec/template/spec/containers/1/volumeMounts/-",
"value":{"name":"runner-config","mountPath":"/data/config.yaml","subPath":"config.yaml"}},
{"op":"add","path":"/spec/template/spec/volumes/-",
"value":{"name":"runner-config","configMap":{"name":"runner-config"}}}
]'
⚠️ نکته مهم: بدون
CONFIG_FILE=/data/config.yamlenv var، فایلrun.shداخل act_runner image فلگ--configرو پاس نمیده!
مشکل ۵: Protobuf restore از nuget.org بجای Nexus
علت: dotnet restore بدون --configfile از دیفالت NuGet sources استفاده میکنه.
راهحل:
dotnet restore "$proj" --configfile src/NuGet.config
مشکل ۶: عدم دسترسی شبکه با --bridge=none
علت: dockerd --bridge=none شبکه Docker bridge رو غیرفعال میکنه. در نتیجه container هایی که با docker run یا docker build ساخته میشن، دسترسی شبکه ندارن (مثلاً dotnet restore نمیتونه به Nexus وصل بشه).
راهحل: استفاده از --network host در docker run و docker build:
# Protobuf step
docker run --rm --network host -v $(pwd):/src -w /src ...
# Build step
DOCKER_BUILDKIT=0 docker build --network host -t ... .
مشکل ۷: failed to prepare ... as ...: invalid argument (BuildKit)
خطا:
ERROR: failed to build: failed to solve: failed to prepare xxx as yyy: invalid argument
علت: BuildKit (بیلدر پیشفرض Docker ≥23) از snapshotter overlay استفاده میکنه که با --storage-driver=vfs سازگاری نداره.
راهحل: غیرفعال کردن BuildKit:
DOCKER_BUILDKIT=0 docker build --network host -t ... .
⚠️ Legacy builder از vfs بدون مشکل استفاده میکنه.
مشکل ۸: COPY libs/ fails in Docker build (BackOffice)
خطا:
COPY failed: file not found in build context: stat libs/: file does not exist
علت: Dockerfile خط COPY ["libs/", "libs/"] داشت ولی libs/ خارج از Docker build context (src/) بود. قبلاً BFF DLLها استفاده میشدن، ولی حالا از NuGet package مستقیم استفاده میشه.
راهحل:
- حذف
COPY ["libs/", "libs/"]از Dockerfile - تغییر
ProjectReferenceبهPackageReferenceدر csproj:
<!-- قبل -->
<ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj" />
<!-- بعد -->
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.178" />
مشکل ۹: ProjectReference خارج از Docker context (FrontOffice/BackOffice)
خطا:
error CS0246: The type or namespace name 'CustomerAddressModel' could not be found
علت: csproj از ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/..." استفاده میکرد. در Docker build context فقط src/ موجوده → CMS قابل دسترسی نیست.
راهحل:
- بامپ نسخه پروتوباف (
0.0.177→0.0.178) dotnet pack -c Releaseو push به Nexus- تغییر هر دو پروژه (FrontOffice + BackOffice) به
PackageReference
# Pack & Push
cd CMS/src/CMSMicroservice.Protobuf
dotnet pack -c Release
dotnet nuget push bin/Release/Foursat.CMSMicroservice.Protobuf.0.0.178.nupkg \
--source http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json \
--api-key admin:87zH26nbqT --skip-duplicate
مشکل ۱۰: nginx:alpine TLS handshake timeout
خطا:
Get "https://registry-1.docker.io/v2/": net/http: TLS handshake timeout
علت: Dockerfile خط FROM nginx:alpine مستقیم از Docker Hub پول میکرد ولی سرور به Docker Hub دسترسی نداره.
راهحل: تغییر به رجیستری لوکال:
# قبل
FROM nginx:alpine AS final
# بعد
FROM 194.5.195.53:32082/nginx:alpine AS final
مشکل ۱۱: SERVER_PASSWORD secret missing → Permission denied
خطا:
Permission denied, please try again.
علت: سکرت SERVER_PASSWORD در ریپو Gitea تنظیم نشده بود. Pipeline از sshpass -e با ${{ secrets.SERVER_PASSWORD }} برای SSH استفاده میکنه.
راهحل: اضافه کردن سکرت از طریق Gitea API:
curl -sk -u "admin:87zH26nbqT" -X PUT \
"https://git.se.kbs1.ir/api/v1/repos/admin/BackOffice/actions/secrets/SERVER_PASSWORD" \
-H "Content-Type: application/json" -d '{"data":"87zH26nbqT"}'
مشکل ۱۲: CMS ingress 502 — backend-protocol: GRPC
خطا: https://cms.se.kbs1.ir/ → 502 Bad Gateway
علت: CMS ingress annotation backend-protocol: GRPC داشت + Kestrel فقط Http2. مرورگر HTTP/1.1 میفرسته → nginx نمیتونه به gRPC backend فوروارد کنه.
راهحل (دو تغییر):
- Kestrel protocol →
Http1AndHttp2(هم gRPC هم REST):
kubectl set env deployment/cms Kestrel__EndpointDefaults__Protocols=Http1AndHttp2
- حذف GRPC annotations از ingress:
kubectl annotate ingress cms-ingress nginx.ingress.kubernetes.io/backend-protocol-
kubectl annotate ingress cms-ingress nginx.ingress.kubernetes.io/grpc-backend-
⚠️ FrontOffice از gRPC-Web استفاده میکنه که روی HTTP/1.1 هم کار میکنه.
🔄 تغییرات prod-deploy (قدیم → جدید)
| مورد | قدیم (prod-deploy) | جدید |
|---|---|---|
| Container image | docker:latest |
docker-sshpass:latest (شامل sshpass + git) |
| Proxy | HTTP_PROXY + HTTPS_PROXY |
حذف شد (آفلاین) |
| Registry | gitea-svc:3000 + external |
فقط 194.5.195.53:30080 |
| kubectl | apk add + curl از اینترنت |
SSH → kubectl مستقیم روی سرور |
| Auth | hardcoded password | secrets.REGISTRY_PASSWORD + secrets.SERVER_PASSWORD |
| BuildKit | فعال (دیفالت) | DOCKER_BUILDKIT=0 |
| Network | Docker bridge (دیفالت) | --network host |
| dockerd | دیفالت | --iptables=false --ip6tables=false --bridge=none --storage-driver=vfs |
| Deploy | KUBECONFIG_PROD (base64) |
SSH + sshpass (مثل kub-stage) |
✅ حالا همه ۶ K8s pipeline (۳ stage + ۳ prod) از یک الگوی مشترک آفلاین استفاده میکنن.
containers:
-
name: docker # DinD sidecar image: 194.5.195.53:32082/docker:dind securityContext: privileged: true env:
- DOCKER_TLS_CERTDIR: "" volumeMounts:
- /var/lib/docker → docker-storage
- /etc/docker/daemon.json → docker-config (ConfigMap)
-
name: runner # Gitea act_runner image: 194.5.195.53:32082/gitea/act_runner:latest env:
- GITEA_INSTANCE_URL: http://gitea-svc:3000
- DOCKER_HOST: tcp://localhost:2375
- CONFIG_FILE: /data/config.yaml # ← حیاتی! بدون این runner config لود نمیشه volumeMounts:
- /data → runner-data
- /data/config.yaml → runner-config (ConfigMap)
### ConfigMaps:
| نام | محتوا | Mount Path |
|-----|-------|------------|
| `docker-daemon-config` | `daemon.json` با insecure-registries | `/etc/docker/daemon.json` |
| `runner-config` | `config.yaml` با privileged + seccomp | `/data/config.yaml` |
### Labels (ثبتشده در Gitea):
ubuntu-latest → docker://docker.gitea.com/runner-images:ubuntu-latest ubuntu-24.04 → docker://docker.gitea.com/runner-images:ubuntu-24.04 ubuntu-22.04 → docker://docker.gitea.com/runner-images:ubuntu-22.04
---
## 🔑 Secrets مورد نیاز (Gitea → Settings → Secrets)
| Secret | استفاده |
|--------|---------|
| `REGISTRY_PASSWORD` | پسورد Docker registry (admin) |
| `SERVER_PASSWORD` | پسورد SSH سرور (root) — ⚠️ باید در هر ۳ ریپو ست بشه |
> **نکته:** اگر `SERVER_PASSWORD` ست نباشه، مرحله Deploy با `Permission denied` فیل میشه.
> با API اضافه کنید:
> ```bash
> curl -sk -u "admin:PASSWORD" -X PUT \
> "https://git.se.kbs1.ir/api/v1/repos/admin/REPO/actions/secrets/SERVER_PASSWORD" \
> -H "Content-Type: application/json" -d '{"data":"PASSWORD"}'
> ```
---
## 🔧 dockerd فلگهای نهایی
```bash
dockerd --iptables=false --ip6tables=false --bridge=none --storage-driver=vfs &
| Flag | دلیل |
|---|---|
--iptables=false |
K3s اجازه تغییر iptables نمیده |
--ip6tables=false |
مشابه بالا برای IPv6 |
--bridge=none |
نیازی به Docker bridge network نیست |
--storage-driver=vfs |
overlay2 نمیتونه mount کنه داخل K3s |
🔍 عیبیابی Pipeline
۱. چک وضعیت Runner:
# SSH به سرور
ssh root@194.5.195.53
# آیا runner pod بالاست؟
kubectl get pods -l app=gitea-runner
# لاگ runner
kubectl logs <pod-name> -c runner --tail=30
# لاگ DinD
kubectl logs <pod-name> -c docker --tail=30
۲. تست Docker داخل Runner:
# exec به DinD container
kubectl exec <pod-name> -c docker -- docker info
# آیا registry قابل دسترسیه؟
kubectl exec <pod-name> -c docker -- docker pull 194.5.195.53:32082/dotnet/sdk:9.0
۳. چک config runner:
# آیا config.yaml mount شده؟
kubectl exec <pod-name> -c runner -- cat /data/config.yaml
# آیا privileged فعاله؟
kubectl exec <pod-name> -c docker -- docker inspect <job-container> \
--format '{{.HostConfig.Privileged}} {{.HostConfig.SecurityOpt}}'
۴. ریاستارت runner:
kubectl rollout restart deployment/gitea-runner
kubectl rollout status deployment/gitea-runner --timeout=120s
📋 Workflow Template (کامل)
name: Build and Deploy to Kubernetes
on:
push:
branches:
- kub-stage
env:
REGISTRY: 194.5.195.53:30080
IMAGE_NAME: admin/<service-name>
K8S_SERVER: 194.5.195.53
jobs:
build-and-deploy:
runs-on: ubuntu-latest
container:
image: 194.5.195.53:32082/docker-sshpass:latest
options: --privileged
steps:
- name: Start Docker daemon
run: |
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'DAEMON'
{
"insecure-registries": ["194.5.195.53:30080", "194.5.195.53:32500", "194.5.195.53:32082"]
}
DAEMON
dockerd --iptables=false --ip6tables=false --bridge=none --storage-driver=vfs &
for i in $(seq 1 90); do
if docker info >/dev/null 2>&1; then
echo "✅ Docker ready"; break
fi
sleep 2
done
- name: Checkout code
run: |
git clone --depth 1 --branch kub-stage http://gitea-svc:3000/admin/<repo>.git .
- name: Login to Docker registries
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login 194.5.195.53:32082 -u admin --password-stdin
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u admin --password-stdin
- name: Build Docker Image
run: |
DOCKER_BUILDKIT=0 docker build --network host -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest .
- name: Push to Registry
run: |
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Deploy to Kubernetes
run: |
export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
kubectl rollout restart deployment/<service>
kubectl rollout status deployment/<service> --timeout=180s
"
🐛 باگ بحرانی: Cross-Deployment — Push به Production ریدیپلوی Staging (اسفند ۱۴۰۴)
علائم:
- Push به برنچ
production→ هم production و هم staging ریدیپلوی شدند - CMS staging pod بعد از push ریستارت شد
- Runner log: ۲ تسک CMS بجای ۱ تسک اجرا شد
علت ریشهای:
Gitea Act Runner تمام فایلهای workflow داخل .gitea/workflows/ برنچ push شده رو اجرا میکنه — حتی اگه on.push.branches برنچ دیگهای باشه. وقتی production push شد، kub-deploy.yml (trigger: kub-stage) هم اجرا شد و ایمیج admin/cms:latest رو با کد production ساخت → staging از latest pull کرد → staging با DB production بالا اومد!
راهحل:
حذف workflowهای staging از برنچ production (هر ۳ ریپو):
git rm .gitea/workflows/kub-deploy.yml .gitea/workflows/cms-stage.yml # CMS
git rm .gitea/workflows/fo-stage.yml .gitea/workflows/kub-deploy.yml # FrontOffice
git rm .gitea/workflows/bo-stage.yml .gitea/workflows/kub-deploy.yml # BackOffice
⚠️ قانون طلایی: هر برنچ فقط workflow مربوط به خودش رو داشته باشه.
🐛 مشکل ۱۳: Production deploy ایمیج pull نمیشد
علت: Production K8s از git.foursat.afrino.co/admin/cms:prod pull میکرد، ولی CI ایمیج رو به 194.5.195.53:30080 push میکرد.
راهحل:
- اضافه کردن
194.5.195.53:30080به/etc/rancher/k3s/registries.yamlپروداکشن + ریاستارت K3s - آپدیت deployment image:
kubectl set image deployment/cms cms=194.5.195.53:30080/admin/cms:prod - فیکس
prod-deploy.yml:K8S_SSH_PASSWORD→SERVER_PASSWORD,rollout restart→set image :sha
🔄 Production Workflow Template (فعلی)
name: Build and Deploy to Production
on:
push:
branches: [production]
env:
REGISTRY: 194.5.195.53:30080
IMAGE_NAME: admin/<service>
K8S_SERVER: 45.149.79.127
jobs:
build-and-deploy:
runs-on: ubuntu-latest
container:
image: 194.5.195.53:32082/docker-sshpass:latest
options: --privileged
steps:
# ... (Start Docker, Checkout, Login — مشابه staging)
- name: Build Docker Image
run: |
DOCKER_BUILDKIT=0 docker build --network host \
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:prod .
- name: Push to Registry
run: |
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:prod
- name: Deploy to Production
run: |
export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
kubectl set image deployment/<svc> <svc>=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
kubectl rollout status deployment/<svc> --timeout=300s
"
تفاوت staging vs production: staging = tag
latest+rollout restart| production = tagsha+set image
🏗️ مشخصات دو محیط
| Staging | Production | |
|---|---|---|
| سرور | 194.5.195.53 |
45.149.79.127 |
| DB | mssql-svc@Foursat |
45.149.79.127,31433@KBS |
| Registry | 194.5.195.53:30080 (local) |
همان staging registry |
| Image Tags | :latest |
:prod + :sha |
| Branch | kub-stage |
production |
| Domains | *.se.kbs1.ir |
*.kbs1.ir |
🐛 مشکل ۱۴: K8S_SERVER اشتباه در prod-deploy.yml (CMS + BackOffice)
تاریخ: February 17, 2026
علت: K8S_SERVER در prod-deploy.yml CMS و BackOffice هنوز 194.5.195.53 (staging) بود بجای 45.149.79.127 (production).
عارضه: kubectl set image به سرور staging ارسال میشد — deployment production آپدیت نمیشد.
فایلهای فیکس شده:
CMS/.gitea/workflows/prod-deploy.yml—K8S_SERVER: 194.5.195.53→45.149.79.127BackOffice/.gitea/workflows/prod-deploy.yml—K8S_SERVER: 194.5.195.53→45.149.79.127- FrontOffice قبلاً درست بود ✅
فیکس اضافی: هر دو workflow از kubectl rollout restart به kubectl set image تغییر کردن تا ایمیج SHA-tagged واقعاً set بشه.
🐛 مشکل ۱۵: نبود appsettings.Production.json — URLهای staging روی production
تاریخ: February 17, 2026
علت: هیچکدوم از ۳ پروژه appsettings.Production.json نداشتن. از طرفی ASPNETCORE_ENVIRONMENT=Production ست بود → fallback به appsettings.json (که URLهای staging داشت).
عارضهها:
- CMS:
CmsBaseUrl=cms.se.kbs1.ir→ ZarinPal callback به staging برمیگشت - CMS:
FrontOfficeBaseUrl=foursat.se.kbs1.ir→ redirect بعد از پرداخت به staging میرفت - FrontOffice:
GwUrl=localhost:32846→ gRPC به هیچجا وصل نمیشد - BackOffice:
GwUrl=localhost:32847→ gRPC به هیچجا وصل نمیشد
فایلهای ساخته شده:
| پروژه | فایل | محتوای کلیدی |
|---|---|---|
| CMS | src/CMSMicroservice.WebApi/appsettings.Production.json |
CmsBaseUrl=cms.kbs1.ir, FrontOfficeBaseUrl=kbs1.ir, DB=KBS, ZarinPal.UseSandbox=false |
| FrontOffice | src/FrontOffice.Main/appsettings.Production.json |
GwUrl=cms.kbs1.ir |
| BackOffice | src/BackOffice/wwwroot/appsettings.Production.json |
GwUrl=cms.kbs1.ir |
⚠️ نکته: CMS فایل
appsettings.Production.jsonدر.gitignoreهست (**/ appsettings.Production.json). باgit add -fترک شد. بعد از هر تغییر باید دوباره force add بشه.
🐛 مشکل ۱۶: nginx image path اشتباه در BackOffice Dockerfile (production branch)
تاریخ: February 17, 2026
علت: Dockerfile روی برنچ production از 194.5.195.53:32082/library/nginx:alpine استفاده میکرد که در رجیستری وجود نداشت. روی kub-stage قبلاً فیکس شده بود ولی merge به production این خط رو override کرده بود.
ارور CI:
Step 9/14 : FROM 194.5.195.53:32082/library/nginx:alpine AS final
manifest for 194.5.195.53:32082/library/nginx:alpine not found: manifest unknown
رفع:
# قبل (اشتباه)
FROM 194.5.195.53:32082/library/nginx:alpine AS final
# بعد (صحیح)
FROM 194.5.195.53:32082/nginx:alpine AS final
نکته: این فیکس مستقیماً روی برنچ production انجام و push شد (کامیت 743403e).