Dify 是一个多模块组成的开源 AI 应用开发平台,其代码仓库包含了多个子项目和服务模块。由于其架构复杂度较高,初次接触时可能难以快速理清各部分之间的关系以及正确的本地部署流程。因此下面将详细介绍如何从 GitHub 获取最新源码并正确地搭建起完整的本地开发环境。

代码仓库地址

仓库地址说明
https://github.com/langgenius/difyweb、api 服务
https://github.com/langgenius/dify-plugin-daemonplugin 插件服务,需要在Linux 运行
https://github.com/langgenius/dify-sandboxsandbox 服务,运行python 代码、nodejs代码需要在 Linux 运行

部署架构图

在这里插入图片描述
图片来源 :https://github.com/langgenius/dify/blob/main/docker/docker-compose.png

本地开发启动 只需要其启动 web、api、plugin、sandbox、api服务相关定时任务

环境准备

  1. 操作系统,Linux 开发机,dify-plugin、dify-sandbox 需要在 Linux 运行
  2. 集成开发环境,推荐使用 vscode
  3. 安装 nodejs、uv、go,配置相关镜像源
$ npm config set registry https://registry.npmmirror.com/
$ npm config get registry
https://registry.npmmirror.com/
$ cat /etc/uv/uv.toml 
[[index]]
url = "https://repo.huaweicloud.com/repository/pypi/simple/"
default = true
$ go env GOPROXY
https://goproxy.cn,direct
  1. 数据库、redis

启动服务

sandbox

步骤

  1. git clone https://github.com/langgenius/dify-sandbox && cd dify-sandbox
  2. 运行 ./install.sh 安装必须的依赖
  3. 运行 ./build/build_[amd64|arm64].sh 构建启动服务
  4. 运行 ./main to 启动服务

遇到的问题

无权限创建文件夹
$ ./main
{"time":"2026-04-11T17:11:15.697504499+08:00","level":"INFO","msg":"initializing nodejs runner environment"}
{"time":"2026-04-11T17:11:15.697995589+08:00","level":"ERROR","msg":"failed to create lib path","path":"/var/sandbox/sandbox-nodejs"}
panic: failed to create /var/sandbox/sandbox-nodejs
$ mkdir -p /var/sandbox/sandbox-nodejs
mkdir: cannot create directory ‘/var/sandbox’: Permission denied

创建目录 && 授予权限

$ sudo mkdir -p /var/sandbox && sudo chown -R $USER:$USER /var/sandbox
启动告警信息
"time":"2026-04-11T17:19:00.340491426+08:00","level":"WARN","msg":"python lib path is not available","path":"/opt/python/lib/python3.14"}
{"time":"2026-04-11T17:19:00.340521999+08:00","level":"WARN","msg":"python lib path is not available","path":"/usr/local/lib/python3.14"}
{"time":"2026-04-11T17:19:00.340541807+08:00","level":"WARN","msg":"python lib path is not available","path":"/usr/lib/python3.14"}

问题代码位置

func PreparePythonDependenciesEnv() error {
	config := static.GetDifySandboxGlobalConfigurations()

	runner := runner.TempDirRunner{}
	err := runner.WithTempDir("/", []string{}, func(root_path string) error {
		err := os.WriteFile(path.Join(root_path, "env.sh"), []byte(env_script), 0755)
		if err != nil {
			return err
		}

		for _, lib_path := range config.PythonLibPaths {
			// check if the lib path is available
			if _, err := os.Stat(lib_path); err != nil {
				slog.Warn("python lib path is not available", "path", lib_path)
				continue
			}
			exec_cmd := exec.Command(
				"bash",
				path.Join(root_path, "env.sh"),
				lib_path,
				LIB_PATH,
			)
			exec_cmd.Stderr = os.Stderr

			if err := exec_cmd.Run(); err != nil {
				return err
			}
		}

		os.RemoveAll(root_path)
		return nil
	})

	return err
}

优先获取环境变量的配置,环境变量未配置再获取 yaml 的配置,如果 yaml 未配置,获取硬编码的配置

	python_lib_path := os.Getenv("PYTHON_LIB_PATH")
	if python_lib_path != "" {
		difySandboxGlobalConfigurations.PythonLibPaths = strings.Split(python_lib_path, ",")
	}

	if len(difySandboxGlobalConfigurations.PythonLibPaths) == 0 {
		difySandboxGlobalConfigurations.PythonLibPaths = DEFAULT_PYTHON_LIB_REQUIREMENTS
	}
var DEFAULT_PYTHON_LIB_REQUIREMENTS = []string{
	"/opt/python/lib/python3.14",
	"/usr/local/lib/python3.14",
	"/usr/lib/python3.14",
	"/usr/lib/python3",
	"/usr/lib/x86_64-linux-gnu",
	"/etc/ssl/certs/ca-certificates.crt",
	"/etc/nsswitch.conf",
	"/etc/hosts",
	"/etc/resolv.conf",
	"/run/systemd/resolve/stub-resolv.conf",
	"/run/resolvconf/resolv.conf",
	"/etc/localtime",
	"/usr/share/zoneinfo",
	"/etc/timezone",
}

修改 yaml 的配置,移除多余的路径包,修改之后的配置 增加了 python_lib_path

$ cat conf/config.yaml
app:
  port: 8194
  debug: True
  key: dify-sandbox
max_workers: 4
max_requests: 50
worker_timeout: 5
python_path: /opt/python/bin/python3
python_lib_path:
  - "/usr/lib/python3"
  - "/usr/lib/x86_64-linux-gnu"
  - "/usr/lib/aarch64-linux-gnu"
  - "/etc/ssl/certs/ca-certificates.crt"
  - "/etc/nsswitch.conf"
  - "/etc/hosts"
  - "/etc/resolv.conf"
  - "/run/systemd/resolve/stub-resolv.conf"
  - "/run/resolvconf/resolv.conf"
  - "/etc/localtime"
  - "/usr/share/zoneinfo"
  - "/etc/timezone"
enable_network: True # please make sure there is no network risk in your environment
enable_preload: False # please keep it as False for security purposes
log_path: "./logs" # path to store log files, default is "./logs"
allowed_syscalls: # please leave it empty if you have no idea how seccomp works
proxy:
  socks5: ''
  http: ''
  https: ''

再次启动服务

rm -rf /var/sandbox/* && ./main
{"time":"2026-04-11T17:48:25.609912649+08:00","level":"INFO","msg":"initializing nodejs runner environment"}
{"time":"2026-04-11T17:48:25.654258127+08:00","level":"INFO","msg":"nodejs runner environment initialized"}
{"time":"2026-04-11T17:48:25.654752995+08:00","level":"INFO","msg":"initializing python runner environment"}
{"time":"2026-04-11T17:48:25.655969634+08:00","level":"INFO","msg":"python runner environment initialized"}
{"time":"2026-04-11T17:48:25.65709941+08:00","level":"INFO","msg":"network has been enabled"}
{"time":"2026-04-11T17:48:25.657143329+08:00","level":"INFO","msg":"config init success"}
{"time":"2026-04-11T17:48:25.657244961+08:00","level":"INFO","msg":"runner dependencies init success"}
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /health                   --> github.com/langgenius/dify-sandbox/internal/controller.Setup.func1 (5 handlers)
{"time":"2026-04-11T17:48:25.657340263+08:00","level":"INFO","msg":"setting max requests","max":50}
{"time":"2026-04-11T17:48:25.657363705+08:00","level":"INFO","msg":"setting max workers","max":4}
[GIN-debug] POST   /v1/sandbox/run           --> github.com/langgenius/dify-sandbox/internal/controller.RunSandboxController (9 handlers)
[GIN-debug] GET    /v1/sandbox/dependencies  --> github.com/langgenius/dify-sandbox/internal/controller.GetDependencies (6 handlers)
[GIN-debug] POST   /v1/sandbox/dependencies/update --> github.com/langgenius/dify-sandbox/internal/controller.UpdateDependencies (6 handlers)
[GIN-debug] GET    /v1/sandbox/dependencies/refresh --> github.com/langgenius/dify-sandbox/internal/controller.RefreshDependencies (6 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :8194
{"time":"2026-04-11T17:48:25.657378554+08:00","level":"INFO","msg":"installing python dependencies"}
{"time":"2026-04-11T17:48:25.657470953+08:00","level":"INFO","msg":"python dependencies installed"}
{"time":"2026-04-11T17:48:25.657493653+08:00","level":"INFO","msg":"initializing python dependencies sandbox"}
{"time":"2026-04-11T17:50:05.341354813+08:00","level":"INFO","msg":"python dependencies sandbox initialized"}

检查服务是否可用

$ curl http://localhost:8194/health
"ok"

测试代码执行

curl -X POST http://localhost:8194/v1/sandbox/run \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: dify-sandbox" \
  -d '{
    "language": "python3",
    "code": "import json\nperson = {\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}\njson_str = json.dumps(person)\nprint(json_str)",
    "preload": "",
    "enable_network": false
  }'
{"code":-500,"message":"chown script to uid 10003: operation not permitted","data":null}

定位到问题代码

	if err = syscall.Chown(untrustedCodePath, uid, static.SANDBOX_GROUP_ID); err != nil {
		os.Remove(untrustedCodePath)
		return "", "", fmt.Errorf("chown script to uid %d: %w", uid, err)
	}

要执行 chown 命令,如何给普通用户授权? 暂时切换到 root 运行吧

# rm -rf /var/sandbox/* && ./main

再次执行测试代码,报错

$ curl -X POST http://localhost:8194/v1/sandbox/run \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: dify-sandbox" \
  -d '{
    "language": "python3",
    "code": "import json\nperson = {\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}\njson_str = json.dumps(person)\nprint(json_str)",
    "preload": "",
    "enable_network": false
  }'
{"code":-500,"message":"fork/exec /opt/python/bin/python3: no such file or directory","data":null}

问题代码

	// create a new process
	cmd := exec.Command(
		configuration.PythonPath,
		untrustedCodePath,
		LIB_PATH,
		key,
	)

python 的路径不对,需要修改 yaml 的配置

$ which python3
/usr/bin/python3

修改后的 yaml

$ cat ./conf/config.yaml 
app:
  port: 8194
  debug: True
  key: dify-sandbox
max_workers: 4
max_requests: 50
worker_timeout: 5
python_path: /usr/bin/python3
nodejs_path: /usr/local/node-v24.14.1/bin/node
python_lib_path:
  - "/usr/lib/python3"
  - "/usr/lib/x86_64-linux-gnu"
  - "/etc/ssl/certs/ca-certificates.crt"
  - "/etc/nsswitch.conf"
  - "/etc/hosts"
  - "/etc/resolv.conf"
  - "/etc/localtime"
  - "/usr/share/zoneinfo"
  - "/etc/timezone"
enable_network: True # please make sure there is no network risk in your environment
enable_preload: False # please keep it as False for security purposes
log_path: "./logs" # path to store log files, default is "./logs"
allowed_syscalls: # please leave it empty if you have no idea how seccomp works
proxy:
  socks5: ''
  http: ''
  https: ''

最终的测试脚本

$ cat test_dify_sandbox.sh 
#!/bin/bash

# 健康检查接口
echo "健康检查接口:"
curl http://localhost:8194/health

# Python3 示例
echo "\nPython3 示例:"
curl -X POST http://localhost:8194/v1/sandbox/run \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: dify-sandbox" \
  -d '{
    "language": "python3",
    "code": "import json\nperson = {\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}\njson_str = json.dumps(person)\nprint(json_str)",
    "preload": "",
    "enable_network": false
  }'

echo "\nNode.js 示例:"
# Node.js 示例
curl -X POST http://localhost:8194/v1/sandbox/run \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: dify-sandbox" \
  -d '{
    "language": "nodejs",
    "code": "const person = {name: \"John\", age: 30, city: \"New York\"};\nconst jsonString = JSON.stringify(person);\nconsole.log(jsonString);",
    "preload": "",
    "enable_network": false
  }'

运行结果

$ sh test_dify_sandbox.sh 
健康检查接口:
"ok"
Python3 示例:
{"code":0,"message":"success","data":{"error":"","stdout":"{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}\n"}}
Node.js 示例:
{"code":0,"message":"success","data":{"error":"","stdout":"{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}\n"}}

plugin

步骤

  1. 将.env.example文件复制到.env中,并设置正确的环境变量,如DB_HOST等。
cp .env.example .env

本地运行使用的是 mysql、redis, 修改如下配置

# redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=difyai123456
REDIS_DB=0
REDIS_USE_SSL=false

DB_TYPE=mysql
DB_USERNAME=root
DB_PASSWORD=difyai123456
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=dify_plugin
  1. 使用以下命令运行守护进程。它会使用godotenv从.env文件中加载环境变量
$ go run github.com/joho/godotenv/cmd/godotenv@latest -f .env go run cmd/server/main.go
2026-04-11T11:55:52.702513374Z INFO dify-plugin-daemon pool.go:34 init routine pool size=1024
2026-04-11T11:55:52.707063438Z INFO dify-plugin-daemon init.go:120 dify plugin db initialized
2026-04-11T11:55:52.707154132Z INFO dify-plugin-daemon manager.go:118 start plugin manager daemon
2026-04-11T11:55:52.708809889Z INFO dify-plugin-daemon init.go:20 persistence initialized
2026-04-11T11:55:52.708828438Z INFO dify-plugin-daemon server_local.go:16 start to handle new plugins path=plugin
2026-04-11T11:55:52.708861823Z INFO dify-plugin-daemon server_local.go:17 launch plugins with max concurrency concurrency=2
2026-04-11T11:55:52.709168884Z INFO dify-plugin-daemon logger.go:27 Launching gnet with 8 event-loops, listening on: tcp://127.0.0.1:5003
2026-04-11T11:55:52.733288393Z INFO dify-plugin-daemon middleware.go:83 trace_id=d6aa3960923e78b44ac37c837d638d11 HTTP request latency_ms=0 client_ip=192.168.1.3 method=GET path=/health/check status=200
2026-04-11T11:55:52.733564699Z INFO dify-plugin-daemon middleware.go:83 trace_id=b43e116a9ca6ae652a81e129ad764caf HTTP request client_ip=192.168.1.3 method=GET path=/health/check status=200 latency_ms=0
2026-04-11T11:55:52.733694625Z INFO dify-plugin-daemon middleware.go:83 trace_id=127a5dd66ed7b1359088037db49e1343 HTTP request status=200 latency_ms=0 client_ip=192.168.1.3 method=GET path=/health/check
2026-04-11T11:55:52.733918034Z INFO dify-plugin-daemon middleware.go:83 trace_id=a9482958069272bee9e966bad6f47b5b HTTP request method=GET path=/health/check status=200 latency_ms=0 client_ip=192.168.1.3
2026-04-11T11:55:52.734122273Z INFO dify-plugin-daemon middleware.go:83 trace_id=ae698a286869db594f28c6fcc654b413 HTTP request method=GET path=/health/check status=200 latency_ms=0 client_ip=192.168.1.3
2026-04-11T11:55:52.73425572Z INFO dify-plugin-daemon middleware.go:83 trace_id=82b83bb68fd3d9a4d5976dbb2c71d783 HTTP request client_ip=192.168.1.3 method=GET path=/health/check status=200 latency_ms=0
2026-04-11T11:55:53.210279248Z INFO dify-plugin-daemon cluster_lifetime.go:114 current node has become the master of the cluster
2026-04-11T11:56:02.75499235Z INFO dify-plugin-daemon node.go:248 node has been removed from the cluster due to being disconnected node_id=ff0be83a-d227-474d-bd7a-259cc3ab6383

检查服务是否可用

$ curl http://localhost:5002/health/check
{"active_dispatch_requests":0,"active_requests":1,"build_time":"","platform":"local","pool_status":{"free":1024,"busy":0,"total":1024},"status":"ok","version":""}

api、web

步骤

  1. 运行初始化脚本复制配置文件,安装依赖, 在项目根目录执行
$ ./dev/setup

检查 api/.env, web/.env.local, 和 docker/middleware.env 文件是否生成了

  1. 修改 api/.env 配置
    生成 SECRET_KEY
sed -i "/^SECRET_KEY=/c\\SECRET_KEY=$(openssl rand -base64 42)" ./api/.env

在这里插入图片描述
修改 数据库、redis 配置

# redis configuration
REDIS_HOST=localhost
REDIS_PORT=6379
# Optional: limit total connections in connection pool (unset for default)
# REDIS_MAX_CONNECTIONS=200
REDIS_USERNAME=
REDIS_PASSWORD=difyai123456
REDIS_USE_SSL=false
# SSL configuration for Redis (when REDIS_USE_SSL=true)
REDIS_SSL_CERT_REQS=CERT_NONE
# Options: CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
REDIS_SSL_CA_CERTS=
# Path to CA certificate file for SSL verification
REDIS_SSL_CERTFILE=
# Path to client certificate file for SSL authentication
REDIS_SSL_KEYFILE=
# Path to client private key file for SSL authentication
REDIS_DB=11

# Database configuration
DB_TYPE=mysql
DB_USERNAME=root
DB_PASSWORD=difyai123456
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=dify
  1. 启动api服务
./dev/start-api

运行 uv run flask db upgrade 报错

sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1049, "Unknown database 'dify'")

创建相关数据库

mysql> create database dify charset=utf8mb4;
Query OK, 1 row affected (0.00 sec)

再次运行 ./dev/start-api

$ ./dev/start-api
+++ realpath ./dev/start-api
++ dirname /home/scd/code/go/dify/dify-main/dev/start-api
+ SCRIPT_DIR=/home/scd/code/go/dify/dify-main/dev
+ cd /home/scd/code/go/dify/dify-main/dev/../api
+ uv run flask db upgrade
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
....
INFO  [alembic.runtime.migration] Running upgrade 0ec65df55790 -> 6b5f9f8b1a2c, add user_id and switch workflow_draft_variables unique key to user scope
+ uv run flask run --host 0.0.0.0 --port=5001 --debug
 * Debug mode: on
2026-04-11 12:28:00,84 INFO [_internal.py:97]  WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5001
 * Running on http://192.168.1.3:5001
2026-04-11 12:28:00,84 INFO [_internal.py:97]  Press CTRL+C to quit
2026-04-11 12:28:00,84 INFO [_internal.py:97]   * Restarting with stat
2026-04-11 12:28:09,719 WARNING [_internal.py:97]   * Debugger is active!
2026-04-11 12:28:09,727 INFO [_internal.py:97]   * Debugger PIN: 121-693-603

测试健康检测接口

curl http://localhost:5001/health
{"pid": 1103970, "status": "ok", "version": "1.13.3"}
  1. 启动web服务
$ ./dev/start-web
+++ realpath ./dev/start-web
++ dirname /home/scd/code/go/dify/dify-main/dev/start-web
+ SCRIPT_DIR=/home/scd/code/go/dify/dify-main/dev
++ dirname /home/scd/code/go/dify/dify-main/dev
+ ROOT_DIR=/home/scd/code/go/dify/dify-main
+ pnpm --dir /home/scd/code/go/dify/dify-main install
 WARN  Unsupported engine: wanted: {"node":"^22.22.1"} (current: {"node":"v24.14.1","pnpm":"10.33.0"})
Scope: all 5 workspace projects
Lockfile is up to date, resolution step is skipped
Already up to date
. prepare$ vp config
└─ Done in 146ms
Done in 1.9s using pnpm v10.33.0
+ pnpm --dir /home/scd/code/go/dify/dify-main/web dev:inspect

> dify-web@1.13.3 dev:inspect /home/scd/code/go/dify/dify-main/web
> next dev --inspect

Debugger listening on ws://127.0.0.1:9229/8029ada1-9c26-48fc-9393-50ebaa3734f4
For help, see: https://nodejs.org/en/docs/inspector
▲ Next.js 16.2.3 (Turbopack)
- Local:         http://localhost:3000
- Network:       http://192.168.1.3:3000
- Debugger port: 9229
- Environments: .env.local
✓ Ready in 445ms
Starting inspector on 127.0.0.1:9229 failed: address already in use
Starting inspector on 127.0.0.1:9229 failed: address already in use
- Experiments (use with caution):
  ⨯ turbopackFileSystemCacheForDev

浏览器访问 http://localhost:3000 首次访问需要等一会儿
在这里插入图片描述
设置管理员账户之后跳转到工作空间
在这里插入图片描述

检查相关数据表

mysql> select * from dify_setups;
+---------+---------------------+
| version | setup_at            |
+---------+---------------------+
| 1.13.3  | 2026-04-11 12:38:08 |
+---------+---------------------+
1 row in set (0.01 sec)

mysql> select id,name,plan,status from tenants;
+--------------------------------------+-----------------+-------+--------+
| id                                   | name            | plan  | status |
+--------------------------------------+-----------------+-------+--------+
| 8b1e249c-2812-4114-8d5d-a3ddc357652f | scd's Workspace | basic | normal |
+--------------------------------------+-----------------+-------+--------+
1 row in set (0.00 sec)

mysql> select id,name,interface_language,interface_theme,timezone from accounts;
+--------------------------------------+------+--------------------+-----------------+---------------+
| id                                   | name | interface_language | interface_theme | timezone      |
+--------------------------------------+------+--------------------+-----------------+---------------+
| f7c5cd88-1b5d-49a1-b949-2b6b5d33358a | scd  | zh-Hans            | light           | Asia/Shanghai |
+--------------------------------------+------+--------------------+-----------------+---------------+
1 row in set (0.00 sec)

mysql> select tenant_id,account_id,role,invited_by from tenant_account_joins;
+--------------------------------------+--------------------------------------+-------+------------+
| tenant_id                            | account_id                           | role  | invited_by |
+--------------------------------------+--------------------------------------+-------+------------+
| 8b1e249c-2812-4114-8d5d-a3ddc357652f | f7c5cd88-1b5d-49a1-b949-2b6b5d33358a | owner | NULL       |
+--------------------------------------+--------------------------------------+-------+------------+
1 row in set (0.00 sec)

注意事项

本地开发,机器吃不消了,Celery 任务队列没有启动
在这里插入图片描述

supervisord 一次启动多个服务

  1. 目录结构
$ tree -L 1
.
├── dify-main
├── dify-plugin-daemon
├── dify-sandbox
├── docker-compose.yml
├── env-check.sh
├── logs
├── process_problem.txt
├── run
├── supervisord.conf
├── test_dify_api.sh
├── test_dify_plugin.sh
└── test_dify_sandbox.sh

6 directories, 7 files

$ tree dify-main -d -L 1
dify-main
├── api
├── dev
├── docker
├── docs
├── e2e
├── images
├── node_modules
├── packages
├── scripts
├── sdks
└── web

12 directories
仓库地址说明文件夹
https://github.com/langgenius/difyweb、api 服务dify-main/api 、dify-main/web
https://github.com/langgenius/dify-plugin-daemonplugin 插件服务,需要在Linux 运行dify-plugin-daemon
https://github.com/langgenius/dify-sandboxsandbox 服务,运行python 代码、nodejs代码需要在 Linux 运行dify-sandbox
  1. supervisord.conf 配置文件, logs、run 文件夹需要手动创建
; Sample supervisor config file.
;
; For more information on the config file, please see:
; http://supervisord.org/configuration.html
;
; Notes:
;  - Shell expansion ("~" or "$HOME") is not supported.  Environment
;    variables can be expanded using this syntax: "%(ENV_HOME)s".
;  - Quotes around values are not supported, except in the case of
;    the environment= options as shown below.
;  - Comments must have a leading space: "a=b ;comment" not "a=b;comment".
;  - Command will be truncated if it looks like a config file comment, e.g.
;    "command=bash -c 'foo ; bar'" will truncate to "command=bash -c 'foo ".
;
; Warning:
;  Paths throughout this example file use /tmp because it is available on most
;  systems.  You will likely need to change these to locations more appropriate
;  for your system.  Some systems periodically delete older files in /tmp.
;  Notably, if the socket file defined in the [unix_http_server] section below
;  is deleted, supervisorctl will be unable to connect to supervisord.

[unix_http_server]
file=./run/supervisor.sock   ; the path to the socket file
;chmod=0700                 ; socket file mode (default 0700)
;chown=nobody:nogroup       ; socket file uid:gid owner
;username=user              ; default is no username (open server)
;password=123               ; default is no password (open server)

; Security Warning:
;  The inet HTTP server is not enabled by default.  The inet HTTP server is
;  enabled by uncommenting the [inet_http_server] section below.  The inet
;  HTTP server is intended for use within a trusted environment only.  It
;  should only be bound to localhost or only accessible from within an
;  isolated, trusted network.  The inet HTTP server does not support any
;  form of encryption.  The inet HTTP server does not use authentication
;  by default (see the username= and password= options to add authentication).
;  Never expose the inet HTTP server to the public internet.

;[inet_http_server]         ; inet (TCP) server disabled by default
;port=127.0.0.1:9001        ; ip_address:port specifier, *:port for all iface
;username=user              ; default is no username (open server)
;password=123               ; default is no password (open server)

[supervisord]
logfile=./logs/supervisord.log ; main log file; default $CWD/supervisord.log
logfile_maxbytes=50MB        ; max main logfile bytes b4 rotation; default 50MB
logfile_backups=10           ; # of main logfile backups; 0 means none, default 10
loglevel=debug                ; log level; default info; others: debug,warn,trace
pidfile=./run/supervisord.pid ; supervisord pidfile; default supervisord.pid
nodaemon=false               ; start in foreground if true; default false
silent=false                 ; no logs to stdout if true; default false
minfds=1024                  ; min. avail startup file descriptors; default 1024
minprocs=200                 ; min. avail process descriptors;default 200
;umask=022                   ; process file creation umask; default 022
;user=supervisord            ; setuid to this UNIX account at startup; recommended if root
;identifier=supervisor       ; supervisord identifier, default is 'supervisor'
;directory=/tmp              ; default is not to cd during start
;nocleanup=true              ; don't clean up tempfiles at start; default false
;childlogdir=/tmp            ; 'AUTO' child log dir, default $TEMP
;environment=KEY="value"     ; key value pairs to add to environment
;strip_ansi=false            ; strip ansi escape codes in logs; def. false

; The rpcinterface:supervisor section must remain in the config file for
; RPC (supervisorctl/web interface) to work.  Additional interfaces may be
; added by defining them in separate [rpcinterface:x] sections.

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

; The supervisorctl section configures how supervisorctl will connect to
; supervisord.  configure it match the settings in either the unix_http_server
; or inet_http_server section.

[supervisorctl]
serverurl=unix://./run/supervisor.sock ; use a unix:// URL  for a unix socket
;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
;username=chris              ; should be same as in [*_http_server] if set
;password=123                ; should be same as in [*_http_server] if set
;prompt=mysupervisor         ; cmd line prompt (default "supervisor")
;history_file=~/.sc_history  ; use readline history if available


; The sample program section below shows all possible program subsection values.
; Create one or more 'real' program: sections to be able to control them under
; supervisor.

[program:dify-sandbox]
command=go run cmd/server/main.go             ; the program (relative uses PATH, can take args)
process_name=dify-sandbox   ; process_name expr (default %(program_name)s)
directory=./dify-sandbox                ; directory to cwd to before exec (def no cwd)
priority=10                  ; the relative start priority (default 999)
stdout_logfile=./logs/dify-sandbox.log        ; stdout log path, NONE for none; default AUTO
stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stdout_logfile_backups=10     ; # of stdout logfile backups (0 means none, default 10)
stderr_logfile=./logs/dify-sandbox-error.log        ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stderr_logfile_backups=10     ; # of stderr logfile backups (0 means none, default 10)
;environment=A="1",B="2"       ; process environment additions (def no adds)


[program:dify-plugin]
command=go run github.com/joho/godotenv/cmd/godotenv@latest -f .env go run cmd/server/main.go             ; the program (relative uses PATH, can take args)
process_name=dify-plugin   ; process_name expr (default %(program_name)s)
directory=./dify-plugin-daemon                ; directory to cwd to before exec (def no cwd)
priority=20                  ; the relative start priority (default 999)
stdout_logfile=./logs/dify-plugin.log        ; stdout log path, NONE for none; default AUTO
stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stdout_logfile_backups=10     ; # of stdout logfile backups (0 means none, default 10)
stderr_logfile=./logs/dify-plugin-error.log        ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stderr_logfile_backups=10     ; # of stderr logfile backups (0 means none, default 10)
;environment=A="1",B="2"       ; process environment additions (def no adds)

[program:dify-api]
command=uv run flask run --host 0.0.0.0 --port=5001             ; the program (relative uses PATH, can take args)
process_name=dify-api   ; process_name expr (default %(program_name)s)
directory=./dify-main/api                ; directory to cwd to before exec (def no cwd)
priority=30                  ; the relative start priority (default 999)
stdout_logfile=./logs/dify-api.log        ; stdout log path, NONE for none; default AUTO
stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stdout_logfile_backups=10     ; # of stdout logfile backups (0 means none, default 10)
stderr_logfile=./logs/dify-api-error.log        ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stderr_logfile_backups=10     ; # of stderr logfile backups (0 means none, default 10)
;environment=A="1",B="2"       ; process environment additions (def no adds)

[program:dify-web]
command=pnpm -C web run start            ; the program (relative uses PATH, can take args)
process_name=dify-web   ; process_name expr (default %(program_name)s)
directory=./dify-main                ; directory to cwd to before exec (def no cwd)
priority=40                  ; the relative start priority (default 999)
stdout_logfile=./logs/dify-web.log        ; stdout log path, NONE for none; default AUTO
stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stdout_logfile_backups=10     ; # of stdout logfile backups (0 means none, default 10)
stderr_logfile=./logs/dify-web-error.log        ; stderr log path, NONE for none; default AUTO
stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
stderr_logfile_backups=10     ; # of stderr logfile backups (0 means none, default 10)
;environment=A="1",B="2"       ; process environment additions (def no adds)

pnpm -C web run start 使用编译好的文件启动前端,访问会流畅点
在这里插入图片描述

  1. 启动命令
supervisord -c supervisord.conf
  1. 查看服务状态
$ supervisorctl status all
dify-api                         RUNNING   pid 861948, uptime 0:37:38
dify-plugin                      RUNNING   pid 927281, uptime 0:26:38
dify-sandbox                     RUNNING   pid 861946, uptime 0:37:38
dify-web                         RUNNING   pid 923249, uptime 0:34:53
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐