🔑

Dev Containers上でClaude Codeの認証が安定しない問題

に公開

はじめに

こんにちは。touyuです。普段はNstockでソフトウェアエンジニアをしています。
私が所属するチームではDev Containersを採用しており、コンテナ内からClaude Codeを利用しているのですが、頻繁に再認証が必要になってしまう問題に困っていました。
本記事では、この問題の詳細と原因、そして現時点での対処法について紹介します。

TL;DR

  • ~/.claude/.credentials.json~/.claude.jsonの永続化が必要だよ
  • マウントして永続化するとファイルが削除されたり(特にmacOS)、破損したりするので辛いよ
  • 少し工夫してNamed volumeで永続化しよう

問題の原因

この認証が持続しない問題は、以下の複数の要因が絡んでいます。

  1. 認証情報を保持する ~/.claude/.credentials.json が永続化されていない、または存在しない
  2. オンボーディング完了状態と作業ディレクトリの信頼設定を保持する ~/.claude.json が永続化されていない

1. ~/.claude/.credentials.json の問題

.credentials.json が永続化されていない

Claude Codeは、環境によって認証情報の保存先が異なります。

  • macOS以外の場合: ~/.claude 配下に accessTokenなどの認証情報を含んだ .credentials.json を生成します。
  • macOSの場合: 通常キーチェーンに保存します。

Dev Containers上では、コンテナのイメージに依存しますが、基本的に前者に該当するため .credentials.json が生成されます。
そのため、コンテナのリビルド時などに .credentials.json が失われると再度認証が必要になってしまうため永続化する必要があります。
とはいえ、公式のリファレンス実装や他のサンプルコードでも ~/.claude 自体を永続化、あるいはマウントされるようになっているため特に意識せずとも実現できていることが多いです。

macOS環境では .credentials.json が削除されてしまう

この問題を少しややこしくしているのが、 ~/.claude をマウントしてホスト環境(macOS)と同期させている場合です。
macOSで、/login/logout 実行時に、.credentials.json を削除することがわかっています。
つまり、Dev Containers上で作成された .credentials.json をホスト側にマウントしていた際に、ホスト側でClaude Codeにログインすると、.credentials.json が削除され、Dev Containers上では認証情報にアクセスできなくなり、未認証状態になってしまいます。

類似のIssueも上がっており、Closeされていますが、この問題は依然として発生しており、現状回避策はありません。
https://github.com/anthropics/claude-code/issues/1414

2. ~/.claude.json の問題

~/.claude.json が永続化されていない

~/.claude/.credentials.json が存在するにも関わらず、依然として再認証を要求されるケースがあります。
その場合、~/.claude.json の設定と永続化を見直すと解決する可能性があります。

~/.claude.json はユーザ設定や、各プロジェクトごとの設定、履歴など様々なものを管理している魔境ファイルです。
settings.json 等に置き換えられていく予定のようですが、現在でも様々な用途で利用されています。

その中でも特に認証周りに関わる項目が次の2つです。

~/.claude.json
{
  "hasCompletedOnboarding": true,
  ...
  "projects": {
    "/workspace": {
      "hasTrustDialogAccepted": true
      ...
    }
  }
}

hasCompletedOnboarding が記載されていない、もしくはfalseの場合、以下のオンボーディング画面が表示されるようになっています。
そのため、仮に認証情報があったとしても true に設定されていない限り未認証状態のように扱われてしまいます。
一度オンボーディング画面を通過し設定を完了すると有効化されるための、その状態で永続化されている必要があります。
オンボーディング画面

hasTrustDialogAccepted が記載されていない、もしくはfalseの場合、プロジェクトを信頼するかどうかの確認画面が以下のように表示されるようになっています。
こちらも同様に一度設定すれば有効化された状態になるので、その状態で永続化されている必要があります。
確認画面

~/.claude.json をマウントすると破損しやすい

~/.claude.json は複数プロセスから編集すると定期的に破損します。
特にホスト環境にマウントしている状態でホスト上、コンテナ上両方(あるいは別コンテナ間)で並列にClaude Codeを実行すると経験上、破損する確率がさらに高くなります。

結局どう設定すればいい?

前述の2つの問題は、ホスト環境にマウントしてしまうことで追加の問題を発生させてしまっていました。
そのため、現状では安定して動作させるためにはホスト環境やコンテナ間での認証や設定の共有は妥協することになりますが、コンテナ内で独立して永続化するのが良さそうだと考えています。

具体的な方法としては、.devcontainer.json の mounts設定で ~/.claudeNamed volumeで設定します。

.devcontainer.json
{
  "mounts": [
    "source=claude-code-config-${devcontainerId},target=/<HOME_DIR>/.claude,type=volume",
  ]
}

~/.claude.json も同様に設定したいところですが、単一のファイルのため純粋にNamed volumeを設定するのは難しいです。
しかし、実は ~/.claude.json~/.claude/.config.json で代替することができます。[1]
~/.claude/.config.json は手動で作成することで、~/.claude.json より優先して利用させることができます。
これを利用し、devcontainer.jsonのpostCreateCommand 等でファイルがまだ存在しなければ作成するようにしておくことで、~/.claudeNamed volumeだけで完結させることができます。

.devcontainer.json
{
  "postCreateCommand": "[ -f ~/.claude/.config.json ] || echo '{}' > ~/.claude/.config.json"
}
脚注
  1. 公式ドキュメントに記載があるわけではなく、アップデート等で急に利用できなくなる可能性があります。 ↩︎

Nstock Tech Blog

Discussion