Dify OSS版 × プロキシ環境(Zscaler 等)で発生する不具合と対策まとめ
〜 docker-compose.yaml フル記述の修正例つき 実務者向け完全ガイド 〜
企業ネットワークでよく使われる Zscaler や 社内プロキシ環境 で
Dify OSS を動かすと大量のエラー が発生します。
公式ドキュメントにも情報が少ないため、
実務で遭遇したトラブル事例と、再現性のある対処方法を 体系的にまとめた記事 です。
社内環境ではZcalerのような仕組みが必要なのは理解しています。
しかし、Webの情報は個人環境でトラブルが少ないです。
社内では何が原因でトラブルに会うかわからないのがZscalerの仕組みです。
この記事の対象
- Dify OSS を 企業ネットワークで運用している / したい 人
- Zscaler や社内 Proxy があって OpenAI / Plugin / Firecrawl がエラーになる 人
- docker-compose.yaml に Proxy / CA 設定をどう書くべきか知りたい 人
- Zscalerが原因で何か通信エラーに苦しんでいる人
前提環境
- Dify OSS 1.9.x~1.10.x
- Docker / Podman
- Zscaler などの HTTPS Inspection 環境
- 社内 Proxy(例:http://proxy.example.co.jp:8080)
- Linux(Ubuntu / RedHat / WSL2)
※ 各プロキシ値は例示、実際の環境に合わせて読み替え。
1. なぜ Zscaler 環境でエラーが多発するのか(ざっくり)
Zscaler は SSL Inspection(HTTPS を一度解読して検査する) 仕組みのため、
- OpenAI / marketplace.dify.ai / firecrawl.dev などへの HTTPS 通信で
- 証明書を Zscaler 独自の証明書にすり替える
- コンテナ内の CA ストアがそれを 信頼しない
- さらに社内 Proxy 設定により
- 本来は内部だけで完結する
api → weaviateなどの通信まで Proxy 経由になって壊れる
- 本来は内部だけで完結する
という現象が起こります。
Dify OSS は
- 外部 API(OpenAI / Azure / Marketplace / Firecrawl など)
- 内部コンテナ間通信(api / worker / sandbox / weaviate / plugin_daemon)
の両方が多く、Zscaler の影響をモロに受ける構成 になっています。
2. プロキシ環境で頻発する不具合(実例)
❌ 事例1:プラグインダウンロードが 403 / timeout
curl: (56) Received HTTP code 403 from proxy
Error: failed to download plugin package
原因
-
marketplace.dify.aiへのアクセスが Zscaler / Proxy で遮断 -
plugin_daemonコンテナが Proxy 経由で外部へ出ていく
対策
-
NO_PROXYにplugin_daemonを含める - Zscaler の CA をコンテナ内に登録
- どうしてもダメな場合は、ローカルに .difypkg をダウンロードして「ローカルインストール」
curl -x "" -O "https://marketplace.dify.ai/…/plugin.difypkg"
❌ 事例2:OpenAI API が 429(RateLimit)っぽく見えるが、実は Proxy / TLS エラー
Dify のエラー上では:
[models] Rate Limit Error, Error code: 429
しかしログを見ると:
connect ETIMEDOUT api.openai.com:443
原因
- Zscaler による TLS 中間者方式で証明書がすり替えられている
- コンテナ内の CA ストアに Zscaler の Root CA がなく、証明書検証に失敗
対策
-
api.openai.com:443や*.openai.azure.com:443を FW / Zscaler 設定で許可 - ホスト OS とコンテナに Zscaler Root CA を登録
❌ 事例3:Firecrawl(Website Crawl)が 500 / timeout
error: Firecrawl fetch timeout
Internal Server Error
原因
-
firecrawl.devへのアクセスが Zscaler / Proxy で止められる - bot / crawler と判断されブロック
対策
-
NO_PROXYにfirecrawl.devを含める - 企業環境では URL クローリングは動作しない前提で、PDF 手動登録に切り替える 運用が現実的
❌ 事例4:Sandbox(ssrf_proxy)が外部 fetch できない
certificate error: unknown authority
原因
- Sandbox コンテナ内で Zscaler CA が信頼されていない
- 外部 HTTP アクセス時に Zscaler 証明書を検証できず失敗
対策
- Zscaler CA を Sandbox コンテナにもマウント
- 必要に応じて
sandbox/ssrf_proxyをNO_PROXYに含める
❌ 事例5:Weaviate が timeout / EOF
connect: connection refused
EOF
原因
-
内部通信 であるはずの
api → weaviateが Proxy に送られてしまう -
NO_PROXYにweaviateやapiが正しく入っていない
対策
-
NO_PROXYにweaviate,api,web,db,redisなど内部ホスト名を正しく列挙する
❌ 事例6:docker pull が x509 エラー
x509: certificate signed by unknown authority
原因
- コンテナイメージ取得時に Zscaler が TLS を改ざん
- Docker デーモンが Zscaler の証明書を信頼していない
対策(ホスト OS 側)
sudo cp ZscalerRootCA.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
3. .env に書くべき Proxy / NO_PROXY
Zscaler + Proxy 環境では、まず .env に以下を定義しておきます。
HTTP_PROXY=http://proxy.example.co.jp:8080
HTTPS_PROXY=http://proxy.example.co.jp:8080
NO_PROXY=localhost,127.0.0.1,api,web,nginx,db,redis,weaviate,ssrf_proxy,sandbox,plugin_daemon
-
HTTP_PROXY/HTTPS_PROXY… 社内 Proxy / Zscaler に合わせて変更 -
NO_PROXY… Dify の内部コンテナ名をすべて列挙するのがポイント
4. Zscaler CA をホスト OS に登録する
Ubuntu 系を想定:
sudo cp ZscalerRootCA.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
これでホスト OS の /etc/ssl/certs/ca-certificates.crt に
Zscaler Root CA が取り込まれます。
このファイルを コンテナに volume マウント して利用します。
5. docker-compose.yaml フル記述の修正例(Proxy + CA 対応)
ここからが本題です。
YAML アンカーは使わず、全サービスにフル記述で Proxy / CA 設定を書いた例 を示します。
🔹 前提
-
.envにHTTP_PROXY/HTTPS_PROXY/NO_PROXYを定義済み - ホスト側に Zscaler Root CA を登録済み(
/usr/local/share/ca-certificates)
🔎 補足
YAML アンカー(&name/*name/<<:)という便利な省略記法もありますが、
この手順書内の docker-compose.yaml の修正例は、すべて “フル記述(展開済み)” にしています。
「実際にどの環境変数と volume を書けばよいか」が一目でわかるようにするためです。
docker-compose.yaml(例)
version: "3.8"
services:
api:
image: langgenius/dify-api:latest
env_file:
- .env
environment:
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
volumes:
- /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro
depends_on:
- db
- redis
- weaviate
web:
image: langgenius/dify-web:latest
env_file:
- .env
environment:
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
volumes:
- /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro
depends_on:
- api
worker:
image: langgenius/dify-api:latest
command: ["celery", "-A", "worker", "worker", "--loglevel=INFO"]
env_file:
- .env
environment:
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
volumes:
- /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro
depends_on:
- api
- redis
worker_beat:
image: langgenius/dify-api:latest
command: ["celery", "-A", "worker", "beat", "--loglevel=INFO"]
env_file:
- .env
environment:
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
volumes:
- /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro
depends_on:
- api
- redis
sandbox:
image: langgenius/dify-sandbox:latest
env_file:
- .env
environment:
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
volumes:
- /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro
depends_on:
- api
plugin_daemon:
image: langgenius/dify-plugin-daemon:latest
env_file:
- .env
environment:
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
volumes:
- /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro
depends_on:
- api
db:
image: postgres:15
environment:
POSTGRES_DB: dify
POSTGRES_USER: dify
POSTGRES_PASSWORD: dify
redis:
image: redis:7
weaviate:
image: semitechnologies/weaviate:latest
environment:
QUERY_DEFAULTS_LIMIT: "25"
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "true"
🔍 ポイント
-
HTTP_PROXY/HTTPS_PROXY/NO_PROXY/SSL_CERT_FILEを
外部と通信する全コンテナ(api / web / worker / worker_beat / sandbox / plugin_daemon)に記述 -
/usr/local/share/ca-certificatesを read-only でマウント し、
その中のca-certificates.crt(Zscaler を含む CA バンドル)をSSL_CERT_FILEで参照
6. YAML アンカー記法の紹介(この記事では採用していないが知識として)
⚠ ここは「知識として紹介」のみです。
上記の docker-compose.yaml の例はすべて フル記述 で書いています。
YAML には以下のような アンカー(&)とエイリアス(*)、マージキー(<<:) があります。
x-proxy-env: &proxy-env
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
を定義しておき、
environment:
<<: *proxy-env
と書くと、実際には
environment:
HTTP_PROXY: ${HTTP_PROXY}
HTTPS_PROXY: ${HTTPS_PROXY}
NO_PROXY: ${NO_PROXY}
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
と同じ意味になります。
- 複数サービスに同じ設定を書く場合に便利
- ただし、YAML に慣れていない人には読みにくいので
この手順書ではあえて使っていません
私自身が利用して核に指定名からです。
7. トラブルシューティング早見表
| 症状 | 主な原因 | 主な対策 |
|---|---|---|
| Plugin ダウンロードが 403 | Zscaler / Proxy によるブロック | NO_PROXY / CA 登録 / ローカルインストール |
| OpenAI が 429 / timeout | TLS Inspection / CA 不一致 | Zscaler CA 登録 / OpenAI 宛の通信許可 |
| Firecrawl が 500 | bot 通信遮断 / Proxy 経由 | firecrawl.dev を NO_PROXY / PDF 手動登録 |
| Sandbox の外部 fetch 失敗 | CA 未登録 / Proxy 経由 | Zscaler CA マウント / NO_PROXY 見直し |
| Weaviate が timeout / EOF | 内部通信が Proxy に送られている | NO_PROXY に weaviate / api / db / redis 追加 |
| docker pull で x509 | TLS 改ざん / CA 未登録 | ホスト OS に Zscaler CA を trust |
8. まとめ
- Zscaler / 社内 Proxy 環境は Dify OSS のような外部 API 多用システムと相性が悪い
- しかし以下を徹底すれば、多くの問題は解消できる
-
.envに正しいHTTP_PROXY/HTTPS_PROXY/NO_PROXYを記述する - Zscaler Root CA をホスト OS に登録し、コンテナに volume マウントする
-
docker-compose.yamlに フル記述 で Proxy / CA 設定を書く - Plugin はローカルインストールも選択肢にする
- Firecrawl は企業ネットワークでは動作制限がある前提で設計する
以上です
