Skip to content

feat: 本番イメージの Nix build 化と ADR-0021 の Accepted 昇格(Phase 3)#501

Merged
yusuke0610 merged 3 commits into
mainfrom
feat/adr-0021-phase3-docker-nix
Jul 16, 2026
Merged

feat: 本番イメージの Nix build 化と ADR-0021 の Accepted 昇格(Phase 3)#501
yusuke0610 merged 3 commits into
mainfrom
feat/adr-0021-phase3-docker-nix

Conversation

@yusuke0610

@yusuke0610 yusuke0610 commented Jul 16, 2026

Copy link
Copy Markdown
Owner

変更概要

ADR-0021 の最終 Phase(Phase 3): 本番イメージのビルドを pip → Nix build 化し、dev / CI / 本番の 3 経路のビルド機構を flake + uv.lock に一元化する。あわせて ADR-0021 を Accepted へ昇格し、関連 ADR(0017 / 0014)の前提記述を追従させる。

実現方式: Nix-in-Dockerfile

backend/Dockerfile を 2 段構成に書き換え:

  1. builder stagenixos/nix): nix build .#backend-runtime — devshell と同一の uv2nix build(Python 3.13 + 全依存 + WeasyPrint ライブラリ + curl + cacert)
  2. final stagedebian:12-slim): closure を /nix/store へコピーし、/runtime symlink 経由で PATH / LD_LIBRARY_PATH / SSL_CERT_FILE を固定パス参照

dockerTools(pure Nix イメージ)ではなくこの方式にしたのは、macOS ローカルで linux イメージを nix build できず、make dev-build(docker compose)の開発フローを維持するため(ADR の実装追記に記録済み)。

付随変更

  • build context をリポジトリルートへ変更(Dockerfile が flake.nix を参照するため): docker-compose.yml / deploy.yml を追従、ルートに whitelist 方式の .dockerignore を新設
  • aarch64-linux(Apple Silicon ローカル)対応: libsql-experimental は aarch64 wheel が PyPI に無く sdist(Rust)ビルドになるため、flake の override で Rust ツールチェーンを注入。--option sandbox false 下で crates.io を取得する(従来 pip 経路と同等の妥協。本番 = amd64 は全依存 wheel でハッシュ検証付き
  • deploy-backend の timeout 20→30 分(Nix レイヤ構築時間を考慮)
  • ADR-0021 Accepted 昇格 + 索引更新、ADR-0017(「uv 非管理・requirements.txt が lockfile」前提)/ ADR-0014(pip manager → pep621)へ更新追記、rules/backend/python.md の「Dockerfile に apt 追加」ルールを「flake の backendRuntime に追加」へ更新

セルフレビューチェックリスト

必須確認

  • make ci が pass している(ruff / pyright 0 errors / pytest 724 passed / vitest 382 passed / build-web)+ make lint-adr-index pass
  • コメント・ドキュメント・エラーメッセージは日本語で記述した

条件付き確認(該当する場合のみ N/A と記入)

  • N/A — app/schemas/ / app/routers/ の変更なし
  • N/A — ページ・認証・ナビゲーション・レイアウトの変更なし(E2E 不要)
  • N/A — 新規環境変数なし(SSL_CERT_FILE はイメージ内固定値)
  • N/A — web/src/ の変更なし

破壊的変更

  • 破壊的変更あり → 概要: docker build の呼び出し規約が変更(context がリポジトリルートに。docker build backend/ は不可、docker build -f backend/Dockerfile . へ)。compose / deploy.yml は追従済みのため運用影響なし。API 契約・DB スキーマは変更なし

ADR

  • ADR-0021 のステータス変更(Proposed → Accepted)+ 実装追記。索引・ADR-0017・ADR-0014 を同 PR で追従(make lint-adr-index green)

検証(実機)

  • Apple Silicon(aarch64 = 最難関経路)で end-to-end 確認済み: docker build 完走(libsql の Rust sdist ビルド込み ~11 分)→ docker compose up/health 200(alembic 適用・libSQL 接続・WeasyPrint import 通過)。イメージ 745MB
  • 実走で潰した不具合 2 件: ① debian slim に CA 証明書が無く libsql(rustls)が起動失敗 → cacert 同梱 + SSL_CERT_FILE。② glib の default output に lib が無く libgobject 不発見 → lib.getLib で lib output 明示

レビュー時の注目点

  • smoke-backend が本 PR の実質的な検証ゲート(amd64 経路はここで初実走。wheel のみなのでローカル arm より速いはず)
  • deploy(Cloud Run)は本 PR マージ後の main push で新経路が初めて走る。deploy-backend の所要時間と Cloud Run 起動を要観察
  • flake / uv.lock 変更時は docker の Nix レイヤが全再構築される(レイヤキャッシュはある環境なら効く)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements
    • Updated the backend production image build for more consistent dependency handling across development, deployment, and runtime environments.
    • Improved Docker and Docker Compose configuration for backend builds using the repository-wide build context.
    • Added platform-specific support for backend dependencies, including ARM-based builds.
    • Extended backend deployment build time to improve reliability in cache-less environments.
    • Strengthened smoke testing to build the production image, start required services, and verify the health endpoint.

backend/Dockerfile の pip wheel 経路を全廃し、builder stage(nixos/nix)内で
flake の backend-runtime(uv2nix build。devshell と同一の Python 環境 +
WeasyPrint ライブラリ + cacert)を nix build して final stage(debian:12-slim)
へ closure コピーする構成に変更。dev / CI / 本番の 3 経路のビルド機構を
flake + uv.lock に一元化する。

- flake.nix: packages.backend-env / backend-runtime を出力に追加。
  WeasyPrint ライブラリは lib.getLib で lib output を明示(glib の default
  output は bin のため)。cacert を同梱し SSL_CERT_FILE で参照(debian slim は
  ca-certificates 非同梱で libsql/rustls が起動時に失敗する)
- aarch64-linux のみ libsql-experimental が sdist(Rust)ビルドとなるため、
  Rust ツールチェーン等を override で注入(本番 amd64 は wheel のみで純粋)
- build context をリポジトリルートへ変更(flake.nix 参照のため)。
  docker-compose.yml / deploy.yml を追従し、ルートに .dockerignore を新設
- deploy-backend の timeout を 20→30 分に拡大(Nix レイヤ構築時間を考慮)
- ADR-0021 を Accepted へ昇格(実装追記付き)。索引・ADR-0017(uv 非管理
  前提)・ADR-0014(Renovate manager)・rules/backend/python.md を追従

検証: Apple Silicon で docker build → compose up → /health 200 を実機確認
(libsql Rust ビルド・alembic 適用・WeasyPrint import を通過)。make ci green。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 218d88b2-7447-4a69-b567-c64da365c5d2

📥 Commits

Reviewing files that changed from the base of the PR and between 31151ce and 8df219f.

📒 Files selected for processing (3)
  • .dockerignore
  • docs/adr/0014-renovate-dependency-automation.md
  • docs/adr/0017-mutation-testing-and-slack-notifications.md
📝 Walkthrough

Walkthrough

The backend production image now uses a Nix-built runtime closure. Flake outputs provide the runtime, Docker builds from the repository root, and Compose and deployment workflows use the updated context. ADRs and backend dependency guidance reflect the accepted Nix-managed environment.

Changes

Backend runtime image

Layer / File(s) Summary
Runtime closure and platform overrides
flake.nix, .claude/rules/backend/python.md
Platform-specific native dependency overrides and a bundled backend-runtime package are added, with guidance covering devshell and production runtime system packages.
Nix-based Docker packaging
backend/Dockerfile
The Dockerfile builds .#backend-runtime with Nix, copies the closure into a Debian image, configures runtime paths, and adds backend application files.
Build context and runtime validation
.dockerignore, docker-compose.yml, .github/workflows/deploy.yml, .github/workflows/test.yml
Docker builds use a restricted repository-root context, deployment allows longer builds, and smoke-test documentation identifies the production image path.
Architecture decision alignment
docs/adr/*
ADR-0021 is marked Accepted, and related ADRs update dependency-management, mutation-testing, and implementation details.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CIOrCompose
  participant Dockerfile
  participant NixBuilder
  participant RuntimeImage
  participant SmokeBackend
  CIOrCompose->>Dockerfile: build from repository root
  Dockerfile->>NixBuilder: build .#backend-runtime
  NixBuilder-->>Dockerfile: return runtime closure
  Dockerfile->>RuntimeImage: copy closure and backend files
  SmokeBackend->>RuntimeImage: start image and libsql
  RuntimeImage-->>SmokeBackend: /health returns 200
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the main changes: switching the production image to a Nix-based build and promoting ADR-0021 to Accepted.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/adr-0021-phase3-docker-nix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added feature 新機能 documentation Improvements or additions to documentation backend バックエンド ci CI / ワークフロー labels Jul 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.claude/rules/backend/python.md (1)

36-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Point contributors to the shared native-library list.

flake.nix derives both the devshell library path and backendRuntime from weasyPrintLibs. Directing contributors to edit the generated consumers independently risks environment drift and may omit LD_LIBRARY_PATH wiring.

Proposed clarification
-- Python ライブラリがシステムパッケージ(C ライブラリ等)に依存する場合、`flake.nix` の **devshell(`devShells.default.packages`)と本番ランタイム(`backendRuntime` の `paths`)の両方**に追加すること
+- Python ライブラリがシステムパッケージ(C ライブラリ等)に依存する場合、`flake.nix` の共有ネイティブライブラリ一覧(現在の `weasyPrintLibs`)へ追加し、devshell の `makeLibraryPath` と `backendRuntime.paths` の両方へ反映されることを確認する
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/rules/backend/python.md around lines 36 - 37, Update the Python
dependency guidance around the devshell and backendRuntime to direct
contributors to the shared weasyPrintLibs native-library list in flake.nix.
Instruct them to add required system libraries there rather than editing
devShells.default.packages or backendRuntime.paths independently, preserving the
shared LD_LIBRARY_PATH wiring.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.dockerignore:
- Around line 9-12: Update the .dockerignore backend rules by first re-including
backend/, then explicitly re-including each required directory and its contents
with !backend/... and !backend/.../** patterns for alembic_migrations, app, and
scripts. Keep backend/app/**/__pycache__ as the final exclusion so Docker COPY
includes the needed files while omitting caches.

In `@docs/adr/0014-renovate-dependency-automation.md`:
- Around line 31-34: Normalize both ADRs to reflect the completed dependency
migration: in docs/adr/0014-renovate-dependency-automation.md lines 31-34,
update stale Python ecosystem and manager descriptions to PEP 621/uv.lock and
the current manager, or explicitly mark them historical; in
docs/adr/0017-mutation-testing-and-slack-notifications.md lines 22-23, update
the preceding bullet and mutmut table to match the completed PEP 621/Nix
migration. Preserve the existing pinning behavior.

---

Nitpick comments:
In @.claude/rules/backend/python.md:
- Around line 36-37: Update the Python dependency guidance around the devshell
and backendRuntime to direct contributors to the shared weasyPrintLibs
native-library list in flake.nix. Instruct them to add required system libraries
there rather than editing devShells.default.packages or backendRuntime.paths
independently, preserving the shared LD_LIBRARY_PATH wiring.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dc1d685a-1f66-4fec-b75a-ed53bebf668a

📥 Commits

Reviewing files that changed from the base of the PR and between 973d8f6 and 31151ce.

📒 Files selected for processing (11)
  • .claude/rules/backend/python.md
  • .dockerignore
  • .github/workflows/deploy.yml
  • .github/workflows/test.yml
  • backend/Dockerfile
  • docker-compose.yml
  • docs/adr/0014-renovate-dependency-automation.md
  • docs/adr/0017-mutation-testing-and-slack-notifications.md
  • docs/adr/0021-nix-managed-python-env.md
  • docs/adr/README.md
  • flake.nix

Comment thread .dockerignore Outdated
Comment thread docs/adr/0014-renovate-dependency-automation.md
yusuke0610 and others added 2 commits July 17, 2026 00:35
BuildKit では旧形式でも動作するが、除外ディレクトリ配下の re-include を解釈しない
ビルダー実装があるため、!backend/ → backend/* → 個別 re-include の標準形にする。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ADR-0014 / 0017 の requirements.txt 前提の記述が更新追記と矛盾して読めるため、
履歴であることを明示する(原文は書き換えず、履歴保持の ADR 規約に沿う)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit a914fb4 into main Jul 16, 2026
20 checks passed
@yusuke0610
yusuke0610 deleted the feat/adr-0021-phase3-docker-nix branch July 20, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend バックエンド ci CI / ワークフロー documentation Improvements or additions to documentation feature 新機能

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant