mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 03:07:20 +08:00
264 lines
6.4 KiB
Go
264 lines
6.4 KiB
Go
package docker
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
"github.com/acepanel/panel/internal/service"
|
|
"github.com/acepanel/panel/pkg/io"
|
|
"github.com/acepanel/panel/pkg/systemctl"
|
|
)
|
|
|
|
type App struct{}
|
|
|
|
func NewApp() *App {
|
|
return &App{}
|
|
}
|
|
|
|
func (s *App) Route(r chi.Router) {
|
|
r.Get("/config", s.GetConfig)
|
|
r.Post("/config", s.UpdateConfig)
|
|
r.Get("/settings", s.GetSettings)
|
|
r.Post("/settings", s.UpdateSettings)
|
|
}
|
|
|
|
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
|
config, err := io.Read("/etc/docker/daemon.json")
|
|
if err != nil {
|
|
service.Error(w, http.StatusInternalServerError, "%v", err)
|
|
return
|
|
}
|
|
|
|
service.Success(w, config)
|
|
}
|
|
|
|
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
|
req, err := service.Bind[UpdateConfig](r)
|
|
if err != nil {
|
|
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
|
return
|
|
}
|
|
|
|
if err = io.Write("/etc/docker/daemon.json", req.Config, 0644); err != nil {
|
|
service.Error(w, http.StatusInternalServerError, "%v", err)
|
|
return
|
|
}
|
|
|
|
if err = systemctl.Restart("docker"); err != nil {
|
|
service.Error(w, http.StatusInternalServerError, "%v", err)
|
|
return
|
|
}
|
|
|
|
service.Success(w, nil)
|
|
}
|
|
|
|
// GetSettings 获取 Docker 设置
|
|
func (s *App) GetSettings(w http.ResponseWriter, r *http.Request) {
|
|
configPath := "/etc/docker/daemon.json"
|
|
|
|
content, err := io.Read(configPath)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
service.Success(w, Settings{})
|
|
return
|
|
}
|
|
service.Error(w, http.StatusInternalServerError, "%v", err)
|
|
return
|
|
}
|
|
|
|
var daemonConfig DaemonConfig
|
|
if err = json.Unmarshal([]byte(content), &daemonConfig); err != nil {
|
|
service.Success(w, Settings{}) // 配置文件可能为空或格式错误,返回默认设置
|
|
return
|
|
}
|
|
|
|
settings := Settings{
|
|
RegistryMirrors: daemonConfig.RegistryMirrors,
|
|
InsecureRegistries: daemonConfig.InsecureRegistries,
|
|
LiveRestore: daemonConfig.LiveRestore,
|
|
LogDriver: daemonConfig.LogDriver,
|
|
Hosts: daemonConfig.Hosts,
|
|
DataRoot: daemonConfig.DataRoot,
|
|
StorageDriver: daemonConfig.StorageDriver,
|
|
DNS: daemonConfig.DNS,
|
|
FirewallBackend: daemonConfig.FirewallBackend,
|
|
Iptables: daemonConfig.Iptables,
|
|
Ip6tables: daemonConfig.Ip6tables,
|
|
IpForward: daemonConfig.IpForward,
|
|
IPv6: daemonConfig.IPv6,
|
|
Bip: daemonConfig.Bip,
|
|
}
|
|
|
|
// 解析 log-opts
|
|
if daemonConfig.LogOpts != nil {
|
|
settings.LogOpts = LogOpts{
|
|
MaxSize: daemonConfig.LogOpts["max-size"],
|
|
MaxFile: daemonConfig.LogOpts["max-file"],
|
|
}
|
|
}
|
|
|
|
// 从 exec-opts 中提取 cgroup-driver
|
|
for _, opt := range daemonConfig.ExecOpts {
|
|
if strings.HasPrefix(opt, "native.cgroupdriver=") {
|
|
settings.CgroupDriver = strings.TrimPrefix(opt, "native.cgroupdriver=")
|
|
break
|
|
}
|
|
}
|
|
|
|
service.Success(w, settings)
|
|
}
|
|
|
|
// UpdateSettings 更新 Docker 设置
|
|
func (s *App) UpdateSettings(w http.ResponseWriter, r *http.Request) {
|
|
req, err := service.Bind[UpdateSettings](r)
|
|
if err != nil {
|
|
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
|
return
|
|
}
|
|
|
|
configPath := "/etc/docker/daemon.json"
|
|
settings := req.Settings
|
|
|
|
// 读取现有配置
|
|
var existingConfig map[string]any
|
|
content, err := io.Read(configPath)
|
|
if err == nil && content != "" {
|
|
if err = json.Unmarshal([]byte(content), &existingConfig); err != nil {
|
|
existingConfig = make(map[string]any)
|
|
}
|
|
} else {
|
|
existingConfig = make(map[string]any)
|
|
}
|
|
|
|
// 更新设置字段
|
|
if len(settings.RegistryMirrors) > 0 {
|
|
existingConfig["registry-mirrors"] = settings.RegistryMirrors
|
|
} else {
|
|
delete(existingConfig, "registry-mirrors")
|
|
}
|
|
|
|
if len(settings.InsecureRegistries) > 0 {
|
|
existingConfig["insecure-registries"] = settings.InsecureRegistries
|
|
} else {
|
|
delete(existingConfig, "insecure-registries")
|
|
}
|
|
|
|
if settings.LiveRestore {
|
|
existingConfig["live-restore"] = true
|
|
} else {
|
|
delete(existingConfig, "live-restore")
|
|
}
|
|
|
|
if settings.LogDriver != "" {
|
|
existingConfig["log-driver"] = settings.LogDriver
|
|
} else {
|
|
delete(existingConfig, "log-driver")
|
|
}
|
|
|
|
// 日志配置
|
|
if settings.LogOpts.MaxSize != "" || settings.LogOpts.MaxFile != "" {
|
|
logOpts := make(map[string]string)
|
|
if settings.LogOpts.MaxSize != "" {
|
|
logOpts["max-size"] = settings.LogOpts.MaxSize
|
|
}
|
|
if settings.LogOpts.MaxFile != "" {
|
|
logOpts["max-file"] = settings.LogOpts.MaxFile
|
|
}
|
|
existingConfig["log-opts"] = logOpts
|
|
} else {
|
|
delete(existingConfig, "log-opts")
|
|
}
|
|
|
|
// cgroup-driver
|
|
if settings.CgroupDriver != "" {
|
|
existingConfig["exec-opts"] = []string{"native.cgroupdriver=" + settings.CgroupDriver}
|
|
} else {
|
|
delete(existingConfig, "exec-opts")
|
|
}
|
|
|
|
if len(settings.Hosts) > 0 {
|
|
existingConfig["hosts"] = settings.Hosts
|
|
} else {
|
|
delete(existingConfig, "hosts")
|
|
}
|
|
|
|
if settings.DataRoot != "" {
|
|
existingConfig["data-root"] = settings.DataRoot
|
|
} else {
|
|
delete(existingConfig, "data-root")
|
|
}
|
|
|
|
if settings.StorageDriver != "" {
|
|
existingConfig["storage-driver"] = settings.StorageDriver
|
|
} else {
|
|
delete(existingConfig, "storage-driver")
|
|
}
|
|
|
|
if len(settings.DNS) > 0 {
|
|
existingConfig["dns"] = settings.DNS
|
|
} else {
|
|
delete(existingConfig, "dns")
|
|
}
|
|
|
|
// 防火墙后端
|
|
if settings.FirewallBackend != "" {
|
|
existingConfig["firewall-backend"] = settings.FirewallBackend
|
|
} else {
|
|
delete(existingConfig, "firewall-backend")
|
|
}
|
|
|
|
if settings.Iptables != nil {
|
|
existingConfig["iptables"] = *settings.Iptables
|
|
} else {
|
|
delete(existingConfig, "iptables")
|
|
}
|
|
|
|
if settings.Ip6tables != nil {
|
|
existingConfig["ip6tables"] = *settings.Ip6tables
|
|
} else {
|
|
delete(existingConfig, "ip6tables")
|
|
}
|
|
|
|
if settings.IpForward != nil {
|
|
existingConfig["ip-forward"] = *settings.IpForward
|
|
} else {
|
|
delete(existingConfig, "ip-forward")
|
|
}
|
|
|
|
if settings.IPv6 != nil {
|
|
existingConfig["ipv6"] = *settings.IPv6
|
|
} else {
|
|
delete(existingConfig, "ipv6")
|
|
}
|
|
|
|
if settings.Bip != "" {
|
|
existingConfig["bip"] = settings.Bip
|
|
} else {
|
|
delete(existingConfig, "bip")
|
|
}
|
|
|
|
// 序列化并写入文件
|
|
newContent, err := json.MarshalIndent(existingConfig, "", " ")
|
|
if err != nil {
|
|
service.Error(w, http.StatusInternalServerError, "%v", err)
|
|
return
|
|
}
|
|
|
|
if err = io.Write(configPath, string(newContent), 0644); err != nil {
|
|
service.Error(w, http.StatusInternalServerError, "%v", err)
|
|
return
|
|
}
|
|
|
|
// 重启 Docker 服务
|
|
if err = systemctl.Restart("docker"); err != nil {
|
|
service.Error(w, http.StatusInternalServerError, "%v", err)
|
|
return
|
|
}
|
|
|
|
service.Success(w, nil)
|
|
}
|