Difyのアップデート手順|1.16から1.18まで実際に上げて分かった注意点

PRこの記事にはアフィリエイト広告が含まれます。紹介したサービスに申し込まれると、運営者が報酬を受け取ることがあります。評価や順位は報酬で変えていません。広告表記について

Dify は、ほぼ毎月新しい版が出ます。2026年10月23日には 1.18.0 が公開されました。ただ、Dify の公式ドキュメントには版をまたいで使える共通のアップデート手順がなく、版ごとのリリースノートを読んで、そのとおりに進める必要があります。

そこで、1.16.1 で動かしていた Dify を、1.17.1 を経て 1.18.0 まで、公式の手順どおりに実際に上げてみました。リリースノートに書かれていない落とし穴も見つかったので、あわせて解説します。

結論:やることの一覧

いまの版 やること
1.17.0 以前(Weaviate 1.27 を使っている) 先に Weaviate を13段階で上げる。そのあと 1.17.1 に更新する
1.17.1 1.18.0 に更新する。サンドボックス用のトークンの設定が必須
どの版でも 更新の前にバックアップを取る。停止は「Weaviate だけ時間無制限、残りは通常」で行う

手元の検証では、1,005件のチャンクを持つナレッジベースが、すべての段階で正しい検索結果を返しました。

1.16 より前の版から上げる場合は、途中の版のリリースノートも読んでください。たとえば 1.16.1 では DIFY_AGENT_API_TOKEN の設定が必須になり、1.17.0 では EDITION が DEPLOYMENT_EDITION に名前を変えています。

手順0:いまの版とベクトルDBを確かめる

Dify の docker ディレクトリで、次を実行します。

git describe --tags
grep -E '^VECTOR_STORE=' .env
docker compose images weaviate

VECTOR_STORE=weaviate(既定値)で、Weaviate のイメージが 1.27.0 なら、手順2の段階的な更新が必要です。外部の Weaviate や、ほかのベクトルDBを使っている場合は不要です。

手順1:止めてからバックアップする

1.18.0 のリリースノートは、データベース、ベクトルDB、アップロードされたファイル、Agent のデータ、すべての設定ファイルをバックアップするよう求めています。公式の Docker Compose の構成では、これらは次の場所にあります。

  • docker/volumes:データベース、Weaviate、アップロードされたファイルなど
  • docker/.env と docker/envs/ の *.env:設定ファイル
  • 名前付きボリューム:Agent のサンドボックスのデータ(dify_agent_local_sandbox_home など)

バックアップの名前には、いまの版を付けます。日付にすると、同じ日に2回更新したときに上書きされてしまうためです。

docker compose stop -t -1 weaviate
docker compose stop

BK=../backup-1.16.1   # いまの版に合わせる
mkdir "$BK"
sudo cp -a volumes "$BK/volumes"
cp -a .env envs "$BK/"
cp -a docker-compose.override.yaml "$BK/"   # 上書き用のファイルを置いている場合

# 名前付きボリューム(プロジェクト名は、既定ではディレクトリ名の docker)
for v in $(docker volume ls -q --filter label=com.docker.compose.project=docker); do
  docker run --rm -v "$v":/data:ro -v "$(realpath "$BK")":/backup alpine:3.22 \
    tar czf "/backup/$v.tgz" -C /data .
done

サンドボックスのボリュームでは「socket ignored」と表示されますが、問題ありません。手元では、このとおりに実行したバックアップから元の状態に戻せることを確かめました(後の「戻し方」)。

公式の「docker compose stop -t -1」は、そのままでは終わりません

1.18.0 のリリースノートは、全体を docker compose stop -t -1(停止を無制限に待つ)で止めるよう案内しています。手元で実行したところ、10分待っても終わりませんでした。

原因は、nginx、sandbox、ssrf_proxy、agent_ssrf_proxy の4つのコンテナです。これらは最初に起動するプロセスがシェルのため、停止の合図が中のプログラムに伝わりません。待ち時間を無制限にすると、いつまでも待ち続けます。

無制限に待つ必要があるのは、データを壊さないように止める必要がある Weaviate だけです。上のように、Weaviate だけを -t -1 で止め、残りは通常の docker compose stop で止めてください(通常の停止は、10秒待っても止まらなければ強制終了します)。

手順2:1.17.0 以前からは、Weaviate を13段階で上げる

1.17.1 では、同梱の Weaviate が 1.27.0 から 1.39.2 に上がりました。Weaviate はマイナー版を飛ばした更新に対応していないため、Dify 公式の手順は 1.27 → 1.28 → … → 1.39 と1段ずつ上げるよう求めています。飛ばすと、ベクトル検索が警告なしに、元に戻らない形で壊れることがあるとされています。

各段で使うイメージは、公式の手順に載っている次の版です。

段 版 段 版
1 1.27.27 8 1.34.20
2 1.28.16 9 1.35.23
3 1.29.11 10 1.36.23
4 1.30.23 11 1.37.16
5 1.31.22 12 1.38.14
6 1.32.27 13 1.39.2
7 1.33.18

手作業で13回繰り返すのは大変なので、次のスクリプトにまとめました。各段で次のことを行います。

  1. docker-compose.yaml の Weaviate のイメージ指定だけを書き換える
  2. Weaviate を正常に止め、新しい版で起動する
  3. 問い合わせに応答するまで待つ
  4. 版、同期の状態、オブジェクトの数を表示する

手元では、このスクリプトをそのまま実行して確かめています。

weaviate-upgrade.sh(docker ディレクトリに置く):

#!/usr/bin/env bash
# 途中で止まったら、最後に表示された版までを RUNGS から消して再実行する(最初からやり直さない)。
set -euo pipefail

RUNGS=(1.27.27 1.28.16 1.29.11 1.30.23 1.31.22 1.32.27 1.33.18 1.34.20 1.35.23 1.36.23 1.37.16 1.38.14 1.39.2)
KEY=$(grep -E '^WEAVIATE_API_KEY=' .env | cut -d= -f2)

weaviate() {
  docker compose exec -T weaviate wget -qO- --header "Authorization: Bearer ${KEY}" "$@"
}

# バージョン、ノードの同期状態、コレクションごとのオブジェクト数を表示する
report() {
  local names
  weaviate http://localhost:8080/v1/meta | python3 -c 'import json,sys; print("version", json.load(sys.stdin)["version"])' || return 1
  weaviate http://localhost:8080/v1/cluster/statistics | python3 -c 'import json,sys; print("synchronized", json.load(sys.stdin)["synchronized"])' || return 1
  names=$(weaviate http://localhost:8080/v1/schema | python3 -c 'import json,sys; print(" ".join(c["class"] for c in json.load(sys.stdin)["classes"]))') || return 1
  for name in ${names}; do
    weaviate --header 'Content-Type: application/json' \
      --post-data "{\"query\":\"{ Aggregate { ${name} { meta { count } } } }\"}" \
      http://localhost:8080/v1/graphql |
      python3 -c "import json,sys; print('${name}', json.load(sys.stdin)['data']['Aggregate']['${name}'][0]['meta']['count'])" || return 1
  done
}

# 起動直後はコレクションの読み込みが終わっておらず、問い合わせが失敗することがある(公式の注意)。
# 成功するまで最大5分待つ
wait_ready() {
  for _ in $(seq 60); do
    if report >/dev/null 2>&1; then
      return 0
    fi
    sleep 5
  done
  echo "Weaviate の確認に失敗しました。ログを確認してください" >&2
  return 1
}

wait_ready
echo "== 開始前"
report

for tag in "${RUNGS[@]}"; do
  perl -pi -e "s#image: (cr\.weaviate\.io/)?semitechnologies/weaviate:[0-9.]+#image: cr.weaviate.io/semitechnologies/weaviate:${tag}#" docker-compose.yaml
  docker compose stop -t -1 weaviate
  docker compose up -d --no-deps weaviate
  sleep 5
  wait_ready
  echo "== ${tag}"
  report
done

手順1でバックアップを取ったあと、Weaviate だけを起動してから実行します。

docker compose up -d weaviate
bash weaviate-upgrade.sh

各段で次の3点を確かめてください。

  • 表示される version が段の版と一致する
  • synchronized が True になっている
  • オブジェクトの数が「開始前」と同じ

手元では、13段すべてで1,005件のまま変わりませんでした。所要時間は、イメージを取得済みの状態で約2分、初めて取得したときは5分弱でした。

途中で止まった場合は、最初からやり直さないでください。 新しい版で書き込まれたデータを古い版で起動すると、データを壊すおそれがあるためです。最後に表示された版までを RUNGS から消して、続きから実行します。

終わったら Weaviate を止め、書き換えた docker-compose.yaml を元に戻します。

docker compose stop -t -1 weaviate
git checkout -- docker-compose.yaml

段階を飛ばすと、すぐに壊れるのか

比較のため、バックアップを取ったうえで、段階を踏まずに 1.17.1 へ直接上げることも試しました。手元の1,005件のデータでは、検索結果は正しく、Weaviate のログにもエラーは出ませんでした。

ただ、公式は、版を飛ばした場合に「警告なしに、元に戻らない形で」壊れることがあると説明しています。小さなデータで壊れなかったことは、安全の保証にはなりません。手間は数分なので、公式の手順どおりに段階を踏んでください。

手順3:版を切り替え、.env を新しい版に合わせる

git fetch --tags
git checkout 1.17.1

新しい版で増えた設定を .env に取り込みます。公式は、.env.example と手元の .env を比べるよう求めています。比べる作業を自動で行う公式のスクリプト dify-env-sync.sh もあります。

./dify-env-sync.sh

このスクリプトは、実行前の .env を env-backup/ に自動で保存し、.env.example に増えた変数を追加します。手元で使ってみて、次の2点に気づきました。

  • .env.example にない変数は、新しい .env から消えます。 警告は表示されますが、自分で追加した変数(手元では COMPOSE_PROJECT_NAME)は残りませんでした。実行後に、env-backup/ の内容と見比べて足し直してください。
  • macOS に標準で入っている古い bash では動きません。VPS の Ubuntu では問題ありません。

手順4:起動して確かめる

docker compose pull
docker compose up -d

データベースの変換(マイグレーション)は、起動時に自動で実行されます(.env の MIGRATION_ENABLED=true が既定値)。手元では worker のコンテナが実行し、api のログには「Database migration skipped」と出ました。複数のコンテナのうち1つだけが実行する仕組みなので、問題ありません。

起動したら、次の2点を確かめます。

  1. ナレッジベースの検索テストで、文書の内容が返ってくること。公式は、オブジェクトの数だけでは検索が正しく動くかは分からないとして、実際に検索してみることを求めています。
  2. docker compose ps で、外に公開されたポートが増えていないこと(構築の記事の上書き用ファイルを使っている場合)。

1.17.1 から 1.18.0 への更新

手順1〜4と同じ流れで、git checkout 1.18.0 に変えて進めます。1.18.0 では、docker compose up -d の前に、次の2点を済ませてください。

サンドボックス用のトークンを設定する

1.18.0 では、Agent 用のサンドボックスが、空でないトークンを必須にしました。推測されにくい値を作ります。

python3 -c 'import secrets; print(secrets.token_urlsafe(32))'

表示された値を .env の DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN= のあとに書いてから、docker compose up -d を実行します。

設定を忘れて起動すると、agent_backend と local_sandbox の2つのコンテナが、次のエラーで再起動を繰り返しました(手元で確認)。

local_sandbox_auth_token is required for the local runtime backend
shellctl: auth token is required: set SHELLCTL_AUTH_TOKEN or --token

この状態でもナレッジベースの検索は動いたため、気づきにくい点に注意してください。トークンを設定して docker compose up -d を実行し直すと、2つとも正常に起動しました。

PASSWORD_PEPPER は空のままにする

1.18.0 では、パスワードの保存に使う PASSWORD_PEPPER という設定が追加されました(置き場所は envs/core-services/api.env)。リリースノートは、既存の環境では空のままにするよう求めています。途中から値を設定すると、既存のパスワードでログインできなくなるためです。手元では空のまま更新し、既存の管理者アカウントでログインできました。

なお、1.17.1 から 1.18.0 では Weaviate はパッチの更新(1.39.2 → 1.39.13)だけなので、段階的な更新は要りません。

うまくいかなかったときの戻し方

手順1のバックアップがあれば、元の版に戻せます。手元でも、次の手順をそのまま実行し、1.16.1 の状態(Weaviate 1.27.0、1,005件、検索も正常)に戻ることを確かめました。

BK=../backup-1.16.1   # 手順1で作ったディレクトリ
docker compose stop -t -1 weaviate
docker compose down
git checkout -- docker-compose.yaml
git checkout 1.16.1   # 元の版
sudo mv volumes ../volumes.failed-$(date +%Y%m%d%H%M)
sudo cp -a "$BK/volumes" volumes
cp -a "$BK/.env" .env
cp -a "$BK/envs/." envs/
for f in "$BK"/*.tgz; do
  v=$(basename "$f" .tgz)
  docker run --rm -v "$v":/data -v "$(realpath "$BK")":/backup:ro alpine:3.22 \
    sh -c "find /data -mindepth 1 -delete && tar xzf /backup/$v.tgz -C /data"
done
docker compose up -d

失敗した状態の volumes は、消さずに volumes.failed-… として残しています。原因を調べ終わってから削除してください。

新しい版で一度起動したデータを、古い版でそのまま使うのは安全ではありません。Dify 公式の Weaviate の更新手順は、イメージの版だけを戻すのは危険だと説明しています。1.17.1 のリリースノートも、データベースの変換の一部は元に戻せないとしています。戻すときは、必ずバックアップから戻してください。

アップデートを後回しにしないために

Dify にも、2026年に入ってから複数の脆弱性が公表されています。たとえば、ログインしていない人がサーバーから任意の URL にアクセスさせられる問題(1.13.0 で修正)や、ほかのワークスペースのファイルを見られる問題(1.14 系で修正)がありました。

古い版のまま使い続けると、こうした修正を受けられません。GitHub のリリース一覧を RSS リーダーなどで購読し(https://github.com/langgenius/dify/releases.atom)、新しい版が出たらリリースノートを確認する習慣をつけてください。

出典

  1. Dify 1.17.1 のリリースノート(GitHub)(に確認)
  2. Dify 1.18.0 のリリースノート(GitHub)(に確認)
  3. Weaviate Server Upgrade Path(Dify 公式ドキュメント)(に確認)
  4. Environment variables synchronization(Dify の docker/README.md)(に確認)
  5. Dify のセキュリティアドバイザリ(GitHub)(に確認)