# Dify - open-source LLM app development platform # Adapted from the official docker/docker-compose.yaml (tag 1.15.0). # Minimal functional stack: api + worker + worker_beat + web + postgres # (pgvector, reused as the vector store) + redis + sandbox + ssrf_proxy # + plugin_daemon, fronted by a lightweight internal nginx gateway that # mirrors the upstream path routing (TLS terminates at Traefik). x-shared-api-env: &shared-api-env LOG_LEVEL: INFO DEPLOY_ENV: PRODUCTION SECRET_KEY: ${SECRET_KEY} MIGRATION_ENABLED: "true" # Public URLs - a single domain, path-routed like the upstream nginx CONSOLE_API_URL: https://${DIFY_DOMAIN} CONSOLE_WEB_URL: https://${DIFY_DOMAIN} SERVICE_API_URL: https://${DIFY_DOMAIN} APP_API_URL: https://${DIFY_DOMAIN} APP_WEB_URL: https://${DIFY_DOMAIN} FILES_URL: https://${DIFY_DOMAIN} INTERNAL_FILES_URL: http://api:5001 TRIGGER_URL: https://${DIFY_DOMAIN} ENDPOINT_URL_TEMPLATE: https://${DIFY_DOMAIN}/e/{hook_id} # The dedicated api_websocket collaboration service is not deployed ENABLE_COLLABORATION_MODE: "false" WEB_API_CORS_ALLOW_ORIGINS: "*" CONSOLE_CORS_ALLOW_ORIGINS: "*" # PostgreSQL DB_USERNAME: postgres DB_PASSWORD: ${POSTGRES_PASSWORD} DB_HOST: db DB_PORT: "5432" DB_DATABASE: dify # Redis / Celery REDIS_HOST: redis REDIS_PORT: "6379" REDIS_PASSWORD: ${REDIS_PASSWORD} REDIS_DB: "0" CELERY_BROKER_URL: redis://:${REDIS_PASSWORD}@redis:6379/1 # File storage on a local volume STORAGE_TYPE: opendal OPENDAL_SCHEME: fs OPENDAL_FS_ROOT: storage # Vector store: pgvector, reusing the same PostgreSQL instance VECTOR_STORE: pgvector PGVECTOR_HOST: db PGVECTOR_PORT: "5432" PGVECTOR_USER: postgres PGVECTOR_PASSWORD: ${POSTGRES_PASSWORD} PGVECTOR_DATABASE: dify PGVECTOR_MIN_CONNECTION: "1" PGVECTOR_MAX_CONNECTION: "5" # Code execution sandbox CODE_EXECUTION_ENDPOINT: http://sandbox:8194 CODE_EXECUTION_API_KEY: ${SANDBOX_API_KEY} # SSRF proxy (squid) for user-triggered outbound requests SSRF_PROXY_HTTP_URL: http://ssrf_proxy:3128 SSRF_PROXY_HTTPS_URL: http://ssrf_proxy:3128 # Plugin daemon (model providers / tools are plugins since Dify 1.0) PLUGIN_DAEMON_URL: http://plugin_daemon:5002 PLUGIN_DAEMON_KEY: ${PLUGIN_DAEMON_KEY} INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_INNER_API_KEY} PLUGIN_MAX_PACKAGE_SIZE: "52428800" PLUGIN_REMOTE_INSTALL_HOST: localhost PLUGIN_REMOTE_INSTALL_PORT: "5003" MARKETPLACE_ENABLED: "true" MARKETPLACE_API_URL: https://marketplace.dify.ai services: nginx: image: nginx:1.27-alpine restart: always volumes: - ../files/dify-nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: api: condition: service_healthy web: condition: service_started plugin_daemon: condition: service_started # The dify-api image runs as the non-root user 1001, so the shared # storage volume has to be handed over to it once (same trick as the # upstream init_permissions container). init_permissions: image: busybox:1.36 command: - sh - -c - | FLAG_FILE="/app/api/storage/.init_permissions" if [ -f "$$FLAG_FILE" ]; then echo "Permissions already initialized." exit 0 fi echo "Initializing permissions for /app/api/storage" chown -R 1001:1001 /app/api/storage && touch "$$FLAG_FILE" volumes: - dify-app-storage:/app/api/storage restart: "no" api: image: langgenius/dify-api:1.15.0 restart: always environment: <<: *shared-api-env MODE: api depends_on: init_permissions: condition: service_completed_successfully db: condition: service_healthy redis: condition: service_healthy volumes: - dify-app-storage:/app/api/storage healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5001/health"] interval: 15s timeout: 5s retries: 20 start_period: 120s worker: image: langgenius/dify-api:1.15.0 restart: always environment: <<: *shared-api-env MODE: worker depends_on: init_permissions: condition: service_completed_successfully db: condition: service_healthy redis: condition: service_healthy volumes: - dify-app-storage:/app/api/storage worker_beat: image: langgenius/dify-api:1.15.0 restart: always environment: <<: *shared-api-env MODE: beat depends_on: db: condition: service_healthy redis: condition: service_healthy web: image: langgenius/dify-web:1.15.0 restart: always environment: CONSOLE_API_URL: https://${DIFY_DOMAIN} APP_API_URL: https://${DIFY_DOMAIN} SERVER_CONSOLE_API_URL: http://api:5001 ENABLE_COLLABORATION_MODE: "false" MARKETPLACE_API_URL: https://marketplace.dify.ai MARKETPLACE_URL: https://marketplace.dify.ai NEXT_TELEMETRY_DISABLED: "1" db: image: pgvector/pgvector:pg16 restart: always environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: dify PGDATA: /var/lib/postgresql/data/pgdata volumes: - dify-db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d dify"] interval: 5s timeout: 3s retries: 30 redis: image: redis:6-alpine restart: always environment: REDISCLI_AUTH: ${REDIS_PASSWORD} command: redis-server --requirepass ${REDIS_PASSWORD} volumes: - dify-redis-data:/data healthcheck: test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"] interval: 5s timeout: 3s retries: 30 sandbox: image: langgenius/dify-sandbox:0.2.15 restart: always environment: API_KEY: ${SANDBOX_API_KEY} GIN_MODE: release WORKER_TIMEOUT: "15" ENABLE_NETWORK: "true" HTTP_PROXY: http://ssrf_proxy:3128 HTTPS_PROXY: http://ssrf_proxy:3128 SANDBOX_PORT: "8194" volumes: - dify-sandbox-deps:/dependencies ssrf_proxy: image: ubuntu/squid:latest restart: always volumes: - ../files/dify-squid.conf:/etc/squid/squid.conf:ro plugin_daemon: image: langgenius/dify-plugin-daemon:0.6.3-local restart: always environment: DB_HOST: db DB_PORT: "5432" DB_USERNAME: postgres DB_PASSWORD: ${POSTGRES_PASSWORD} DB_DATABASE: dify_plugin DB_SSL_MODE: disable REDIS_HOST: redis REDIS_PORT: "6379" REDIS_PASSWORD: ${REDIS_PASSWORD} SERVER_PORT: "5002" SERVER_KEY: ${PLUGIN_DAEMON_KEY} MAX_PLUGIN_PACKAGE_SIZE: "52428800" DIFY_INNER_API_URL: http://api:5001 DIFY_INNER_API_KEY: ${PLUGIN_INNER_API_KEY} PLUGIN_REMOTE_INSTALLING_HOST: 0.0.0.0 PLUGIN_REMOTE_INSTALLING_PORT: "5003" PLUGIN_WORKING_PATH: /app/storage/cwd FORCE_VERIFYING_SIGNATURE: "true" PYTHON_ENV_INIT_TIMEOUT: "120" PLUGIN_MAX_EXECUTION_TIMEOUT: "600" PLUGIN_STORAGE_TYPE: local PLUGIN_STORAGE_LOCAL_ROOT: /app/storage PLUGIN_INSTALLED_PATH: plugin PLUGIN_PACKAGE_CACHE_PATH: plugin_packages PLUGIN_MEDIA_CACHE_PATH: assets volumes: - dify-plugin-storage:/app/storage depends_on: db: condition: service_healthy redis: condition: service_healthy volumes: dify-app-storage: dify-db-data: dify-redis-data: dify-sandbox-deps: dify-plugin-storage: