Compare commits

..

1 Commits

Author SHA1 Message Date
WH-2099
50156f822b add podman compose middleware helpers 2026-04-02 02:29:38 +08:00
39 changed files with 374 additions and 105 deletions

View File

@@ -115,6 +115,12 @@ ignore = [
"controllers/console/human_input_form.py" = ["TID251"]
"controllers/web/human_input_form.py" = ["TID251"]
[lint.pyflakes]
allowed-unused-imports = [
"tests.integration_tests",
"tests.unit_tests",
]
[lint.flake8-tidy-imports]
[lint.flake8-tidy-imports.banned-api."flask_restx.reqparse"]

View File

@@ -4,28 +4,23 @@ from typing import Literal
import httpx
import pytest
from core.plugin.entities.plugin_daemon import PluginDaemonBasicResponse, PluginToolProviderEntity
from core.plugin.entities.plugin_daemon import PluginDaemonBasicResponse
from core.tools.entities.common_entities import I18nObject
from core.tools.entities.tool_entities import ToolProviderEntityWithPlugin, ToolProviderIdentity
from core.tools.entities.tool_entities import ToolProviderEntity, ToolProviderIdentity
class MockedHttp:
@classmethod
def list_tools(cls) -> list[PluginToolProviderEntity]:
def list_tools(cls) -> list[ToolProviderEntity]:
return [
PluginToolProviderEntity(
provider="Yeuoly",
plugin_unique_identifier="langgenius/yeuoly:0.0.1@mock",
plugin_id="mock-plugin",
declaration=ToolProviderEntityWithPlugin(
identity=ToolProviderIdentity(
author="Yeuoly",
name="Yeuoly",
description=I18nObject(en_US="Yeuoly"),
icon="ssss.svg",
label=I18nObject(en_US="Yeuoly"),
)
),
ToolProviderEntity(
identity=ToolProviderIdentity(
author="Yeuoly",
name="Yeuoly",
description=I18nObject(en_US="Yeuoly"),
icon="ssss.svg",
label=I18nObject(en_US="Yeuoly"),
)
)
]
@@ -38,7 +33,7 @@ class MockedHttp:
"""
request = httpx.Request(method, url)
if url.endswith("/tools"):
content = PluginDaemonBasicResponse[list[PluginToolProviderEntity]](
content = PluginDaemonBasicResponse[list[ToolProviderEntity]](
code=0, message="success", data=cls.list_tools()
).model_dump_json()
else:

View File

@@ -1,6 +1,5 @@
from core.plugin.impl.tool import PluginToolManager
pytest_plugins = ("tests.integration_tests.plugin.__mock.http",)
from tests.integration_tests.plugin.__mock.http import setup_http_mock
def test_fetch_all_plugin_tools(setup_http_mock):

View File

@@ -3,8 +3,7 @@ from core.tools.custom_tool.tool import ApiTool
from core.tools.entities.common_entities import I18nObject
from core.tools.entities.tool_bundle import ApiToolBundle
from core.tools.entities.tool_entities import ToolEntity, ToolIdentity
pytest_plugins = ("tests.integration_tests.tools.__mock.http",)
from tests.integration_tests.tools.__mock.http import setup_http_mock
tool_bundle = {
"server_url": "http://www.example.com/{path_param}",

View File

@@ -1,9 +1,7 @@
from core.rag.datasource.vdb.analyticdb.analyticdb_vector import AnalyticdbVector
from core.rag.datasource.vdb.analyticdb.analyticdb_vector_openapi import AnalyticdbVectorOpenAPIConfig
from core.rag.datasource.vdb.analyticdb.analyticdb_vector_sql import AnalyticdbVectorBySqlConfig
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, setup_mock_redis
class AnalyticdbVectorTest(AbstractVectorTest):

View File

@@ -1,10 +1,6 @@
from core.rag.datasource.vdb.baidu.baidu_vector import BaiduConfig, BaiduVector
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text
pytest_plugins = (
"tests.integration_tests.vdb.test_vector_store",
"tests.integration_tests.vdb.__mock.baiduvectordb",
)
from tests.integration_tests.vdb.__mock.baiduvectordb import setup_baiduvectordb_mock
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text, setup_mock_redis
class BaiduVectorTest(AbstractVectorTest):

View File

@@ -4,10 +4,9 @@ from core.rag.datasource.vdb.chroma.chroma_vector import ChromaConfig, ChromaVec
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
get_example_text,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class ChromaVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -4,10 +4,9 @@ import time
from core.rag.datasource.vdb.couchbase.couchbase_vector import CouchbaseConfig, CouchbaseVector
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
def wait_for_healthy_container(service_name="couchbase-server", timeout=300):
start_time = time.time()

View File

@@ -1,10 +1,9 @@
from core.rag.datasource.vdb.elasticsearch.elasticsearch_vector import ElasticSearchConfig, ElasticSearchVector
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class ElasticSearchVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -6,12 +6,8 @@ from holo_search_sdk.types import BaseQuantizationType, DistanceType, TokenizerT
from core.rag.datasource.vdb.hologres.hologres_vector import HologresVector, HologresVectorConfig
from core.rag.models.document import Document
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text
pytest_plugins = (
"tests.integration_tests.vdb.test_vector_store",
"tests.integration_tests.vdb.__mock.hologres",
)
from tests.integration_tests.vdb.__mock.hologres import setup_hologres_mock
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text, setup_mock_redis
MOCK = os.getenv("MOCK_SWITCH", "false").lower() == "true"

View File

@@ -1,10 +1,6 @@
from core.rag.datasource.vdb.huawei.huawei_cloud_vector import HuaweiCloudVector, HuaweiCloudVectorConfig
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text
pytest_plugins = (
"tests.integration_tests.vdb.test_vector_store",
"tests.integration_tests.vdb.__mock.huaweicloudvectordb",
)
from tests.integration_tests.vdb.__mock.huaweicloudvectordb import setup_client_mock
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text, setup_mock_redis
class HuaweiCloudVectorTest(AbstractVectorTest):

View File

@@ -3,10 +3,9 @@
from core.rag.datasource.vdb.iris.iris_vector import IrisVector, IrisVectorConfig
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class IrisVectorTest(AbstractVectorTest):
"""Test suite for IRIS vector store implementation."""

View File

@@ -1,9 +1,7 @@
import os
from core.rag.datasource.vdb.lindorm.lindorm_vector import LindormVectorStore, LindormVectorStoreConfig
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, setup_mock_redis
class Config:

View File

@@ -1,10 +1,9 @@
from core.rag.datasource.vdb.matrixone.matrixone_vector import MatrixoneConfig, MatrixoneVector
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class MatrixoneVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -2,10 +2,9 @@ from core.rag.datasource.vdb.milvus.milvus_vector import MilvusConfig, MilvusVec
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
get_example_text,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class MilvusVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -1,10 +1,9 @@
from core.rag.datasource.vdb.myscale.myscale_vector import MyScaleConfig, MyScaleVector
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class MyScaleVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -6,10 +6,9 @@ from core.rag.datasource.vdb.oceanbase.oceanbase_vector import (
)
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
@pytest.fixture
def oceanbase_vector():

View File

@@ -5,10 +5,9 @@ import psycopg2
from core.rag.datasource.vdb.opengauss.opengauss import OpenGauss, OpenGaussConfig
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class OpenGaussTest(AbstractVectorTest):
def __init__(self):

View File

@@ -3,10 +3,9 @@ from core.rag.models.document import Document
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
get_example_text,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class OracleVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -2,10 +2,9 @@ from core.rag.datasource.vdb.pgvecto_rs.pgvecto_rs import PGVectoRS, PgvectoRSCo
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
get_example_text,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class PGVectoRSVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -1,10 +1,10 @@
from core.rag.datasource.vdb.pgvector.pgvector import PGVector, PGVectorConfig
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
get_example_text,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class PGVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -1,10 +1,9 @@
from core.rag.datasource.vdb.pyvastbase.vastbase_vector import VastbaseVector, VastbaseVectorConfig
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class VastbaseVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -4,10 +4,9 @@ from core.rag.datasource.vdb.qdrant.qdrant_vector import QdrantConfig, QdrantVec
from core.rag.models.document import Document
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class QdrantVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -12,10 +12,9 @@ from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
get_example_document,
get_example_text,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class TableStoreVectorTest(AbstractVectorTest):
def __init__(self, normalize_full_text_score: bool = False):

View File

@@ -1,12 +1,8 @@
from unittest.mock import MagicMock
from core.rag.datasource.vdb.tencent.tencent_vector import TencentConfig, TencentVector
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text
pytest_plugins = (
"tests.integration_tests.vdb.test_vector_store",
"tests.integration_tests.vdb.__mock.tcvectordb",
)
from tests.integration_tests.vdb.__mock.tcvectordb import setup_tcvectordb_mock
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text, setup_mock_redis
mock_client = MagicMock()
mock_client.list_databases.return_value = [{"name": "test"}]

View File

@@ -2,9 +2,7 @@ import pytest
from core.rag.datasource.vdb.tidb_vector.tidb_vector import TiDBVector, TiDBVectorConfig
from models.dataset import Document
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text, setup_mock_redis
@pytest.fixture

View File

@@ -1,9 +1,8 @@
from core.rag.datasource.vdb.upstash.upstash_vector import UpstashVector, UpstashVectorConfig
from core.rag.models.document import Document
from tests.integration_tests.vdb.__mock.upstashvectordb import setup_upstashvector_mock
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text
pytest_plugins = ("tests.integration_tests.vdb.__mock.upstashvectordb",)
class UpstashVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -1,10 +1,6 @@
from core.rag.datasource.vdb.vikingdb.vikingdb_vector import VikingDBConfig, VikingDBVector
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text
pytest_plugins = (
"tests.integration_tests.vdb.test_vector_store",
"tests.integration_tests.vdb.__mock.vikingdb",
)
from tests.integration_tests.vdb.__mock.vikingdb import setup_vikingdb_mock
from tests.integration_tests.vdb.test_vector_store import AbstractVectorTest, get_example_text, setup_mock_redis
class VikingDBVectorTest(AbstractVectorTest):

View File

@@ -1,10 +1,9 @@
from core.rag.datasource.vdb.weaviate.weaviate_vector import WeaviateConfig, WeaviateVector
from tests.integration_tests.vdb.test_vector_store import (
AbstractVectorTest,
setup_mock_redis,
)
pytest_plugins = ("tests.integration_tests.vdb.test_vector_store",)
class WeaviateVectorTest(AbstractVectorTest):
def __init__(self):

View File

@@ -13,10 +13,9 @@ from configs import dify_config
from core.app.entities.app_invoke_entities import InvokeFrom, UserFrom
from core.workflow.node_factory import DifyNodeFactory
from core.workflow.system_variables import build_system_variables
from tests.integration_tests.workflow.nodes.__mock.code_executor import setup_code_executor_mock
from tests.workflow_test_utils import build_test_graph_init_params
pytest_plugins = ("tests.integration_tests.workflow.nodes.__mock.code_executor",)
CODE_MAX_STRING_LENGTH = dify_config.CODE_MAX_STRING_LENGTH

View File

@@ -16,10 +16,9 @@ from core.tools.tool_file_manager import ToolFileManager
from core.workflow.node_factory import DifyNodeFactory
from core.workflow.node_runtime import DifyFileReferenceFactory
from core.workflow.system_variables import build_system_variables
from tests.integration_tests.workflow.nodes.__mock.http import setup_http_mock
from tests.workflow_test_utils import build_test_graph_init_params
pytest_plugins = ("tests.integration_tests.workflow.nodes.__mock.http",)
HTTP_REQUEST_CONFIG = HttpRequestNodeConfig(
max_connect_timeout=dify_config.HTTP_REQUEST_MAX_CONNECT_TIMEOUT,
max_read_timeout=dify_config.HTTP_REQUEST_MAX_READ_TIMEOUT,

View File

@@ -17,7 +17,8 @@ from extensions.ext_database import db
from tests.integration_tests.workflow.nodes.__mock.model import get_mocked_fetch_model_instance
from tests.workflow_test_utils import build_test_graph_init_params
pytest_plugins = ("tests.integration_tests.model_runtime.__mock.plugin_daemon",)
"""FOR MOCK FIXTURES, DO NOT REMOVE"""
from tests.integration_tests.model_runtime.__mock.plugin_daemon import setup_model_mock
def get_mocked_fetch_memory(memory_text: str):

View File

@@ -4,14 +4,13 @@ import pytest
from oss2 import Auth
from extensions.storage.aliyun_oss_storage import AliyunOssStorage
from tests.unit_tests.oss.__mock.aliyun_oss import setup_aliyun_oss_mock
from tests.unit_tests.oss.__mock.base import (
BaseStorageTest,
get_example_bucket,
get_example_folder,
)
pytest_plugins = ("tests.unit_tests.oss.__mock.aliyun_oss",)
class TestAliyunOss(BaseStorageTest):
@pytest.fixture(autouse=True)

View File

@@ -8,8 +8,7 @@ from tests.unit_tests.oss.__mock.base import (
BaseStorageTest,
get_example_bucket,
)
pytest_plugins = ("tests.unit_tests.oss.__mock.tencent_cos",)
from tests.unit_tests.oss.__mock.tencent_cos import setup_tencent_cos_mock
class TestTencentCos(BaseStorageTest):

View File

@@ -8,8 +8,7 @@ from tests.unit_tests.oss.__mock.base import (
BaseStorageTest,
get_example_bucket,
)
pytest_plugins = ("tests.unit_tests.oss.__mock.volcengine_tos",)
from tests.unit_tests.oss.__mock.volcengine_tos import setup_volcengine_tos_mock
class TestVolcengineTos(BaseStorageTest):

19
dev/start-podman-compose Executable file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
ROOT="$(dirname "$SCRIPT_DIR")"
PROJECT_NAME="${PODMAN_PROJECT_NAME:-dify}"
COMPOSE_FILE="${PODMAN_COMPOSE_FILE:-$ROOT/docker/podman-compose.middleware.yaml}"
NETWORK_NAME="${PODMAN_NETWORK_NAME:-dify}"
cd "$ROOT/docker"
podman compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" down -v --remove-orphans || true
if ! podman network inspect "$NETWORK_NAME" >/dev/null 2>&1; then
podman network create "$NETWORK_NAME"
fi
podman compose -f "$COMPOSE_FILE" --profile postgresql --profile weaviate -p "$PROJECT_NAME" up -d

20
dev/start-web-image Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
BACKEND_URL="${DIFY_WEB_BACKEND_URL:-http://localhost:5001}"
IMAGE="${DIFY_WEB_IMAGE:-docker.io/langgenius/dify-web:1.13.2}"
HOST_BIND="${DIFY_WEB_HOSTNAME:-localhost}"
WEB_URL="${DIFY_WEB_FRONTEND_URL:-}"
CONTAINER_NAME="${DIFY_WEB_CONTAINER_NAME:-dify-web}"
NEXT_PUBLIC_COOKIE_DOMAIN="${DIFY_WEB_NEXT_PUBLIC_COOKIE_DOMAIN:-}"
podman rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
exec podman run --rm --name "$CONTAINER_NAME" --network host \
-e HOSTNAME="${HOST_BIND}" \
-e CONSOLE_API_URL="${BACKEND_URL}" \
-e APP_API_URL="${BACKEND_URL}" \
-e SERVICE_API_URL="${BACKEND_URL}" \
${WEB_URL:+-e CONSOLE_WEB_URL="${WEB_URL}"} \
${NEXT_PUBLIC_COOKIE_DOMAIN:+-e NEXT_PUBLIC_COOKIE_DOMAIN="${NEXT_PUBLIC_COOKIE_DOMAIN}"} \
"${IMAGE}"

10
dev/stop-podman-compose Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
ROOT="$(dirname "$SCRIPT_DIR")"
COMPOSE_FILE="${PODMAN_COMPOSE_FILE:-$ROOT/docker/podman-compose.middleware.yaml}"
PROJECT_NAME="${PODMAN_PROJECT_NAME:-dify}"
cd "$ROOT/docker"
podman compose -f "$COMPOSE_FILE" -p "$PROJECT_NAME" down -v

View File

@@ -0,0 +1,267 @@
services:
# The postgres database.
db_postgres:
image: docker.io/postgres:15-alpine
profiles:
- ""
- postgresql
restart: always
env_file:
- ./middleware.env
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD:-difyai123456}
POSTGRES_DB: ${DB_DATABASE:-dify}
PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata}
command: >
postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}'
-c 'shared_buffers=${POSTGRES_SHARED_BUFFERS:-128MB}'
-c 'work_mem=${POSTGRES_WORK_MEM:-4MB}'
-c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}'
-c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}'
-c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-0}'
-c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-0}'
volumes:
- ${PGDATA_HOST_VOLUME:-./volumes/db/data}:/var/lib/postgresql/data
ports:
- "${EXPOSE_POSTGRES_PORT:-5432}:5432"
healthcheck:
test:
[
"CMD",
"pg_isready",
"-h",
"db_postgres",
"-U",
"${DB_USERNAME:-postgres}",
"-d",
"${DB_DATABASE:-dify}",
]
interval: 1s
timeout: 3s
retries: 30
networks:
- dify
db_mysql:
image: docker.io/mysql:8.0
profiles:
- mysql
restart: always
env_file:
- ./middleware.env
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-difyai123456}
MYSQL_DATABASE: ${DB_DATABASE:-dify}
command: >
--max_connections=1000
--innodb_buffer_pool_size=${MYSQL_INNODB_BUFFER_POOL_SIZE:-512M}
--innodb_log_file_size=${MYSQL_INNODB_LOG_FILE_SIZE:-128M}
--innodb_flush_log_at_trx_commit=${MYSQL_INNODB_FLUSH_LOG_AT_TRX_COMMIT:-2}
volumes:
- ${MYSQL_HOST_VOLUME:-./volumes/mysql/data}:/var/lib/mysql
ports:
- "${EXPOSE_MYSQL_PORT:-3306}:3306"
healthcheck:
test:
[
"CMD",
"mysqladmin",
"ping",
"-u",
"root",
"-p${DB_PASSWORD:-difyai123456}",
]
interval: 1s
timeout: 3s
retries: 30
networks:
- dify
# The redis cache.
redis:
image: docker.io/redis:6-alpine
restart: always
env_file:
- ./middleware.env
environment:
REDISCLI_AUTH: ${REDIS_PASSWORD:-difyai123456}
volumes:
# Mount the redis data directory to the container.
- ${REDIS_HOST_VOLUME:-./volumes/redis/data}:/data
# Set the redis password when startup redis server.
command: redis-server --requirepass ${REDIS_PASSWORD:-difyai123456}
ports:
- "${EXPOSE_REDIS_PORT:-6379}:6379"
healthcheck:
test:
[
"CMD-SHELL",
"redis-cli -a ${REDIS_PASSWORD:-difyai123456} ping | grep -q PONG",
]
networks:
- dify
# The DifySandbox
sandbox:
image: docker.io/langgenius/dify-sandbox:0.2.12
restart: always
env_file:
- ./middleware.env
environment:
# The DifySandbox configurations
# Make sure you are changing this key for your deployment with a strong key.
# You can generate a strong key using `openssl rand -base64 42`.
API_KEY: ${SANDBOX_API_KEY:-dify-sandbox}
GIN_MODE: ${SANDBOX_GIN_MODE:-release}
WORKER_TIMEOUT: ${SANDBOX_WORKER_TIMEOUT:-15}
ENABLE_NETWORK: ${SANDBOX_ENABLE_NETWORK:-true}
HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}
HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128}
SANDBOX_PORT: ${SANDBOX_PORT:-8194}
PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
volumes:
- ./volumes/sandbox/dependencies:/dependencies
- ./volumes/sandbox/conf:/conf
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8194/health"]
networks:
- ssrf_proxy_network
# plugin daemon
plugin_daemon:
image: docker.io/langgenius/dify-plugin-daemon:0.5.4-local
restart: always
env_file:
- ./middleware.env
environment:
# Use the shared environment variables.
LOG_OUTPUT_FORMAT: ${LOG_OUTPUT_FORMAT:-text}
DB_DATABASE: ${DB_PLUGIN_DATABASE:-dify_plugin}
REDIS_HOST: ${REDIS_HOST:-redis}
REDIS_PORT: ${REDIS_PORT:-6379}
REDIS_PASSWORD: ${REDIS_PASSWORD:-difyai123456}
SERVER_PORT: ${PLUGIN_DAEMON_PORT:-5002}
SERVER_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi}
MAX_PLUGIN_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false}
DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://host.containers.internal:5001}
DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0}
PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003}
PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd}
PYTHON_ENV_INIT_TIMEOUT: ${PLUGIN_PYTHON_ENV_INIT_TIMEOUT:-120}
PLUGIN_MAX_EXECUTION_TIMEOUT: ${PLUGIN_MAX_EXECUTION_TIMEOUT:-600}
PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
PLUGIN_STORAGE_TYPE: ${PLUGIN_STORAGE_TYPE:-local}
PLUGIN_STORAGE_LOCAL_ROOT: ${PLUGIN_STORAGE_LOCAL_ROOT:-/app/storage}
PLUGIN_INSTALLED_PATH: ${PLUGIN_INSTALLED_PATH:-plugin}
PLUGIN_PACKAGE_CACHE_PATH: ${PLUGIN_PACKAGE_CACHE_PATH:-plugin_packages}
PLUGIN_MEDIA_CACHE_PATH: ${PLUGIN_MEDIA_CACHE_PATH:-assets}
PLUGIN_STORAGE_OSS_BUCKET: ${PLUGIN_STORAGE_OSS_BUCKET:-}
S3_USE_AWS: ${PLUGIN_S3_USE_AWS:-false}
S3_USE_AWS_MANAGED_IAM: ${PLUGIN_S3_USE_AWS_MANAGED_IAM:-false}
S3_ENDPOINT: ${PLUGIN_S3_ENDPOINT:-}
S3_USE_PATH_STYLE: ${PLUGIN_S3_USE_PATH_STYLE:-false}
AWS_ACCESS_KEY: ${PLUGIN_AWS_ACCESS_KEY:-}
AWS_SECRET_KEY: ${PLUGIN_AWS_SECRET_KEY:-}
AWS_REGION: ${PLUGIN_AWS_REGION:-}
AZURE_BLOB_STORAGE_CONNECTION_STRING: ${PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING:-}
AZURE_BLOB_STORAGE_CONTAINER_NAME: ${PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME:-}
TENCENT_COS_SECRET_KEY: ${PLUGIN_TENCENT_COS_SECRET_KEY:-}
TENCENT_COS_SECRET_ID: ${PLUGIN_TENCENT_COS_SECRET_ID:-}
TENCENT_COS_REGION: ${PLUGIN_TENCENT_COS_REGION:-}
ALIYUN_OSS_REGION: ${PLUGIN_ALIYUN_OSS_REGION:-}
ALIYUN_OSS_ENDPOINT: ${PLUGIN_ALIYUN_OSS_ENDPOINT:-}
ALIYUN_OSS_ACCESS_KEY_ID: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID:-}
ALIYUN_OSS_ACCESS_KEY_SECRET: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET:-}
ALIYUN_OSS_AUTH_VERSION: ${PLUGIN_ALIYUN_OSS_AUTH_VERSION:-v4}
ALIYUN_OSS_PATH: ${PLUGIN_ALIYUN_OSS_PATH:-}
VOLCENGINE_TOS_ENDPOINT: ${PLUGIN_VOLCENGINE_TOS_ENDPOINT:-}
VOLCENGINE_TOS_ACCESS_KEY: ${PLUGIN_VOLCENGINE_TOS_ACCESS_KEY:-}
VOLCENGINE_TOS_SECRET_KEY: ${PLUGIN_VOLCENGINE_TOS_SECRET_KEY:-}
VOLCENGINE_TOS_REGION: ${PLUGIN_VOLCENGINE_TOS_REGION:-}
THIRD_PARTY_SIGNATURE_VERIFICATION_ENABLED: true
THIRD_PARTY_SIGNATURE_VERIFICATION_PUBLIC_KEYS: /app/keys/publickey.pem
FORCE_VERIFYING_SIGNATURE: false
depends_on:
db_postgres:
condition: service_healthy
redis:
condition: service_started
ports:
- "${EXPOSE_PLUGIN_DAEMON_PORT:-5002}:${PLUGIN_DAEMON_PORT:-5002}"
- "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}"
volumes:
- ./volumes/plugin_daemon:/app/storage
networks:
- dify
# ssrf_proxy server
# for more information, please refer to
# https://docs.dify.ai/learn-more/faq/install-faq#18-why-is-ssrf-proxy-needed%3F
ssrf_proxy:
image: docker.io/ubuntu/squid:latest
restart: always
volumes:
- ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template
- ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh
entrypoint:
[
"sh",
"-c",
"cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh",
]
env_file:
- ./middleware.env
environment:
# pls clearly modify the squid env vars to fit your network environment.
HTTP_PORT: ${SSRF_HTTP_PORT:-3128}
COREDUMP_DIR: ${SSRF_COREDUMP_DIR:-/var/spool/squid}
REVERSE_PROXY_PORT: ${SSRF_REVERSE_PROXY_PORT:-8194}
SANDBOX_HOST: ${SSRF_SANDBOX_HOST:-sandbox}
SANDBOX_PORT: ${SSRF_SANDBOX_PORT:-8194}
ports:
- "${EXPOSE_SSRF_PROXY_PORT:-3128}:${SSRF_HTTP_PORT:-3128}"
- "${EXPOSE_SANDBOX_PORT:-8194}:${SANDBOX_PORT:-8194}"
networks:
- ssrf_proxy_network
- dify
# The Weaviate vector store.
weaviate:
image: docker.io/semitechnologies/weaviate:1.27.0
profiles:
- ""
- weaviate
restart: always
volumes:
# Mount the Weaviate data directory to the con tainer.
- ${WEAVIATE_HOST_VOLUME:-./volumes/weaviate}:/var/lib/weaviate
env_file:
- ./middleware.env
environment:
# The Weaviate configurations
# You can refer to the [Weaviate](https://weaviate.io/developers/weaviate/config-refs/env-vars) documentation for more information.
PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate}
QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25}
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-false}
DEFAULT_VECTORIZER_MODULE: ${WEAVIATE_DEFAULT_VECTORIZER_MODULE:-none}
CLUSTER_HOSTNAME: ${WEAVIATE_CLUSTER_HOSTNAME:-node1}
AUTHENTICATION_APIKEY_ENABLED: ${WEAVIATE_AUTHENTICATION_APIKEY_ENABLED:-true}
AUTHENTICATION_APIKEY_ALLOWED_KEYS: ${WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS:-WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih}
AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai}
AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true}
AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai}
DISABLE_TELEMETRY: ${WEAVIATE_DISABLE_TELEMETRY:-false}
ports:
- "${EXPOSE_WEAVIATE_PORT:-8080}:8080"
- "${EXPOSE_WEAVIATE_GRPC_PORT:-50051}:50051"
networks:
# create a network between sandbox, api and ssrf_proxy, and can not access outside.
ssrf_proxy_network:
driver: bridge
internal: true
dify:
name: dify
driver: bridge