Phase1 ナレッジ
WBS 1.1(サーバー環境構築・Tunnel 移行)を進める過程で発生した疑問・エラー・判断を、 後から読んでも再現できるよう丁寧に残した資料です。
開発ログ は「いつ・何を実行したか」の時系列。 本ページは「なぜそうなったか」「どう調べて・何を直して解消したか」を中心に記述します。 各項目の末尾に、インフラ実務の視点からのSuperengineer からの一言を添えています。
この資料の読み方
| 見出し | 意味 |
|---|---|
| きっかけ | 質問が生まれた背景、またはエラーに気づいた状況 |
| 経緯 | 試したこと・判明したこと・次に何をしたか(解決までの流れ) |
| 結論 | 最終的な理解・正しい操作・再発防止 |
| Superengineer からの一言 | 現場のインフラ担当が伝えそうな助言(第3者視点) |
目次
| ID | テーマ | 種別 |
|---|---|---|
| K-01 | PoC から Windows PC への Tunnel 移行 | 設計理解 |
| K-02 | server/ と .env の役割 | 設計理解 |
| K-03 | TUNNEL_TOKEN 誤設定(Tunnel ID と Connector Token の混同) | エラー解消 |
| K-04 | Pi 側 cloudflared を止める理由 | 設計理解 |
| K-05 | Cloudflare 画面の cloudflared.exe 指示 | 設計理解 |
| K-06 | Docker Desktop 未起動(pipe エラー) | エラー解消 |
| K-07 | docker compose コマンドの意味 | 設計理解 |
| K-08 | Pi 上 Docker 停止(sudo・サービス名) | エラー解消 |
| K-09 | PowerShell の curl 問題 | エラー解消 |
| K-10 | PostgreSQL を compose に含める理由 | 設計理解 |
| K-11 | 疎通確認 — localhost と公開 URL | 設計理解 |
| K-12 | MS-1 達成までの全体の流れ | まとめ |
| K-13 | エラー早見表 | 参照 |
| K-14 | Git — add / commit / push の順序 | 運用 |
| K-15 | 次の段階 — WBS 1.2 スタブ Android アプリ | 移行 |
K-01 PoC から Windows PC への Tunnel 移行
きっかけ
runbook では「PoC の Tunnel を再利用し、cloudflared の接続先を Raspberry Pi から Windows PC に移す」とある。 一方で、「Pi の cloudflared を止めなくても、別 Tunnel を新規に立てればよいのでは?」という疑問が生じた。
経緯
poc-api-tunnel・DNS・api.dammy-otoko.com が稼働していることを確認。
新規 Tunnel 作成は DNS 設定の重複・手戻りリスクがあるため不採用と決定。
結論
変更するのは cloudflared が動くマシン だけ。 Tunnel 名・公開 URL・DNS は PoC 資産をそのまま使う。 自宅 PC は CGNAT(キャリア側の NAT により、自宅回線にインターネットから直接届くグローバル IP が無い状態)のため、 ルーターのポート開放だけでは外部公開できない。cloudflared が Cloudflare へ外向きに接続し、 そのトンネル経由でリクエストを受け取る構成が必須。
flowchart LR
subgraph before["移行前"]
APP1[クライアント] --> CF1[Cloudflare]
CF1 --> PI[cloudflared @ Pi] --> API1[PoC API]
end
subgraph after["移行後"]
APP2[クライアント] --> CF2[Cloudflare]
CF2 --> PC[cloudflared @ Windows] --> API2[FastAPI + DB]
end
before -.->|"Tunnel・URLは同じ"| after
K-02 server/ ディレクトリと .env
きっかけ
リポジトリ内に server/ があり、runbook では server/.env に
TUNNEL_TOKEN を書くとある。
「server という名前のディレクトリは単にバックエンドをまとめただけ?」
「.env はなぜ Git に載せず、.env.example だけ載せるの?」という整理の質問。
経緯
server/ 配下に実装。クライアント(将来の Flutter スタブ)と役割を分ける命名。
.env.example(テンプレ)を Git 管理し、実値の .env は .gitignore で除外。
db api を起動し localhost 疎通(1.1.2 / 1.1.3)。
その後 TUNNEL_TOKEN を設定して cloudflared(1.1.1)— 段階的に確認する方が効率的と runbook で並べ替え。
結論
flowchart TB
EX[.env.example Git管理] -->|copy| ENV[.env ローカルのみ]
ENV --> COMPOSE[docker-compose.yml]
COMPOSE --> DB[(db)]
COMPOSE --> API[api]
COMPOSE --> CF[cloudflared]
server/= バックエンド実行一式(API・DB・Tunnel)。物理サーバーそのものではない.env= Compose 起動時に読み込む秘密情報・接続設定.env.example= 必須キーの説明付きテンプレ。clone 後の最初の一歩
K-03 TUNNEL_TOKEN 誤設定 — Tunnel ID と Connector Token の混同
きっかけ
Pi 側 cloudflared 停止後、PC で docker compose --profile tunnel up -d cloudflared を実行。
docker compose ps で cloudflared が Restarting (255) を繰り返す。
外部 URL は error code: 1033。localhost の API は正常。
経緯
server/.env の TUNNEL_TOKEN に
UUID 形式(例: 716ae640-c39a-....)を設定していた。
Cloudflare ダッシュボードで Tunnel を選ぶと ID が目立つため、これがトークンだと誤解しやすい。
docker compose logs cloudflared を確認すると、
繰り返し Provided Tunnel token is not valid. が出力。
コンテナは起動直後に終了コード 255 で再起動ループに入る。
poc-api-tunnel → Configure を開く。
Windows タブに次のような1行コマンドが表示される。
cloudflared.exe service install eyJhIioi...(ここから末尾までがトークン)
cloudflared.exe service install の直後に続く長い文字列全体が
Connector Token(コネクタ認証用トークン)である。これを server/.env の TUNNEL_TOKEN= に
1行で貼り付ける(引用符なし・改行なし)。
docker compose --profile tunnel up -d cloudflared を再実行。
curl.exe https://api.dammy-otoko.com/api/v1/health → {"status":"ok"}。
test-feedback.ps1 → HTTP 201。MS-1 達成。
結論
flowchart LR
UUID["Tunnel ID UUID"] -->|誤| X["255 / 1033"]
EYJ["Connector Token service install 以降"] -->|正| OK["cloudflared Up / MS-1"]
| 種類 | 形式 | 用途 |
|---|---|---|
| Tunnel ID | UUID 形式(716ae640-c39a-4fd0-.... のような短い識別子) | ダッシュボード上で Tunnel を区別するための ID。TUNNEL_TOKEN には使えない |
| Connector Token(コネクタトークン) | cloudflared.exe service install の後に続く長い1行の文字列(多くは eyJ で始まる) | server/.env の TUNNEL_TOKEN= に設定する値 |
cloudflared.exe を入れなくてよい。まず docker compose logs cloudflared を見る。
トークン系の不具合は、ログに token is not valid と正直に出ることが多い。
正しいトークンは、画面に表示される
cloudflared.exe service install (ここから末尾まで)
の部分だけをコピーする。Tunnel 一覧に出る UUID 形式の ID とは別物なので混同しない。
K-04 Pi 側 cloudflared を止める理由(同一 Tunnel への二重接続)
きっかけ
runbook では移行前に Pi で docker compose stop cloudflared とある。
「止めずに PC でも繋いだらダメなのか?」
経緯
poc-api-tunnel に接続していた(2026-06-07 時点で /ping 応答確認済み)。
sudo docker compose stop cloudflared で停止してから PC 側を起動。
結論
flowchart TB
REQ[api.dammy-otoko.com] --> CF[Cloudflare]
CF --> PI[Pi cloudflared]
CF --> PC[PC cloudflared]
PI --> OLD[PoC API]
PC --> NEW[新 FastAPI]
手順の順序: Pi 停止 → PC 起動。PoC の api サービス停止は任意(Tunnel には無関係)。
/ping か、新 API の /api/v1/health か)で向き先を必ず確認する。
K-05 Cloudflare 画面の「cloudflared.exe をインストール」
きっかけ
PC 側 cloudflared が token エラーで落ちている間、Cloudflare ダッシュボードに
「Install cloudflared connector」および Windows 向け cloudflared.exe service install が表示された。
「これを実行しないと Tunnel が有効化されないのでは?」という不安。
経緯
cloudflared.exe service install の後に続く長いトークン文字列 を
server/.env の TUNNEL_TOKEN= に設定すること。
Docker タブを選んでも同じトークンが表示される。
結論
ダッシュボードの .exe 手順 = コネクタ未接続時のガイド。
本プロジェクトでは docker compose --profile tunnel up -d cloudflared が .exe インストールに相当する。
docker compose --profile tunnel up)で渡せているか」だけでよい。
K-06 Docker Desktop 未起動 — pipe エラー
きっかけ
Windows PC で docker compose up を実行したところ、
最初は docker コマンド自体が見つからない。
インストール後は docker version で Client(クライアント)の情報だけ表示され、
Server(サーバー=コンテナを実際に動かす Docker Desktop 本体)の行がなく、
open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified というエラー。
Raspberry Pi 用の sudo docker を Windows で試すも、Windows 標準では sudo は使えない。
経緯
%LOCALAPPDATA%\Programs\DockerDesktop\ 配下に置かれる。
インストール直後は docker コマンド(CLI)だけが使える状態になり、
Docker Desktop アプリ本体(Engine)がまだ起動していないことがある。
docker version を再実行。
出力に Server: 行(例: Docker Desktop 4.76.0)が表示されれば、
Engine(コンテナ実行エンジン)の起動完了。
docker compose up -d --build db api が成功。
結論
docker コマンドは「リモコン(Client)」、Docker Desktop 本体は「エンジン(Server)」。
リモコンだけあっても、エンジンが止まっていればコンテナは動かない。
Windows では Linux と違い sudo は不要。
flowchart LR
PS[PowerShell の docker コマンド]
CLI[Docker Client]
ENG[Docker Engine Docker Desktop本体]
PS --> CLI
CLI -->|"名前付きパイプで接続"| ENG
ENG --> CNT[db api cloudflared コンテナ]
CLI -.->|"Engine 未起動"| ERR[pipe not found エラー]
docker コマンドが打てることと、Docker でコンテナが動くことは別問題。
作業開始時は docker version を実行し、Server: の行があるかを習慣的に確認する。
PC 再起動後は、いつもより先に Docker Desktop アプリを起動する。経験者でもここを忘れがち。
K-07 docker compose コマンドの読み方
きっかけ
MS-1 確認用に4つのコマンドを実行したが、「何をしているか分からない」状態だった。 runbook の手順を理解するための整理。
経緯
2026-06-07、次の順で実行し MS-1 を達成した。
docker compose up -d --build db api— DB・API 起動(Tunnel なし)curl.exe http://localhost:8000/api/v1/health— ローカル疎通docker compose --profile tunnel up -d cloudflared— Tunnel 接続test-feedback.ps1 -BaseUrl "https://api.dammy-otoko.com"— 外部経路で FB 送信
結論
sequenceDiagram
participant U as 操作者
participant DC as docker compose
participant DB as db
participant API as api
participant CF as cloudflared
U->>DC: up -d --build db api
DC->>DB: Healthy 待ち
DC->>API: 起動 port 8000
U->>DC: --profile tunnel up cloudflared
DC->>CF: TUNNEL_TOKEN で接続
| オプション | 意味 |
|---|---|
-d | バックグラウンド実行(detached)。ターミナルを占有せず、裏でコンテナを動かし続ける |
--build | 起動前に Docker イメージをソースから再ビルドする(コード変更を反映) |
db api | db と api サービスだけ起動(cloudflared はこの段階では起動しない) |
--profile tunnel | docker-compose.yml で profiles: [tunnel] が付いた cloudflared だけを追加で有効化する |
db・api・cloudflared を一括起動せず、
「DB+API 起動 → localhost 疎通 → cloudflared 起動 → 公開 URL 疎通」の順に進めたのは良い判断。
障害が出たとき「どの段階まで成功しているか」が分かりやすく、切り分けに時間がかからない。
K-08 Raspberry Pi 上 Docker 停止 — sudo とサービス名
きっかけ
Pi に SSH 接続し docker compose ps を実行。
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock。
sudo 付きで再実行すると cloudflared が Up 5 weeks と確認できた。
停止後、PoC API(コンテナ名 poc-api)も止めたいが
docker compose stop poc-api → no such service。
経緯
damio01 は docker グループに所属しておらず、
Docker デーモン(/var/run/docker.sock)へのアクセス権がない。
そのため sudo docker compose ...(管理者権限で実行)が必要だった。
sudo docker compose ps の出力には NAME 列と SERVICE 列がある。
docker compose stop に指定するのは SERVICE 列 の名前
(cloudflared / api)。
NAME 列の poc-api はコンテナ名であり、stop の引数には使えない。
sudo docker compose stop cloudflared で Tunnel コネクタを停止 — 成功。
Tunnel 移行に必須。
sudo docker compose stop api(サービス名)。
コンテナ名 poc-api ではない。
結論
flowchart TB
PS[docker compose ps]
PS --> NAME[NAME = コンテナ名]
PS --> SVC[SERVICE = stop で指定する名前]
docker compose ps を見るときは SERVICE 列を確認する癖をつける。
permission denied が出たら、まず sudo を付けて再実行してよい。
恒久的には Pi のユーザーを docker グループに追加する方法もあるが、
今回の移行作業では sudo docker compose stop cloudflared だけで Tunnel 切り替えは足りる。
PoC の api まで止めるのは必須ではなく、旧 API と混同しないための任意作業。
K-09 PowerShell の curl — 別名問題
きっかけ
docker compose up 成功直後、
curl http://localhost:8000/api/v1/health が
「接続が予期せずに閉じられました」。
コンテナは Started なのに疎通失敗 — API が壊れたのかと誤解しやすい。
経緯
curl と打つと、実際には
Invoke-WebRequest(PowerShell 組み込みの HTTP コマンド)の別名が動く。
Linux や runbook で想定している curl とは挙動が異なる。
curl.exe http://localhost:8000/api/v1/health に変更 →
{"status":"ok"}。Invoke-RestMethod でも同様に成功。
test-feedback.ps1 の JSON 送信は
Windows curl のインライン JSON 問題(BOM・エスケープ)を避けるため、
事前に inference.json ファイルを生成する方式に修正済み(開発ログ参照)。
結論
Windows の runbook 疎通確認は curl.exe を明示する。runbook v1.3 で反映済み。
curl.exe と拡張子まで付けて実行する。
コンテナ起動直後の一瞬だけ失敗することもあるが、今回の主因は PowerShell の別名問題だった。
失敗したら API のログ(docker compose logs api)と curl.exe の両方で切り分ける。
K-10 なぜ PostgreSQL があるか
きっかけ
FB 受信で画像は data/storage/ に保存される。
それならファイルだけで足りないか — DB の役割の質問。
経緯
結論
flowchart LR
POST[POST /feedback] --> IMG[画像 storage/]
POST --> DB[(feedbacks)]
feedbacks テーブルは「いつ・どのファイルか」の索引とメタデータ。
最初は SQLite でも動くが、本番に近い Docker Compose の練習として PostgreSQL を入れた判断は妥当。
K-11 疎通確認 — localhost と公開 URL
きっかけ
test-feedback.ps1 に -BaseUrl がある。
引数なしと https://api.dammy-otoko.com 指定の違いが MS-1 確認で重要。
経緯
localhost:8000)で API 実装の正しさを確認 — 完了。
結論
flowchart TB
subgraph A["経路A localhost"]
L1[PC] --> L2[api:8000]
end
subgraph B["経路B 公開URL MS-1"]
T1[PC] --> T2[Cloudflare] --> T3[cloudflared] --> T4[api]
end
localhost で health が通って安心した段階は、あくまで「PC 内の API が動いている」証明まで。
MS-1 の完了条件は「インターネット経由(https://api.dammy-otoko.com)でも同じ API が応答する」こと。
公開 URL で test-feedback.ps1 が成功するまで、Tunnel 移行は完了と言わないでほしい。
K-12 MS-1 達成までの全体の流れ(2026-06-07)
経緯(時系列まとめ)
flowchart TD
A[Docker Desktop 起動] --> B[db + api 起動]
B --> C[localhost 疎通 OK]
C --> D[Pi cloudflared 停止 sudo]
D --> E[PC cloudflared 起動]
E --> F{TUNNEL_TOKEN 正しい?}
F -->|Tunnel ID を誤設定| G[255 / 1033]
G --> H[service install 以降のトークンに修正]
F -->|Connector Token 正| I[cloudflared Up]
H --> I
I --> J[公開 URL health OK]
J --> K[test-feedback.ps1 MS-1]
最大のハマりどころは TUNNEL_TOKEN に Tunnel ID(UUID)を入れてしまったこと。
正しくは Cloudflare 画面の cloudflared.exe service install の後に続く長い文字列。
それ以外(Docker Desktop 未起動、Pi で sudo が必要、PowerShell の curl 別名)は、
個別に切り分け可能な問題だった。
docker compose up)を一度だけ試しておくと安心。
K-13 エラー早見表
flowchart TD
START[問題発生]
START --> Q1{docker version Server?}
Q1 -->|No| A1[Docker Desktop 起動]
Q1 -->|Yes| Q2{cloudflared STATUS}
Q2 -->|Restarting 255| A2[logs: token invalid → service install 以降を設定]
Q2 -->|Up| Q3{外部 URL}
Q3 -->|1033| A3[Pi 残存? token?]
Q3 -->|OK| OK[疎通成功]
| 症状 | 今回の経緯での原因 | 最初の一手 |
|---|---|---|
docker 未認識 | Desktop 未インストール / PATH | Desktop インストール・起動 |
dockerDesktopLinuxEngine | Docker Desktop 本体(Engine)が起動していない | Docker Desktop アプリを起動し、docker version で Server 行を確認してからターミナルを開き直す |
token is not valid | Tunnel ID(UUID)を TUNNEL_TOKEN に設定 | Configure 画面の cloudflared.exe service install 以降の文字列をコピー |
error code: 1033 | cloudflared が Tunnel に接続できていない(上記 token 誤りが典型) | docker compose ps で STATUS を確認し、docker compose logs cloudflared を読む |
| PowerShell curl 失敗 | Invoke-WebRequest 別名 | curl.exe |
| Pi permission denied | docker.sock 権限 | sudo docker compose |
no such service: poc-api | サービス名とコンテナ名の混同 | stop api / stop cloudflared |
docker compose logs は現在地の確認。
困ったらまず docker compose ps で各コンテナの STATUS を見、
続けて docker compose logs cloudflared --tail 20(または api)を読む。
これでも原因が分からなければ K-03(トークン設定)と K-06(Docker Desktop 起動)に戻る。
今回の作業時間の大半は、この2点のどちらかだった。
K-14 Git — add / commit / push の順序
きっかけ
MS-1 達成後、README・開発ログ・Phase1 ナレッジなどの変更を GitHub へ反映しようとした。
git add . のあと、
git push -m "Cloudflaredをraspberry pi →Windowsへ置き換え" を実行したところ、
error: unknown switch 'm' となった。
「add の次は push ではなかったか?」という疑問。
経緯
git status で変更ファイルを確認。
修正済み HTML・README と、新規の docs/dev-log.html・docs/phase1-knowledge.html などが
「Changes not staged」または「Untracked」として表示された。
git add . を実行。
変更が「Changes to be committed」(ステージ済み)に移動。
この時点ではまだ GitHub には何も送られていない。ローカル PC 上の「コミット予定箱」に載っただけ。
git push -m "..." を実行 → 失敗。
push コマンドには -m(メッセージ)オプションがない。
-m は git commit 用。
git commit -m "メッセージ"(ローカルに記録)→
git push(GitHub へ送信)。
git status に
Your branch is ahead of 'origin/main' by 1 commit と出ている場合、
以前に commit 済みで push だけされていないコミット がある。
新しい commit のあと、push 1回で複数コミットまとめて送れる。
結論
flowchart LR
W[作業ディレクトリの変更] --> A["git add"]
A --> S[ステージ領域]
S --> C["git commit -m メッセージ"]
C --> L[ローカル履歴]
L --> P[git push]
P --> R[GitHub origin]
| コマンド | 意味 | メッセージ -m |
|---|---|---|
git add | 次の commit に含めるファイルを選ぶ | 使わない |
git commit -m "..." | ステージ内容をローカル履歴に記録する | ここで書く |
git push | ローカルの commit を GitHub へ送る | 使わない |
実行例:
git status
git add .
git commit -m "CloudflaredをRaspberry PiからWindows PCへ移行し、MS-1達成のドキュメントを更新"
git push
コミットに含めない方がよいもの:
server/.env(秘密情報)は .gitignore 済み。
scripts/inference.json は test-feedback.ps1 実行時に毎回生成される一時ファイルのため、
必要なければ add しない(または今後 .gitignore に追加する)。
git status で「ahead of origin by N commits」を見れば、送る commit の数も分かる。
.env が accidentally staged されていないかだけは毎回目視確認する習慣を。
K-15 次の段階 — WBS 1.2 スタブ Android アプリ
きっかけ
WBS 1.1(サーバー環境構築)と MS-1(Tunnel 経由 FB 受信)が完了した。 次に何をするか — WBS・検証計画では 1.2 スタブ Android アプリ が続く。
経緯
test-feedback.ps1 から
https://api.dammy-otoko.com へ FB を送り、インフラ経路を確認した。
結論 — WBS 1.2 の内訳
flowchart LR
S1["1.2.1 Flutter プロジェクト app/"]
S2["1.2.2 画像選択・ダミー推論・FB 送信"]
S3["1.2.3 端末から Tunnel 経由 FB 検証"]
S1 --> S2 --> S3
| WBS | 内容 | 成果物イメージ |
|---|---|---|
| 1.2.1 | Flutter プロジェクト作成 | app/ 最小構成 |
| 1.2.2 | FB 送信実装 | 画像 + 推論 JSON を POST /api/v1/feedback |
| 1.2.3 | 端末検証 | 実機/エミュレータから api.dammy-otoko.com へ送信成功 |
前提(サーバー側): Windows PC で Docker Desktop 起動 → db・api・cloudflared が稼働していること。
参照: WBS・ガントチャート、機能・関数定義一覧(F-01〜F-03)、データフロー
関連資料
| 資料 | 用途 |
|---|---|
| Phase1 サーバー手順 | 手順の再現 |
| 開発ログ | 日付付き実施記録 |
| データフロー | FB 受信の論理構造 |
| 用語集 | Connector Token 等の定義 |