feat: add opensandbox-server and volume-manager to docker-compose, migrate to named volumes

- Add opensandbox-server service with TOML config (runtime, egress, docker security settings)
- Add volume-manager service for PVC/volume lifecycle management
- Rename sandbox container to fastgpt-code-sandbox for consistency
- Migrate all bind mounts (pg, mongo, redis, minio, aiproxy_pg) to Docker named volumes
- Add healthcheck for fastgpt-code-sandbox service
- Bump opensandbox-egress version from v1.0.1 to v1.0.3
- Update port comments to include opensandbox-server:8090 and volume-manager:3004
This commit is contained in:
Jon
2026-03-19 17:02:18 +08:00
committed by archer
parent 09a93715f5
commit ed6bed5e14
7 changed files with 451 additions and 30 deletions

View File

@@ -17,7 +17,7 @@
"seekdb": "1.0.1.0-100000392025122619",
"opensandbox-server": "v0.1.7",
"opensandbox-execd": "v1.0.7",
"opensandbox-egress": "v1.0.1"
"opensandbox-egress": "v1.0.3"
},
"images": {
"cn": {

View File

@@ -5,10 +5,41 @@
# - pg: 5432
# - mongo: 27017
# - redis: 6379
# - fastgpt-sandbox: 3002
# - fastgpt-code-sandbox: 3002
# - fastgpt-plugin: 3003
# - opensandbox-server: 8090
# - volume-manager: 3004
# - aiproxy: 3010
# - 使用 pgvector 作为默认的向量库
# - 配置 opensandbox-config 的 network_mode 为 docker 网络,如 dev_fastgpt
# - 配置 opensandbox-config 的 host_ip 为宿主机 LAN IP如 192.168.1.100
configs:
opensandbox-config:
content: |
[server]
host = "0.0.0.0"
port = 8090
log_level = "INFO"
[runtime]
type = "docker"
execd_image = "sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/execd:v1.0.7"
[egress]
image = "sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/egress:v1.0.3"
[docker]
network_mode = "bridge"
# When server runs in a container, set host_ip to the host's IP or hostname so bridge-mode endpoints are reachable (e.g. host.docker.internal or the host LAN IP).
# It's required when server deployed with docker container under host.
host_ip = "host.docker.internal"
drop_capabilities = ["AUDIT_WRITE", "MKNOD", "NET_ADMIN", "NET_RAW", "SYS_ADMIN", "SYS_MODULE", "SYS_PTRACE", "SYS_TIME", "SYS_TTY_CONFIG"]
no_new_privileges = true
pids_limit = 512
[ingress]
mode = "direct"
services:
# Vector DB
@@ -26,7 +57,7 @@ services:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=postgres
volumes:
- ./pg/data:/var/lib/postgresql/data
- fastgpt-pg_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'username', '-d', 'postgres']
interval: 5s
@@ -47,7 +78,7 @@ services:
- MONGO_INITDB_ROOT_USERNAME=myusername
- MONGO_INITDB_ROOT_PASSWORD=mypassword
volumes:
- ./mongo/data:/data/db
- fastgpt-mongo_data:/data/db
healthcheck:
test:
[
@@ -113,9 +144,9 @@ services:
retries: 3
start_period: 30s
volumes:
- ./redis/data:/data
- fastgpt-redis_data:/data
fastgpt-minio:
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/minio:RELEASE.2025-09-07T16-13-09Z
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/minio:RELEASE.2025-09-07T16-13-09Z # cpu 不支持 AVX 时候使用 -cpuv1
container_name: fastgpt-minio
restart: always
networks:
@@ -127,15 +158,15 @@ services:
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=minioadmin
volumes:
- ./fastgpt-minio:/data
- fastgpt-minio_data:/data
command: server /data --console-address ":9001"
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
interval: 30s
timeout: 20s
retries: 3
sandbox:
container_name: sandbox
fastgpt-code-sandbox:
container_name: fastgpt-code-sandbox
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.14.8
ports:
- 3002:3000
@@ -178,6 +209,11 @@ services:
depends_on:
fastgpt-minio:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
interval: 30s
timeout: 20s
retries: 3
# AI Proxy
aiproxy:
image: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.3.5
@@ -214,7 +250,7 @@ services:
restart: unless-stopped
container_name: aiproxy_pg
volumes:
- ./aiproxy_pg:/var/lib/postgresql/data
- fastgpt-aiproxy_pg_data:/var/lib/postgresql/data
networks:
- aiproxy
environment:
@@ -227,6 +263,54 @@ services:
interval: 5s
timeout: 5s
retries: 10
opensandbox-server:
image: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/server:v0.1.7
container_name: opensandbox-server
restart: always
networks:
- fastgpt
ports:
- '8090:8090'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
configs:
- source: opensandbox-config
target: /etc/opensandbox/config.toml
environment:
- SANDBOX_CONFIG_PATH=/etc/opensandbox/config.toml
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8090/health']
interval: 10s
timeout: 5s
retries: 5
volume-manager:
image: fastgpt-volume-manager:latest
container_name: volume-manager
restart: always
networks:
- fastgpt
ports:
- 3004:3001
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- VM_RUNTIME=docker
- VM_AUTH_TOKEN=changeme
- VM_VOLUME_NAME_PREFIX=fastgpt-session
- VM_LOG_LEVEL=info
healthcheck:
test:
['CMD', 'bun', '-e', "fetch('http://localhost:3001/health').then((res) => { if (!res.ok) throw new Error(String(res.status)); })"]
interval: 10s
timeout: 5s
retries: 5
networks:
fastgpt:
aiproxy:
volumes:
fastgpt-pg_data:
fastgpt-mongo_data:
fastgpt-redis_data:
fastgpt-minio_data:
fastgpt-aiproxy_pg_data:

View File

@@ -5,10 +5,41 @@
# - pg: 5432
# - mongo: 27017
# - redis: 6379
# - fastgpt-sandbox: 3002
# - fastgpt-code-sandbox: 3002
# - fastgpt-plugin: 3003
# - opensandbox-server: 8090
# - volume-manager: 3004
# - aiproxy: 3010
# - 使用 pgvector 作为默认的向量库
# - 配置 opensandbox-config 的 network_mode 为 docker 网络,如 dev_fastgpt
# - 配置 opensandbox-config 的 host_ip 为宿主机 LAN IP如 192.168.1.100
configs:
opensandbox-config:
content: |
[server]
host = "0.0.0.0"
port = 8090
log_level = "INFO"
[runtime]
type = "docker"
execd_image = "opensandbox/execd:v1.0.7"
[egress]
image = "opensandbox/egress:v1.0.3"
[docker]
network_mode = "bridge"
# When server runs in a container, set host_ip to the host's IP or hostname so bridge-mode endpoints are reachable (e.g. host.docker.internal or the host LAN IP).
# It's required when server deployed with docker container under host.
host_ip = "host.docker.internal"
drop_capabilities = ["AUDIT_WRITE", "MKNOD", "NET_ADMIN", "NET_RAW", "SYS_ADMIN", "SYS_MODULE", "SYS_PTRACE", "SYS_TIME", "SYS_TTY_CONFIG"]
no_new_privileges = true
pids_limit = 512
[ingress]
mode = "direct"
services:
# Vector DB
@@ -26,7 +57,7 @@ services:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=postgres
volumes:
- ./pg/data:/var/lib/postgresql/data
- fastgpt-pg_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'username', '-d', 'postgres']
interval: 5s
@@ -47,7 +78,7 @@ services:
- MONGO_INITDB_ROOT_USERNAME=myusername
- MONGO_INITDB_ROOT_PASSWORD=mypassword
volumes:
- ./mongo/data:/data/db
- fastgpt-mongo_data:/data/db
healthcheck:
test:
[
@@ -113,9 +144,9 @@ services:
retries: 3
start_period: 30s
volumes:
- ./redis/data:/data
- fastgpt-redis_data:/data
fastgpt-minio:
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
image: minio/minio:RELEASE.2025-09-07T16-13-09Z # cpu 不支持 AVX 时候使用 -cpuv1
container_name: fastgpt-minio
restart: always
networks:
@@ -127,15 +158,15 @@ services:
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=minioadmin
volumes:
- ./fastgpt-minio:/data
- fastgpt-minio_data:/data
command: server /data --console-address ":9001"
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
interval: 30s
timeout: 20s
retries: 3
sandbox:
container_name: sandbox
fastgpt-code-sandbox:
container_name: fastgpt-code-sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.14.8
ports:
- 3002:3000
@@ -178,6 +209,11 @@ services:
depends_on:
fastgpt-minio:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
interval: 30s
timeout: 20s
retries: 3
# AI Proxy
aiproxy:
image: ghcr.io/labring/aiproxy:v0.3.5
@@ -214,7 +250,7 @@ services:
restart: unless-stopped
container_name: aiproxy_pg
volumes:
- ./aiproxy_pg:/var/lib/postgresql/data
- fastgpt-aiproxy_pg_data:/var/lib/postgresql/data
networks:
- aiproxy
environment:
@@ -227,6 +263,54 @@ services:
interval: 5s
timeout: 5s
retries: 10
opensandbox-server:
image: opensandbox/server:v0.1.7
container_name: opensandbox-server
restart: always
networks:
- fastgpt
ports:
- '8090:8090'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
configs:
- source: opensandbox-config
target: /etc/opensandbox/config.toml
environment:
- SANDBOX_CONFIG_PATH=/etc/opensandbox/config.toml
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8090/health']
interval: 10s
timeout: 5s
retries: 5
volume-manager:
image: fastgpt-volume-manager:latest
container_name: volume-manager
restart: always
networks:
- fastgpt
ports:
- 3004:3001
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- VM_RUNTIME=docker
- VM_AUTH_TOKEN=changeme
- VM_VOLUME_NAME_PREFIX=fastgpt-session
- VM_LOG_LEVEL=info
healthcheck:
test:
['CMD', 'bun', '-e', "fetch('http://localhost:3001/health').then((res) => { if (!res.ok) throw new Error(String(res.status)); })"]
interval: 10s
timeout: 5s
retries: 5
networks:
fastgpt:
aiproxy:
volumes:
fastgpt-pg_data:
fastgpt-mongo_data:
fastgpt-redis_data:
fastgpt-minio_data:
fastgpt-aiproxy_pg_data:

View File

@@ -0,0 +1,111 @@
apiVersion: v1
kind: Secret
metadata:
name: volume-manager-secret
namespace: opensandbox
type: Opaque
stringData:
auth-token: changeme
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fastgpt-local
provisioner: rancher.io/local-path
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: volume-manager
namespace: opensandbox
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: volume-manager
namespace: opensandbox
rules:
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "create", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: volume-manager
namespace: opensandbox
subjects:
- kind: ServiceAccount
name: volume-manager
namespace: opensandbox
roleRef:
kind: Role
name: volume-manager
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: volume-manager
namespace: opensandbox
labels:
app: volume-manager
spec:
replicas: 1
selector:
matchLabels:
app: volume-manager
template:
metadata:
labels:
app: volume-manager
spec:
serviceAccountName: volume-manager
containers:
- name: volume-manager
image: fastgpt-volume-manager:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3001
env:
- name: VM_RUNTIME
value: kubernetes
- name: VM_K8S_NAMESPACE
value: opensandbox
- name: VM_K8S_PVC_STORAGE_CLASS
value: fastgpt-local
- name: VM_LOG_LEVEL
value: info
- name: VM_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: volume-manager-secret
key: auth-token
readinessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 3
periodSeconds: 10
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: volume-manager
namespace: opensandbox
spec:
selector:
app: volume-manager
ports:
- port: 3001
targetPort: 3001
type: ClusterIP

View File

@@ -5,10 +5,41 @@
# - pg: 5432
# - mongo: 27017
# - redis: 6379
# - fastgpt-sandbox: 3002
# - fastgpt-code-sandbox: 3002
# - fastgpt-plugin: 3003
# - opensandbox-server: 8090
# - volume-manager: 3004
# - aiproxy: 3010
# - 使用 pgvector 作为默认的向量库
# - 配置 opensandbox-config 的 network_mode 为 docker 网络,如 dev_fastgpt
# - 配置 opensandbox-config 的 host_ip 为宿主机 LAN IP如 192.168.1.100
configs:
opensandbox-config:
content: |
[server]
host = "0.0.0.0"
port = 8090
log_level = "INFO"
[runtime]
type = "docker"
execd_image = "${{opensandbox-execd.image}}:${{opensandbox-execd.tag}}"
[egress]
image = "${{opensandbox-egress.image}}:${{opensandbox-egress.tag}}"
[docker]
network_mode = "bridge"
# When server runs in a container, set host_ip to the host's IP or hostname so bridge-mode endpoints are reachable (e.g. host.docker.internal or the host LAN IP).
# It's required when server deployed with docker container under host.
host_ip = "host.docker.internal"
drop_capabilities = ["AUDIT_WRITE", "MKNOD", "NET_ADMIN", "NET_RAW", "SYS_ADMIN", "SYS_MODULE", "SYS_PTRACE", "SYS_TIME", "SYS_TTY_CONFIG"]
no_new_privileges = true
pids_limit = 512
[ingress]
mode = "direct"
services:
# Vector DB
@@ -26,7 +57,7 @@ services:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=postgres
volumes:
- ./pg/data:/var/lib/postgresql/data
- fastgpt-pg_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'username', '-d', 'postgres']
interval: 5s
@@ -47,7 +78,7 @@ services:
- MONGO_INITDB_ROOT_USERNAME=myusername
- MONGO_INITDB_ROOT_PASSWORD=mypassword
volumes:
- ./mongo/data:/data/db
- fastgpt-mongo_data:/data/db
healthcheck:
test:
[
@@ -113,9 +144,9 @@ services:
retries: 3
start_period: 30s
volumes:
- ./redis/data:/data
- fastgpt-redis_data:/data
fastgpt-minio:
image: ${{minio.image}}:${{minio.tag}}
image: ${{minio.image}}:${{minio.tag}} # cpu 不支持 AVX 时候使用 -cpuv1
container_name: fastgpt-minio
restart: always
networks:
@@ -127,15 +158,15 @@ services:
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=minioadmin
volumes:
- ./fastgpt-minio:/data
- fastgpt-minio_data:/data
command: server /data --console-address ":9001"
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
interval: 30s
timeout: 20s
retries: 3
sandbox:
container_name: sandbox
fastgpt-code-sandbox:
container_name: fastgpt-code-sandbox
image: ${{fastgpt-sandbox.image}}:${{fastgpt-sandbox.tag}}
ports:
- 3002:3000
@@ -178,6 +209,11 @@ services:
depends_on:
fastgpt-minio:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
interval: 30s
timeout: 20s
retries: 3
# AI Proxy
aiproxy:
image: ${{aiproxy.image}}:${{aiproxy.tag}}
@@ -214,7 +250,7 @@ services:
restart: unless-stopped
container_name: aiproxy_pg
volumes:
- ./aiproxy_pg:/var/lib/postgresql/data
- fastgpt-aiproxy_pg_data:/var/lib/postgresql/data
networks:
- aiproxy
environment:
@@ -227,6 +263,54 @@ services:
interval: 5s
timeout: 5s
retries: 10
opensandbox-server:
image: ${{opensandbox-server.image}}:${{opensandbox-server.tag}}
container_name: opensandbox-server
restart: always
networks:
- fastgpt
ports:
- '8090:8090'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
configs:
- source: opensandbox-config
target: /etc/opensandbox/config.toml
environment:
- SANDBOX_CONFIG_PATH=/etc/opensandbox/config.toml
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:8090/health']
interval: 10s
timeout: 5s
retries: 5
volume-manager:
image: fastgpt-volume-manager:latest
container_name: volume-manager
restart: always
networks:
- fastgpt
ports:
- 3004:3001
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- VM_RUNTIME=docker
- VM_AUTH_TOKEN=changeme
- VM_VOLUME_NAME_PREFIX=fastgpt-session
- VM_LOG_LEVEL=info
healthcheck:
test:
['CMD', 'bun', '-e', "fetch('http://localhost:3001/health').then((res) => { if (!res.ok) throw new Error(String(res.status)); })"]
interval: 10s
timeout: 5s
retries: 5
networks:
fastgpt:
aiproxy:
volumes:
fastgpt-pg_data:
fastgpt-mongo_data:
fastgpt-redis_data:
fastgpt-minio_data:
fastgpt-aiproxy_pg_data:

View File

@@ -35,11 +35,25 @@ CODE_SANDBOX_TOKEN=
AIPROXY_API_ENDPOINT=https://localhost:3010
AIPROXY_API_TOKEN=aiproxy
# Agent sandbox
# Agent sandboxopensandbox | sealos
AGENT_SANDBOX_PROVIDER=
# OpenSandbox 配置
AGENT_SANDBOX_BASE_URL=
AGENT_SANDBOX_RUNTIME=docker
AGENT_SANDBOX_DEFAULT_IMAGE=
AGENT_SANDBOX_DEFAULT_IMAGE_TAG=latest
AGENT_SANDBOX_WORK_DIRECTORY=/home/sandbox/workspace
AGENT_SANDBOX_ENTRYPOINT=/home/sandbox/entrypoint.sh
AGENT_SANDBOX_USE_SERVER_PROXY=false
# Sealos 配置
AGENT_SANDBOX_SEALOS_BASEURL=
AGENT_SANDBOX_SEALOS_TOKEN=
# Volume manager
VOLUME_MANAGER_URL=
VOLUME_MANAGER_TOKEN=
VOLUME_MANAGER_MOUNT_PATH=/home/sandbox/workspace
# 辅助生成模型(暂时只能指定一个,需保证系统中已激活该模型)
HELPER_BOT_MODEL=qwen-max

View File

@@ -68,10 +68,54 @@ DELETE /v1/volumes/:sessionId
| `VM_VOLUME_NAME_PREFIX` | | `fastgpt-session` | 卷名前缀 |
| `VM_DOCKER_SOCKET` | | `/var/run/docker.sock` | Docker socket 路径docker 模式) |
| `VM_K8S_NAMESPACE` | | `opensandbox` | PVC 所在命名空间k8s 模式) |
| `VM_K8S_KUBECONFIG` | | - | kubeconfig 路径,集群内运行时留空 |
| `VM_K8S_PVC_STORAGE_CLASS` | | `standard` | PVC StorageClassk8s 模式) |
| `VM_K8S_PVC_STORAGE_SIZE` | | `1Gi` | PVC 容量k8s 模式) |
## Kubernetes 部署要求
### StorageClass
volume-manager 默认使用 StorageClass `fastgpt-local`(可通过 `VM_K8S_PVC_STORAGE_CLASS` 覆盖)。参考配置:
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fastgpt-local
provisioner: rancher.io/local-path
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
```
关键特性说明:
- `reclaimPolicy: Delete`PVC 删除时自动清理底层数据
- `volumeBindingMode: WaitForFirstConsumer`:延迟绑定,等待 Pod 调度后再绑定节点
也可使用集群现有的其他 StorageClass需支持 `ReadWriteOnce` accessMode。
### RBAC 权限
volume-manager 需要在 `VM_K8S_NAMESPACE` 命名空间内操作 PVC最小权限如下
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
rules:
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "create", "delete"]
```
volume-manager 使用集群内 ServiceAccount 认证,无需挂载外部 kubeconfig。
### 部署检查清单
- [ ] 命名空间 `opensandbox`(或自定义值)已存在
- [ ] StorageClass `fastgpt-local`(或自定义值)已创建并可用
- [ ] ServiceAccount + Role + RoleBinding 已创建
- [ ] Secret 中包含有效的 `VM_AUTH_TOKEN`
## 项目结构
```