2026 年 5 月 5 日 14 時、複数の デスクトップクライアントが「アクセスしようとしているリソースは現在ロックされており、変更できません」というエラーを画面いっぱいに並べました。サーバー側で テーブルを確認すると、エントリ数は 663,899 件。同期は完全に止まっていました。
本記事では、緊急復旧(30 分)から、真因究明、 への恒久移行までを、実コマンドと数値で記録します。
まず緊急復旧 — 30 分で同期を戻す
ロック詰まりが起きた時点で、サーバー側で確認すべきは 1 点だけです。
docker exec nextcloud-db mariadb -u root -p"$DB_PASS" nextcloud \
-e 'SELECT COUNT(*) FROM oc_file_locks;'
返ってきた件数が 500 を超えていたら異常、5,000 を超えていたら復旧操作が必要です。当方は 663,899 件でした。
復旧手順は 3 ステップ。 を有効にしてから、ロックテーブルを TRUNCATE します。
# 1. メンテナンスモード ON(同期セッションを切断)
docker exec --user www-data nextcloud-app php occ maintenance:mode --on
# 2. ロックテーブルを空にする
docker exec nextcloud-db mariadb -u root -p"$DB_PASS" nextcloud \
-e 'TRUNCATE TABLE oc_file_locks;'
# 3. メンテナンスモード OFF
docker exec --user www-data nextcloud-app php occ maintenance:mode --off
| 要素 | 観測結果 |
|---|---|
| 同期クライアント数 | 4 台(Mac × 2、Windows × 2) |
| クライアントバージョン | 33.0.2 / 33.0.3 / 33.0.4 が混在 |
| 同期対象に含まれていた問題ファイル | 、.next/cache、turbopack/.sst(各 100MB 超) |
| ロックバックエンド | DB()、Redis 未設定 |
恒久対策 — Redis ロック化の実装
DB ロックを Redis ロックに切り替える手順です。Nextcloud 公式 イメージはredis.config.php という上書きファイルが標準で含まれており、環境変数 REDIS_HOST を渡すだけで自動的に Redis ロックが有効になります。
Step 1: docker-compose.yml に Redis サービス追加
services:
nextcloud-redis:
image: redis:7-alpine
container_name: nextcloud-redis
restart: always
command: ["redis-server", "--save", "", "--appendonly", "no"]
networks:
- nextcloud-net
nextcloud-app:
# 既存設定 +
environment:
REDIS_HOST: nextcloud-redis
REDIS_HOST_PORT: 6379
depends_on:
- nextcloud-db
- nextcloud-redis
save "" と appendonly no でディスク永続化を無効化しています。ロック情報は揮発性で十分(コンテナ再起動で消えても問題ない)。
Step 2: 起動 + 再起動
docker compose up -d nextcloud-redis # Redis を先に起動
docker compose up -d nextcloud-app # nextcloud-app を再生成(env 変数反映)
ここで nextcloud-app の再起動が必須です。env 変数は再起動するまで反映されません。
Step 3: 動作確認
# Redis 接続確認
docker exec nextcloud-app php -r '$r = new Redis(); $r->connect("nextcloud-redis", 6379); echo $r->ping();'
# → +PONG
# 設定反映確認
docker exec --user www-data nextcloud-app php occ config:system:get memcache.locking
# → \OC\Memcache\Redis
# Redis にキーが書かれているか
docker exec nextcloud-redis redis-cli DBSIZE
# → 正の整数(11 など)
当方の場合、切り替え後 5 分間で
oc_file_locksの件数は 0 のまま、Redis 側の DBSIZE は安定して 10〜20 件で推移しました。これが正常な状態です。
💡 KEY TAKEAWAYS
Redis ロックは標準でサポートされているのに、デフォルト OFF。docker-compose.ymlに Redis サービスとREDIS_HOSTenv 変数を足すだけで有効化できます。
ハマりポイント 3 つ — 実体験ベース
Nextcloud Redis 化で踏んだ 3 つの罠
落とし穴 1: 設定ファイルの重ね順を見落とす
Nextcloud は/var/www/html/config/配下の*.config.phpをアルファベット順に読み込みます。apcu.config.phpがmemcache.localを に上書き、redis.config.phpがmemcache.lockingを Redis に上書きします。
occ config:system:set memcache.local --value='\OC\Memcache\Redis'で上書きしようとしても、後から読まれるapcu.config.phpで APCu に戻されてしまいます。
突破:memcache.localは APCu のままがベストプラクティス(in-process キャッシュで最速)。Redis 化すべきはmemcache.lockingとmemcache.distributedのみ。これはredis.config.phpが自動で処理します。
落とし穴 2: 環境変数を追加してもコンテナ再起動を忘れる
docker-compose.ymlにREDIS_HOST: nextcloud-redisを追加しただけでは、稼働中のnextcloud-appコンテナには反映されません。docker compose up -d nextcloud-appで再生成するか、docker restart nextcloud-appで再起動が必要です。
これを忘れるとredis.config.phpのif (getenv('REDIS_HOST'))が false で評価され、Redis ロック設定が無効化されたまま稼働します。当方も初回はここで詰まり、occ config:system:get memcache.lockingが空を返して気づきました。
# env 変数の反映確認
docker exec nextcloud-app sh -c 'echo "REDIS_HOST=$REDIS_HOST"'
# → 空ならコンテナ再起動が必要
落とし穴 3: Nextcloud Desktop 側の除外パターンに IME が混入
クライアント側で「無視リストを編集」ダイアログからnode_modules や .next を追加する際、日本語 IME が ON のまま入力すると .turbo…(U+2026 三点リーダー)のような不可視文字が混入します。.turbo ではマッチしないので、除外設定が機能しません。
突破: 除外パターン入力時は IME を強制 OFF(英数モード)にする。追加した行を再度ダブルクリックして文字列を確認する習慣をつける。

