1 概述
在kubernetes部署dify,yaml文件参考大佬文档:
https://github.com/Winson-030/dify-kubernetes
2 环境准备
2.1 购买SFS Turbo实例
2.2 购买华为云容器集群CCE实例
2.3 在k8s中创建storageclass对象
参数everest.io/share-access-to是VPC的ID。
参数everest.io/share-export-location是sfs turbo实例的共享路径:自定义子目录,sfs turbo实例的共享路径是在sfs实例的详细页查询,自定义子目录可以是任意路径。
参数everest.io/volume-id是sfs turbo实例的ID。
只需要修改以上三个参数。
在本文,storageclass的名称叫做sfsturbo-subpath-sc。
apiVersion: storage.k8s.io/v1
allowVolumeExpansion: true
kind: StorageClass
metadata:
name: sfsturbo-subpath-sc
mountOptions:
- lock
parameters:
csi.storage.k8s.io/csi-driver-name: sfsturbo.csi.everest.io
csi.storage.k8s.io/fstype: nfs
everest.io/archive-on-delete: "true"
everest.io/share-access-to: xxxxxxxxxxxxxxxxxx # VPC ID
everest.io/share-expand-type: bandwidth
everest.io/share-export-location: xxxxx.sfsturbo.internal:/mydir # sfs turbo实例的共享路径:自定义子目录
everest.io/share-source: sfs-turbo
everest.io/share-volume-type: STANDARD
everest.io/volume-as: subpath
everest.io/volume-id: xxxxxxxxxxxxx # sfs turbo实例的ID
provisioner: everest-csi-provisioner
reclaimPolicy: Retain
volumeBindingMode: Immediate
3 部署
直接apply下面的文件即可,所用的storageclass名称是刚刚创建的sfsturbo-subpath-sc。
###############################################################################
# Author: Winson Li
# Email: a623719265@gmail.com
# Github: @Winson-030
###############################################################################
# Namespace
apiVersion: v1
kind: Namespace
metadata:
name: dify
# Dify Credentials
# apiVersion: v1
# kind: Secret
# metadata:
# name: dify-credentials
# namespace: dify
# data:
# # Base64 encoded postgres username, default is postgres
# pg-username: cG9zdGdyZXM=
# # Base64 encoded postgres password, default is difyai123456
# pg-password: ZGlmeWFpMTIzNDU2
# # Base64 encoded postgres host, default is dify-postgres
# pg-host: ZGlmeS1wb3N0Z3Jlcw==
# # Base64 encoded postgres port 5432
# pg-port: NTQzMg==
# # Base64 encoded redis username, default is empty
# redis-username: ""
# # Base64 encoded redis password, default is difyai123456
# redis-password: ZGlmeWFpMTIzNDU2
# # Base64 encoded redis host, default is dify-redis
# redis-host: ZGlmeS1yZWRpcw==
# # Base64 encoded redis port 6379
# redis-port: NjM3OQ==
# # Base64 encoded weaviate host, default is dify-weaviate
# weaviate-host: ZGlmeS13ZWF2aWF0ZQ==
# # Base64 encoded weaviate port 8080
# weaviate-port: ODA4MA==
# type: Opaque
# Postgres Server Start
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/instance: dify-postgres
name: dify-postgres
namespace: dify
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/instance: dify-postgres
name: dify-postgres
namespace: dify
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/instance: dify-postgres
name: dify-postgres
namespace: dify
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dify-postgres
subjects:
- kind: ServiceAccount
name: dify-postgres
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dify-postgres
namespace: dify
spec:
selector:
matchLabels:
app: dify-postgres
serviceName: "dify-postgres"
replicas: 1
template:
metadata:
labels:
app: dify-postgres
spec:
serviceAccountName: dify-postgres
terminationGracePeriodSeconds: 10
nodeSelector:
kubernetes.io/os: linux
containers:
- name: dify-postgres
image: postgres:15-alpine
env:
- name: PGUSER
value: postgres
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-username
- name: POSTGRES_PASSWORD
value: difyai123456
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-password
- name: POSTGRES_DB
value: dify
livenessProbe:
exec:
command:
- "pg_isready"
- "-U"
- "$(PGUSER)"
- "-d"
- "$(POSTGRES_DB)"
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 2
successThreshold: 1
failureThreshold: 10
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 100m
memory: 128Mi
ports:
- containerPort: 5432
name: postgres-port
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
storageClassName: sfsturbo-subpath-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: dify-postgres
namespace: dify
spec:
selector:
app: dify-postgres
type: ClusterIP
clusterIP: None
ports:
- name: postgres
protocol: TCP
port: 5432
targetPort: 5432
# Postgres Server End
# Redis Server Start
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/instance: dify-redis
name: dify-redis
namespace: dify
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/instance: dify-redis
name: dify-redis
namespace: dify
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/instance: dify-redis
name: dify-redis
namespace: dify
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dify-redis
subjects:
- kind: ServiceAccount
name: dify-redis
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dify-redis
namespace: dify
spec:
selector:
matchLabels:
app: dify-redis
serviceName: "dify-redis"
replicas: 1
template:
metadata:
labels:
app: dify-redis
spec:
terminationGracePeriodSeconds: 10
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: dify-redis
containers:
- name: dify-redis
image: redis:6-alpine
ports:
- containerPort: 6379
name: redis-p
command: ["redis-server", "--save", "20", "1", "--loglevel", "warning", "--requirepass", "$(REDIS_PASSWORD)"]
resources:
limits:
cpu: 500m
memory: 1024Mi
requests:
cpu: 100m
memory: 102Mi
env:
- name: REDIS_PASSWORD
value: difyai123456
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-password
livenessProbe:
exec:
command:
- redis-cli
- ping
volumeMounts:
- name: redis-data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
storageClassName: sfsturbo-subpath-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: dify-redis
namespace: dify
spec:
selector:
app: dify-redis
type: ClusterIP
clusterIP: None
ports:
- name: redis
protocol: TCP
port: 6379
targetPort: 6379
# Redis Server End
# Weaviate Server Start
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/instance: dify-weaviate
name: dify-weaviate
namespace: dify
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/instance: dify-weaviate
name: dify-weaviate
namespace: dify
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/instance: dify-weaviate
name: dify-weaviate
namespace: dify
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dify-weaviate
subjects:
- kind: ServiceAccount
name: dify-weaviate
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dify-weaviate
namespace: dify
spec:
selector:
matchLabels:
app: dify-weaviate
serviceName: "dify-weaviate"
replicas: 1
volumeClaimTemplates:
- metadata:
name: weaviate-data
spec:
storageClassName: sfsturbo-subpath-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
template:
metadata:
labels:
app: dify-weaviate
spec:
terminationGracePeriodSeconds: 10
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: dify-weaviate
containers:
- name: dify-weaviate
image: semitechnologies/weaviate:1.19.0
ports:
- containerPort: 8080
name: weaviate-p
resources:
limits:
cpu: 500m
memory: 1024Mi
requests:
cpu: 100m
memory: 102Mi
env:
- name: QUERY_DEFAULTS_LIMIT
value: "25"
- name: AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED
value: "false"
- name: PERSISTENCE_DATA_PATH
value: "/var/lib/weaviate"
- name: "DEFAULT_VECTORIZER_MODULE"
value: "none"
- name: "AUTHENTICATION_APIKEY_ENABLED"
value: "true"
- name: "AUTHENTICATION_APIKEY_ALLOWED_KEYS"
value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
- name: "AUTHENTICATION_APIKEY_USERS"
value: "hello@dify.ai"
- name: "AUTHORIZATION_ADMINLIST_ENABLED"
value: "true"
- name: "AUTHORIZATION_ADMINLIST_USERS"
value: "hello@dify.ai"
volumeMounts:
- name: weaviate-data
mountPath: /var/lib/weaviate
---
apiVersion: v1
kind: Service
metadata:
name: dify-weaviate
namespace: dify
spec:
selector:
app: dify-weaviate
type: ClusterIP
clusterIP: None
ports:
- name: weaviate
protocol: TCP
port: 8080
targetPort: 8080
# Weaviate Server End
# Dify Sandbox Server Start
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify-sandbox
namespace: dify
labels:
app: dify-sandbox
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
app: dify-sandbox
template:
metadata:
labels:
app: dify-sandbox
spec:
automountServiceAccountToken: false
nodeSelector:
kubernetes.io/os: linux
containers:
- name: dify-sandbox
image: langgenius/dify-sandbox:0.2.10
env:
- name: API_KEY
value: "dify-sandbox"
- name: GIN_MODE
value: "release"
- name: WORKER_TIMEOUT
value: "15"
- name: ENABLE_NETWORK
value: "true"
- name: SANDBOX_PORT
value: "8194"
# uncomment if you want to use proxy
- name: HTTP_PROXY
value: 'http://dify-ssrf:3128'
- name: HTTPS_PROXY
value: 'http://dify-ssrf:3128'
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 1Gi
ports:
- containerPort: 8194
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: dify-sandbox
namespace: dify
spec:
ports:
- port: 8194
targetPort: 8194
protocol: TCP
name: dify-sandbox
type: ClusterIP
clusterIP: None
selector:
app: dify-sandbox
# Dify Sandbox Server End
# Dify SSRF Proxy Start
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ssrf-proxy-config
namespace: dify
data:
squid.conf: |
acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12 # RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN)
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localhost
http_access allow localnet
http_access deny all
################################## Proxy Server ################################
http_port 3128
coredump_dir /var/spool/squid
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern . 0 20% 4320
# upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks
# cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default
################################## Reverse Proxy To Sandbox ################################
http_port 8194 accel vhost
# Notice:
# default is 'sandbox' in dify's github repo, here is 'dify-sandbox' because the service name of sandbox is 'dify-sandbox'
# you can change it to your own service name
cache_peer dify-sandbox parent 8194 0 no-query originserver
acl src_all src all
http_access allow src_all
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ssrf-proxy-entrypoint
namespace: dify
data:
docker-entrypoint-mount.sh: |
#!/bin/bash
# Modified based on Squid OCI image entrypoint
# This entrypoint aims to forward the squid logs to stdout to assist users of
# common container related tooling (e.g., kubernetes, docker-compose, etc) to
# access the service logs.
# Moreover, it invokes the squid binary, leaving all the desired parameters to
# be provided by the "command" passed to the spawned container. If no command
# is provided by the user, the default behavior (as per the CMD statement in
# the Dockerfile) will be to use Ubuntu's default configuration [1] and run
# squid with the "-NYC" options to mimic the behavior of the Ubuntu provided
# systemd unit.
# [1] The default configuration is changed in the Dockerfile to allow local
# network connections. See the Dockerfile for further information.
echo "[ENTRYPOINT] re-create snakeoil self-signed certificate removed in the build process"
if [ ! -f /etc/ssl/private/ssl-cert-snakeoil.key ]; then
/usr/sbin/make-ssl-cert generate-default-snakeoil --force-overwrite > /dev/null 2>&1
fi
tail -F /var/log/squid/access.log 2>/dev/null &
tail -F /var/log/squid/error.log 2>/dev/null &
tail -F /var/log/squid/store.log 2>/dev/null &
tail -F /var/log/squid/cache.log 2>/dev/null &
# Replace environment variables in the template and output to the squid.conf
echo "[ENTRYPOINT] replacing environment variables in the template"
awk '{
while(match($0, /\${[A-Za-z_][A-Za-z_0-9]*}/)) {
var = substr($0, RSTART+2, RLENGTH-3)
val = ENVIRON[var]
$0 = substr($0, 1, RSTART-1) val substr($0, RSTART+RLENGTH)
}
print
}' /etc/squid/squid.conf.template > /etc/squid/squid.conf
/usr/sbin/squid -Nz
echo "[ENTRYPOINT] starting squid"
/usr/sbin/squid -f /etc/squid/squid.conf -NYC 1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify-ssrf
namespace: dify
labels:
app: dify-ssrf
spec:
selector:
matchLabels:
app: dify-ssrf
replicas: 1
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: dify-ssrf
spec:
nodeSelector:
kubernetes.io/os: linux
containers:
- name: dify-ssrf
image: ubuntu/squid:latest
env:
- name: HTTP_PORT
value: "3128"
- name: COREDUMP_DIR
value: "/var/spool/squid"
- name: REVERSE_PROXY_PORT
value: "8194"
- name: SANDBOX_HOST
value: "dify-sandbox"
- name: SANDBOX_PORT
value: "8194"
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 300m
memory: 300Mi
ports:
- containerPort: 3128
name: dify-ssrf
volumeMounts:
- name: ssrf-proxy-config
mountPath: /etc/squid/
- name: ssrf-proxy-entrypoint
mountPath: /tmp/
command: [ "sh", "-c", "cp /tmp/docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ]
volumes:
- name: ssrf-proxy-config
configMap:
name: ssrf-proxy-config
- name: ssrf-proxy-entrypoint
configMap:
name: ssrf-proxy-entrypoint
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: dify-ssrf
namespace: dify
spec:
selector:
app: dify-ssrf
ports:
- protocol: TCP
port: 3128
targetPort: 3128
# Dify SSRF Proxy End
# Dify API Server Start
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dify-api-storage
namespace: dify
spec:
storageClassName: sfsturbo-subpath-sc
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dify-api
labels:
app.kubernetes.io/instance: dify-api
app: dify-api
namespace: dify
spec:
replicas: 1
revisionHistoryLimit: 1
minReadySeconds: 10
serviceName: dify-api
selector:
matchLabels:
app: dify-api
template:
metadata:
labels:
app: dify-api
spec:
nodeSelector:
kubernetes.io/os: linux
volumes:
- name: dify-api-storage
persistentVolumeClaim:
claimName: dify-api-storage
containers:
- name: dify-api
image: langgenius/dify-api:0.15.2
env:
- name: MODE
value: api
- name: LOG_LEVEL
value: DEBUG
- name: SECRET_KEY
value: "sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U"
- name: CONSOLE_WEB_URL
value: ""
- name: INIT_PASSWORD
value: password
- name: CONSOLE_API_URL
value: ""
- name: SERVICE_API_URL
value: ""
- name: APP_WEB_URL
value: ""
- name: FILES_URL
value: ""
- name: MIGRATION_ENABLED
value: "true"
- name: DB_USERNAME
value: postgres
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-username
- name: DB_PASSWORD
value: "difyai123456"
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-password
- name: DB_HOST
value: dify-postgres
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-host
- name: DB_PORT
value: '5432'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-port
- name: DB_DATABASE
value: dify
- name: REDIS_HOST
value: dify-redis
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-host
- name: REDIS_PORT
value: '6379'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-port
# default redis username is empty
- name: REDIS_USERNAME
value: ''
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-username
- name: REDIS_PASSWORD
value: "difyai123456"
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-password
- name: REDIS_USE_SSL
value: "false"
- name: REDIS_DB
value: "0"
- name: CELERY_BROKER_URL
value: >-
redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/1
- name: WEB_API_CORS_ALLOW_ORIGINS
value: "*"
- name: CONSOLE_CORS_ALLOW_ORIGINS
value: "*"
- name: STORAGE_TYPE
value: opendal
- name: OPENDAL_SCHEME
value: fs
- name: OPENDAL_FS_ROOT
value: storage
- name: STORAGE_LOCAL_PATH
value: /app/api/storage
- name: VECTOR_STORE
value: weaviate
- name: WEAVIATE_HOST
value: dify-weaviate
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: weaviate-host
- name: WEAVIATE_PORT
value: '8080'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: weaviate-port
- name: WEAVIATE_ENDPOINT
value: http://$(WEAVIATE_HOST):$(WEAVIATE_PORT)
- name: WEAVIATE_API_KEY
value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
- name: CODE_EXECUTION_ENDPOINT
value: http://dify-sandbox:8194
- name: CODE_EXECUTION_API_KEY
value: dify-sandbox
- name: CODE_MAX_NUMBER
value: "9223372036854775807"
- name: CODE_MIN_NUMBER
value: "-9223372036854775808"
- name: CODE_MAX_STRING_LENGTH
value: "80000"
- name: TEMPLATE_TRANSFORM_MAX_LENGTH
value: "80000"
- name: CODE_MAX_STRING_ARRAY_LENGTH
value: "30"
- name: CODE_MAX_OBJECT_ARRAY_LENGTH
value: "30"
- name: CODE_MAX_NUMBER_ARRAY_LENGTH
value: "1000"
- name: INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH
value: "1000"
# uncommect to enable SSRF
- name: SSRF_PROXY_HTTP_URL
value: 'http://dify-ssrf:3128'
- name: SSRF_PROXY_HTTPS_URL
value: 'http://dify-ssrf:3128'
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 2Gi
ports:
- containerPort: 5001
imagePullPolicy: IfNotPresent
volumeMounts:
- name: dify-api-storage
mountPath: /app/api/storage
---
apiVersion: v1
kind: Service
metadata:
name: dify-api
namespace: dify
spec:
ports:
- port: 5001
targetPort: 5001
protocol: TCP
name: dify-api
type: ClusterIP
selector:
app: dify-api
# Dify API Server End
# Dify Worker Server Start
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dify-worker
namespace: dify
labels:
app: dify-worker
app.kubernetes.io/instance: dify-worker
spec:
serviceName: "dify-worker"
replicas: 1
selector:
matchLabels:
app: dify-worker
template:
metadata:
labels:
app: dify-worker
spec:
nodeSelector:
kubernetes.io/os: linux
volumes:
- name: dify-api-storage
persistentVolumeClaim:
claimName: dify-api-storage
containers:
- name: dify-worker
image: langgenius/dify-api:0.15.2
ports:
- containerPort: 5001
protocol: TCP
env:
- name: CONSOLE_WEB_URL
value: ""
- name: MODE
value: worker
- name: LOG_LEVEL
value: INFO
- name: SECRET_KEY
value: "sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U"
- name: DB_USERNAME
value: postgres
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-username
- name: DB_PASSWORD
value: "difyai123456"
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-password
- name: DB_HOST
value: dify-postgres
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-host
- name: DB_PORT
value: '5432'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-port
- name: DB_DATABASE
value: dify
- name: REDIS_HOST
value: dify-redis
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-host
- name: REDIS_PORT
value: '6379'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-port
# default redis username is empty
- name: REDIS_USERNAME
value: ''
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-username
- name: REDIS_PASSWORD
value: "difyai123456"
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-password
- name: REDIS_USE_SSL
value: "false"
- name: REDIS_DB
value: "0"
- name: CELERY_BROKER_URL
value: >-
redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/1
- name: WEB_API_CORS_ALLOW_ORIGINS
value: "*"
- name: CONSOLE_CORS_ALLOW_ORIGINS
value: "*"
- name: STORAGE_TYPE
value: opendal
- name: OPENDAL_SCHEME
value: fs
- name: OPENDAL_FS_ROOT
value: storage
- name: STORAGE_LOCAL_PATH
value: /app/api/storage
- name: VECTOR_STORE
value: weaviate
- name: WEAVIATE_HOST
value: dify-weaviate
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: weaviate-host
- name: WEAVIATE_PORT
value: '8080'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: weaviate-port
- name: WEAVIATE_ENDPOINT
value: http://$(WEAVIATE_HOST):$(WEAVIATE_PORT)
- name: WEAVIATE_API_KEY
value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
- name: SSRF_PROXY_HTTP_URL
value: 'http://dify-ssrf:3128'
- name: SSRF_PROXY_HTTPS_URL
value: 'http://dify-ssrf:3128'
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 2Gi
volumeMounts:
- name: dify-api-storage
mountPath: /app/api/storage
imagePullPolicy: IfNotPresent
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: dify-worker
namespace: dify
spec:
ports:
- protocol: TCP
port: 5001
targetPort: 5001
selector:
app: dify-worker
type: ClusterIP
# Dify Worker Server End
# Dify Web Server Start
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify-web
namespace: dify
labels:
app: dify-web
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
app: dify-web
template:
metadata:
labels:
app: dify-web
spec:
nodeSelector:
kubernetes.io/os: linux
automountServiceAccountToken: false
containers:
- name: dify-web
image: langgenius/dify-web:0.15.2
env:
- name: EDITION
value: SELF_HOSTED
- name: CONSOLE_API_URL
value: ""
- name: APP_API_URL
value: ""
- name: SENTRY_DSN
value: ""
- name: NEXT_TELEMETRY_DISABLED
value: "0"
- name: TEXT_GENERATION_TIMEOUT_MS
value: "60000"
- name: CSP_WHITELIST
value: ""
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 1Gi
ports:
- containerPort: 3000
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: dify-web
namespace: dify
spec:
ports:
- port: 3000
targetPort: 3000
protocol: TCP
name: dify-web
type: ClusterIP
selector:
app: dify-web
# Dify Web Server End
# Dify Nginx Server Start
---
apiVersion: v1
kind: ConfigMap
metadata:
name: dify-nginx
namespace: dify
data:
nginx.conf: |-
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
client_max_body_size 15M;
server {
listen 80;
server_name _;
location /console/api {
proxy_pass http://dify-api:5001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /api {
proxy_pass http://dify-api:5001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /v1 {
proxy_pass http://dify-api:5001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /files {
proxy_pass http://dify-api:5001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location / {
proxy_pass http://dify-web:3000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
# If you want to support HTTPS, please uncomment the code snippet below
#listen 443 ssl;
#ssl_certificate ./../ssl/your_cert_file.cer;
#ssl_certificate_key ./../ssl/your_cert_key.key;
#ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
#ssl_prefer_server_ciphers on;
#ssl_session_cache shared:SSL:10m;
#ssl_session_timeout 10m;
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify-nginx
namespace: dify
labels:
app: dify-nginx
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
app: dify-nginx
template:
metadata:
labels:
app: dify-nginx
spec:
nodeSelector:
kubernetes.io/os: linux
automountServiceAccountToken: false
containers:
- name: dify-nginx
image: nginx:stable
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 1Gi
ports:
- containerPort: 80
volumeMounts:
- name: dify-nginx
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
- name: dify-nginx-config
mountPath: /etc/nginx/conf.d
imagePullPolicy: IfNotPresent
volumes:
- name: dify-nginx
configMap:
name: dify-nginx
# Persistent volume could be better
- name: dify-nginx-config
emptyDir: {}
---
kind: Service
apiVersion: v1
metadata:
name: dify-nginx
namespace: dify
spec:
selector:
app: dify-nginx
type: ClusterIP
ports:
- name: dify-nginx
port: 80
targetPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: dify-nginx-nodeport
namespace: dify
spec:
selector:
app: dify-nginx
type: NodePort
ports:
- name: dify-nginx
port: 80
targetPort: 80
nodePort: 30000
# Dify Nginx Server End
4 ingress暴露dify-nginx服务
通过ingress的status字段可以发现LB的内网IP是10.0.17.174,在浏览器访问http://10.0.17.174:80/,输入校验密码"password"后(yaml文件指定了该字符串),即可初始化管理员账号密码,最后成功添加一个ollama实例:
5 pg和redis使用云服务的方式来部署dify
5.1 准备redis和pg服务
创建一个5.0版本的redis,如下图:
创建一个pg 15服务,并创建一个名称为dify的数据库。
5.1 部署dify服务
storageclass依然使用上面创建的sfsturbo-subpath-sc,搜索如下所有环境变量,值设置成你的云服务即可。
环境变量DB_HOST是pg服务的IP。
环境变量DB_PASSWORD是pg服务的密码。
环境变量REDIS_HOST是redis服务的IP。
环境变量REDIS_PASSWORD是redis服务的密码。
部署到名称为自定义的namespace,以dify-new名字为例:
kubectl create ns dify-new
kubectl apply -f dify.yaml -n dify-new
dify.yaml文件(此文件和上面的文件不一样,删除了固定的namespace、pg和redis两个sts工作负载)如下:
###############################################################################
# Author: Winson Li
# Email: a623719265@gmail.com
# Github: @Winson-030
###############################################################################
# Dify Credentials
# apiVersion: v1
# kind: Secret
# metadata:
# name: dify-credentials
# namespace: dify
# data:
# # Base64 encoded postgres username, default is postgres
# pg-username: cG9zdGdyZXM=
# # Base64 encoded postgres password, default is difyai123456
# pg-password: ZGlmeWFpMTIzNDU2
# # Base64 encoded postgres host, default is dify-postgres
# pg-host: ZGlmeS1wb3N0Z3Jlcw==
# # Base64 encoded postgres port 5432
# pg-port: NTQzMg==
# # Base64 encoded redis username, default is empty
# redis-username: ""
# # Base64 encoded redis password, default is difyai123456
# redis-password: ZGlmeWFpMTIzNDU2
# # Base64 encoded redis host, default is dify-redis
# redis-host: ZGlmeS1yZWRpcw==
# # Base64 encoded redis port 6379
# redis-port: NjM3OQ==
# # Base64 encoded weaviate host, default is dify-weaviate
# weaviate-host: ZGlmeS13ZWF2aWF0ZQ==
# # Base64 encoded weaviate port 8080
# weaviate-port: ODA4MA==
# type: Opaque
# Weaviate Server Start
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/instance: dify-weaviate
name: dify-weaviate
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/instance: dify-weaviate
name: dify-weaviate
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/instance: dify-weaviate
name: dify-weaviate
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dify-weaviate
subjects:
- kind: ServiceAccount
name: dify-weaviate
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dify-weaviate
spec:
selector:
matchLabels:
app: dify-weaviate
serviceName: "dify-weaviate"
replicas: 1
volumeClaimTemplates:
- metadata:
name: weaviate-data
spec:
storageClassName: sfsturbo-subpath-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
template:
metadata:
labels:
app: dify-weaviate
spec:
terminationGracePeriodSeconds: 10
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: dify-weaviate
containers:
- name: dify-weaviate
image: semitechnologies/weaviate:1.19.0
ports:
- containerPort: 8080
name: weaviate-p
resources:
limits:
cpu: 500m
memory: 1024Mi
requests:
cpu: 100m
memory: 102Mi
env:
- name: QUERY_DEFAULTS_LIMIT
value: "25"
- name: AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED
value: "false"
- name: PERSISTENCE_DATA_PATH
value: "/var/lib/weaviate"
- name: "DEFAULT_VECTORIZER_MODULE"
value: "none"
- name: "AUTHENTICATION_APIKEY_ENABLED"
value: "true"
- name: "AUTHENTICATION_APIKEY_ALLOWED_KEYS"
value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
- name: "AUTHENTICATION_APIKEY_USERS"
value: "hello@dify.ai"
- name: "AUTHORIZATION_ADMINLIST_ENABLED"
value: "true"
- name: "AUTHORIZATION_ADMINLIST_USERS"
value: "hello@dify.ai"
volumeMounts:
- name: weaviate-data
mountPath: /var/lib/weaviate
---
apiVersion: v1
kind: Service
metadata:
name: dify-weaviate
spec:
selector:
app: dify-weaviate
type: ClusterIP
clusterIP: None
ports:
- name: weaviate
protocol: TCP
port: 8080
targetPort: 8080
# Weaviate Server End
# Dify Sandbox Server Start
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify-sandbox
labels:
app: dify-sandbox
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
app: dify-sandbox
template:
metadata:
labels:
app: dify-sandbox
spec:
automountServiceAccountToken: false
nodeSelector:
kubernetes.io/os: linux
containers:
- name: dify-sandbox
image: langgenius/dify-sandbox:0.2.10
env:
- name: API_KEY
value: "dify-sandbox"
- name: GIN_MODE
value: "release"
- name: WORKER_TIMEOUT
value: "15"
- name: ENABLE_NETWORK
value: "true"
- name: SANDBOX_PORT
value: "8194"
# uncomment if you want to use proxy
- name: HTTP_PROXY
value: 'http://dify-ssrf:3128'
- name: HTTPS_PROXY
value: 'http://dify-ssrf:3128'
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 1Gi
ports:
- containerPort: 8194
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: dify-sandbox
spec:
ports:
- port: 8194
targetPort: 8194
protocol: TCP
name: dify-sandbox
type: ClusterIP
clusterIP: None
selector:
app: dify-sandbox
# Dify Sandbox Server End
# Dify SSRF Proxy Start
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ssrf-proxy-config
data:
squid.conf: |
acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12 # RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN)
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localhost
http_access allow localnet
http_access deny all
################################## Proxy Server ################################
http_port 3128
coredump_dir /var/spool/squid
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern . 0 20% 4320
# upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks
# cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default
################################## Reverse Proxy To Sandbox ################################
http_port 8194 accel vhost
# Notice:
# default is 'sandbox' in dify's github repo, here is 'dify-sandbox' because the service name of sandbox is 'dify-sandbox'
# you can change it to your own service name
cache_peer dify-sandbox parent 8194 0 no-query originserver
acl src_all src all
http_access allow src_all
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ssrf-proxy-entrypoint
data:
docker-entrypoint-mount.sh: |
#!/bin/bash
# Modified based on Squid OCI image entrypoint
# This entrypoint aims to forward the squid logs to stdout to assist users of
# common container related tooling (e.g., kubernetes, docker-compose, etc) to
# access the service logs.
# Moreover, it invokes the squid binary, leaving all the desired parameters to
# be provided by the "command" passed to the spawned container. If no command
# is provided by the user, the default behavior (as per the CMD statement in
# the Dockerfile) will be to use Ubuntu's default configuration [1] and run
# squid with the "-NYC" options to mimic the behavior of the Ubuntu provided
# systemd unit.
# [1] The default configuration is changed in the Dockerfile to allow local
# network connections. See the Dockerfile for further information.
echo "[ENTRYPOINT] re-create snakeoil self-signed certificate removed in the build process"
if [ ! -f /etc/ssl/private/ssl-cert-snakeoil.key ]; then
/usr/sbin/make-ssl-cert generate-default-snakeoil --force-overwrite > /dev/null 2>&1
fi
tail -F /var/log/squid/access.log 2>/dev/null &
tail -F /var/log/squid/error.log 2>/dev/null &
tail -F /var/log/squid/store.log 2>/dev/null &
tail -F /var/log/squid/cache.log 2>/dev/null &
# Replace environment variables in the template and output to the squid.conf
echo "[ENTRYPOINT] replacing environment variables in the template"
awk '{
while(match($0, /\${[A-Za-z_][A-Za-z_0-9]*}/)) {
var = substr($0, RSTART+2, RLENGTH-3)
val = ENVIRON[var]
$0 = substr($0, 1, RSTART-1) val substr($0, RSTART+RLENGTH)
}
print
}' /etc/squid/squid.conf.template > /etc/squid/squid.conf
/usr/sbin/squid -Nz
echo "[ENTRYPOINT] starting squid"
/usr/sbin/squid -f /etc/squid/squid.conf -NYC 1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify-ssrf
labels:
app: dify-ssrf
spec:
selector:
matchLabels:
app: dify-ssrf
replicas: 1
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: dify-ssrf
spec:
nodeSelector:
kubernetes.io/os: linux
containers:
- name: dify-ssrf
image: ubuntu/squid:latest
env:
- name: HTTP_PORT
value: "3128"
- name: COREDUMP_DIR
value: "/var/spool/squid"
- name: REVERSE_PROXY_PORT
value: "8194"
- name: SANDBOX_HOST
value: "dify-sandbox"
- name: SANDBOX_PORT
value: "8194"
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 300m
memory: 300Mi
ports:
- containerPort: 3128
name: dify-ssrf
volumeMounts:
- name: ssrf-proxy-config
mountPath: /etc/squid/
- name: ssrf-proxy-entrypoint
mountPath: /tmp/
command: [ "sh", "-c", "cp /tmp/docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ]
volumes:
- name: ssrf-proxy-config
configMap:
name: ssrf-proxy-config
- name: ssrf-proxy-entrypoint
configMap:
name: ssrf-proxy-entrypoint
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: dify-ssrf
spec:
selector:
app: dify-ssrf
ports:
- protocol: TCP
port: 3128
targetPort: 3128
# Dify SSRF Proxy End
# Dify API Server Start
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dify-api-storage
spec:
storageClassName: sfsturbo-subpath-sc
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dify-api
labels:
app.kubernetes.io/instance: dify-api
app: dify-api
spec:
replicas: 1
revisionHistoryLimit: 1
minReadySeconds: 10
serviceName: dify-api
selector:
matchLabels:
app: dify-api
template:
metadata:
labels:
app: dify-api
spec:
nodeSelector:
kubernetes.io/os: linux
volumes:
- name: dify-api-storage
persistentVolumeClaim:
claimName: dify-api-storage
containers:
- name: dify-api
image: langgenius/dify-api:0.15.2
env:
- name: MODE
value: api
- name: LOG_LEVEL
value: DEBUG
- name: SECRET_KEY
value: "sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U"
- name: CONSOLE_WEB_URL
value: ""
- name: INIT_PASSWORD
value: password
- name: CONSOLE_API_URL
value: ""
- name: SERVICE_API_URL
value: ""
- name: APP_WEB_URL
value: ""
- name: FILES_URL
value: ""
- name: MIGRATION_ENABLED
value: "true"
- name: DB_USERNAME
value: root
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-username
- name: DB_PASSWORD
value: "you db password"
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-password
- name: DB_HOST
value: f54af10dfc*****.internal.cn-south-1.postgresql.rds.myhuaweicloud.com
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-host
- name: DB_PORT
value: '5432'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-port
- name: DB_DATABASE
value: dify
- name: REDIS_HOST
value: redis-de9e86bc-7822-4651-8f42-2eadab05d868.cn-south-1.dcs.myhuaweicloud.com
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-host
- name: REDIS_PORT
value: '6379'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-port
# default redis username is empty
- name: REDIS_USERNAME
value: ''
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-username
- name: REDIS_PASSWORD
value: iloveredis@2025
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-password
- name: REDIS_USE_SSL
value: "false"
- name: REDIS_DB
value: "0"
- name: CELERY_BROKER_URL
value: >-
redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/1
- name: WEB_API_CORS_ALLOW_ORIGINS
value: "*"
- name: CONSOLE_CORS_ALLOW_ORIGINS
value: "*"
- name: STORAGE_TYPE
value: opendal
- name: OPENDAL_SCHEME
value: fs
- name: OPENDAL_FS_ROOT
value: storage
- name: STORAGE_LOCAL_PATH
value: /app/api/storage
- name: VECTOR_STORE
value: weaviate
- name: WEAVIATE_HOST
value: dify-weaviate
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: weaviate-host
- name: WEAVIATE_PORT
value: '8080'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: weaviate-port
- name: WEAVIATE_ENDPOINT
value: http://$(WEAVIATE_HOST):$(WEAVIATE_PORT)
- name: WEAVIATE_API_KEY
value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
- name: CODE_EXECUTION_ENDPOINT
value: http://dify-sandbox:8194
- name: CODE_EXECUTION_API_KEY
value: dify-sandbox
- name: CODE_MAX_NUMBER
value: "9223372036854775807"
- name: CODE_MIN_NUMBER
value: "-9223372036854775808"
- name: CODE_MAX_STRING_LENGTH
value: "80000"
- name: TEMPLATE_TRANSFORM_MAX_LENGTH
value: "80000"
- name: CODE_MAX_STRING_ARRAY_LENGTH
value: "30"
- name: CODE_MAX_OBJECT_ARRAY_LENGTH
value: "30"
- name: CODE_MAX_NUMBER_ARRAY_LENGTH
value: "1000"
- name: INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH
value: "1000"
# uncommect to enable SSRF
- name: SSRF_PROXY_HTTP_URL
value: 'http://dify-ssrf:3128'
- name: SSRF_PROXY_HTTPS_URL
value: 'http://dify-ssrf:3128'
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 2Gi
ports:
- containerPort: 5001
imagePullPolicy: IfNotPresent
volumeMounts:
- name: dify-api-storage
mountPath: /app/api/storage
---
apiVersion: v1
kind: Service
metadata:
name: dify-api
spec:
ports:
- port: 5001
targetPort: 5001
protocol: TCP
name: dify-api
type: ClusterIP
selector:
app: dify-api
# Dify API Server End
# Dify Worker Server Start
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: dify-worker
labels:
app: dify-worker
app.kubernetes.io/instance: dify-worker
spec:
serviceName: "dify-worker"
replicas: 1
selector:
matchLabels:
app: dify-worker
template:
metadata:
labels:
app: dify-worker
spec:
nodeSelector:
kubernetes.io/os: linux
volumes:
- name: dify-api-storage
persistentVolumeClaim:
claimName: dify-api-storage
containers:
- name: dify-worker
image: langgenius/dify-api:0.15.2
ports:
- containerPort: 5001
protocol: TCP
env:
- name: CONSOLE_WEB_URL
value: ""
- name: MODE
value: worker
- name: LOG_LEVEL
value: INFO
- name: SECRET_KEY
value: "sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U"
- name: DB_USERNAME
value: root
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-username
- name: DB_PASSWORD
value: iloveyou@2025
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-password
- name: DB_HOST
value: f54a*********.internal.cn-south-1.postgresql.rds.myhuaweicloud.com
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-host
- name: DB_PORT
value: '5432'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: pg-port
- name: DB_DATABASE
value: dify
- name: REDIS_HOST
value: redis-de9e*********8.cn-south-1.dcs.myhuaweicloud.com
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-host
- name: REDIS_PORT
value: '6379'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-port
# default redis username is empty
- name: REDIS_USERNAME
value: ''
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-username
- name: REDIS_PASSWORD
value: redis@2025
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: redis-password
- name: REDIS_USE_SSL
value: "false"
- name: REDIS_DB
value: "0"
- name: CELERY_BROKER_URL
value: >-
redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/1
- name: WEB_API_CORS_ALLOW_ORIGINS
value: "*"
- name: CONSOLE_CORS_ALLOW_ORIGINS
value: "*"
- name: STORAGE_TYPE
value: opendal
- name: OPENDAL_SCHEME
value: fs
- name: OPENDAL_FS_ROOT
value: storage
- name: STORAGE_LOCAL_PATH
value: /app/api/storage
- name: VECTOR_STORE
value: weaviate
- name: WEAVIATE_HOST
value: dify-weaviate
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: weaviate-host
- name: WEAVIATE_PORT
value: '8080'
# valueFrom:
# secretKeyRef:
# name: dify-credentials
# key: weaviate-port
- name: WEAVIATE_ENDPOINT
value: http://$(WEAVIATE_HOST):$(WEAVIATE_PORT)
- name: WEAVIATE_API_KEY
value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
- name: SSRF_PROXY_HTTP_URL
value: 'http://dify-ssrf:3128'
- name: SSRF_PROXY_HTTPS_URL
value: 'http://dify-ssrf:3128'
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 2Gi
volumeMounts:
- name: dify-api-storage
mountPath: /app/api/storage
imagePullPolicy: IfNotPresent
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: dify-worker
spec:
ports:
- protocol: TCP
port: 5001
targetPort: 5001
selector:
app: dify-worker
type: ClusterIP
# Dify Worker Server End
# Dify Web Server Start
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify-web
labels:
app: dify-web
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
app: dify-web
template:
metadata:
labels:
app: dify-web
spec:
nodeSelector:
kubernetes.io/os: linux
automountServiceAccountToken: false
containers:
- name: dify-web
image: langgenius/dify-web:0.15.2
env:
- name: EDITION
value: SELF_HOSTED
- name: CONSOLE_API_URL
value: ""
- name: APP_API_URL
value: ""
- name: SENTRY_DSN
value: ""
- name: NEXT_TELEMETRY_DISABLED
value: "0"
- name: TEXT_GENERATION_TIMEOUT_MS
value: "60000"
- name: CSP_WHITELIST
value: ""
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 1Gi
ports:
- containerPort: 3000
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: dify-web
spec:
ports:
- port: 3000
targetPort: 3000
protocol: TCP
name: dify-web
type: ClusterIP
selector:
app: dify-web
# Dify Web Server End
# Dify Nginx Server Start
---
apiVersion: v1
kind: ConfigMap
metadata:
name: dify-nginx
data:
nginx.conf: |-
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
client_max_body_size 15M;
server {
listen 80;
server_name _;
location /console/api {
proxy_pass http://dify-api:5001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /api {
proxy_pass http://dify-api:5001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /v1 {
proxy_pass http://dify-api:5001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /files {
proxy_pass http://dify-api:5001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location / {
proxy_pass http://dify-web:3000;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
# If you want to support HTTPS, please uncomment the code snippet below
#listen 443 ssl;
#ssl_certificate ./../ssl/your_cert_file.cer;
#ssl_certificate_key ./../ssl/your_cert_key.key;
#ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
#ssl_prefer_server_ciphers on;
#ssl_session_cache shared:SSL:10m;
#ssl_session_timeout 10m;
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: dify-nginx
labels:
app: dify-nginx
spec:
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
app: dify-nginx
template:
metadata:
labels:
app: dify-nginx
spec:
nodeSelector:
kubernetes.io/os: linux
automountServiceAccountToken: false
containers:
- name: dify-nginx
image: nginx:stable
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 1Gi
ports:
- containerPort: 80
volumeMounts:
- name: dify-nginx
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
- name: dify-nginx-config
mountPath: /etc/nginx/conf.d
imagePullPolicy: IfNotPresent
volumes:
- name: dify-nginx
configMap:
name: dify-nginx
# Persistent volume could be better
- name: dify-nginx-config
emptyDir: {}
---
kind: Service
apiVersion: v1
metadata:
name: dify-nginx
spec:
selector:
app: dify-nginx
type: ClusterIP
ports:
- name: dify-nginx
port: 80
targetPort: 80
dify-api服务会自动初始化pg数据库,日志如下:
Starting database migration.
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 64b051264f32, init
INFO [alembic.runtime.migration] Running upgrade 64b051264f32 -> 9f4e3427ea84, add created by role
INFO [alembic.runtime.migration] Running upgrade 9f4e3427ea84 -> a45f4dfde53b, add language to recommend apps
INFO [alembic.runtime.migration] Running upgrade a45f4dfde53b -> 614f77cecc48, add last active at
INFO [alembic.runtime.migration] Running upgrade 614f77cecc48 -> e32f6ccb87c6, e08af0a69ccefbb59fa80c778efee300bb780980
INFO [alembic.runtime.migration] Running upgrade e32f6ccb87c6 -> d3d503a3471c, add is_deleted to conversations
INFO [alembic.runtime.migration] Running upgrade d3d503a3471c -> a5b56fb053ef, app config add speech_to_text
INFO [alembic.runtime.migration] Running upgrade a5b56fb053ef -> 2beac44e5f5f, add is_universal in apps
INFO [alembic.runtime.migration] Running upgrade 2beac44e5f5f -> 7ce5a52e4eee, add tool providers
INFO [alembic.runtime.migration] Running upgrade 7ce5a52e4eee -> 8d2d099ceb74, add_qa_model_support
INFO [alembic.runtime.migration] Running upgrade 8d2d099ceb74 -> 16fa53d9faec, add provider model support
INFO [alembic.runtime.migration] Running upgrade 16fa53d9faec -> e35ed59becda, modify quota limit field type
INFO [alembic.runtime.migration] Running upgrade e35ed59becda -> bf0aec5ba2cf, add provider order
INFO [alembic.runtime.migration] Running upgrade bf0aec5ba2cf -> 5022897aaceb, add model name in embedding
INFO [alembic.runtime.migration] Running upgrade 5022897aaceb -> 2c8af9671032, add_qa_document_language
INFO [alembic.runtime.migration] Running upgrade 2c8af9671032 -> e8883b0148c9, add_dataset_model_name
INFO [alembic.runtime.migration] Running upgrade e8883b0148c9 -> 853f9b9cd3b6, add message price unit
INFO [alembic.runtime.migration] Running upgrade 853f9b9cd3b6 -> 4bcffcd64aa4, update_dataset_model_field_null_available
INFO [alembic.runtime.migration] Running upgrade 4bcffcd64aa4 -> 6dcb43972bdc, add_dataset_retriever_resource
INFO [alembic.runtime.migration] Running upgrade 6dcb43972bdc -> 77e83833755c, add_app_config_retriever_resource
INFO [alembic.runtime.migration] Running upgrade 77e83833755c -> 6e2cfb077b04, add_dataset_collection_binding
INFO [alembic.runtime.migration] Running upgrade 6e2cfb077b04 -> ab23c11305d4, add dataset query variable at app model configs.
INFO [alembic.runtime.migration] Running upgrade ab23c11305d4 -> 2e9819ca5b28, add_tenant_id_in_api_token
INFO [alembic.runtime.migration] Running upgrade 2e9819ca5b28 -> b3a09c049e8e, add advanced prompt templates
INFO [alembic.runtime.migration] Running upgrade b3a09c049e8e -> 968fff4c0ab9, add_api_based_extension
INFO [alembic.runtime.migration] Running upgrade 968fff4c0ab9 -> a9836e3baeee, add external_data_tools in app model config
INFO [alembic.runtime.migration] Running upgrade a9836e3baeee -> 8fe468ba0ca5, add gpt4v supports
INFO [alembic.runtime.migration] Running upgrade 8fe468ba0ca5 -> fca025d3b60f, add-dataset-retrieval-model
INFO [alembic.runtime.migration] Running upgrade fca025d3b60f -> e1901f623fd0, add-annotation-reply
INFO [alembic.runtime.migration] Running upgrade e1901f623fd0 -> 46976cc39132, add-annotation-histoiry-score
INFO [alembic.runtime.migration] Running upgrade 46976cc39132 -> f2a6fc85e260, add_anntation_history_message_id
INFO [alembic.runtime.migration] Running upgrade f2a6fc85e260 -> 714aafe25d39, add_anntation_history_match_response
INFO [alembic.runtime.migration] Running upgrade 714aafe25d39 -> 246ba09cbbdb, add_app_anntation_setting
INFO [alembic.runtime.migration] Running upgrade 246ba09cbbdb -> 88072f0caa04, add custom config in tenant
INFO [alembic.runtime.migration] Running upgrade 88072f0caa04 -> 187385f442fc, modify provider model name length
INFO [alembic.runtime.migration] Running upgrade 187385f442fc -> 89c7899ca936, empty message
INFO [alembic.runtime.migration] Running upgrade 89c7899ca936 -> 3ef9b2b6bee6, add_assistant_app
INFO [alembic.runtime.migration] Running upgrade 3ef9b2b6bee6 -> ad472b61a054, add api provider icon
INFO [alembic.runtime.migration] Running upgrade ad472b61a054 -> 8ec536f3c800, rename api provider credentials
INFO [alembic.runtime.migration] Running upgrade 8ec536f3c800 -> 00bacef91f18, rename api provider description
INFO [alembic.runtime.migration] Running upgrade 00bacef91f18 -> f25003750af4, add created/updated at
INFO [alembic.runtime.migration] Running upgrade f25003750af4 -> c71211c8f604, add tool_invoke_model_log
INFO [alembic.runtime.migration] Running upgrade c71211c8f604 -> 114eed84c228, remove tool id from model invoke
INFO [alembic.runtime.migration] Running upgrade 114eed84c228 -> 4829e54d2fee, change message chain id to nullable
INFO [alembic.runtime.migration] Running upgrade 4829e54d2fee -> 053da0c1d756, add api tool privacy
INFO [alembic.runtime.migration] Running upgrade 053da0c1d756 -> 4823da1d26cf, add tool file
INFO [alembic.runtime.migration] Running upgrade 4823da1d26cf -> 9fafbd60eca1, add message file belongs to
INFO [alembic.runtime.migration] Running upgrade 9fafbd60eca1 -> 8ae9bc661daa, add tool conversation variables idx
INFO [alembic.runtime.migration] Running upgrade 8ae9bc661daa -> 23db93619b9d, add message files into agent thought
INFO [alembic.runtime.migration] Running upgrade 23db93619b9d -> de95f5c77138, migration serpapi_api_key
INFO [alembic.runtime.migration] Running upgrade de95f5c77138 -> b24be59fbb04, empty message
INFO [alembic.runtime.migration] Running upgrade b24be59fbb04 -> dfb3b7f477da, add-tool-index
INFO [alembic.runtime.migration] Running upgrade dfb3b7f477da -> 380c6aa5a70d, add tool labels to agent thought
INFO [alembic.runtime.migration] Running upgrade 380c6aa5a70d -> 16830a790f0f, empty message
INFO [alembic.runtime.migration] Running upgrade 16830a790f0f -> a8f9b3c45e4a, add_tenant_id_db_index
INFO [alembic.runtime.migration] Running upgrade a8f9b3c45e4a -> 17b5ab037c40, add-keyworg-table-storage-type
INFO [alembic.runtime.migration] Running upgrade 17b5ab037c40 -> a8d7385a7b66, add-embeddings-provider-name
INFO [alembic.runtime.migration] Running upgrade a8d7385a7b66 -> b289e2408ee2, add workflow
INFO [alembic.runtime.migration] Running upgrade b289e2408ee2 -> cc04d0998d4d, set model config column nullable
INFO [alembic.runtime.migration] Running upgrade cc04d0998d4d -> f9107f83abab, add desc for apps
INFO [alembic.runtime.migration] Running upgrade f9107f83abab -> 42e85ed5564d, conversation columns set nullable
INFO [alembic.runtime.migration] Running upgrade 42e85ed5564d -> b5429b71023c, messages columns set nullable
INFO [alembic.runtime.migration] Running upgrade b5429b71023c -> 563cf8bf777b, enable tool file without conversation id
INFO [alembic.runtime.migration] Running upgrade 563cf8bf777b -> e2eacc9a1b63, add status for message
INFO [alembic.runtime.migration] Running upgrade e2eacc9a1b63 -> c3311b089690, add tool meta
INFO [alembic.runtime.migration] Running upgrade c3311b089690 -> 3c7cac9521c6, add-tags-and-binding-table
INFO [alembic.runtime.migration] Running upgrade 3c7cac9521c6 -> 47cc7df8c4f3, modify default model name length
INFO [alembic.runtime.migration] Running upgrade 47cc7df8c4f3 -> 5fda94355fce, Custom Disclaimer
INFO [alembic.runtime.migration] Running upgrade 5fda94355fce -> 7bdef072e63a, add workflow tool
INFO [alembic.runtime.migration] Running upgrade 7bdef072e63a -> 3b18fea55204, add tool label bings
INFO [alembic.runtime.migration] Running upgrade 3b18fea55204 -> 9e98fbaffb88, add workflow tool version
INFO [alembic.runtime.migration] Running upgrade 9e98fbaffb88 -> 03f98355ba0e, add workflow tool label and tool bindings idx
INFO [alembic.runtime.migration] Running upgrade 03f98355ba0e -> 64a70a7aab8b, add workflow run index
INFO [alembic.runtime.migration] Running upgrade 64a70a7aab8b -> 4e99a8df00ff, add load balancing
INFO [alembic.runtime.migration] Running upgrade 4e99a8df00ff -> 7b45942e39bb, add-api-key-auth-binding
INFO [alembic.runtime.migration] Running upgrade 7b45942e39bb -> 4ff534e1eb11, add workflow to site
INFO [alembic.runtime.migration] Running upgrade 4ff534e1eb11 -> b69ca54b9208, add chatbot color theme
INFO [alembic.runtime.migration] Running upgrade 4ff534e1eb11 -> 04c602f5dc9b, update AppModelConfig and add table TracingAppConfig
INFO [alembic.runtime.migration] Running upgrade 04c602f5dc9b -> c031d46af369, remove app model config trace config and rename trace app config
INFO [alembic.runtime.migration] Running upgrade c031d46af369 -> 2a3aebbbf4bb, add app tracing
INFO [alembic.runtime.migration] Running upgrade 2a3aebbbf4bb, b69ca54b9208 -> 63f9175e515b, merge branches
INFO [alembic.runtime.migration] Running upgrade 63f9175e515b -> b2602e131636, add workflow_run_id index for message
INFO [alembic.runtime.migration] Running upgrade b2602e131636 -> 7e6a8693e07a, add table dataset_permissions
INFO [alembic.runtime.migration] Running upgrade 7e6a8693e07a -> 161cadc1af8d, add dataset permission tenant id
INFO [alembic.runtime.migration] Running upgrade 161cadc1af8d -> 408176b91ad3, 'add_max_active_requests'
INFO [alembic.runtime.migration] Running upgrade 408176b91ad3 -> fecff1c3da27, remove extra tracing app config table and add idx_dataset_permissions_tenant_id
INFO [alembic.runtime.migration] Running upgrade fecff1c3da27 -> 6e957a32015b, add-embedding-cache-created_at_index
INFO [alembic.runtime.migration] Running upgrade 6e957a32015b -> 8e5588e6412e, add environment variable to workflow model
INFO [alembic.runtime.migration] Running upgrade 8e5588e6412e -> 53bf8af60645, update model
INFO [alembic.runtime.migration] Running upgrade 53bf8af60645 -> eeb2e349e6ac, increase max model_name length
INFO [alembic.runtime.migration] Running upgrade eeb2e349e6ac -> 1787fbae959a, update tools original_url length
INFO [alembic.runtime.migration] Running upgrade 1787fbae959a -> 63a83fcf12ba, support conversation variables
INFO [alembic.runtime.migration] Running upgrade 63a83fcf12ba -> 8782057ff0dc, add conversations.dialogue_count
INFO [alembic.runtime.migration] Running upgrade 8782057ff0dc -> a6be81136580, app and site icon type
INFO [alembic.runtime.migration] Running upgrade a6be81136580 -> 2dbe42621d96, rename workflow__conversation_variables to workflow_conversation_variables
INFO [alembic.runtime.migration] Running upgrade 2dbe42621d96 -> d0187d6a88dd, add created_by and updated_by to app, modelconfig, and site
INFO [alembic.runtime.migration] Running upgrade d0187d6a88dd -> 030f4915f36a, add use_icon_as_answer_icon fields for app and site
INFO [alembic.runtime.migration] Running upgrade 030f4915f36a -> 675b5321501b, add node_execution_id into node_executions
INFO [alembic.runtime.migration] Running upgrade 675b5321501b -> d57ba9ebb251, add parent_message_id to messages
INFO [alembic.runtime.migration] Running upgrade d57ba9ebb251 -> 6af6a521a53e, update-retrieval-resource
INFO [alembic.runtime.migration] Running upgrade 6af6a521a53e -> 33f5fac87f29, external_knowledge_api
INFO [alembic.runtime.migration] Running upgrade 33f5fac87f29 -> d8e744d88ed6, fix wrong service-api history
INFO [alembic.runtime.migration] Running upgrade d8e744d88ed6 -> bbadea11becb, add name and size to tool_files
INFO [alembic.runtime.migration] Running upgrade bbadea11becb -> 0251a1c768cc, add-tidb-auth-binding
INFO [alembic.runtime.migration] Running upgrade 0251a1c768cc -> 43fa78bc3b7d, add_white_list
INFO [alembic.runtime.migration] Running upgrade 43fa78bc3b7d -> d3f6769a94a3, Add upload_files.source_url
INFO [alembic.runtime.migration] Running upgrade d3f6769a94a3 -> 93ad8c19c40b, rename conversation variables index name
INFO [alembic.runtime.migration] Running upgrade 93ad8c19c40b -> f4d7ce70a7ca, update upload_files.source_url
INFO [alembic.runtime.migration] Running upgrade f4d7ce70a7ca -> d07474999927, update type of custom_disclaimer to TEXT
INFO [alembic.runtime.migration] Running upgrade d07474999927 -> 09a8d1878d9b, update workflows graph, features and updated_at
INFO [alembic.runtime.migration] Running upgrade 09a8d1878d9b -> 01d6889832f7, add_created_at_index_for_messages
INFO [alembic.runtime.migration] Running upgrade 01d6889832f7 -> cf8f4fc45278, add exceptions_count field to WorkflowRun model
INFO [alembic.runtime.migration] Running upgrade cf8f4fc45278 -> 11b07f66c737, remove unused tool_providers
INFO [alembic.runtime.migration] Running upgrade 11b07f66c737 -> e1944c35e15e, add retry_index field to node-execution model
Revision ID: e1944c35e15e
Revises: 11b07f66c737
Create Date: 2024-12-20 06:28:30.287197
INFO [alembic.runtime.migration] Running upgrade e1944c35e15e -> d7999dfa4aae, remove workflow_node_executions.retry_index if exists
INFO [alembic.runtime.migration] Running upgrade d7999dfa4aae -> e19037032219, parent-child-index
INFO [alembic.runtime.migration] Running upgrade e19037032219 -> 923752d42eb6, add_auto_disabled_dataset_logs
INFO [alembic.runtime.migration] Running upgrade 923752d42eb6 -> a91b476a53de, change workflow_runs.total_tokens to bigint
Database migration successful!
另外,dify-api服务的环境变量SERVICE_API_URL和APP_WEB_URL,应该指向ELB的地址和端口,这样在dify控制台点击[ Run App ]按钮才能跳转到正确的地址。