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 未設定
同じ事故を起こさないために、御社の運用体力を 3 分で見える化しませんか?
細マッチョ企業診断 / 3 分 8 問
診断する

恒久対策 — 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_HOST env 変数を足すだけで有効化できます。

ハマりポイント 3 つ — 実体験ベース



Nextcloud Redis 化で踏んだ 3 つの罠
Nextcloud Redis 化で踏んだ 3 つの罠


落とし穴 1: 設定ファイルの重ね順を見落とす



Nextcloud は /var/www/html/config/ 配下の *.config.phpアルファベット順に読み込みます。apcu.config.phpmemcache.local に上書き、redis.config.phpmemcache.locking を Redis に上書きします。

occ config:system:set memcache.local --value='\OC\Memcache\Redis' で上書きしようとしても、後から読まれる apcu.config.php で APCu に戻されてしまいます。

突破: memcache.local は APCu のままがベストプラクティス(in-process キャッシュで最速)。Redis 化すべきは memcache.lockingmemcache.distributed のみ。これは redis.config.php が自動で処理します。

落とし穴 2: 環境変数を追加してもコンテナ再起動を忘れる



docker-compose.ymlREDIS_HOST: nextcloud-redis を追加しただけでは、稼働中の nextcloud-app コンテナには反映されません。docker compose up -d nextcloud-app再生成するか、docker restart nextcloud-app で再起動が必要です。

これを忘れると redis.config.phpif (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(英数モード)にする。追加した行を再度ダブルクリックして文字列を確認する習慣をつける。

次のアクション

Nextcloud は構築の容易さと引き換えに「初期設定が最低限」で出荷されます。本番運用に耐えるには、Redis ロック化・除外パターン整理・バックアップ計画の 3 点が欠かせません。 本シリーズの第 2 回では、当方が同じ事故をきっかけに構築した「Cloudflare R2 + restic で月 22 円バックアップ」(翌日公開)、第 3 回では「Dropbox 代替を自社で組む判断軸」(翌々日公開)を扱います。 「Nextcloud 同期が重い・止まる」「自社にどの構成が合うか判断したい」という方は、まず 細マッチョ企業診断 で運用体力の現在地を把握ください。神経系(判断速度)・耐久力(継続力)・筋力(実行力)の 5 軸で、どこを優先的に補強すべきかが見える化されます。 EXBANK では Nextcloud の構築・運用代行も承っています。事故対応より「事故を起こさない体制づくり」から始めましょう。