Skip to content

English {#english}

prego-docker Implementation Plan (Custom Apps Build + Auto Rebuild)

Purpose: Specify files, folders, workflows, and Secrets for prego-docker so implementation can follow directly.
No code generation — plan, file tree, requirements, tag policy, integration only.

  • Target: /Users/marco/prego-docker (image build, config, custom app definition).
  • Two axes: (1) Single optimized image from Frappe official custom Containerfile (ERPNext + HRMS + prego-saas-app). (2) Auto rebuild when custom app changes (prego-saas-app → repository_dispatch → prego-docker).
  • Related: prego-docker-github-actions-docker-hub-plan, frappe-docker-hrms-custom-image-build-plan, docker-hub-stack-ansible-deploy-plan; resource-optimization-safe-adoption-plan (Gunicorn, plan limits).

Current: apps.json with ERPNext, HRMS, prego-saas-app (tag e.g. v1.0.0); single bench init; no APP_SHA block; clone_token for private; repository_dispatch only; Verify image apps (4 apps); trivy-scan (Critical 0).


1. Design: single image (no merge)

Recommended: Base on official Frappe/ERPNext image; one runtime image with apps.json (ERPNext + HRMS + prego-saas-app). Not: merging multiple images. Forbidden: bench get-app/install-app at runtime; production = immutable image.


2–7. File tree, Dockerfile, apps.json, build.yml, repository_dispatch, secrets

  • §2 Tree: Dockerfile, apps.json, .dockerignore, README; resources/core/nginx/; .github/workflows/build.yml, trivy-scan.yml.
  • §3 Vendoring from frappe_docker: Containerfile → Dockerfile; nginx-template.conf, nginx-entrypoint.sh. Dockerfile: Base (frappe user, nginx, node, wkhtmltopdf), Builder (APPS_JSON_BASE64, bench init), backend (COPY, VOLUME, CMD gunicorn).
  • §4 apps.json: ERPNext version-15, HRMS version-15, prego-saas-app tag (e.g. v1.0.0). Workflow Base64 for APPS_JSON_BASE64; tag validated via GitHub API.
  • §5 build.yml: Trigger repository_dispatch custom_app_updated only. Steps: checkout, validate tag, setup-qemu/buildx, Docker Hub login, APPS_JSON_BASE64, set tag, build & push (iamfork/prego-repo:$TAG, latest), Verify image apps.
  • §6 prego-saas-app: notify-image-rebuild.yml — on push/tag v*.., POST dispatches to prego-docker with event_type custom_app_updated; PREGODOCKER_DISPATCH_PAT.
  • §7 Secrets: prego-docker (DOCKERHUB_*, PREGO_SAAS_APP_CLONE_TOKEN); prego-saas-app (PREGODOCKER_DISPATCH_PAT).

Full tables (§1–§7) and exact wording are in the Korean section below.


한국어 {#korean}

기획서: prego-docker 코드 구현 상세 (Custom Apps 포함 빌드 + 자동 재빌드 전략)

목적: prego-docker 레포(/Users/marco/prego-docker)에 생성할 파일·폴더·워크플로우·Secrets를 구현 단계에서 그대로 따라 쓸 수 있는 형태로 명세한다.
코드 생성 없음 — 기획·파일 트리·요구사항·태그 정책·연동 시나리오만 정리.

현재 반영 (tag 기반 pinning·검증·취약점): apps.json에 ERPNext(version-15), HRMS(version-15), prego-saas-app(태그 예: v1.0.0) 포함. 단일 bench init 만 사용하며, Dockerfile의 APP_SHA 블록은 제거됨. private 레포인 경우 clone_token으로 bench init 시 clone URL만 치환. 빌드 트리거는 repository_dispatch 전용(push 없음). 푸시 후 Verify image apps 단계로 4개 앱 존재 검증, trivy-scan.yml로 취약점 스캔(정책: Critical 0). 상세: prego-docker-exit-128-duplicate-clone-resolution-plan.md, prego-docker-image-verify-and-vulnerability-plan.md.


1. 설계 원칙: 이미지 통합 빌드 (합치기 방식 비권장)

구분내용
권장공식 Frappe/ERPNext 이미지를 베이스로 두고, apps.json으로 ERPNext + HRMS + custom app(prego-saas-app)을 포함한 단일 Runtime 이미지를 재빌드.
비권장여러 이미지(erpnext-image + hrms-image + custom-app-image)를 “합쳐서” 하나로 쓰는 방식. Docker는 실행 시 이미지 병합을 지원하지 않음.
금지실행 중 bench get-app / bench install-app으로 앱 추가. Production에서는 코드가 이미지에 포함된 immutable image가 전제.

Bench 환경은 apps/ 아래에 erpnext, hrms, prego_saas_app 등이 물리적으로 설치되어 있어야 하며, SaaS 멀티테넌트는 코드=이미지, Site=데이터 구조로 단일 통합 Runtime 이미지가 표준이다.


2. prego-docker 최종 파일 트리 (구현 시 산출물)

대상: Pregoi/prego-docker (로컬 경로: /Users/marco/prego-docker).

prego-docker/
├── Dockerfile
├── apps.json
├── .dockerignore
├── README.md
├── resources/
│ └── core/
│ └── nginx/
│ ├── nginx-template.conf
│ └── nginx-entrypoint.sh
└── .github/
└── workflows/
├── build.yml
└── trivy-scan.yml
  • Dockerfile: frappe_docker images/custom/Containerfile 패턴 기반. Base·Builder·backend 멀티 스테이지, APPS_JSON_BASE64·FRAPPE_BRANCH·PYTHON_VERSION 빌드 인자, VOLUME·gunicorn CMD.
  • resources/core/nginx/ : 공식 custom Containerfile이 COPY하는 두 파일. Vendoring(복사) 필수. 소스: frappe_docker 리포 동일 경로.
  • apps.json: 앱 목록(ERPNext version-15, HRMS version-15, prego-saas-app 태그 예: v1.0.0). 단일 소스; 워크플로는 checkout된 파일을 Base64로 전달.
  • .dockerignore: 빌드 컨텍스트 경량화(.git, .github, README 등).
  • README.md: 빌드 원리, Secrets, 멀티아키텍처, custom app 자동 재빌드 흐름, (선택) Hetzner/운영 안내.
  • .github/workflows/build.yml: repository_dispatch 전용 (custom_app_updated). 태그 유효성 검사(GitHub API), 레포 apps.json → APPS_JSON_BASE64, build-push·캐시·태그, 푸시 후 Verify image apps 단계.
  • .github/workflows/trivy-scan.yml: 취약점 스캔(workflow_dispatch·주기). 정책: CRITICAL 시 실패. prego-docker-image-verify-and-vulnerability-plan.md §5.

3. Frappe 공식 custom Containerfile 기반 Vendoring

3.1 복사할 소스 (frappe_docker)

prego-docker 경로frappe_docker 소스비고
Dockerfileimages/custom/Containerfile내용 기반. 버전 고정: FRAPPE_BRANCH=version-15, PYTHON_VERSION=3.11.
resources/core/nginx/nginx-template.confresources/core/nginx/nginx-template.conf그대로 복사.
resources/core/nginx/nginx-entrypoint.shresources/core/nginx/nginx-entrypoint.sh그대로 복사.

공식 custom Containerfile은 위 nginx 두 파일을 COPY하므로 prego-docker에도 동일 경로로 두어야 빌드가 성공한다.

3.2 Dockerfile 요구사항 (구현 시 반영)

항목내용
베이스python:${PYTHON_VERSION}-slim-bookworm. ARG: PYTHON_VERSION=3.11, WKHTMLTOPDF, NODE_VERSION=20.
Base 스테이지frappe 사용자 생성, nginx·node(nvm)·wkhtmltopdf·frappe-bench 설치, templates/nginx·nginx-entrypoint.sh 복사·권한.
Builder 스테이지APPS_JSON_BASE64 있으면 /opt/frappe/apps.json으로 decode. USER frappe 전환 후 bench init --apps_path=... --frappe-branch=version-15 등으로 앱 설치. common_site_config.json 초기화.
backend 스테이지Builder 결과물 COPY, WORKDIR, VOLUME(sites, sites/assets, logs), CMD gunicorn.
고정 인자FRAPPE_BRANCH=version-15, (선택) FRAPPE_PATH=https://github.com/frappe/frappe.

구현 시 frappe_docker 최신 images/custom/Containerfile을 참고해 위 구조와 동일하게 작성한다.


4. apps.json 정의

현재 구현: apps.json에 ERPNext(version-15), HRMS(version-15), prego-saas-app(태그 예: v1.0.0) 세 가지 모두 포함. bench init 한 번으로 설치. prego-saas-app이 private이면 빌드 시 PREGO_SAAS_APP_CLONE_TOKEN으로 clone URL만 치환. Dockerfile에 APP_SHA 블록 없음.

4.1 레포에 커밋된 apps.json

urlbranch
ERPNexthttps://github.com/frappe/erpnextversion-15
HRMShttps://github.com/frappe/hrmsversion-15
prego-saas-apphttps://github.com/Pregoi/prego-saas-appv1.0.0 (Git 태그)

워크플로는 checkout된 apps.json을 Base64로 APPS_JSON_BASE64에 넣어 Dockerfile에 전달. prego-saas-app 태그는 build.yml의 “Validate prego-saas-app tag exists” 단계에서 GitHub API로 존재 여부 검사.

(4.2 구 절 제거: 현재는 tag 기반 단일 bench init만 사용, commit pin/APP_SHA 블록 없음.)


5. prego-docker GitHub Actions: build.yml

5.1 트리거

트리거용도
repository_dispatch types: custom_app_updatedprego-saas-app에서 custom app 변경 시 prego-docker 빌드 자동 실행. 유일한 빌드 트리거(push·tag 트리거 없음).

5.2 단계 요구사항 (순서)

순서단계내용
1checkoutactions/checkout@v4.
2Validate prego-saas-app tag existsapps.json에서 prego-saas-app의 branch(태그) 추출, GitHub API로 Pregoi/prego-saas-app refs/tags/ 존재 여부 확인. CLONE_TOKEN 사용.
3setup-qemu · setup-buildxdocker/setup-qemu-action@v3, docker/setup-buildx-action@v3.
4login Docker Hubdocker/login-action@v3, DOCKERHUB_USERNAME, DOCKERHUB_TOKEN.
5Prepare APPS_JSON_BASE64레포의 apps.json을 base64로 GITHUB_ENV에 설정.
6Set Tagclient_payload.tag 또는 pregoapp-<short_sha>, 항상 latest도 푸시.
7Build & Pushbuild-args: APPS_JSON_BASE64, FRAPPE_BRANCH=version-15. secrets: clone_token(PREGO_SAAS_APP_CLONE_TOKEN). tags: iamfork/prego-repo:$TAG, iamfork/prego-repo:latest.
8Verify image apps푸시한 이미지 pull 후 docker run ... ls .../apps/ 로 frappe, erpnext, hrms, prego_saas_app 존재 검사. 누락 시 job 실패.

이미지 이름: iamfork/prego-repo.

5.3 태그 정책 요약

상황이미지 태그 예시
repository_dispatch (custom_app_updated)pregoapp-<short_sha>, latest (또는 client_payload.tag가 있으면 해당 태그 + latest).

6. custom app 변경 시 자동 재빌드: repository_dispatch

6.1 전략

prego-saas-app(Repo A) push 시 prego-docker(Repo B)의 workflow를 repository_dispatch로 호출하는 방식. GitHub 커뮤니티 표준 패턴.

6.2 prego-saas-app 쪽 산출물 (구현 시)

대상: Pregoi/prego-saas-app (별도 레포).

경로내용
.github/workflows/notify-image-rebuild.ymlprego-saas-app의 main/staging/develop push 및 tag v*.. 시, prego-docker로 repository_dispatch 전송. payload에 tag·app_sha 포함.

6.3 notify-image-rebuild.yml 요구사항

항목내용
트리거push branches: main, staging, develop / tags: v*...
단계curl로 POST https://api.github.com/repos/Pregoi/prego-docker/dispatches. event_type: custom_app_updated. client_payload: tag(태그 push면 태그명, 아니면 pregoapp-<short_sha>), app_sha: GITHUB_SHA.
인증Authorization: Bearer ${{ secrets.PREGODOCKER_DISPATCH_PAT }}.

prego-docker가 private이면 PAT scope repo 필요. public이면 최소 권한 PAT 또는 GitHub App 토큰 권장.

6.4 prego-saas-app GitHub Secret

Secret설명
PREGODOCKER_DISPATCH_PATprego-docker 레포를 호출할 수 있는 Personal Access Token. prego-docker가 private이면 repo scope.

7. GitHub Secrets 정리

7.1 prego-docker

Secret용도
DOCKERHUB_USERNAMEDocker Hub 로그인 아이디.
DOCKERHUB_TOKENDocker Hub Access Token (Account Settings → Security).
APPS_JSON_BASE64기본 빌드용. 레포의 apps.json 내용을 base64 인코딩한 값. repository_dispatch가 아닌 push 빌드에서 사용.

7.2 prego-saas-app

Secret용도
PREGODOCKER_DISPATCH_PATprego-docker repository_dispatch 호출용 PAT.

8. 동작 흐름 요약

[기본 빌드]
main/staging/develop push 또는 v*.*.* tag push
→ prego-docker build.yml 실행
→ APPS_JSON_BASE64 = Secret 또는 레포 apps.json base64
→ 멀티아키텍처 빌드·푸시 (latest / 태그)
[Custom app 변경 시 재빌드]
prego-saas-app push (main/staging/develop 또는 tag)
→ notify-image-rebuild.yml 실행
→ repository_dispatch → prego-docker (event_type: custom_app_updated, client_payload: app_sha, tag)
→ prego-docker build.yml 실행
→ pinned apps.json 생성 (prego-saas-app = app_sha)
→ 멀티아키텍처 빌드·푸시 (pregoapp-<sha> 등)

9. (선택) Production Compose · Staging→Prod 승격 · Blue/Green

아래는 구현 순서에서 나중 단계 또는 별도 Runbook/레포로 둘 수 있는 항목이다. 기획만 명세.

9.1 Production docker-compose

  • 목적: MariaDB·Redis 분리, sites·logs 볼륨 분리. 이미지: iamfork/prego-repo:${IMAGE_TAG} 또는 digest.
  • 구성: mariadb, redis, admin(사이트 생성/마이그레이션용 1회성·대기 컨테이너), internal 네트워크. 환경변수: DB_HOST, REDIS_CACHE/QUEUE/SOCKETIO, SOCKETIO_PORT.
  • 볼륨: mariadb_data, redis_data, sites, logs. 멀티테넌트 SaaS는 sites 볼륨이 핵심.
  • 배치: 구현 시 prego-dockercompose/ 또는 deploy/ 하위에 예시로 두거나, prego-ansible·Hetzner runbook에서 참조할 수 있도록 경로를 문서화.

9.2 Staging → Production 승격 (digest 고정)

  • 원칙: Staging에서 검증한 동일 이미지(digest) 를 Production에 승격. 태그 재빌드가 아닌 digest 고정으로 배포.
  • prego-docker: build 단계에서 docker/build-push-actionoutputs.digest를 artifact 또는 로그로 보관. (선택) digest를 파일로 저장해 upload-artifact.
  • 승격 워크플로우: workflow_dispatch로 “Staging 검증 digest” 입력받아, Production 환경(GitHub Environment·Required reviewers)에서만 배포 스크립트 실행. SSH 등으로 서버에 동일 digest 이미지 배포.

9.3 Zero-downtime Blue/Green

  • 구성: app_blue, app_green 두 서비스 + nginx(또는 Traefik). 프록시가 active 쪽만 upstream으로 사용.
  • 배포: 새 digest를 inactive 쪽에 먼저 배포 → healthcheck 통과 후 nginx upstream을 전환 → nginx reload. 스크립트 예: deploy-bluegreen.sh가 현재 active 판단, inactive에만 새 이미지로 recreate, healthcheck 후 upstream 교체·reload.
  • 이미지 참조: image: iamfork/prego-repo@${IMAGE_DIGEST} 형태로 digest 고정 사용 권장.

구현 완료 반영: prego-docker 레포에 다음이 추가됨.

  • 9.1: compose/docker-compose.prod.example.yml, compose/README.md.
  • 9.2: 빌드 워크플로에서 digest 출력; .github/workflows/promote.yml.example (workflow_dispatch + digest 입력).
  • 9.3: compose/bluegreen/ (docker-compose.bg.example.yml, nginx upstream 예시, deploy-bluegreen.sh, README).
    서버 Runbook: Prego 레포 docs/runbook/prego-docker-image-deploy.md.

10. 구현 시 체크리스트

prego-docker

  • resources/core/nginx/nginx-template.conf, nginx-entrypoint.sh vendoring (frappe_docker 동일 경로에서 복사).
  • Dockerfile 작성 (frappe_docker images/custom/Containerfile 기반, version-15·3.11 고정, Base/Builder/backend, APPS_JSON_BASE64·FRAPPE_BRANCH).
  • apps.json 커밋 (ERPNext, HRMS, prego-saas-app main).
  • .dockerignore 작성.
  • .github/workflows/build.yml 작성: 트리거(push·repository_dispatch), QEMU·buildx·login, (dispatch 시) pinned apps.json 생성, Set Tag, Build & Push(cache, multi-arch, build-args).
  • README.md: 빌드 원리, Secrets, 멀티아키텍처, custom app 자동 재빌드 흐름.
  • GitHub Secrets: DOCKERHUB_USERNAME, DOCKERHUB_TOKEN, APPS_JSON_BASE64.

prego-saas-app

  • .github/workflows/notify-image-rebuild.yml 작성: push·tag 시 repository_dispatch to prego-docker, client_payload (tag, app_sha).
  • GitHub Secret: PREGODOCKER_DISPATCH_PAT.

검증

  • prego-docker main push → 이미지 빌드·푸시(latest) 확인.
  • prego-saas-app push → prego-docker 빌드 트리거·pregoapp-* 태그 푸시 확인.
  • Docker Hub에서 해당 태그에 linux/amd64, linux/arm64 매니페스트 확인.

11. 연관 문서

문서연계
prego-docker-github-actions-docker-hub-plan.md기본 워크플로우·Secrets·멀티아키텍처·Hetzner CPX.
frappe-docker-hrms-custom-image-build-plan.mdapps.json·custom Containerfile·buildx.
docker-hub-stack-ansible-deploy-plan.mdAnsible에서 사용할 이미지 소스·패턴 A(서버 분리).
naming-conventions.md이미지·태그 네이밍 일관성.

다음 단계: 이 기획서에 따라 prego-docker·prego-saas-app에 위 파일 트리·워크플로우·Secrets를 구현한다. 코드는 본 기획서의 요구사항을 만족하는 범위에서 별도 생성한다.

Help