Skip to content

Commit 7f8bd2e

Browse files
feat: Runtime environment supports running without port configuration
1 parent 9035445 commit 7f8bd2e

File tree

26 files changed

+179
-146
lines changed

26 files changed

+179
-146
lines changed

agent/app/dto/request/runtime.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ type Volume struct {
4242
}
4343

4444
type ExposedPort struct {
45-
HostPort int `json:"hostPort"`
46-
ContainerPort int `json:"containerPort"`
45+
HostPort int `json:"hostPort"`
46+
ContainerPort int `json:"containerPort"`
47+
HostIP string `json:"hostIP"`
4748
}
4849

4950
type RuntimeDelete struct {

agent/app/dto/response/runtime.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type RuntimeDTO struct {
2323
CreatedAt time.Time `json:"createdAt"`
2424
CodeDir string `json:"codeDir"`
2525
AppParams []AppParam `json:"appParams"`
26-
Port int `json:"port"`
26+
Port string `json:"port"`
2727
Path string `json:"path"`
2828
ExposedPorts []request.ExposedPort `json:"exposedPorts"`
2929
Environments []request.Environment `json:"environments"`

agent/app/model/runtime.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type Runtime struct {
1919
Type string `gorm:"not null" json:"type"`
2020
Status string `gorm:"not null" json:"status"`
2121
Resource string `gorm:"not null" json:"resource"`
22-
Port int `json:"port"`
22+
Port string `json:"port"`
2323
Message string `json:"message"`
2424
CodeDir string `json:"codeDir"`
2525
ContainerName string `json:"containerName"`

agent/app/repo/common.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ func WithByID(id uint) DBOption {
1818
}
1919
}
2020

21+
func WithByNOTID(id uint) DBOption {
22+
return func(g *gorm.DB) *gorm.DB {
23+
return g.Where("id != ?", id)
24+
}
25+
}
26+
2127
func WithByIDs(ids []uint) DBOption {
2228
return func(g *gorm.DB) *gorm.DB {
2329
return g.Where("id in (?)", ids)

agent/app/repo/runtime.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package repo
22

33
import (
44
"context"
5+
"fmt"
56

67
"github.com/1Panel-dev/1Panel/agent/app/model"
78
"github.com/1Panel-dev/1Panel/agent/global"
@@ -53,9 +54,19 @@ func (r *RuntimeRepo) WithNotId(id uint) DBOption {
5354
}
5455
}
5556

57+
//func (r *RuntimeRepo) WithPort(port int) DBOption {
58+
// return func(g *gorm.DB) *gorm.DB {
59+
// return g.Where("port = ?", port)
60+
// }
61+
//}
62+
5663
func (r *RuntimeRepo) WithPort(port int) DBOption {
5764
return func(g *gorm.DB) *gorm.DB {
58-
return g.Where("port = ?", port)
65+
// 将端口号转换为字符串,并构造正则表达式
66+
portStr := fmt.Sprintf("%d", port)
67+
// 构造正则表达式:匹配以逗号分隔的完整端口号
68+
regexPattern := fmt.Sprintf("(^|,)%s(,|$)", portStr)
69+
return g.Where("port REGEXP ?", regexPattern)
5970
}
6071
}
6172

agent/app/service/runtime.go

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
9393
return nil, err
9494
}
9595
}
96-
96+
var hostPorts []string
9797
switch create.Type {
9898
case constant.RuntimePHP:
9999
if create.Resource == constant.ResourceLocal {
@@ -116,17 +116,12 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
116116
}
117117
create.Install = true
118118
for _, export := range create.ExposedPorts {
119+
hostPorts = append(hostPorts, strconv.Itoa(export.HostPort))
119120
if err := checkPortExist(export.HostPort); err != nil {
120121
return nil, err
121122
}
122123
}
123124
}
124-
portValue, _ := create.Params["PANEL_APP_PORT_HTTP"]
125-
if portValue != nil {
126-
if err := checkPortExist(int(portValue.(float64))); err != nil {
127-
return nil, err
128-
}
129-
}
130125
containerName, ok := create.Params["CONTAINER_NAME"]
131126
if !ok {
132127
return nil, buserr.New("ErrContainerNameIsNull")
@@ -159,7 +154,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (*model.Runtime, e
159154
Resource: create.Resource,
160155
Version: create.Version,
161156
ContainerName: containerName.(string),
162-
Port: int(portValue.(float64)),
157+
Port: strings.Join(hostPorts, ","),
163158
}
164159

165160
switch create.Type {
@@ -352,34 +347,30 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeDTO, error) {
352347
return nil, err
353348
}
354349
for k, v := range envs {
355-
switch k {
356-
case "APP_PORT", "PANEL_APP_PORT_HTTP":
357-
port, err := strconv.Atoi(v)
358-
if err != nil {
359-
return nil, err
360-
}
361-
res.Params[k] = port
362-
default:
363-
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
364-
if strings.Contains(k, "CONTAINER_PORT") {
365-
r := regexp.MustCompile(`_(\d+)$`)
366-
matches := r.FindStringSubmatch(k)
367-
containerPort, err := strconv.Atoi(v)
368-
if err != nil {
369-
return nil, err
370-
}
371-
hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])])
372-
if err != nil {
373-
return nil, err
374-
}
375-
res.ExposedPorts = append(res.ExposedPorts, request.ExposedPort{
376-
ContainerPort: containerPort,
377-
HostPort: hostPort,
378-
})
350+
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
351+
if strings.Contains(k, "CONTAINER_PORT") {
352+
r := regexp.MustCompile(`_(\d+)$`)
353+
matches := r.FindStringSubmatch(k)
354+
containerPort, err := strconv.Atoi(v)
355+
if err != nil {
356+
return nil, err
379357
}
380-
} else {
381-
res.Params[k] = v
358+
hostPort, err := strconv.Atoi(envs[fmt.Sprintf("HOST_PORT_%s", matches[1])])
359+
if err != nil {
360+
return nil, err
361+
}
362+
hostIP := envs[fmt.Sprintf("HOST_IP_%s", matches[1])]
363+
if hostIP == "" {
364+
hostIP = "0.0.0.0"
365+
}
366+
res.ExposedPorts = append(res.ExposedPorts, request.ExposedPort{
367+
ContainerPort: containerPort,
368+
HostPort: hostPort,
369+
HostIP: hostIP,
370+
})
382371
}
372+
} else {
373+
res.Params[k] = v
383374
}
384375
}
385376
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
@@ -437,22 +428,17 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
437428
}
438429
oldImage := runtime.Image
439430
oldEnv := runtime.Env
440-
port := int(req.Params["PANEL_APP_PORT_HTTP"].(float64))
431+
var hostPorts []string
441432
switch runtime.Type {
442433
case constant.RuntimePHP:
443434
exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithImage(req.Name), runtimeRepo.WithNotId(req.ID))
444435
if exist != nil {
445436
return buserr.New("ErrImageExist")
446437
}
447438
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
448-
if runtime.Port != port {
449-
if err = checkPortExist(port); err != nil {
450-
return err
451-
}
452-
runtime.Port = port
453-
}
454439
for _, export := range req.ExposedPorts {
455-
if err = checkPortExist(export.HostPort); err != nil {
440+
hostPorts = append(hostPorts, strconv.Itoa(export.HostPort))
441+
if err = checkRuntimePortExist(export.HostPort, false, runtime.ID); err != nil {
456442
return err
457443
}
458444
}
@@ -522,7 +508,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
522508
case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo, constant.RuntimePython, constant.RuntimeDotNet:
523509
runtime.Version = req.Version
524510
runtime.CodeDir = req.CodeDir
525-
runtime.Port = port
511+
runtime.Port = strings.Join(hostPorts, ",")
526512
runtime.Status = constant.RuntimeReCreating
527513
_ = runtimeRepo.Save(runtime)
528514
go reCreateRuntime(runtime)

agent/app/service/runtime_utils.go

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"context"
77
"encoding/json"
88
"fmt"
9+
"github.com/1Panel-dev/1Panel/agent/i18n"
10+
"github.com/1Panel-dev/1Panel/agent/utils/common"
911
"io"
1012
"os"
1113
"os/exec"
@@ -319,7 +321,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte
319321
return
320322
}
321323
for k := range env {
322-
if strings.HasPrefix(k, "CONTAINER_PORT_") || strings.HasPrefix(k, "HOST_PORT_") {
324+
if strings.HasPrefix(k, "CONTAINER_PORT_") || strings.HasPrefix(k, "HOST_PORT_") || strings.HasPrefix(k, "HOST_IP_") || strings.Contains(k, "APP_PORT") {
323325
delete(env, k)
324326
}
325327
}
@@ -431,18 +433,19 @@ func handleCompose(env gotenv.Env, composeContent []byte, create request.Runtime
431433
for name, service := range services {
432434
serviceName = name
433435
serviceValue = service.(map[string]interface{})
434-
_, ok := serviceValue["ports"].([]interface{})
435-
if ok {
436+
delete(serviceValue, "ports")
437+
if create.ExposedPorts != nil && len(create.ExposedPorts) > 0 {
436438
var ports []interface{}
437-
ports = append(ports, "${HOST_IP}:${PANEL_APP_PORT_HTTP}:${APP_PORT}")
438439
for i, port := range create.ExposedPorts {
439440
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
440441
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
441442
existMap[containerPortStr] = struct{}{}
442443
existMap[hostPortStr] = struct{}{}
443-
ports = append(ports, fmt.Sprintf("${HOST_IP}:${%s}:${%s}", hostPortStr, containerPortStr))
444+
hostIPStr := fmt.Sprintf("HOST_IP_%d", i)
445+
ports = append(ports, fmt.Sprintf("${%s}:${%s}:${%s}", hostIPStr, hostPortStr, containerPortStr))
444446
create.Params[containerPortStr] = port.ContainerPort
445447
create.Params[hostPortStr] = port.HostPort
448+
create.Params[hostIPStr] = port.HostIP
446449
}
447450
serviceValue["ports"] = ports
448451
}
@@ -667,3 +670,34 @@ func getDockerComposeVolumes(yml []byte) ([]request.Volume, error) {
667670
}
668671
return res, nil
669672
}
673+
674+
func checkRuntimePortExist(port int, scanPort bool, runtimeID uint) error {
675+
errMap := make(map[string]interface{})
676+
errMap["port"] = port
677+
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port))
678+
if appInstall.ID > 0 {
679+
errMap["type"] = i18n.GetMsgByKey("TYPE_APP")
680+
errMap["name"] = appInstall.Name
681+
return buserr.WithMap("ErrPortExist", errMap, nil)
682+
}
683+
opts := []repo.DBOption{runtimeRepo.WithPort(port)}
684+
if runtimeID > 0 {
685+
opts = append(opts, repo.WithByNOTID(runtimeID))
686+
}
687+
runtime, _ := runtimeRepo.GetFirst(opts...)
688+
if runtime != nil {
689+
errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME")
690+
errMap["name"] = runtime.Name
691+
return buserr.WithMap("ErrPortExist", errMap, nil)
692+
}
693+
domain, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithPort(port))
694+
if domain.ID > 0 {
695+
errMap["type"] = i18n.GetMsgByKey("TYPE_DOMAIN")
696+
errMap["name"] = domain.Domain
697+
return buserr.WithMap("ErrPortExist", errMap, nil)
698+
}
699+
if scanPort && common.ScanPort(port) {
700+
return buserr.WithDetail("ErrPortInUsed", port, nil)
701+
}
702+
return nil
703+
}

agent/cmd/server/conf/app.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ base:
22
install_dir: /opt
33
mode: dev
44

5-
remote_rul:
5+
remote_url:
66
repo_url: https://resource.fit2cloud.com/1panel/package
77
resource_url: https://resource.fit2cloud.com/1panel/resource
88
app_repo: https://apps-assets.fit2cloud.com

frontend/src/api/interface/runtime.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export namespace Runtime {
6565
export interface ExposedPort {
6666
hostPort: number;
6767
containerPort: number;
68+
hostIP: string;
6869
}
6970

7071
export interface Environment {

frontend/src/components/drawer-pro/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<el-drawer v-model="localOpenPage" :destroy-on-close="true" :close-on-click-modal="false" :size="size">
2+
<el-drawer v-model="localOpenPage" :destroy-on-close="true" :size="size">
33
<template #header>
44
<el-page-header @back="handleBack">
55
<template #content>

0 commit comments

Comments
 (0)