OpenClaw Docker環境の崩壊と復旧 — ボリュームマウントの罠

OpenClaw Docker環境の崩壊と復旧 — ボリュームマウントの罠

FF6の世界崩壊後。前日6時間かけて構築した全設定が、ボリュームマウントのミス1つで全滅した記録。

前日までの状態(崩壊前)

所要時間:約6時間

崩壊の瞬間

Googleカレンダー連携のためにdocker-compose.yamlに env_file を追加して docker compose up -d openclaw を実行。コンテナが再作成された瞬間、全ての設定が消えた。

根本原因:ボリュームマウント先の間違い

# ❌ 最初の設定(間違い)
volumes:
  - ./openclaw/data:/root/.openclaw

# ✅ 正しい設定
volumes:
  - ./openclaw/data:/home/node/.openclaw

OpenClawのDockerイメージは nodeユーザー(uid=1000)で動作し、設定は /home/node/.openclaw/ に保存される。/root/.openclaw にマウントしても、OpenClawはそこを使わない。

つまり設定ファイルは最初からホスト側に永続化されていなかった。 コンテナ内の /home/node/.openclaw/ にだけ存在し、コンテナ再作成で蒸発。

失われたもの

項目 状態
openclaw.json(gateway.bind, trustedProxies, LINE設定等) 全滅
auth-profiles.json(OpenRouter APIキー) 全滅
gogcliバイナリ(/home/node/.local/bin/gog) 全滅
gogcli OAuth認証データ(/home/node/.config/gogcli/) 全滅
SOUL.md(日本語設定・パーソナリティ) 全滅
USER.md(ユーザー情報) 全滅
MEMORY.md(会話記憶) 全滅
devices ペアリング 全滅
LINE ペアリング 全滅

復旧作業(2回目の地獄)

1. ボリュームマウントの修正

volumes:
  - ./openclaw/data:/home/node/.openclaw
  - ./openclaw/gogcli:/home/node/.config/gogcli

2. 権限の問題

ボリュームマウント変更後、ホスト側のファイルがroot所有だったため Permission denied で起動失敗。

chown -R 1000:1000 /root/dify/docker/openclaw/data/
chown -R 1000:1000 /root/dify/docker/openclaw/gogcli/

3. 環境変数が設定ファイルを上書きする罠

docker-compose.yamlに OPENCLAW_GATEWAY_BIND=0.0.0.0 が残っていた。これが openclaw.jsongateway.bind: "lan" を毎回上書きしていた。しかも 0.0.0.0 は旧バージョンの書き方で無効 → loopbackにフォールバック → 502。

「何度CLIで直しても元に戻る」の正体。

# ❌ 削除すべき行
environment:
  - OPENCLAW_GATEWAY_BIND=0.0.0.0

4. onboardで設定を再投入

docker exec -it docker-openclaw openclaw onboard

モデル、APIキー、LINEチャネルを再設定。ただしonboardでは言語選択が出なかったため、SOUL.mdはデフォルトの英語テンプレートで再生成された。

5. gateway設定を再投入

docker exec docker-openclaw openclaw config set gateway.bind "lan"
docker exec docker-openclaw openclaw config set gateway.trustedProxies '["172.18.0.0/16"]'
docker exec docker-openclaw openclaw config set gateway.controlUi.allowedOrigins '["http://localhost:18789","http://127.0.0.1:18789","https://your-domain"]'

6. gogcliの再インストール

コンテナ内の /home/node/.local/bin/ に入れたバイナリも消えていた。永続化ボリューム内に置き直し:

# ホスト側で
mkdir -p /root/dify/docker/openclaw/data/bin
curl -fsSL "https://github.com/steipete/gogcli/releases/download/v0.12.0/gogcli_0.12.0_linux_amd64.tar.gz" -o /tmp/gog.tar.gz
tar -xzf /tmp/gog.tar.gz -C /tmp/
cp /tmp/gog /root/dify/docker/openclaw/data/bin/gog
chmod +x /root/dify/docker/openclaw/data/bin/gog
chown 1000:1000 /root/dify/docker/openclaw/data/bin/gog

コンテナ内からは /home/node/.openclaw/bin/gog で参照。PATHを通すにはシンボリックリンクを作成:

docker exec -u 0 docker-openclaw ln -sf /home/node/.openclaw/bin/gog /usr/local/bin/gog

※ シンボリックリンクはコンテナ再作成時に消えるので再実行が必要。恒久対策はdocker-compose.yamlのenvironmentにPATHを追加:

environment:
  - PATH=/home/node/.openclaw/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

7. gogcli OAuth認証のやり直し

docker exec docker-openclaw /home/node/.openclaw/bin/gog auth credentials /home/node/.openclaw/credentials.json
docker exec -it docker-openclaw /home/node/.openclaw/bin/gog auth add g1989n@gmail.com --services calendar --remote --step 1
# → ブラウザで承認 → リダイレクトURLをStep 2に貼り戻し(--services calendar 必須)
docker exec -it docker-openclaw /home/node/.openclaw/bin/gog auth add g1989n@gmail.com --services calendar --remote --step 2 --auth-url 'コピーしたURL全文'

8. ペアリングの再承認(devices + LINE)

docker exec docker-openclaw openclaw devices list
docker exec docker-openclaw openclaw devices approve <ID>
docker exec docker-openclaw openclaw pairing approve line <コード>

9. SOUL.mdに日本語設定を追加

デフォルトの英語テンプレートを活かしつつ、末尾に追記:

## Language

- 必ず日本語で返答する。ユーザーが英語で話しかけても日本語で返す。
- 日本語の丁寧語(です・ます)を基本とするが、堅すぎない。

docker-compose.yaml 最終形(二度と壊さないために)

  openclaw:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: docker-openclaw
    restart: unless-stopped
    ports:
      - "18789:18789"
    volumes:
      - ./openclaw/data:/home/node/.openclaw      # ← /root/.openclawではない!
      - ./openclaw/gogcli:/home/node/.config/gogcli  # gogのOAuthトークン永続化
    environment:
      - OPENCLAW_GATEWAY_PORT=18789
      - PATH=/home/node/.openclaw/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      # OPENCLAW_GATEWAY_BINDは書かない(設定ファイルで管理)
    env_file:
      - ./openclaw/.env   # GOG_ACCOUNT, GOG_KEYRING_PASSWORD

.envファイル(./openclaw/.env, chmod 600)

GOG_ACCOUNT=g1989n@gmail.com
GOG_KEYRING_PASSWORD=(設定したパスワード)

教訓

1. ボリュームマウント先はコンテナ内のユーザーを確認してから決める

docker exec <container> id
# uid=1000(node) → /home/node/.openclaw
# uid=0(root) → /root/.openclaw

2. docker compose restartdocker compose up -d --force-recreate は別物

コマンド 動作 データ
restart 再起動のみ 消えない
up -d 変更なければ何もしない 消えない
up -d --force-recreate コンテナ作り直し マウント正しければ消えない

3. 環境変数は設定ファイルより優先される

docker-compose.yamlの environment に書いた値は、openclaw.json の設定を毎回上書きする。CLIで何度直しても無意味。

4. コンテナ内にインストールしたバイナリは再作成で消える

docker cpapt install でコンテナ内に入れたものは全て揮発性。永続化するにはボリュームマウント内に置く。

5. 困ったらエージェント自身に聞く

OpenClawに「なぜ書き込みできないのか調べて」と聞くと、カレンダーごとのaccessRoleを一覧して原因を教えてくれた。


複数ユーザーからのアクセス

問題

OpenClawは「1つのゲートウェイ、1人の信頼されたオペレーター」設計。ペアリングで承認されたユーザーでも、オーナー以外はexecツール(シェルコマンド実行)が使えない。

解決策:allowFromに複数ユーザーを登録

docker exec docker-openclaw openclaw config set channels.line.allowFrom '["U_owner_id", "U_second_user_id"]'

Googleカレンダー書き込みの注意点

複数カレンダーが紐づいたGoogleアカウントでは、OpenClawが読み取り専用カレンダー(「日本の祝日」等)に書き込もうとして「edit failed」になる場合がある。書き込み先のカレンダーIDを明示的に指定して伝えること。 デフォルトの書き込み先カレンダーの選択ロジックは不明。


ハマりポイント全14個

# 問題 原因 解決策
1 Nginx起動しない $http_upgrade がenvsubstで空文字に 別ファイルに切り出してinclude
2 502 Bad Gateway OpenClawがloopbackでしかリッスンしてない gateway.bind "lan"
3 pairing required DockerのNATでlocalhostに見えない trustedProxies + devices approve
4 Webhook POST 404 パスが /webhooks/line ではなく /line/webhook POSTでパスを検証
5 LINE Access Token 401 Channel IDをAccess Tokenと間違えた 正しいTokenを再発行
6 LINE返信来ない LINEペアリング未承認 pairing approve line <code>
7 ダッシュボード1006 (pairing) devicesペアリング未承認 devices approve
8 ダッシュボード1006 (WebSocket) JSが末尾スラッシュなしでWS接続 location = /openclaw を追加
9 ダッシュボード origin拒否 allowedOriginsに外部ドメインがない allowedOriginsに追加
10 ローカルLLMのハルシネーション qwen2.5:3bが「公式クラウドゲートウェイ」を捏造 公式ドキュメントでダブルチェック
11 設定全消滅 ボリュームマウント /root/.openclaw/home/node/.openclaw マウント先を修正
12 gogバイナリ消滅 コンテナ再作成で揮発 永続化ボリューム内に配置
13 gateway.bindが毎回戻る 環境変数が設定ファイルを上書き docker-compose.yamlから環境変数を削除
14 gog認証state mismatch Step 2にも--services calendarを付ける Step 1と同じフラグをStep 2にも

復旧にかかった時間

約3時間。前日の構築(6時間)と合わせて合計9時間