Просмотр исходного кода

add pruner stage and optimize build

Yuki Takei 1 месяц назад
Родитель
Сommit
911325d14e

+ 1 - 1
.kiro/specs/official-docker-image/spec.json

@@ -3,7 +3,7 @@
   "created_at": "2026-02-20T00:00:00.000Z",
   "created_at": "2026-02-20T00:00:00.000Z",
   "updated_at": "2026-02-20T14:05:00.000Z",
   "updated_at": "2026-02-20T14:05:00.000Z",
   "language": "ja",
   "language": "ja",
-  "phase": "validating",
+  "phase": "implemented",
   "approvals": {
   "approvals": {
     "requirements": {
     "requirements": {
       "generated": true,
       "generated": true,

+ 8 - 7
.kiro/specs/official-docker-image/tasks.md

@@ -150,21 +150,22 @@ DHI runtime イメージ (`dhi.io/node:24-debian13`) には `/bin/sh` が存在
 
 
 > Phase 1 で runtime が安定した後に実施する。現行の `COPY . .` + 3 ステージ構成を `turbo prune --docker` + 5 ステージ構成に移行し、ビルドキャッシュ効率を向上させる。
 > Phase 1 で runtime が安定した後に実施する。現行の `COPY . .` + 3 ステージ構成を `turbo prune --docker` + 5 ステージ構成に移行し、ビルドキャッシュ効率を向上させる。
 
 
-- [ ] 7. turbo prune --docker パターンの導入
-- [ ] 7.1 pruner ステージの新設
-  - base ステージの直後に pruner ステージを追加し、`turbo prune @growi/app --docker` でモノレポを Docker 用に最小化する
-  - pnpm workspace との互換性を検証する(非互換の場合は Phase 1 の `COPY . .` パターンを維持)
-  - 出力(json ディレクトリ、lockfile、full ディレクトリ)が正しく生成されることを確認する
+- [x] 7. turbo prune --docker パターンの導入
+- [x] 7.1 pruner ステージの新設
+  - base ステージの直後に pruner ステージを追加し、`turbo prune @growi/app @growi/pdf-converter --docker` でモノレポを Docker 用に最小化する
+  - `@growi/pdf-converter` を含める理由: `@growi/pdf-converter-client/turbo.json` が `@growi/pdf-converter#gen:swagger-spec` タスク依存を持つため、pruned workspace に含めないと turbo がタスク依存を解決できない
+  - pnpm workspace との互換性を検証済み(18 パッケージが正しく出力される)
+  - 出力(json ディレクトリ、lockfile、full ディレクトリ)が正しく生成されることを確認済み
   - _Requirements: 3.1_
   - _Requirements: 3.1_
 
 
-- [ ] 7.2 deps ステージの分離と builder の再構成
+- [x] 7.2 deps ステージの分離と builder の再構成
   - builder ステージから依存インストールを分離し、deps ステージとして独立させる
   - builder ステージから依存インストールを分離し、deps ステージとして独立させる
   - pruner の出力から package.json 群と lockfile のみをコピーして依存をインストールする(レイヤーキャッシュ効率化)
   - pruner の出力から package.json 群と lockfile のみをコピーして依存をインストールする(レイヤーキャッシュ効率化)
   - builder ステージは deps をベースにソースコードをコピーしてビルドのみを行う構成に変更する
   - builder ステージは deps をベースにソースコードをコピーしてビルドのみを行う構成に変更する
   - 依存変更なし・ソースコードのみ変更の場合に、依存インストールレイヤーがキャッシュされることを検証する
   - 依存変更なし・ソースコードのみ変更の場合に、依存インストールレイヤーがキャッシュされることを検証する
   - _Requirements: 3.1, 3.2_
   - _Requirements: 3.1, 3.2_
 
 
-- [ ] 7.3 5 ステージ構成の統合検証
+- [x] 7.3 5 ステージ構成の統合検証
   - base → pruner → deps → builder → release の 5 ステージ全てが正常完了することを確認する
   - base → pruner → deps → builder → release の 5 ステージ全てが正常完了することを確認する
   - Phase 1 の 3 ステージ構成と同等の runtime 動作を維持していることを確認する
   - Phase 1 の 3 ステージ構成と同等の runtime 動作を維持していることを確認する
   - ビルドキャッシュの効率改善(ソースコード変更時に依存インストールがスキップされること)を検証する
   - ビルドキャッシュの効率改善(ソースコード変更時に依存インストールがスキップされること)を検証する

+ 39 - 4
apps/app/docker-new/Dockerfile

@@ -28,11 +28,28 @@ RUN --mount=type=cache,target=$PNPM_HOME/store,sharing=locked \
   pnpm add turbo --global
   pnpm add turbo --global
 
 
 
 
+##
+## pruner — turbo prune for Docker-optimized monorepo subset
+##
+FROM base AS pruner
+
+ARG OPT_DIR
+
+WORKDIR $OPT_DIR
+
+COPY . .
+
+# Include @growi/pdf-converter because @growi/pdf-converter-client has a turbo
+# task dependency on @growi/pdf-converter#gen:swagger-spec (generates the OpenAPI
+# spec that orval uses to build the client). Without it, turbo cannot resolve
+# the cross-package task dependency in the pruned workspace.
+RUN turbo prune @growi/app @growi/pdf-converter --docker
+
 
 
 ##
 ##
-## builder — build + produce artifacts (current 3-stage COPY . . pattern)
+## deps — dependency installation (layer cached when only source changes)
 ##
 ##
-FROM base AS builder
+FROM base AS deps
 
 
 ARG OPT_DIR
 ARG OPT_DIR
 ARG PNPM_HOME
 ARG PNPM_HOME
@@ -42,13 +59,32 @@ ENV PATH="$PNPM_HOME:$PATH"
 
 
 WORKDIR $OPT_DIR
 WORKDIR $OPT_DIR
 
 
-COPY . .
+# Copy only package manifests and lockfile for dependency caching
+COPY --from=pruner $OPT_DIR/out/json/ .
 
 
+# Install build tools and dependencies
 RUN --mount=type=cache,target=$PNPM_HOME/store,sharing=locked \
 RUN --mount=type=cache,target=$PNPM_HOME/store,sharing=locked \
   pnpm add node-gyp --global
   pnpm add node-gyp --global
 RUN --mount=type=cache,target=$PNPM_HOME/store,sharing=locked \
 RUN --mount=type=cache,target=$PNPM_HOME/store,sharing=locked \
   pnpm install --frozen-lockfile
   pnpm install --frozen-lockfile
 
 
+
+##
+## builder — build + produce artifacts
+##
+FROM deps AS builder
+
+ARG OPT_DIR
+
+WORKDIR $OPT_DIR
+
+# Copy full source on top of installed dependencies
+COPY --from=pruner $OPT_DIR/out/full/ .
+
+# turbo prune does not include root-level config files in its output.
+# tsconfig.base.json is referenced by most packages via "extends": "../../tsconfig.base.json"
+COPY tsconfig.base.json .
+
 # Build
 # Build
 RUN turbo run clean
 RUN turbo run clean
 RUN turbo run build --filter @growi/app
 RUN turbo run build --filter @growi/app
@@ -68,7 +104,6 @@ RUN mkdir -p /tmp/release/apps/app && \
   (cp apps/app/.env.production* /tmp/release/apps/app/ 2>/dev/null || true)
   (cp apps/app/.env.production* /tmp/release/apps/app/ 2>/dev/null || true)
 
 
 
 
-
 ##
 ##
 ## release — DHI runtime (no shell, no additional binaries)
 ## release — DHI runtime (no shell, no additional binaries)
 ##
 ##

+ 46 - 21
apps/app/docker-new/Dockerfile.dockerignore

@@ -1,54 +1,79 @@
-# Dependencies and build caches
+# ============================================================
+# Build artifacts and caches
+# ============================================================
 **/node_modules
 **/node_modules
-**/coverage
-**/.pnpm-store
 **/.next
 **/.next
 **/.turbo
 **/.turbo
+**/.pnpm-store
+**/coverage
 out
 out
 
 
-# Docker files (prevent recursive context)
+# ============================================================
+# Version control
+# ============================================================
+.git
+
+# ============================================================
+# Docker files (prevent recursive inclusion)
+# ============================================================
 **/Dockerfile
 **/Dockerfile
 **/*.dockerignore
 **/*.dockerignore
 
 
-# Git
-.git
-
-# IDE and editor settings
-.vscode
-.idea
-**/.DS_Store
+# ============================================================
+# Unrelated apps
+# ============================================================
+apps/slackbot-proxy
 
 
+# ============================================================
 # Test files
 # Test files
+# ============================================================
 **/*.spec.*
 **/*.spec.*
 **/*.test.*
 **/*.test.*
 **/test/
 **/test/
 **/__tests__/
 **/__tests__/
 **/playwright/
 **/playwright/
 
 
-# Documentation (not needed for build)
+# ============================================================
+# Documentation (no .md files are needed for build)
+# ============================================================
 **/*.md
 **/*.md
-!**/README.md
 
 
-# Environment files for local development
+# ============================================================
+# Local environment overrides
+# ============================================================
 .env.local
 .env.local
 .env.*.local
 .env.*.local
 
 
-# Unrelated apps
-apps/slackbot-proxy
+# ============================================================
+# IDE and editor settings
+# ============================================================
+.vscode
+.idea
+**/.DS_Store
 
 
-# CI/CD and config
+# ============================================================
+# CI/CD, DevOps, and project management
+# ============================================================
+.changeset
+.devcontainer
 .github
 .github
+aws
+bin
+
+# ============================================================
+# Linter, formatter, and tool configs (not needed for build)
+# ============================================================
 **/.editorconfig
 **/.editorconfig
 **/.markdownlint.yml
 **/.markdownlint.yml
-**/.mcp.json
 **/.prettier*
 **/.prettier*
 **/.stylelintrc*
 **/.stylelintrc*
 **/biome.json
 **/biome.json
 **/lefthook.yml
 **/lefthook.yml
 
 
-# AI related files
+# ============================================================
+# AI agent configuration
+# ============================================================
 **/.claude
 **/.claude
 **/.kiro
 **/.kiro
+**/.mcp.json
 **/.serena
 **/.serena
-**/AGENTS.md
-**/CLAUDE.md