Browse Source

feat(wip): docker ui only

Jacky 2 months ago
parent
commit
d4a4ed1e1c
43 changed files with 1268 additions and 371 deletions
  1. 23 0
      .devcontainer/docker-compose.yml
  2. 1 1
      .devcontainer/init-nginx.sh
  3. 1 1
      .devcontainer/start.sh
  4. 6 1
      api/config/add.go
  5. 21 4
      api/nginx/control.go
  6. 1 1
      api/nginx/router.go
  7. 6 3
      api/nginx/status.go
  8. 10 0
      app/src/constants/errors/docker.ts
  9. 1 0
      app/src/constants/errors/nginx.ts
  10. 62 21
      app/src/language/ar/app.po
  11. 63 22
      app/src/language/de_DE/app.po
  12. 62 22
      app/src/language/en/app.po
  13. 62 21
      app/src/language/es/app.po
  14. 61 21
      app/src/language/fr_FR/app.po
  15. 62 22
      app/src/language/ko_KR/app.po
  16. 53 21
      app/src/language/messages.pot
  17. 62 21
      app/src/language/ru_RU/app.po
  18. 62 21
      app/src/language/tr_TR/app.po
  19. 53 21
      app/src/language/uk_UA/app.po
  20. 62 22
      app/src/language/vi_VN/app.po
  21. 62 21
      app/src/language/zh_CN/app.po
  22. 62 21
      app/src/language/zh_TW/app.po
  23. 13 0
      go.mod
  24. 37 9
      go.sum
  25. 5 1
      internal/config/save.go
  26. 22 0
      internal/docker/docker.go
  27. 15 0
      internal/docker/errors.go
  28. 80 0
      internal/docker/exec.go
  29. 29 0
      internal/docker/stat_path.go
  30. 58 0
      internal/docker/status.go
  31. 1 0
      internal/nginx/errors.go
  32. 28 0
      internal/nginx/exec.go
  33. 38 51
      internal/nginx/nginx.go
  34. 4 1
      internal/site/disable.go
  35. 8 2
      internal/site/enable.go
  36. 16 4
      internal/site/maintenance.go
  37. 13 6
      internal/site/rename.go
  38. 9 2
      internal/site/save.go
  39. 4 1
      internal/stream/disable.go
  40. 8 2
      internal/stream/enable.go
  41. 8 2
      internal/stream/rename.go
  42. 9 2
      internal/stream/save.go
  43. 5 0
      settings/nginx.go

+ 23 - 0
.devcontainer/docker-compose.yml

@@ -7,6 +7,7 @@ services:
       - ../..:/workspaces:cached
       - ../..:/workspaces:cached
       - ./go-path:/root/go
       - ./go-path:/root/go
       - ./data/nginx:/etc/nginx
       - ./data/nginx:/etc/nginx
+      - /var/run/docker.sock:/var/run/docker.sock
     command: sleep infinity
     command: sleep infinity
     environment:
     environment:
       - NGINX_UI_CERT_CA_DIR=https://pebble:14000/dir
       - NGINX_UI_CERT_CA_DIR=https://pebble:14000/dir
@@ -25,6 +26,28 @@ services:
       - nginx-ui
       - nginx-ui
     networks:
     networks:
       nginxui:
       nginxui:
+  nginx-ui-3:
+    image: nginx-ui-dev
+    container_name: nginx-ui-3
+    volumes:
+      - ../..:/workspaces:cached
+      - ./data/nginx-ui-3/nginx:/etc/nginx
+      - ./data/nginx-ui-3/nginx-ui:/etc/nginx-ui
+      - /var/run/docker.sock:/var/run/docker.sock
+    working_dir: /workspaces/nginx-ui
+    command: ./.devcontainer/node-supervisor.sh
+    depends_on:
+      - nginx-ui
+    networks:
+      nginxui:
+  nginx:
+    image: nginx-ui-dev
+    container_name: nginx
+    volumes:
+      - ./data/nginx-ui-3/nginx:/etc/nginx
+    command: sleep infinity
+    networks:
+      nginxui:
   pebble:
   pebble:
     image: ghcr.io/letsencrypt/pebble:latest
     image: ghcr.io/letsencrypt/pebble:latest
     volumes:
     volumes:

+ 1 - 1
.devcontainer/init-nginx.sh

@@ -6,4 +6,4 @@ if [ "$(ls -A /etc/nginx)" = "" ]; then
 fi
 fi
 
 
 # start nginx
 # start nginx
-nginx -g "daemon off;"
+nginx

+ 1 - 1
.devcontainer/start.sh

@@ -3,7 +3,7 @@
 # install air
 # install air
 go install github.com/air-verse/air@latest
 go install github.com/air-verse/air@latest
 
 
-# install zsh-autosuggestions
+install zsh-autosuggestions
 git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions
 git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions
 
 
 if ! grep -q "zsh-autosuggestions" ~/.zshrc; then
 if ! grep -q "zsh-autosuggestions" ~/.zshrc; then

+ 6 - 1
api/config/add.go

@@ -74,7 +74,12 @@ func AddConfig(c *gin.Context) {
 		return
 		return
 	}
 	}
 
 
-	output := nginx.Reload()
+	output, err := nginx.Reload()
+	if err != nil {
+		cosy.ErrHandler(c, err)
+		return
+	}
+
 	if nginx.GetLogLevel(output) >= nginx.Warn {
 	if nginx.GetLogLevel(output) >= nginx.Warn {
 		cosy.ErrHandler(c, cosy.WrapErrorWithParams(config.ErrNginxReloadFailed, output))
 		cosy.ErrHandler(c, cosy.WrapErrorWithParams(config.ErrNginxReloadFailed, output))
 		return
 		return

+ 21 - 4
api/nginx/control.go

@@ -5,24 +5,36 @@ import (
 
 
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/uozi-tech/cosy"
 )
 )
 
 
+// Reload reloads the nginx
 func Reload(c *gin.Context) {
 func Reload(c *gin.Context) {
-	output := nginx.Reload()
+	output, err := nginx.Reload()
+	if err != nil {
+		cosy.ErrHandler(c, err)
+		return
+	}
 	c.JSON(http.StatusOK, gin.H{
 	c.JSON(http.StatusOK, gin.H{
 		"message": output,
 		"message": output,
 		"level":   nginx.GetLogLevel(output),
 		"level":   nginx.GetLogLevel(output),
 	})
 	})
 }
 }
 
 
-func Test(c *gin.Context) {
-	output := nginx.TestConf()
+// TestConfig tests the nginx config
+func TestConfig(c *gin.Context) {
+	output, err := nginx.TestConfig()
+	if err != nil {
+		cosy.ErrHandler(c, err)
+		return
+	}
 	c.JSON(http.StatusOK, gin.H{
 	c.JSON(http.StatusOK, gin.H{
 		"message": output,
 		"message": output,
 		"level":   nginx.GetLogLevel(output),
 		"level":   nginx.GetLogLevel(output),
 	})
 	})
 }
 }
 
 
+// Restart restarts the nginx
 func Restart(c *gin.Context) {
 func Restart(c *gin.Context) {
 	c.JSON(http.StatusOK, gin.H{
 	c.JSON(http.StatusOK, gin.H{
 		"message": "ok",
 		"message": "ok",
@@ -30,8 +42,13 @@ func Restart(c *gin.Context) {
 	go nginx.Restart()
 	go nginx.Restart()
 }
 }
 
 
+// Status returns the status of the nginx
 func Status(c *gin.Context) {
 func Status(c *gin.Context) {
-	lastOutput := nginx.GetLastOutput()
+	lastOutput, err := nginx.GetLastOutput()
+	if err != nil {
+		cosy.ErrHandler(c, err)
+		return
+	}
 
 
 	running := nginx.IsNginxRunning()
 	running := nginx.IsNginxRunning()
 
 

+ 1 - 1
api/nginx/router.go

@@ -11,7 +11,7 @@ func InitRouter(r *gin.RouterGroup) {
 	r.POST("ngx/format_code", FormatNginxConfig)
 	r.POST("ngx/format_code", FormatNginxConfig)
 	r.POST("nginx/reload", Reload)
 	r.POST("nginx/reload", Reload)
 	r.POST("nginx/restart", Restart)
 	r.POST("nginx/restart", Restart)
-	r.POST("nginx/test", Test)
+	r.POST("nginx/test", TestConfig)
 	r.GET("nginx/status", Status)
 	r.GET("nginx/status", Status)
 	// Get detailed Nginx status information, including connection count, process information, etc. (Issue #850)
 	// Get detailed Nginx status information, including connection count, process information, etc. (Issue #850)
 	r.GET("nginx/detail_status", GetDetailStatus)
 	r.GET("nginx/detail_status", GetDetailStatus)

+ 6 - 3
api/nginx/status.go

@@ -4,7 +4,6 @@
 package nginx
 package nginx
 
 
 import (
 import (
-	"errors"
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
 	"time"
 	"time"
@@ -119,10 +118,14 @@ func ToggleStubStatus(c *gin.Context) {
 	}
 	}
 
 
 	// Reload Nginx configuration
 	// Reload Nginx configuration
-	reloadOutput := nginx.Reload()
+	reloadOutput, err := nginx.Reload()
+	if err != nil {
+		cosy.ErrHandler(c, err)
+		return
+	}
 	if len(reloadOutput) > 0 && (strings.Contains(strings.ToLower(reloadOutput), "error") ||
 	if len(reloadOutput) > 0 && (strings.Contains(strings.ToLower(reloadOutput), "error") ||
 		strings.Contains(strings.ToLower(reloadOutput), "failed")) {
 		strings.Contains(strings.ToLower(reloadOutput), "failed")) {
-		cosy.ErrHandler(c, errors.New("Reload Nginx failed"))
+		cosy.ErrHandler(c, cosy.WrapErrorWithParams(nginx.ErrReloadFailed, reloadOutput))
 		return
 		return
 	}
 	}
 
 

+ 10 - 0
app/src/constants/errors/docker.ts

@@ -0,0 +1,10 @@
+export default {
+  500001: () => $gettext('Docker client not initialized'),
+  500002: () => $gettext('Failed to exec command: {0}'),
+  500003: () => $gettext('Failed to attach to exec instance: {0}'),
+  500004: () => $gettext('Failed to read output: {0}'),
+  500005: () => $gettext('Command exited with unexpected exit code: {0}, error: {1}'),
+  500006: () => $gettext('Container status unknown'),
+  500007: () => $gettext('Failed to inspect container: {0}'),
+  500008: () => $gettext('Nginx is not running in another container'),
+}

+ 1 - 0
app/src/constants/errors/nginx.ts

@@ -1,3 +1,4 @@
 export default {
 export default {
   50001: () => $gettext('Block is nil'),
   50001: () => $gettext('Block is nil'),
+  50002: () => $gettext('Reload nginx failed: {0}'),
 }
 }

+ 62 - 21
app/src/language/ar/app.po

@@ -80,7 +80,7 @@ msgid "Add a passkey"
 msgstr "أضف مفتاح مرور"
 msgstr "أضف مفتاح مرور"
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "إضافة تكوين"
 msgstr "إضافة تكوين"
 
 
@@ -301,7 +301,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -355,7 +355,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "المعلومات الأساسية"
 msgstr "المعلومات الأساسية"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -594,7 +594,7 @@ msgstr[3] "الشهادات المعدلة"
 msgstr[4] "الشهادات المعدلة"
 msgstr[4] "الشهادات المعدلة"
 msgstr[5] "الشهادات المعدلة"
 msgstr[5] "الشهادات المعدلة"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "المسار المتغير"
 msgstr "المسار المتغير"
 
 
@@ -707,6 +707,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "أمر"
 msgstr "أمر"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -787,6 +791,10 @@ msgstr "تم فقدان الاتصال، يرجى تحديث الصفحة."
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1018,7 +1026,7 @@ msgstr "تم الحذف بنجاح"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "نشر"
 msgstr "نشر"
 
 
@@ -1218,6 +1226,10 @@ msgstr "هل تريد إزالة هذا الخادم؟"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "هل تريد إزالة هذا المصدر؟"
 msgstr "هل تريد إزالة هذا المصدر؟"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1281,7 +1293,7 @@ msgstr "تعديل %{n}"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "تعديل %{n}"
 msgstr "تعديل %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "تعديل التكوين"
 msgstr "تعديل التكوين"
 
 
@@ -1495,6 +1507,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "فشل في الحصول على الشهادة"
 msgstr "فشل في الحصول على الشهادة"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "فشل في التفعيل %{msg}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 #, fuzzy
 #, fuzzy
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
@@ -1680,6 +1697,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "فشل في التفعيل %{msg}"
 msgstr "فشل في التفعيل %{msg}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "فشل في التفعيل %{msg}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1709,6 +1731,11 @@ msgstr "فشل في الحصول على معلومات الشهادة"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "فشل في الحصول على معلومات الشهادة"
 msgstr "فشل في الحصول على معلومات الشهادة"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "فشل في التفعيل %{msg}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1753,6 +1780,11 @@ msgstr "فشل في التفعيل %{msg}"
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr "فشل في التفعيل %{msg}"
 msgstr "فشل في التفعيل %{msg}"
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "فشل في التفعيل %{msg}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1838,14 +1870,10 @@ msgstr "للمستخدمين الصين: /https://mirror.ghproxy.com"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "فشل التكرار"
 msgstr "فشل التكرار"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "تنسيق الكود"
 msgstr "تنسيق الكود"
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr "خطأ في التنسيق %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr "تم التنسيق بنجاح"
 msgstr "تم التنسيق بنجاح"
@@ -1920,7 +1948,7 @@ msgstr "إخفاء"
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 #, fuzzy
 #, fuzzy
@@ -2101,7 +2129,7 @@ msgid "Invalid file path: {0}"
 msgstr "رمز 2FA أو الاسترداد غير صالح"
 msgstr "رمز 2FA أو الاسترداد غير صالح"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "اسم ملف غير صالح"
 msgstr "اسم ملف غير صالح"
 
 
@@ -2525,7 +2553,7 @@ msgstr "توجيه متعدد الأسطر"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2568,7 +2596,7 @@ msgstr "تثبيت"
 msgid "New name"
 msgid "New name"
 msgstr "اسم جديد"
 msgstr "اسم جديد"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "New Path"
 msgid "New Path"
 msgstr "مسار جديد"
 msgstr "مسار جديد"
 
 
@@ -2669,6 +2697,11 @@ msgstr "مسار سجل أخطاء Nginx"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr "Nginx لا يعمل"
 msgstr "Nginx لا يعمل"
 
 
+#: src/constants/errors/docker.ts:9
+#, fuzzy
+msgid "Nginx is not running in another container"
+msgstr "Nginx لا يعمل"
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 #, fuzzy
 #, fuzzy
 msgid "Nginx is running"
 msgid "Nginx is running"
@@ -2999,11 +3032,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr "استخدم رمز الاسترداد"
 msgstr "استخدم رمز الاسترداد"
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "الكتابة فوق"
 msgstr "الكتابة فوق"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "الكتابة فوق الملف الموجود"
 msgstr "الكتابة فوق الملف الموجود"
 
 
@@ -3054,7 +3087,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "مسار"
 msgstr "مسار"
@@ -3150,7 +3183,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "يرجى إدخال اسم الملف"
 msgstr "يرجى إدخال اسم الملف"
 
 
@@ -3386,6 +3419,11 @@ msgstr "إعادة تحميل"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "إعادة تحميل nginx"
 msgstr "إعادة تحميل nginx"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "فشل في التفعيل %{msg}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3675,7 +3713,7 @@ msgstr "يعمل"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4519,7 +4557,7 @@ msgstr "تم التحديث بنجاح"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4816,6 +4854,9 @@ msgstr ""
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr "مفاتيح المرور الخاصة بك"
 msgstr "مفاتيح المرور الخاصة بك"
 
 
+#~ msgid "Format error %{msg}"
+#~ msgstr "خطأ في التنسيق %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr "فشل في الحفظ، تم اكتشاف خطأ(أخطاء) في بناء الجملة في التكوين."
 #~ msgstr "فشل في الحفظ، تم اكتشاف خطأ(أخطاء) في بناء الجملة في التكوين."
 
 

+ 63 - 22
app/src/language/de_DE/app.po

@@ -77,7 +77,7 @@ msgid "Add a passkey"
 msgstr "Passkey hinzufügen"
 msgstr "Passkey hinzufügen"
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 #, fuzzy
 #, fuzzy
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "Konfiguration bearbeiten"
 msgstr "Konfiguration bearbeiten"
@@ -315,7 +315,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -370,7 +370,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "Basisinformationen"
 msgstr "Basisinformationen"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #, fuzzy
 #, fuzzy
@@ -610,7 +610,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] "Zertifikat ist gültig"
 msgstr[0] "Zertifikat ist gültig"
 msgstr[1] "Zertifikat ist gültig"
 msgstr[1] "Zertifikat ist gültig"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
@@ -726,6 +726,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "Kommando"
 msgstr "Kommando"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -806,6 +810,10 @@ msgstr "Ver"
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1045,7 +1053,7 @@ msgstr "Erfolgreich deaktiviert"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "Ausführen"
 msgstr "Ausführen"
 
 
@@ -1255,6 +1263,10 @@ msgstr "Bist du sicher, dass du diese Richtlinie löschen möchtest?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "Bist du sicher, dass du diese Richtlinie löschen möchtest?"
 msgstr "Bist du sicher, dass du diese Richtlinie löschen möchtest?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1318,7 +1330,7 @@ msgstr "Bearbeiten %{n}"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "Bearbeiten %{n}"
 msgstr "Bearbeiten %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "Konfiguration bearbeiten"
 msgstr "Konfiguration bearbeiten"
 
 
@@ -1542,6 +1554,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Zertifikat ist gültig"
 msgstr "Zertifikat ist gültig"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "Aktiviern von %{msg} fehlgeschlagen"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr ""
 msgstr ""
@@ -1726,6 +1743,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "Aktiviern von %{msg} fehlgeschlagen"
 msgstr "Aktiviern von %{msg} fehlgeschlagen"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "Aktiviern von %{msg} fehlgeschlagen"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1755,6 +1777,11 @@ msgstr "Fehler beim Abrufen von Zertifikatsinformationen"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "Fehler beim Abrufen von Zertifikatsinformationen"
 msgstr "Fehler beim Abrufen von Zertifikatsinformationen"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "Aktiviern von %{msg} fehlgeschlagen"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1796,6 +1823,11 @@ msgstr ""
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "Aktiviern von %{msg} fehlgeschlagen"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1882,15 +1914,10 @@ msgstr "Für chinesische Benutzer: https://mirror.ghproxy.com/"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "Anlegen fehlgeschlagen"
 msgstr "Anlegen fehlgeschlagen"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "Formatcode"
 msgstr "Formatcode"
 
 
-#: src/views/config/ConfigEditor.vue:218
-#, fuzzy
-msgid "Format error %{msg}"
-msgstr "Fehler beim Speichern %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 #, fuzzy
 #, fuzzy
 msgid "Format successfully"
 msgid "Format successfully"
@@ -1968,7 +1995,7 @@ msgstr "Verstecken"
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 msgid "History"
 msgid "History"
@@ -2150,7 +2177,7 @@ msgid "Invalid file path: {0}"
 msgstr "Ungültige E-Mail!"
 msgstr "Ungültige E-Mail!"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 #, fuzzy
 #, fuzzy
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "Ungültige E-Mail!"
 msgstr "Ungültige E-Mail!"
@@ -2595,7 +2622,7 @@ msgstr "Einzelne Anweisung"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2639,7 +2666,7 @@ msgstr "Installieren"
 msgid "New name"
 msgid "New name"
 msgstr "Benutzername"
 msgstr "Benutzername"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "New Path"
 msgid "New Path"
 msgstr "Pfad"
 msgstr "Pfad"
@@ -2743,6 +2770,11 @@ msgstr "Nginx Fehlerlog-Pfad"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr "Nginx läuft nicht"
 msgstr "Nginx läuft nicht"
 
 
+#: src/constants/errors/docker.ts:9
+#, fuzzy
+msgid "Nginx is not running in another container"
+msgstr "Nginx läuft nicht"
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 #, fuzzy
 #, fuzzy
 msgid "Nginx is running"
 msgid "Nginx is running"
@@ -3082,11 +3114,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr "Benuzte Wiederherstellungscode"
 msgstr "Benuzte Wiederherstellungscode"
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "Überschreiben"
 msgstr "Überschreiben"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "Zu überschreibende Datei existiert"
 msgstr "Zu überschreibende Datei existiert"
 
 
@@ -3137,7 +3169,7 @@ msgstr "Passwort darf nicht länger als 20 Zeichen sein"
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "Pfad"
 msgstr "Pfad"
@@ -3237,7 +3269,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 #, fuzzy
 #, fuzzy
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "Bitte Benutzernamen eingeben!"
 msgstr "Bitte Benutzernamen eingeben!"
@@ -3488,6 +3520,11 @@ msgstr "Neu laden"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Lade Nginx neu"
 msgstr "Lade Nginx neu"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "Aktiviern von %{msg} fehlgeschlagen"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3792,7 +3829,7 @@ msgstr "Arbeite"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4653,7 +4690,7 @@ msgstr "Speichern erfolgreich"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4961,6 +4998,10 @@ msgstr ""
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr "Deine Passkeys"
 msgstr "Deine Passkeys"
 
 
+#, fuzzy
+#~ msgid "Format error %{msg}"
+#~ msgstr "Fehler beim Speichern %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr ""
 #~ msgstr ""
 #~ "Fehler beim Speichern, Syntaxfehler wurden in der Konfiguration erkannt."
 #~ "Fehler beim Speichern, Syntaxfehler wurden in der Konfiguration erkannt."

+ 62 - 22
app/src/language/en/app.po

@@ -78,7 +78,7 @@ msgid "Add a passkey"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 #, fuzzy
 #, fuzzy
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "Edit Configuration"
 msgstr "Edit Configuration"
@@ -312,7 +312,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -367,7 +367,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "Base information"
 msgstr "Base information"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #, fuzzy
 #, fuzzy
@@ -603,7 +603,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] "Certificate is valid"
 msgstr[0] "Certificate is valid"
 msgstr[1] "Certificate is valid"
 msgstr[1] "Certificate is valid"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
@@ -718,6 +718,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "Comments"
 msgstr "Comments"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -798,6 +802,10 @@ msgstr ""
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1034,7 +1042,7 @@ msgstr "Disabled successfully"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr ""
 msgstr ""
 
 
@@ -1243,6 +1251,10 @@ msgstr "Are you sure you want to remove this directive?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "Are you sure you want to remove this directive?"
 msgstr "Are you sure you want to remove this directive?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1302,7 +1314,7 @@ msgstr "Edit %{n}"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "Edit %{n}"
 msgstr "Edit %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "Edit Configuration"
 msgstr "Edit Configuration"
 
 
@@ -1525,6 +1537,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "Failed to enable %{msg}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 #, fuzzy
 #, fuzzy
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
@@ -1710,6 +1727,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "Failed to enable %{msg}"
 msgstr "Failed to enable %{msg}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "Failed to enable %{msg}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1740,6 +1762,11 @@ msgstr "Certificate is valid"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "Certificate is valid"
 msgstr "Certificate is valid"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "Failed to enable %{msg}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1784,6 +1811,11 @@ msgstr "Failed to enable %{msg}"
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr "Failed to enable %{msg}"
 msgstr "Failed to enable %{msg}"
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "Failed to enable %{msg}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1869,15 +1901,10 @@ msgstr ""
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "Enable failed"
 msgstr "Enable failed"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:218
-#, fuzzy
-msgid "Format error %{msg}"
-msgstr "Save error %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 #, fuzzy
 #, fuzzy
 msgid "Format successfully"
 msgid "Format successfully"
@@ -1954,7 +1981,7 @@ msgstr ""
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 #, fuzzy
 #, fuzzy
@@ -2129,7 +2156,7 @@ msgid "Invalid file path: {0}"
 msgstr "Invalid E-mail!"
 msgstr "Invalid E-mail!"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 #, fuzzy
 #, fuzzy
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "Invalid E-mail!"
 msgstr "Invalid E-mail!"
@@ -2567,7 +2594,7 @@ msgstr "Single Directive"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2611,7 +2638,7 @@ msgstr "Install"
 msgid "New name"
 msgid "New name"
 msgstr "Username"
 msgstr "Username"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "New Path"
 msgid "New Path"
 msgstr "Path"
 msgstr "Path"
@@ -2714,6 +2741,10 @@ msgstr ""
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:9
+msgid "Nginx is not running in another container"
+msgstr ""
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 msgid "Nginx is running"
 msgid "Nginx is running"
 msgstr ""
 msgstr ""
@@ -3045,11 +3076,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr ""
 msgstr ""
 
 
@@ -3097,7 +3128,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "Path"
 msgstr "Path"
@@ -3189,7 +3220,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 #, fuzzy
 #, fuzzy
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "Please input your username!"
 msgstr "Please input your username!"
@@ -3431,6 +3462,11 @@ msgstr ""
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "Failed to enable %{msg}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3734,7 +3770,7 @@ msgstr ""
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4573,7 +4609,7 @@ msgstr "Saved successfully"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4871,6 +4907,10 @@ msgstr ""
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr ""
 msgstr ""
 
 
+#, fuzzy
+#~ msgid "Format error %{msg}"
+#~ msgstr "Save error %{msg}"
+
 #, fuzzy
 #, fuzzy
 #~ msgid "Access Token"
 #~ msgid "Access Token"
 #~ msgstr "Sites List"
 #~ msgstr "Sites List"

+ 62 - 21
app/src/language/es/app.po

@@ -83,7 +83,7 @@ msgid "Add a passkey"
 msgstr "Agregar una llave de acceso"
 msgstr "Agregar una llave de acceso"
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "Agregar configuración"
 msgstr "Agregar configuración"
 
 
@@ -306,7 +306,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -360,7 +360,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "Información general"
 msgstr "Información general"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -593,7 +593,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] "Cambiar Certificado"
 msgstr[0] "Cambiar Certificado"
 msgstr[1] "Cambiar Certificados"
 msgstr[1] "Cambiar Certificados"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "Ruta cambiada"
 msgstr "Ruta cambiada"
 
 
@@ -706,6 +706,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "Comando"
 msgstr "Comando"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -786,6 +790,10 @@ msgstr "Conexión perdida, por favor actualice la página."
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1019,7 +1027,7 @@ msgstr "Borrado exitoso"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "Desplegar"
 msgstr "Desplegar"
 
 
@@ -1219,6 +1227,10 @@ msgstr "¿Quieres eliminar este servidor?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "¿Quieres eliminar esta transmisión?"
 msgstr "¿Quieres eliminar esta transmisión?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1281,7 +1293,7 @@ msgstr "Editar %{n}"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "Editar %{n}"
 msgstr "Editar %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "Editar Configuración"
 msgstr "Editar Configuración"
 
 
@@ -1498,6 +1510,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Falla al obtener el certificado"
 msgstr "Falla al obtener el certificado"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "Error al habilitar %{msg}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr ""
 msgstr ""
@@ -1682,6 +1699,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "Error al habilitar %{msg}"
 msgstr "Error al habilitar %{msg}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "Error al habilitar %{msg}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1711,6 +1733,11 @@ msgstr "No se pudo obtener la información del certificado"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "No se pudo obtener la información del certificado"
 msgstr "No se pudo obtener la información del certificado"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "Error al habilitar %{msg}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1752,6 +1779,11 @@ msgstr ""
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "Error al habilitar %{msg}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1838,14 +1870,10 @@ msgstr "Para usuario chino: https://mirror.ghproxy.com/"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "Duplicado fallido"
 msgstr "Duplicado fallido"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "Código de formato"
 msgstr "Código de formato"
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr "Error de formato %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr "Formateado correctamente"
 msgstr "Formateado correctamente"
@@ -1920,7 +1948,7 @@ msgstr "Ocultar"
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 #, fuzzy
 #, fuzzy
@@ -2101,7 +2129,7 @@ msgid "Invalid file path: {0}"
 msgstr "Nombre de archivo inválido"
 msgstr "Nombre de archivo inválido"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "Nombre de archivo inválido"
 msgstr "Nombre de archivo inválido"
 
 
@@ -2527,7 +2555,7 @@ msgstr "Directiva multilínea"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2570,7 +2598,7 @@ msgstr "Instalar"
 msgid "New name"
 msgid "New name"
 msgstr "Nuevo nombre"
 msgstr "Nuevo nombre"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "New Path"
 msgid "New Path"
 msgstr "Nueva ruta"
 msgstr "Nueva ruta"
 
 
@@ -2672,6 +2700,11 @@ msgstr "Ruta de registro de errores de Nginx"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr "Nginx no se está ejecutando"
 msgstr "Nginx no se está ejecutando"
 
 
+#: src/constants/errors/docker.ts:9
+#, fuzzy
+msgid "Nginx is not running in another container"
+msgstr "Nginx no se está ejecutando"
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 #, fuzzy
 #, fuzzy
 msgid "Nginx is running"
 msgid "Nginx is running"
@@ -3006,11 +3039,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr "Usar código de recuperación"
 msgstr "Usar código de recuperación"
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "Sobrescribir"
 msgstr "Sobrescribir"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "Sobrescribir archivo existente"
 msgstr "Sobrescribir archivo existente"
 
 
@@ -3062,7 +3095,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "Ruta"
 msgstr "Ruta"
@@ -3163,7 +3196,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "Por favor, ingrese un nombre de archivo"
 msgstr "Por favor, ingrese un nombre de archivo"
 
 
@@ -3410,6 +3443,11 @@ msgstr "Recargar"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Recargando Nginx"
 msgstr "Recargando Nginx"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "Error al habilitar %{msg}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3702,7 +3740,7 @@ msgstr "Corriendo"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4560,7 +4598,7 @@ msgstr "Actualización exitosa"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4862,6 +4900,9 @@ msgstr ""
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr "Sus llaves de acceso"
 msgstr "Sus llaves de acceso"
 
 
+#~ msgid "Format error %{msg}"
+#~ msgstr "Error de formato %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr ""
 #~ msgstr ""
 #~ "No se pudo guardar, se detectó un error(es) de sintaxis en la "
 #~ "No se pudo guardar, se detectó un error(es) de sintaxis en la "

+ 61 - 21
app/src/language/fr_FR/app.po

@@ -82,7 +82,7 @@ msgid "Add a passkey"
 msgstr "Ajouter une clé d'accès"
 msgstr "Ajouter une clé d'accès"
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 #, fuzzy
 #, fuzzy
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "Modifier la configuration"
 msgstr "Modifier la configuration"
@@ -319,7 +319,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -373,7 +373,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "Information générale"
 msgstr "Information générale"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -612,7 +612,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] "Changer de certificat"
 msgstr[0] "Changer de certificat"
 msgstr[1] "Changer de certificat"
 msgstr[1] "Changer de certificat"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "Changer de certificat"
 msgstr "Changer de certificat"
@@ -733,6 +733,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "Commentaires"
 msgstr "Commentaires"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -813,6 +817,10 @@ msgstr "Connexion perdue, merci de recharger la page."
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1053,7 +1061,7 @@ msgstr "Désactivé avec succès"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "Déployer"
 msgstr "Déployer"
 
 
@@ -1262,6 +1270,10 @@ msgstr "Voulez-vous supprimer ce serveur ?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "Voulez-vous supprimer ce serveur ?"
 msgstr "Voulez-vous supprimer ce serveur ?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1327,7 +1339,7 @@ msgstr "Modifier %{n}"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "Modifier %{n}"
 msgstr "Modifier %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "Modifier la configuration"
 msgstr "Modifier la configuration"
 
 
@@ -1552,6 +1564,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Obtenir un certificat"
 msgstr "Obtenir un certificat"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "Impossible d'activer %{msg}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 #, fuzzy
 #, fuzzy
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
@@ -1737,6 +1754,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "Impossible d'activer %{msg}"
 msgstr "Impossible d'activer %{msg}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "Impossible d'activer %{msg}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1766,6 +1788,11 @@ msgstr "Échec de l'obtention des informations sur le certificat"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "Échec de l'obtention des informations sur le certificat"
 msgstr "Échec de l'obtention des informations sur le certificat"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "Impossible d'activer %{msg}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1811,6 +1838,11 @@ msgstr "Impossible d'activer %{msg}"
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr "Impossible d'activer %{msg}"
 msgstr "Impossible d'activer %{msg}"
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "Impossible d'activer %{msg}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1901,14 +1933,10 @@ msgstr "Utilisateur chinois : https://mirror.ghproxy.com/"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "Dupliquer"
 msgstr "Dupliquer"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "Code de formatage"
 msgstr "Code de formatage"
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr "Erreur de format %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr "Formaté avec succès"
 msgstr "Formaté avec succès"
@@ -1982,7 +2010,7 @@ msgstr "Cacher"
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 #, fuzzy
 #, fuzzy
@@ -2170,7 +2198,7 @@ msgid "Invalid file path: {0}"
 msgstr "Format de la requête invalide"
 msgstr "Format de la requête invalide"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "Nom de fichier invalide"
 msgstr "Nom de fichier invalide"
 
 
@@ -2608,7 +2636,7 @@ msgstr "Directive multiligne"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2652,7 +2680,7 @@ msgstr "Installer"
 msgid "New name"
 msgid "New name"
 msgstr "Nom d'utilisateur"
 msgstr "Nom d'utilisateur"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "New Path"
 msgid "New Path"
 msgstr "Chemin"
 msgstr "Chemin"
@@ -2756,6 +2784,10 @@ msgstr "Chemin du journal des erreurs Nginx"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:9
+msgid "Nginx is not running in another container"
+msgstr ""
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 msgid "Nginx is running"
 msgid "Nginx is running"
 msgstr ""
 msgstr ""
@@ -3086,11 +3118,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr ""
 msgstr ""
 
 
@@ -3138,7 +3170,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "Chemin"
 msgstr "Chemin"
@@ -3234,7 +3266,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "Veuillez renseigner un nom de fichier"
 msgstr "Veuillez renseigner un nom de fichier"
 
 
@@ -3482,6 +3514,11 @@ msgstr "Recharger"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Rechargement de nginx"
 msgstr "Rechargement de nginx"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "Impossible d'activer %{msg}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3786,7 +3823,7 @@ msgstr "En cours d'éxécution"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4632,7 +4669,7 @@ msgstr "Mis à jour avec succés"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4927,6 +4964,9 @@ msgstr ""
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr ""
 msgstr ""
 
 
+#~ msgid "Format error %{msg}"
+#~ msgstr "Erreur de format %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr ""
 #~ msgstr ""
 #~ "Échec de l'enregistrement, une ou plusieurs erreurs de syntaxe ont été "
 #~ "Échec de l'enregistrement, une ou plusieurs erreurs de syntaxe ont été "

+ 62 - 22
app/src/language/ko_KR/app.po

@@ -81,7 +81,7 @@ msgid "Add a passkey"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "구성 추가"
 msgstr "구성 추가"
 
 
@@ -296,7 +296,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr "사이트 및 스트림 구성에서 자동으로 색인됩니다."
 msgstr "사이트 및 스트림 구성에서 자동으로 색인됩니다."
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -350,7 +350,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "기본 정보"
 msgstr "기본 정보"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -582,7 +582,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] "인증서 변경"
 msgstr[0] "인증서 변경"
 msgstr[1] "인증서 변경"
 msgstr[1] "인증서 변경"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "인증서 변경"
 msgstr "인증서 변경"
@@ -695,6 +695,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "명령어"
 msgstr "명령어"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -775,6 +779,10 @@ msgstr "연결이 끊어졌습니다. 페이지를 새로 고침하세요."
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1009,7 +1017,7 @@ msgstr "성공적으로 삭제됨"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "배포"
 msgstr "배포"
 
 
@@ -1211,6 +1219,10 @@ msgstr "이 서버를 제거하시겠습니까?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "이 업스트림을 제거하시겠습니까?"
 msgstr "이 업스트림을 제거하시겠습니까?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1269,7 +1281,7 @@ msgstr "%{n} 편집"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "%{n} 편집"
 msgstr "%{n} 편집"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "구성 편집"
 msgstr "구성 편집"
 
 
@@ -1491,6 +1503,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "인증서 획득 실패"
 msgstr "인증서 획득 실패"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "%{msg} 활성화 실패"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr ""
 msgstr ""
@@ -1675,6 +1692,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "%{msg} 활성화 실패"
 msgstr "%{msg} 활성화 실패"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "%{msg} 활성화 실패"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1704,6 +1726,11 @@ msgstr "인증서 정보 가져오기 실패"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "인증서 정보 가져오기 실패"
 msgstr "인증서 정보 가져오기 실패"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "%{msg} 활성화 실패"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1745,6 +1772,11 @@ msgstr ""
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "%{msg} 활성화 실패"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1829,15 +1861,10 @@ msgstr "중국 사용자를 위해: https://mirror.ghproxy.com/"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "복제 실패"
 msgstr "복제 실패"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "코드 형식"
 msgstr "코드 형식"
 
 
-#: src/views/config/ConfigEditor.vue:218
-#, fuzzy
-msgid "Format error %{msg}"
-msgstr "형식 오류 %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 #, fuzzy
 #, fuzzy
 msgid "Format successfully"
 msgid "Format successfully"
@@ -1913,7 +1940,7 @@ msgstr ""
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 #, fuzzy
 #, fuzzy
@@ -2088,7 +2115,7 @@ msgid "Invalid file path: {0}"
 msgstr "Invalid E-mail!"
 msgstr "Invalid E-mail!"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 #, fuzzy
 #, fuzzy
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "Invalid E-mail!"
 msgstr "Invalid E-mail!"
@@ -2528,7 +2555,7 @@ msgstr "단일 지시문"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2572,7 +2599,7 @@ msgstr "설치"
 msgid "New name"
 msgid "New name"
 msgstr "이름 변경"
 msgstr "이름 변경"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "New Path"
 msgid "New Path"
 msgstr "경로"
 msgstr "경로"
@@ -2676,6 +2703,10 @@ msgstr "Nginx 오류 로그 경로"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:9
+msgid "Nginx is not running in another container"
+msgstr ""
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 msgid "Nginx is running"
 msgid "Nginx is running"
 msgstr ""
 msgstr ""
@@ -3008,11 +3039,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "덮어쓰기"
 msgstr "덮어쓰기"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "기존 파일 덮어쓰기"
 msgstr "기존 파일 덮어쓰기"
 
 
@@ -3060,7 +3091,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "경로"
 msgstr "경로"
@@ -3153,7 +3184,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 #, fuzzy
 #, fuzzy
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "사용자 이름을 입력해주세요!"
 msgstr "사용자 이름을 입력해주세요!"
@@ -3402,6 +3433,11 @@ msgstr "리로드"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Nginx 리로딩 중"
 msgstr "Nginx 리로딩 중"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "%{msg} 활성화 실패"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3707,7 +3743,7 @@ msgstr "실행 중"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4544,7 +4580,7 @@ msgstr "성공적으로 저장되었습니다"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4844,6 +4880,10 @@ msgstr ""
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr ""
 msgstr ""
 
 
+#, fuzzy
+#~ msgid "Format error %{msg}"
+#~ msgstr "형식 오류 %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr "저장 실패, 구성에서 구문 오류가 감지되었습니다."
 #~ msgstr "저장 실패, 구성에서 구문 오류가 감지되었습니다."
 
 

+ 53 - 21
app/src/language/messages.pot

@@ -71,7 +71,7 @@ msgstr ""
 
 
 #: src/routes/modules/config.ts:20
 #: src/routes/modules/config.ts:20
 #: src/views/config/ConfigEditor.vue:171
 #: src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr ""
 msgstr ""
 
 
@@ -285,7 +285,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268
+#: src/views/config/ConfigEditor.vue:266
 #: src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195
 #: src/views/config/ConfigList.vue:195
 #: src/views/nginx_log/NginxLog.vue:173
 #: src/views/nginx_log/NginxLog.vue:173
@@ -338,7 +338,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -553,7 +553,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] ""
 msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr ""
 msgstr ""
 
 
@@ -659,6 +659,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -734,6 +738,10 @@ msgstr ""
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -953,7 +961,7 @@ msgstr ""
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr ""
 msgstr ""
 
 
@@ -1144,6 +1152,10 @@ msgstr ""
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 msgid "Document"
 msgid "Document"
@@ -1198,7 +1210,7 @@ msgid "Edit %{n}"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/config.ts:30
 #: src/routes/modules/config.ts:30
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr ""
 msgstr ""
 
 
@@ -1403,6 +1415,10 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:4
+msgid "Failed to attach to exec instance: {0}"
+msgstr ""
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr ""
 msgstr ""
@@ -1563,6 +1579,10 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:3
+msgid "Failed to exec command: {0}"
+msgstr ""
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
 msgstr ""
 msgstr ""
@@ -1587,6 +1607,10 @@ msgstr ""
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:8
+msgid "Failed to inspect container: {0}"
+msgstr ""
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 msgid "Failed to load history records"
 msgid "Failed to load history records"
 msgstr ""
 msgstr ""
@@ -1623,6 +1647,10 @@ msgstr ""
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:5
+msgid "Failed to read output: {0}"
+msgstr ""
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
 msgstr ""
 msgstr ""
@@ -1701,14 +1729,10 @@ msgstr ""
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr ""
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr ""
 msgstr ""
@@ -1779,7 +1803,7 @@ msgstr ""
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 msgid "History"
 msgid "History"
@@ -1938,7 +1962,7 @@ msgid "Invalid file path: {0}"
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr ""
 msgstr ""
 
 
@@ -2336,7 +2360,7 @@ msgstr ""
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/configColumns.tsx:7
 #: src/views/config/configColumns.tsx:7
-#: src/views/config/ConfigEditor.vue:311
+#: src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2379,7 +2403,7 @@ msgstr ""
 msgid "New name"
 msgid "New name"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "New Path"
 msgid "New Path"
 msgstr ""
 msgstr ""
 
 
@@ -2476,6 +2500,10 @@ msgstr ""
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:9
+msgid "Nginx is not running in another container"
+msgstr ""
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 msgid "Nginx is running"
 msgid "Nginx is running"
 msgstr ""
 msgstr ""
@@ -2785,11 +2813,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr ""
 msgstr ""
 
 
@@ -2833,7 +2861,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr ""
 msgstr ""
@@ -2914,7 +2942,7 @@ msgid "Please generate new recovery codes in the preferences immediately to prev
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr ""
 msgstr ""
 
 
@@ -3137,6 +3165,10 @@ msgstr ""
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/nginx.ts:3
+msgid "Reload nginx failed: {0}"
+msgstr ""
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr ""
 msgstr ""
@@ -3400,7 +3432,7 @@ msgstr ""
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4127,7 +4159,7 @@ msgstr ""
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/config/configColumns.tsx:36
 #: src/views/config/configColumns.tsx:36
-#: src/views/config/ConfigEditor.vue:331
+#: src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38

+ 62 - 21
app/src/language/ru_RU/app.po

@@ -83,7 +83,7 @@ msgid "Add a passkey"
 msgstr "Добавить ключ доступа"
 msgstr "Добавить ключ доступа"
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "Добавить конфигурацию"
 msgstr "Добавить конфигурацию"
 
 
@@ -300,7 +300,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -354,7 +354,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "Основная информация"
 msgstr "Основная информация"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -581,7 +581,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] "Сертификат изменен"
 msgstr[0] "Сертификат изменен"
 msgstr[1] "Сертификаты изменены"
 msgstr[1] "Сертификаты изменены"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "Путь изменён"
 msgstr "Путь изменён"
 
 
@@ -694,6 +694,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "Команда"
 msgstr "Команда"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -774,6 +778,10 @@ msgstr "Соединение потеряно, пожалуйста, обнов
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1004,7 +1012,7 @@ msgstr "Удалено успешно"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "Развернуть"
 msgstr "Развернуть"
 
 
@@ -1207,6 +1215,10 @@ msgstr "Хотите удалить этот сервер?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "Хотите удалить этот сервер?"
 msgstr "Хотите удалить этот сервер?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1268,7 +1280,7 @@ msgstr "Редактировать %{n}"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "Редактировать %{n}"
 msgstr "Редактировать %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "Редактировать Конфигурацию"
 msgstr "Редактировать Конфигурацию"
 
 
@@ -1482,6 +1494,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Не удалось получить сертификат"
 msgstr "Не удалось получить сертификат"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "Не удалось включить %{msg}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr ""
 msgstr ""
@@ -1666,6 +1683,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "Не удалось включить %{msg}"
 msgstr "Не удалось включить %{msg}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "Не удалось включить %{msg}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1695,6 +1717,11 @@ msgstr "Не удалось получить информацию о серти
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "Не удалось получить информацию о сертификате"
 msgstr "Не удалось получить информацию о сертификате"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "Не удалось включить %{msg}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1736,6 +1763,11 @@ msgstr ""
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "Не удалось включить %{msg}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1822,14 +1854,10 @@ msgstr "Для китайских пользователей: https://mirror.ghp
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "Дублирование не удалось"
 msgstr "Дублирование не удалось"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "Форматировать код"
 msgstr "Форматировать код"
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr "Ошибка формата %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr "Форматирование успешно"
 msgstr "Форматирование успешно"
@@ -1904,7 +1932,7 @@ msgstr "Скрыть"
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 #, fuzzy
 #, fuzzy
@@ -2085,7 +2113,7 @@ msgid "Invalid file path: {0}"
 msgstr "Неверное имя файла"
 msgstr "Неверное имя файла"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "Неверное имя файла"
 msgstr "Неверное имя файла"
 
 
@@ -2508,7 +2536,7 @@ msgstr "Многострочная директива"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2551,7 +2579,7 @@ msgstr "Установить"
 msgid "New name"
 msgid "New name"
 msgstr "Новое имя"
 msgstr "Новое имя"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "New Path"
 msgid "New Path"
 msgstr "Новый путь"
 msgstr "Новый путь"
 
 
@@ -2653,6 +2681,11 @@ msgstr "Путь для Nginx Error Log"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr "Nginx не работает"
 msgstr "Nginx не работает"
 
 
+#: src/constants/errors/docker.ts:9
+#, fuzzy
+msgid "Nginx is not running in another container"
+msgstr "Nginx не работает"
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 #, fuzzy
 #, fuzzy
 msgid "Nginx is running"
 msgid "Nginx is running"
@@ -2983,11 +3016,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr "Код OTP или восстановления пуст"
 msgstr "Код OTP или восстановления пуст"
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "Перезаписать"
 msgstr "Перезаписать"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "Перезаписать существующий файл"
 msgstr "Перезаписать существующий файл"
 
 
@@ -3035,7 +3068,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "Путь"
 msgstr "Путь"
@@ -3134,7 +3167,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "Пожалуйста, введите имя файла"
 msgstr "Пожалуйста, введите имя файла"
 
 
@@ -3380,6 +3413,11 @@ msgstr "Перегрузить"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Перезагружается nginx"
 msgstr "Перезагружается nginx"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "Не удалось включить %{msg}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3670,7 +3708,7 @@ msgstr "Выполняется"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4517,7 +4555,7 @@ msgstr "Успешно обновлено"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4811,6 +4849,9 @@ msgstr "Ваши старые коды больше не будут работа
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr ""
 msgstr ""
 
 
+#~ msgid "Format error %{msg}"
+#~ msgstr "Ошибка формата %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr ""
 #~ msgstr ""
 #~ "Не удалось сохранить, обнаружены синтаксические ошибки в конфигурации."
 #~ "Не удалось сохранить, обнаружены синтаксические ошибки в конфигурации."

+ 62 - 21
app/src/language/tr_TR/app.po

@@ -80,7 +80,7 @@ msgid "Add a passkey"
 msgstr "Geçiş anahtarı ekleme"
 msgstr "Geçiş anahtarı ekleme"
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "Yapılandırma Ekle"
 msgstr "Yapılandırma Ekle"
 
 
@@ -297,7 +297,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -351,7 +351,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "Temel bilgiler"
 msgstr "Temel bilgiler"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -582,7 +582,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] "Değişen Sertifika"
 msgstr[0] "Değişen Sertifika"
 msgstr[1] "Değişen Sertifikalar"
 msgstr[1] "Değişen Sertifikalar"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "Değişen Dosya Yolu"
 msgstr "Değişen Dosya Yolu"
 
 
@@ -695,6 +695,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "Komut"
 msgstr "Komut"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -775,6 +779,10 @@ msgstr "Bağlantı kesildi, lütfen sayfayı yenileyin."
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1011,7 +1019,7 @@ msgstr "Başarıyla silindi"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "Yayınla"
 msgstr "Yayınla"
 
 
@@ -1225,6 +1233,10 @@ msgstr "Bu sunucuyu kaldırmak istiyor musunuz?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "Bu upstream'i kaldırmak istiyor musunuz?"
 msgstr "Bu upstream'i kaldırmak istiyor musunuz?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1287,7 +1299,7 @@ msgstr "Düzenle %{n}"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "Düzenle %{n}"
 msgstr "Düzenle %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "Yapılandırmayı Düzenle"
 msgstr "Yapılandırmayı Düzenle"
 
 
@@ -1515,6 +1527,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Sertifika alınamadı"
 msgstr "Sertifika alınamadı"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "Etkinleştirilemedi %{msg}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr ""
 msgstr ""
@@ -1699,6 +1716,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "Etkinleştirilemedi %{msg}"
 msgstr "Etkinleştirilemedi %{msg}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "Etkinleştirilemedi %{msg}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1728,6 +1750,11 @@ msgstr "Sertifika bilgileri alınamadı"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "Sertifika bilgileri alınamadı"
 msgstr "Sertifika bilgileri alınamadı"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "Etkinleştirilemedi %{msg}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1769,6 +1796,11 @@ msgstr ""
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "Etkinleştirilemedi %{msg}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1855,14 +1887,10 @@ msgstr "Çinli kullanıcılar için: https://mirror.ghproxy.com/"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "Kopyalama başarısız oldu"
 msgstr "Kopyalama başarısız oldu"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "Kodu Biçimlendir"
 msgstr "Kodu Biçimlendir"
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr "Biçimlendirme hatası %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr "Başarıyla biçimlendirildi"
 msgstr "Başarıyla biçimlendirildi"
@@ -1937,7 +1965,7 @@ msgstr "Gizle"
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 #, fuzzy
 #, fuzzy
@@ -2119,7 +2147,7 @@ msgid "Invalid file path: {0}"
 msgstr "Geçersiz dosya adı"
 msgstr "Geçersiz dosya adı"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "Geçersiz dosya adı"
 msgstr "Geçersiz dosya adı"
 
 
@@ -2559,7 +2587,7 @@ msgstr "Çok Hatlı Direktif"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2608,7 +2636,7 @@ msgstr "Yükle"
 msgid "New name"
 msgid "New name"
 msgstr "Yeni Ad"
 msgstr "Yeni Ad"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "New Path"
 msgid "New Path"
 msgstr "Yeni Yol"
 msgstr "Yeni Yol"
@@ -2719,6 +2747,11 @@ msgstr "Nginx Hata Günlüğü Yolu"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr "Nginx çalışmıyor"
 msgstr "Nginx çalışmıyor"
 
 
+#: src/constants/errors/docker.ts:9
+#, fuzzy
+msgid "Nginx is not running in another container"
+msgstr "Nginx çalışmıyor"
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 #, fuzzy
 #, fuzzy
 msgid "Nginx is running"
 msgid "Nginx is running"
@@ -3074,12 +3107,12 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr "Kurtarma kodunu kullanın"
 msgstr "Kurtarma kodunu kullanın"
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 #, fuzzy
 #, fuzzy
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "Üzerine yaz"
 msgstr "Üzerine yaz"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 #, fuzzy
 #, fuzzy
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "Mevcut dosyanın üzerine yaz"
 msgstr "Mevcut dosyanın üzerine yaz"
@@ -3136,7 +3169,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 #, fuzzy
 #, fuzzy
 msgid "Path"
 msgid "Path"
@@ -3245,7 +3278,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 #, fuzzy
 #, fuzzy
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "Lütfen bir dosya adı girin"
 msgstr "Lütfen bir dosya adı girin"
@@ -3522,6 +3555,11 @@ msgstr "Tekrar yükle"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Nginx'i yeniden yükleme"
 msgstr "Nginx'i yeniden yükleme"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "Etkinleştirilemedi %{msg}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3843,7 +3881,7 @@ msgstr "Çalışıyor"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4768,7 +4806,7 @@ msgstr "Güncellendi"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -5098,6 +5136,9 @@ msgstr ""
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr "Geçiş anahtarlarınız"
 msgstr "Geçiş anahtarlarınız"
 
 
+#~ msgid "Format error %{msg}"
+#~ msgstr "Biçimlendirme hatası %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr "Kaydedilemedi, yapılandırmada sözdizimi hatası(ları) tespit edildi."
 #~ msgstr "Kaydedilemedi, yapılandırmada sözdizimi hatası(ları) tespit edildi."
 
 

+ 53 - 21
app/src/language/uk_UA/app.po

@@ -80,7 +80,7 @@ msgid "Add a passkey"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "Додати конфігурацію"
 msgstr "Додати конфігурацію"
 
 
@@ -296,7 +296,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -347,7 +347,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -566,7 +566,7 @@ msgstr[0] ""
 msgstr[1] ""
 msgstr[1] ""
 msgstr[2] ""
 msgstr[2] ""
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr ""
 msgstr ""
 
 
@@ -678,6 +678,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -753,6 +757,10 @@ msgstr ""
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -971,7 +979,7 @@ msgstr ""
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr ""
 msgstr ""
 
 
@@ -1158,6 +1166,10 @@ msgstr ""
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 msgid "Document"
 msgid "Document"
@@ -1214,7 +1226,7 @@ msgstr ""
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr ""
 msgstr ""
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr ""
 msgstr ""
 
 
@@ -1415,6 +1427,10 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:4
+msgid "Failed to attach to exec instance: {0}"
+msgstr ""
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr ""
 msgstr ""
@@ -1575,6 +1591,10 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:3
+msgid "Failed to exec command: {0}"
+msgstr ""
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
 msgstr ""
 msgstr ""
@@ -1599,6 +1619,10 @@ msgstr ""
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:8
+msgid "Failed to inspect container: {0}"
+msgstr ""
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 msgid "Failed to load history records"
 msgid "Failed to load history records"
 msgstr ""
 msgstr ""
@@ -1635,6 +1659,10 @@ msgstr ""
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:5
+msgid "Failed to read output: {0}"
+msgstr ""
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
 msgstr ""
 msgstr ""
@@ -1714,14 +1742,10 @@ msgstr ""
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr ""
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr ""
 msgstr ""
@@ -1792,7 +1816,7 @@ msgstr ""
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 msgid "History"
 msgid "History"
@@ -1959,7 +1983,7 @@ msgid "Invalid file path: {0}"
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr ""
 msgstr ""
 
 
@@ -2358,7 +2382,7 @@ msgstr ""
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2400,7 +2424,7 @@ msgstr ""
 msgid "New name"
 msgid "New name"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "New Path"
 msgid "New Path"
 msgstr ""
 msgstr ""
 
 
@@ -2496,6 +2520,10 @@ msgstr ""
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:9
+msgid "Nginx is not running in another container"
+msgstr ""
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 msgid "Nginx is running"
 msgid "Nginx is running"
 msgstr ""
 msgstr ""
@@ -2807,11 +2835,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr ""
 msgstr ""
 
 
@@ -2857,7 +2885,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr ""
 msgstr ""
@@ -2947,7 +2975,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr ""
 msgstr ""
 
 
@@ -3175,6 +3203,10 @@ msgstr ""
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/nginx.ts:3
+msgid "Reload nginx failed: {0}"
+msgstr ""
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr ""
 msgstr ""
@@ -3441,7 +3473,7 @@ msgstr ""
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4216,7 +4248,7 @@ msgstr ""
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38

+ 62 - 22
app/src/language/vi_VN/app.po

@@ -77,7 +77,7 @@ msgid "Add a passkey"
 msgstr ""
 msgstr ""
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 #, fuzzy
 #, fuzzy
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "Sửa cấu hình"
 msgstr "Sửa cấu hình"
@@ -312,7 +312,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr ""
 msgstr ""
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -367,7 +367,7 @@ msgstr ""
 msgid "Base information"
 msgid "Base information"
 msgstr "Thông tin"
 msgstr "Thông tin"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #, fuzzy
 #, fuzzy
@@ -606,7 +606,7 @@ msgid_plural "Changed Certificates"
 msgstr[0] "Thay đổi chứng chỉ"
 msgstr[0] "Thay đổi chứng chỉ"
 msgstr[1] "Thay đổi chứng chỉ"
 msgstr[1] "Thay đổi chứng chỉ"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "Thay đổi chứng chỉ"
 msgstr "Thay đổi chứng chỉ"
@@ -721,6 +721,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "Bình luận"
 msgstr "Bình luận"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -801,6 +805,10 @@ msgstr ""
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -1038,7 +1046,7 @@ msgstr "Đã xoá thành công"
 msgid "Demo"
 msgid "Demo"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "Triển khai"
 msgstr "Triển khai"
 
 
@@ -1246,6 +1254,10 @@ msgstr "Bạn muốn xóa máy chủ này ?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "Bạn muốn xóa máy chủ này ?"
 msgstr "Bạn muốn xóa máy chủ này ?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #, fuzzy
 #, fuzzy
@@ -1306,7 +1318,7 @@ msgstr "Sửa %{n}"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "Sửa %{n}"
 msgstr "Sửa %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "Sửa cấu hình"
 msgstr "Sửa cấu hình"
 
 
@@ -1531,6 +1543,11 @@ msgstr ""
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "Nhận chứng chỉ"
 msgstr "Nhận chứng chỉ"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "Không thể bật %{msg}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr ""
 msgstr ""
@@ -1715,6 +1732,11 @@ msgstr ""
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "Không thể bật %{msg}"
 msgstr "Không thể bật %{msg}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "Không thể bật %{msg}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 #, fuzzy
 #, fuzzy
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
@@ -1744,6 +1766,11 @@ msgstr "Không thể truy xuất thông tin chứng chỉ"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "Không thể truy xuất thông tin chứng chỉ"
 msgstr "Không thể truy xuất thông tin chứng chỉ"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "Không thể bật %{msg}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #, fuzzy
 #, fuzzy
 msgid "Failed to load history records"
 msgid "Failed to load history records"
@@ -1785,6 +1812,11 @@ msgstr ""
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "Không thể bật %{msg}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 #, fuzzy
 #, fuzzy
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
@@ -1870,15 +1902,10 @@ msgstr "Người dùng Trung Quốc: https://mirror.ghproxy.com/"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "Nhân bản thất bại"
 msgstr "Nhân bản thất bại"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "Định dạng code"
 msgstr "Định dạng code"
 
 
-#: src/views/config/ConfigEditor.vue:218
-#, fuzzy
-msgid "Format error %{msg}"
-msgstr "Lưu lỗi %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 #, fuzzy
 #, fuzzy
 msgid "Format successfully"
 msgid "Format successfully"
@@ -1954,7 +1981,7 @@ msgstr ""
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 #, fuzzy
 #, fuzzy
@@ -2128,7 +2155,7 @@ msgid "Invalid file path: {0}"
 msgstr "E-mail không chính xác!"
 msgstr "E-mail không chính xác!"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 #, fuzzy
 #, fuzzy
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "E-mail không chính xác!"
 msgstr "E-mail không chính xác!"
@@ -2562,7 +2589,7 @@ msgstr "Single Directive"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2606,7 +2633,7 @@ msgstr "Cài đặt"
 msgid "New name"
 msgid "New name"
 msgstr "Username"
 msgstr "Username"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 #, fuzzy
 #, fuzzy
 msgid "New Path"
 msgid "New Path"
 msgstr "Đường dẫn"
 msgstr "Đường dẫn"
@@ -2709,6 +2736,10 @@ msgstr "Vị trí lưu log lỗi (Error log) của Nginx"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr ""
 msgstr ""
 
 
+#: src/constants/errors/docker.ts:9
+msgid "Nginx is not running in another container"
+msgstr ""
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 msgid "Nginx is running"
 msgid "Nginx is running"
 msgstr ""
 msgstr ""
@@ -3039,11 +3070,11 @@ msgstr ""
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "Ghi đè"
 msgstr "Ghi đè"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "Ghi đè tập tin đã tồn tại"
 msgstr "Ghi đè tập tin đã tồn tại"
 
 
@@ -3091,7 +3122,7 @@ msgstr ""
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "Đường dẫn"
 msgstr "Đường dẫn"
@@ -3185,7 +3216,7 @@ msgid ""
 msgstr ""
 msgstr ""
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 #, fuzzy
 #, fuzzy
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "Vui lòng nhập username!"
 msgstr "Vui lòng nhập username!"
@@ -3431,6 +3462,11 @@ msgstr "Tải lại"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "Tải lại nginx"
 msgstr "Tải lại nginx"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "Không thể bật %{msg}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 #, fuzzy
 #, fuzzy
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
@@ -3736,7 +3772,7 @@ msgstr "Running"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4566,7 +4602,7 @@ msgstr "Cập nhật thành công"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4866,6 +4902,10 @@ msgstr ""
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr ""
 msgstr ""
 
 
+#, fuzzy
+#~ msgid "Format error %{msg}"
+#~ msgstr "Lưu lỗi %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr "Không lưu được, đã phát hiện thấy (các) lỗi cú pháp trong cấu hình."
 #~ msgstr "Không lưu được, đã phát hiện thấy (các) lỗi cú pháp trong cấu hình."
 
 

+ 62 - 21
app/src/language/zh_CN/app.po

@@ -81,7 +81,7 @@ msgid "Add a passkey"
 msgstr "添加 Passkey"
 msgstr "添加 Passkey"
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "添加配置"
 msgstr "添加配置"
 
 
@@ -294,7 +294,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr "自动索引站点和 Stream 的配置文件。"
 msgstr "自动索引站点和 Stream 的配置文件。"
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -345,7 +345,7 @@ msgstr "Bark"
 msgid "Base information"
 msgid "Base information"
 msgstr "基本信息"
 msgstr "基本信息"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -562,7 +562,7 @@ msgid "Changed Certificate"
 msgid_plural "Changed Certificates"
 msgid_plural "Changed Certificates"
 msgstr[0] "变更证书"
 msgstr[0] "变更证书"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "变更后的路径"
 msgstr "变更后的路径"
 
 
@@ -677,6 +677,10 @@ msgstr "代码补全模型"
 msgid "Command"
 msgid "Command"
 msgstr "命令"
 msgstr "命令"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -752,6 +756,10 @@ msgstr "连接中断,请刷新页面。"
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr "连接超时时间"
 msgstr "连接超时时间"
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -971,7 +979,7 @@ msgstr "删除成功"
 msgid "Demo"
 msgid "Demo"
 msgstr "Demo"
 msgstr "Demo"
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "部署"
 msgstr "部署"
 
 
@@ -1158,6 +1166,10 @@ msgstr "你想删除这个服务器吗?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "你想删除这个 Upstream 吗?"
 msgstr "你想删除这个 Upstream 吗?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 msgid "Document"
 msgid "Document"
@@ -1214,7 +1226,7 @@ msgstr "编辑"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "编辑 %{n}"
 msgstr "编辑 %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "编辑配置"
 msgstr "编辑配置"
 
 
@@ -1415,6 +1427,11 @@ msgstr "外部通知"
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "获取证书失败"
 msgstr "获取证书失败"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "解压缩失败:{0}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr "备份 Nginx 配置文件失败:{0}"
 msgstr "备份 Nginx 配置文件失败:{0}"
@@ -1575,6 +1592,11 @@ msgstr "加密 Nginx UI 目录失败:{0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "符号链接解析失败:{0}"
 msgstr "符号链接解析失败:{0}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "读取文件失败:{0}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
 msgstr "解压缩失败:{0}"
 msgstr "解压缩失败:{0}"
@@ -1599,6 +1621,11 @@ msgstr "获取 Nginx 性能参数失败"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "获取性能数据失败"
 msgstr "获取性能数据失败"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "复制文件内容失败:{0}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 msgid "Failed to load history records"
 msgid "Failed to load history records"
 msgstr "加载历史记录失败"
 msgstr "加载历史记录失败"
@@ -1635,6 +1662,11 @@ msgstr "读取哈希信息文件失败:{0}"
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr "读取 nginx.conf 失败"
 msgstr "读取 nginx.conf 失败"
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "读取文件失败:{0}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
 msgstr "读取符号链接失败:{0}"
 msgstr "读取符号链接失败:{0}"
@@ -1714,14 +1746,10 @@ msgstr "中国用户:https://mirror.ghproxy.com/"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "表单解析失败"
 msgstr "表单解析失败"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "代码格式化"
 msgstr "代码格式化"
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr "保存错误 %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr "格式化成功"
 msgstr "格式化成功"
@@ -1792,7 +1820,7 @@ msgstr "隐藏"
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr "更高的值意味着更好的连接再利用"
 msgstr "更高的值意味着更好的连接再利用"
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 msgid "History"
 msgid "History"
@@ -1962,7 +1990,7 @@ msgid "Invalid file path: {0}"
 msgstr "文件路径无效:{0}"
 msgstr "文件路径无效:{0}"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "文件名无效"
 msgstr "文件名无效"
 
 
@@ -2368,7 +2396,7 @@ msgstr "多行指令"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2410,7 +2438,7 @@ msgstr "新安装"
 msgid "New name"
 msgid "New name"
 msgstr "新名称"
 msgstr "新名称"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "New Path"
 msgid "New Path"
 msgstr "新路径"
 msgstr "新路径"
 
 
@@ -2506,6 +2534,11 @@ msgstr "Nginx 错误日志路径"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr "Nginx 未启动"
 msgstr "Nginx 未启动"
 
 
+#: src/constants/errors/docker.ts:9
+#, fuzzy
+msgid "Nginx is not running in another container"
+msgstr "Nginx 未启动"
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 msgid "Nginx is running"
 msgid "Nginx is running"
 msgstr "Nginx 正在运行"
 msgstr "Nginx 正在运行"
@@ -2817,11 +2850,11 @@ msgstr "其他"
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr "OTP 或恢复代码为空"
 msgstr "OTP 或恢复代码为空"
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "覆盖"
 msgstr "覆盖"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "覆盖现有文件"
 msgstr "覆盖现有文件"
 
 
@@ -2869,7 +2902,7 @@ msgstr "密码长度不能超过 20 个字符"
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "路径"
 msgstr "路径"
@@ -2961,7 +2994,7 @@ msgid ""
 msgstr "请立即在偏好设置中生成新的恢复码,以防止无法访问您的账户。"
 msgstr "请立即在偏好设置中生成新的恢复码,以防止无法访问您的账户。"
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "请输入文件名"
 msgstr "请输入文件名"
 
 
@@ -3191,6 +3224,11 @@ msgstr "重载"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "重载 Nginx"
 msgstr "重载 Nginx"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "Nginx 重载失败:{0}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "在 %{node} 上重载 Nginx 失败,响应:%{resp}"
 msgstr "在 %{node} 上重载 Nginx 失败,响应:%{resp}"
@@ -3459,7 +3497,7 @@ msgstr "运行中"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4252,7 +4290,7 @@ msgstr "更新成功"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4545,6 +4583,9 @@ msgstr "您的旧代码将不再有效。"
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr "你的 Passkeys"
 msgstr "你的 Passkeys"
 
 
+#~ msgid "Format error %{msg}"
+#~ msgstr "保存错误 %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr "保存失败,在配置中检测到语法错误。"
 #~ msgstr "保存失败,在配置中检测到语法错误。"
 
 

+ 62 - 21
app/src/language/zh_TW/app.po

@@ -85,7 +85,7 @@ msgid "Add a passkey"
 msgstr "新增通行金鑰"
 msgstr "新增通行金鑰"
 
 
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
 #: src/routes/modules/config.ts:20 src/views/config/ConfigEditor.vue:171
-#: src/views/config/ConfigEditor.vue:246
+#: src/views/config/ConfigEditor.vue:244
 msgid "Add Configuration"
 msgid "Add Configuration"
 msgstr "新增設定"
 msgstr "新增設定"
 
 
@@ -298,7 +298,7 @@ msgid "Automatically indexed from site and stream configurations."
 msgstr "自動從網站和串流設定中索引。"
 msgstr "自動從網站和串流設定中索引。"
 
 
 #: src/views/certificate/components/CertificateEditor.vue:259
 #: src/views/certificate/components/CertificateEditor.vue:259
-#: src/views/config/ConfigEditor.vue:268 src/views/config/ConfigList.vue:112
+#: src/views/config/ConfigEditor.vue:266 src/views/config/ConfigList.vue:112
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/config/ConfigList.vue:195 src/views/nginx_log/NginxLog.vue:173
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:150
 #: src/views/stream/components/StreamEditor.vue:106
 #: src/views/stream/components/StreamEditor.vue:106
@@ -349,7 +349,7 @@ msgstr "Bark"
 msgid "Base information"
 msgid "Base information"
 msgstr "基本資訊"
 msgstr "基本資訊"
 
 
-#: src/views/config/ConfigEditor.vue:296
+#: src/views/config/ConfigEditor.vue:294
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/site/site_edit/components/RightPanel/RightPanel.vue:30
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 #: src/views/stream/components/RightPanel/RightPanel.vue:19
 msgid "Basic"
 msgid "Basic"
@@ -566,7 +566,7 @@ msgid "Changed Certificate"
 msgid_plural "Changed Certificates"
 msgid_plural "Changed Certificates"
 msgstr[0] "變更後憑證"
 msgstr[0] "變更後憑證"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "Changed Path"
 msgid "Changed Path"
 msgstr "變更後路徑"
 msgstr "變更後路徑"
 
 
@@ -685,6 +685,10 @@ msgstr ""
 msgid "Command"
 msgid "Command"
 msgstr "命令"
 msgstr "命令"
 
 
+#: src/constants/errors/docker.ts:6
+msgid "Command exited with unexpected exit code: {0}, error: {1}"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:115
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:104
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
 #: src/components/NgxConfigEditor/LocationEditor.vue:135
@@ -761,6 +765,10 @@ msgstr "連線中斷,請重新整理此頁面。"
 msgid "Connection timeout period"
 msgid "Connection timeout period"
 msgstr "連線逾時時間"
 msgstr "連線逾時時間"
 
 
+#: src/constants/errors/docker.ts:7
+msgid "Container status unknown"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/directive/DirectiveEditorItem.vue:120
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:116
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
 #: src/components/NgxConfigEditor/LocationEditor.vue:144
@@ -980,7 +988,7 @@ msgstr "刪除成功"
 msgid "Demo"
 msgid "Demo"
 msgstr "演示"
 msgstr "演示"
 
 
-#: src/views/config/ConfigEditor.vue:340
+#: src/views/config/ConfigEditor.vue:338
 msgid "Deploy"
 msgid "Deploy"
 msgstr "部署"
 msgstr "部署"
 
 
@@ -1168,6 +1176,10 @@ msgstr "您要移除此伺服器嗎?"
 msgid "Do you want to remove this upstream?"
 msgid "Do you want to remove this upstream?"
 msgstr "您要移除這個 Upstream 嗎?"
 msgstr "您要移除這個 Upstream 嗎?"
 
 
+#: src/constants/errors/docker.ts:2
+msgid "Docker client not initialized"
+msgstr ""
+
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveAdd.vue:88
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 #: src/components/NgxConfigEditor/directive/DirectiveDocuments.vue:16
 msgid "Document"
 msgid "Document"
@@ -1224,7 +1236,7 @@ msgstr "編輯"
 msgid "Edit %{n}"
 msgid "Edit %{n}"
 msgstr "編輯 %{n}"
 msgstr "編輯 %{n}"
 
 
-#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:246
+#: src/routes/modules/config.ts:30 src/views/config/ConfigEditor.vue:244
 msgid "Edit Configuration"
 msgid "Edit Configuration"
 msgstr "編輯設定"
 msgstr "編輯設定"
 
 
@@ -1425,6 +1437,11 @@ msgstr "外部通知"
 msgid "Fail to obtain certificate"
 msgid "Fail to obtain certificate"
 msgstr "取得憑證失敗"
 msgstr "取得憑證失敗"
 
 
+#: src/constants/errors/docker.ts:4
+#, fuzzy
+msgid "Failed to attach to exec instance: {0}"
+msgstr "無法提取存檔:{0}"
+
 #: src/constants/errors/backup.ts:5
 #: src/constants/errors/backup.ts:5
 msgid "Failed to backup Nginx config files: {0}"
 msgid "Failed to backup Nginx config files: {0}"
 msgstr "備份 Nginx 設定檔案失敗:{0}"
 msgstr "備份 Nginx 設定檔案失敗:{0}"
@@ -1585,6 +1602,11 @@ msgstr "加密 Nginx UI 目錄失敗:{0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgid "Failed to evaluate symbolic links: {0}"
 msgstr "無法評估符號連結:{0}"
 msgstr "無法評估符號連結:{0}"
 
 
+#: src/constants/errors/docker.ts:3
+#, fuzzy
+msgid "Failed to exec command: {0}"
+msgstr "讀取檔案失敗:{0}"
+
 #: src/constants/errors/backup.ts:35
 #: src/constants/errors/backup.ts:35
 msgid "Failed to extract archive: {0}"
 msgid "Failed to extract archive: {0}"
 msgstr "無法提取存檔:{0}"
 msgstr "無法提取存檔:{0}"
@@ -1609,6 +1631,11 @@ msgstr "無法取得 Nginx 效能設定"
 msgid "Failed to get performance data"
 msgid "Failed to get performance data"
 msgstr "無法取得效能資料"
 msgstr "無法取得效能資料"
 
 
+#: src/constants/errors/docker.ts:8
+#, fuzzy
+msgid "Failed to inspect container: {0}"
+msgstr "複製檔案內容失敗:{0}"
+
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 #: src/components/ConfigHistory/ConfigHistory.vue:77
 msgid "Failed to load history records"
 msgid "Failed to load history records"
 msgstr "無法載入歷史記錄"
 msgstr "無法載入歷史記錄"
@@ -1645,6 +1672,11 @@ msgstr "無法讀取雜湊資訊檔案:{0}"
 msgid "Failed to read nginx.conf"
 msgid "Failed to read nginx.conf"
 msgstr "讀取 nginx.conf 失敗"
 msgstr "讀取 nginx.conf 失敗"
 
 
+#: src/constants/errors/docker.ts:5
+#, fuzzy
+msgid "Failed to read output: {0}"
+msgstr "讀取檔案失敗:{0}"
+
 #: src/constants/errors/backup.ts:21
 #: src/constants/errors/backup.ts:21
 msgid "Failed to read symlink: {0}"
 msgid "Failed to read symlink: {0}"
 msgstr "讀取符號連結失敗:{0}"
 msgstr "讀取符號連結失敗:{0}"
@@ -1724,14 +1756,10 @@ msgstr "中國使用者:https://mirror.ghproxy.com/"
 msgid "Form parse failed"
 msgid "Form parse failed"
 msgstr "表單解析失敗"
 msgstr "表單解析失敗"
 
 
-#: src/views/config/ConfigEditor.vue:271
+#: src/views/config/ConfigEditor.vue:269
 msgid "Format Code"
 msgid "Format Code"
 msgstr "格式化代碼"
 msgstr "格式化代碼"
 
 
-#: src/views/config/ConfigEditor.vue:218
-msgid "Format error %{msg}"
-msgstr "格式錯誤 %{msg}"
-
 #: src/views/config/ConfigEditor.vue:216
 #: src/views/config/ConfigEditor.vue:216
 msgid "Format successfully"
 msgid "Format successfully"
 msgstr "成功格式化"
 msgstr "成功格式化"
@@ -1802,7 +1830,7 @@ msgstr "隱藏"
 msgid "Higher value means better connection reuse"
 msgid "Higher value means better connection reuse"
 msgstr ""
 msgstr ""
 
 
-#: src/views/config/ConfigEditor.vue:256
+#: src/views/config/ConfigEditor.vue:254
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/site/site_edit/components/SiteEditor/SiteEditor.vue:81
 #: src/views/stream/components/StreamEditor.vue:43
 #: src/views/stream/components/StreamEditor.vue:43
 msgid "History"
 msgid "History"
@@ -1972,7 +2000,7 @@ msgid "Invalid file path: {0}"
 msgstr "無效的檔案路徑:{0}"
 msgstr "無效的檔案路徑:{0}"
 
 
 #: src/views/config/components/Rename.vue:66
 #: src/views/config/components/Rename.vue:66
-#: src/views/config/ConfigEditor.vue:305
+#: src/views/config/ConfigEditor.vue:303
 msgid "Invalid filename"
 msgid "Invalid filename"
 msgstr "無效的檔案名"
 msgstr "無效的檔案名"
 
 
@@ -2379,7 +2407,7 @@ msgstr "多行指令"
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/components/CertificateEditor.vue:162
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/certificate/DNSCredential.vue:11
 #: src/views/config/components/Mkdir.vue:64
 #: src/views/config/components/Mkdir.vue:64
-#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:311
+#: src/views/config/configColumns.tsx:7 src/views/config/ConfigEditor.vue:309
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/group/columns.ts:8
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/environments/list/envColumns.tsx:9
 #: src/views/nginx_log/NginxLogList.vue:33
 #: src/views/nginx_log/NginxLogList.vue:33
@@ -2421,7 +2449,7 @@ msgstr "新安裝"
 msgid "New name"
 msgid "New name"
 msgstr "新名稱"
 msgstr "新名稱"
 
 
-#: src/views/config/ConfigEditor.vue:324
+#: src/views/config/ConfigEditor.vue:322
 msgid "New Path"
 msgid "New Path"
 msgstr "新路徑"
 msgstr "新路徑"
 
 
@@ -2519,6 +2547,11 @@ msgstr "Nginx 錯誤日誌路徑"
 msgid "Nginx is not running"
 msgid "Nginx is not running"
 msgstr "Nginx 未執行"
 msgstr "Nginx 未執行"
 
 
+#: src/constants/errors/docker.ts:9
+#, fuzzy
+msgid "Nginx is not running in another container"
+msgstr "Nginx 未執行"
+
 #: src/views/dashboard/NginxDashBoard.vue:112
 #: src/views/dashboard/NginxDashBoard.vue:112
 msgid "Nginx is running"
 msgid "Nginx is running"
 msgstr "Nginx 執行中"
 msgstr "Nginx 執行中"
@@ -2832,11 +2865,11 @@ msgstr "其他"
 msgid "Otp or recovery code empty"
 msgid "Otp or recovery code empty"
 msgstr "OTP 或復原碼為空"
 msgstr "OTP 或復原碼為空"
 
 
-#: src/views/config/ConfigEditor.vue:349
+#: src/views/config/ConfigEditor.vue:347
 msgid "Overwrite"
 msgid "Overwrite"
 msgstr "覆寫"
 msgstr "覆寫"
 
 
-#: src/views/config/ConfigEditor.vue:353
+#: src/views/config/ConfigEditor.vue:351
 msgid "Overwrite exist file"
 msgid "Overwrite exist file"
 msgstr "覆寫現有檔案"
 msgstr "覆寫現有檔案"
 
 
@@ -2884,7 +2917,7 @@ msgstr "密碼長度不能超過 20 個字元"
 
 
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:110
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
 #: src/components/NgxConfigEditor/LocationEditor.vue:138
-#: src/views/config/ConfigEditor.vue:318
+#: src/views/config/ConfigEditor.vue:316
 #: src/views/nginx_log/NginxLogList.vue:41
 #: src/views/nginx_log/NginxLogList.vue:41
 msgid "Path"
 msgid "Path"
 msgstr "路徑"
 msgstr "路徑"
@@ -2976,7 +3009,7 @@ msgid ""
 msgstr "請立即在偏好設定中產生新的恢復碼,以免無法存取您的賬戶。"
 msgstr "請立即在偏好設定中產生新的恢復碼,以免無法存取您的賬戶。"
 
 
 #: src/views/config/components/Rename.vue:65
 #: src/views/config/components/Rename.vue:65
-#: src/views/config/ConfigEditor.vue:304
+#: src/views/config/ConfigEditor.vue:302
 msgid "Please input a filename"
 msgid "Please input a filename"
 msgstr "請輸入檔案名稱"
 msgstr "請輸入檔案名稱"
 
 
@@ -3205,6 +3238,11 @@ msgstr "重新載入"
 msgid "Reload Nginx"
 msgid "Reload Nginx"
 msgstr "重新載入 Nginx"
 msgstr "重新載入 Nginx"
 
 
+#: src/constants/errors/nginx.ts:3
+#, fuzzy
+msgid "Reload nginx failed: {0}"
+msgstr "讀取檔案失敗:{0}"
+
 #: src/components/Notification/notifications.ts:10
 #: src/components/Notification/notifications.ts:10
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgid "Reload Nginx on %{node} failed, response: %{resp}"
 msgstr "在節點 %{node} 上重新載入 Nginx 失敗,回應:%{resp}"
 msgstr "在節點 %{node} 上重新載入 Nginx 失敗,回應:%{resp}"
@@ -3473,7 +3511,7 @@ msgstr "執行中"
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/components/StdDesign/StdDetail/StdDetail.vue:93
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/certificate/components/CertificateEditor.vue:266
 #: src/views/config/components/ConfigName.vue:59
 #: src/views/config/components/ConfigName.vue:59
-#: src/views/config/ConfigEditor.vue:277
+#: src/views/config/ConfigEditor.vue:275
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/components/Passkey.vue:130
 #: src/views/preference/Preference.vue:231
 #: src/views/preference/Preference.vue:231
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
 #: src/views/site/site_edit/components/ConfigName/ConfigName.vue:52
@@ -4266,7 +4304,7 @@ msgstr "更新成功"
 
 
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/ACMEUser.vue:88
 #: src/views/certificate/DNSCredential.vue:27
 #: src/views/certificate/DNSCredential.vue:27
-#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:331
+#: src/views/config/configColumns.tsx:36 src/views/config/ConfigEditor.vue:329
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/group/columns.ts:37
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/environments/list/envColumns.tsx:90
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
 #: src/views/site/site_edit/components/RightPanel/Basic.vue:38
@@ -4562,6 +4600,9 @@ msgstr "您的舊代碼將不再有效。"
 msgid "Your passkeys"
 msgid "Your passkeys"
 msgstr "您的通行金鑰"
 msgstr "您的通行金鑰"
 
 
+#~ msgid "Format error %{msg}"
+#~ msgstr "格式錯誤 %{msg}"
+
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgid "Failed to save, syntax error(s) was detected in the configuration."
 #~ msgstr "儲存失敗,在設定中偵測到語法錯誤。"
 #~ msgstr "儲存失敗,在設定中偵測到語法錯誤。"
 
 

+ 13 - 0
go.mod

@@ -9,6 +9,7 @@ require (
 	github.com/casdoor/casdoor-go-sdk v1.5.0
 	github.com/casdoor/casdoor-go-sdk v1.5.0
 	github.com/creack/pty v1.1.24
 	github.com/creack/pty v1.1.24
 	github.com/dgraph-io/ristretto/v2 v2.2.0
 	github.com/dgraph-io/ristretto/v2 v2.2.0
+	github.com/docker/docker v28.1.1+incompatible
 	github.com/dustin/go-humanize v1.0.1
 	github.com/dustin/go-humanize v1.0.1
 	github.com/elliotchance/orderedmap/v3 v3.1.0
 	github.com/elliotchance/orderedmap/v3 v3.1.0
 	github.com/fsnotify/fsnotify v1.9.0
 	github.com/fsnotify/fsnotify v1.9.0
@@ -75,6 +76,7 @@ require (
 	github.com/Azure/go-autorest/logger v0.2.2 // indirect
 	github.com/Azure/go-autorest/logger v0.2.2 // indirect
 	github.com/Azure/go-autorest/tracing v0.6.1 // indirect
 	github.com/Azure/go-autorest/tracing v0.6.1 // indirect
 	github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
 	github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
+	github.com/Microsoft/go-winio v0.4.14 // indirect
 	github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
 	github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
 	github.com/StackExchange/wmi v1.2.1 // indirect
 	github.com/StackExchange/wmi v1.2.1 // indirect
 	github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
 	github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
@@ -106,10 +108,14 @@ require (
 	github.com/civo/civogo v0.3.98 // indirect
 	github.com/civo/civogo v0.3.98 // indirect
 	github.com/cloudflare/cloudflare-go v0.115.0 // indirect
 	github.com/cloudflare/cloudflare-go v0.115.0 // indirect
 	github.com/cloudwego/base64x v0.1.5 // indirect
 	github.com/cloudwego/base64x v0.1.5 // indirect
+	github.com/containerd/log v0.1.0 // indirect
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/dimchansky/utfbom v1.1.1 // indirect
 	github.com/dimchansky/utfbom v1.1.1 // indirect
+	github.com/distribution/reference v0.6.0 // indirect
 	github.com/dnsimple/dnsimple-go v1.7.0 // indirect
 	github.com/dnsimple/dnsimple-go v1.7.0 // indirect
+	github.com/docker/go-connections v0.5.0 // indirect
+	github.com/docker/go-units v0.5.0 // indirect
 	github.com/ebitengine/purego v0.8.2 // indirect
 	github.com/ebitengine/purego v0.8.2 // indirect
 	github.com/exoscale/egoscale/v3 v3.1.14 // indirect
 	github.com/exoscale/egoscale/v3 v3.1.14 // indirect
 	github.com/fatih/color v1.18.0 // indirect
 	github.com/fatih/color v1.18.0 // indirect
@@ -184,8 +190,12 @@ require (
 	github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
 	github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
+	github.com/moby/docker-image-spec v1.3.1 // indirect
+	github.com/moby/sys/atomicwriter v0.1.0 // indirect
+	github.com/moby/term v0.5.2 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/morikuni/aec v1.0.0 // indirect
 	github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
 	github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
 	github.com/nrdcg/auroradns v1.1.0 // indirect
 	github.com/nrdcg/auroradns v1.1.0 // indirect
 	github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea // indirect
 	github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea // indirect
@@ -199,6 +209,8 @@ require (
 	github.com/nrdcg/nodion v0.1.0 // indirect
 	github.com/nrdcg/nodion v0.1.0 // indirect
 	github.com/nrdcg/porkbun v0.4.0 // indirect
 	github.com/nrdcg/porkbun v0.4.0 // indirect
 	github.com/nzdjb/go-metaname v1.0.0 // indirect
 	github.com/nzdjb/go-metaname v1.0.0 // indirect
+	github.com/opencontainers/go-digest v1.0.0 // indirect
+	github.com/opencontainers/image-spec v1.1.1 // indirect
 	github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
 	github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
 	github.com/oracle/oci-go-sdk/v65 v65.89.1 // indirect
 	github.com/oracle/oci-go-sdk/v65 v65.89.1 // indirect
 	github.com/ovh/go-ovh v1.7.0 // indirect
 	github.com/ovh/go-ovh v1.7.0 // indirect
@@ -257,6 +269,7 @@ require (
 	go.opentelemetry.io/auto/sdk v1.1.0 // indirect
 	go.opentelemetry.io/auto/sdk v1.1.0 // indirect
 	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
 	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
 	go.opentelemetry.io/otel v1.35.0 // indirect
 	go.opentelemetry.io/otel v1.35.0 // indirect
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect
 	go.opentelemetry.io/otel/metric v1.35.0 // indirect
 	go.opentelemetry.io/otel/metric v1.35.0 // indirect
 	go.opentelemetry.io/otel/trace v1.35.0 // indirect
 	go.opentelemetry.io/otel/trace v1.35.0 // indirect
 	go.uber.org/atomic v1.11.0 // indirect
 	go.uber.org/atomic v1.11.0 // indirect

+ 37 - 9
go.sum

@@ -632,6 +632,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourceg
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0/go.mod h1:wVEOJfGTj0oPAUGA1JuRAvz/lxXQsWW16axmHPP47Bk=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0/go.mod h1:wVEOJfGTj0oPAUGA1JuRAvz/lxXQsWW16axmHPP47Bk=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
+github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
 github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
 github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA=
 github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA=
@@ -675,6 +677,8 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXY
 github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
 github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
 github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
+github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 h1:xPMsUicZ3iosVPSIP7bW5EcGUzjiiMl1OYTe14y/R24=
 github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 h1:xPMsUicZ3iosVPSIP7bW5EcGUzjiiMl1OYTe14y/R24=
 github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
 github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks=
@@ -698,8 +702,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
-github.com/aliyun/alibaba-cloud-sdk-go v1.63.105 h1:Bj8SsBTGElGniuL83+VqfHnxZIPc7n+rzpwDZIB4rZg=
-github.com/aliyun/alibaba-cloud-sdk-go v1.63.105/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
 github.com/aliyun/alibaba-cloud-sdk-go v1.63.106 h1:+YPfQheppCKOPJxhWDmStF1UMJrxnA1iiwBH12t6Fa4=
 github.com/aliyun/alibaba-cloud-sdk-go v1.63.106 h1:+YPfQheppCKOPJxhWDmStF1UMJrxnA1iiwBH12t6Fa4=
 github.com/aliyun/alibaba-cloud-sdk-go v1.63.106/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
 github.com/aliyun/alibaba-cloud-sdk-go v1.63.106/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
 github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
@@ -790,7 +792,6 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
 github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -825,6 +826,8 @@ github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWH
 github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
 github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
+github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
+github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -853,8 +856,16 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
 github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
 github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
 github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
+github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
+github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
 github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j611ZY=
 github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j611ZY=
 github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8=
 github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8=
+github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I=
+github.com/docker/docker v28.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
+github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
@@ -912,8 +923,6 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
 github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
 github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
 github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
 github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
-github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
-github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
 github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
 github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
 github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
 github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
 github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
@@ -1168,9 +1177,12 @@ github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
 github.com/guregu/null/v6 v6.0.0 h1:N14VRS+4di81i1PXRiprbQJ9EM9gqBa0+KVMeS/QSjQ=
 github.com/guregu/null/v6 v6.0.0 h1:N14VRS+4di81i1PXRiprbQJ9EM9gqBa0+KVMeS/QSjQ=
 github.com/guregu/null/v6 v6.0.0/go.mod h1:hrMIhIfrOZeLPZhROSn149tpw2gHkidAqxoXNyeX3iQ=
 github.com/guregu/null/v6 v6.0.0/go.mod h1:hrMIhIfrOZeLPZhROSn149tpw2gHkidAqxoXNyeX3iQ=
 github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
 github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
@@ -1478,6 +1490,14 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
 github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
+github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
+github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
+github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
+github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
+github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
+github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -1486,6 +1506,8 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g=
 github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 h1:o6uBwrhM5C8Ll3MAAxrQxRHEu7FkapwTuI2WmL1rw4g=
@@ -1549,6 +1571,10 @@ github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5h
 github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
 github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
 github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
 github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
+github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
@@ -1770,8 +1796,6 @@ github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSW
 github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
 github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
 github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
 github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
-github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1145 h1:DETyir/MtG+GLOD0OatzjrQTTXRguFSJo1ZtPXtbIQw=
-github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1145/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1146 h1:PMhgU4BETyTiikegps6gDtLamNWUiLMEx4fv16UWspY=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1146 h1:PMhgU4BETyTiikegps6gDtLamNWUiLMEx4fv16UWspY=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1146/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1146/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 h1:kMIdSU5IvpOROh27ToVQ3hlm6ym3lCRs9tnGCOBoZqk=
 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 h1:kMIdSU5IvpOROh27ToVQ3hlm6ym3lCRs9tnGCOBoZqk=
@@ -1817,8 +1841,6 @@ github.com/urfave/cli/v3 v3.1.1 h1:bNnl8pFI5dxPOjeONvFCDFoECLQsceDG4ejahs4Jtxk=
 github.com/urfave/cli/v3 v3.1.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
 github.com/urfave/cli/v3 v3.1.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
 github.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4ulRMcQ=
 github.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4ulRMcQ=
 github.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q=
 github.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q=
-github.com/volcengine/volc-sdk-golang v1.0.203 h1:y4zZEjKp6nz3UK8Tb/qdz9tvB915KLO6nc1WNME0Zb8=
-github.com/volcengine/volc-sdk-golang v1.0.203/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
 github.com/volcengine/volc-sdk-golang v1.0.204 h1:Njid6coReHV2gWc3bsqWMQf+K8jveauzW8zEX08CTzI=
 github.com/volcengine/volc-sdk-golang v1.0.204 h1:Njid6coReHV2gWc3bsqWMQf+K8jveauzW8zEX08CTzI=
 github.com/volcengine/volc-sdk-golang v1.0.204/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
 github.com/volcengine/volc-sdk-golang v1.0.204/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
 github.com/vultr/govultr/v3 v3.19.1 h1:31rOP5Tz40AOc8h6Ws4ryzqAniUBffgRhy9uMG/EFvs=
 github.com/vultr/govultr/v3 v3.19.1 h1:31rOP5Tz40AOc8h6Ws4ryzqAniUBffgRhy9uMG/EFvs=
@@ -1881,6 +1903,10 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRND
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
 go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
 go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
 go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
 go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
 go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
 go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
 go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
 go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
 go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
 go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
@@ -1892,6 +1918,8 @@ go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
 go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
 go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
 go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
+go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
+go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=

+ 5 - 1
internal/config/save.go

@@ -45,7 +45,11 @@ func Save(absPath string, content string, cfg *model.Config) (err error) {
 		return
 		return
 	}
 	}
 
 
-	output := nginx.Reload()
+	output, err := nginx.Reload()
+	if err != nil {
+		return
+	} 
+
 	if nginx.GetLogLevel(output) >= nginx.Warn {
 	if nginx.GetLogLevel(output) >= nginx.Warn {
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 	}
 	}

+ 22 - 0
internal/docker/docker.go

@@ -0,0 +1,22 @@
+package docker
+
+import (
+	"context"
+
+	"github.com/docker/docker/client"
+)
+
+// Initialize Docker client from environment variables
+func initClient() (cli *client.Client, err error) {
+	cli, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
+	if err != nil {
+		return
+	}
+	// Optionally ping the server to ensure the connection is valid
+	_, err = cli.Ping(context.Background())
+	if err != nil {
+		return
+	}
+
+	return
+}

+ 15 - 0
internal/docker/errors.go

@@ -0,0 +1,15 @@
+package docker
+
+import "github.com/uozi-tech/cosy"
+
+var (
+	e                                    = cosy.NewErrorScope("docker")
+	ErrClientNotInitialized              = e.New(500001, "docker client not initialized")
+	ErrFailedToExec                      = e.New(500002, "failed to exec command: {0}")
+	ErrFailedToAttach                    = e.New(500003, "failed to attach to exec instance: {0}")
+	ErrReadOutput                        = e.New(500004, "failed to read output: {0}")
+	ErrExitUnexpected                    = e.New(500005, "command exited with unexpected exit code: {0}, error: {1}")
+	ErrContainerStatusUnknown            = e.New(500006, "container status unknown")
+	ErrInspectContainer                  = e.New(500007, "failed to inspect container: {0}")
+	ErrNginxNotRunningInAnotherContainer = e.New(500008, "nginx is not running in another container")
+)

+ 80 - 0
internal/docker/exec.go

@@ -0,0 +1,80 @@
+package docker
+
+import (
+	"bytes"
+	"context"
+	"io"
+	"strconv"
+
+	"github.com/0xJacky/Nginx-UI/settings"
+	"github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/pkg/stdcopy"
+	"github.com/uozi-tech/cosy"
+	"github.com/uozi-tech/cosy/logger"
+)
+
+// Exec executes a command in a specific container and returns the output.
+func Exec(ctx context.Context, command []string) (string, error) {
+	if !settings.NginxSettings.RunningInAnotherContainer() {
+		return "", ErrNginxNotRunningInAnotherContainer
+	}
+
+	cli, err := initClient()
+	if err != nil {
+		return "", cosy.WrapErrorWithParams(ErrClientNotInitialized, err.Error())
+	}
+	defer cli.Close()
+
+	execConfig := container.ExecOptions{
+		AttachStdout: true,
+		AttachStderr: true, // Also attach stderr to capture errors from the command
+		Cmd:          command,
+	}
+
+	// Create the exec instance
+	execCreateResp, err := cli.ContainerExecCreate(ctx, settings.NginxSettings.ContainerName, execConfig)
+	if err != nil {
+		return "", cosy.WrapErrorWithParams(ErrFailedToExec, err.Error())
+	}
+	execID := execCreateResp.ID
+
+	// Attach to the exec instance
+	hijackedResp, err := cli.ContainerExecAttach(ctx, execID, container.ExecAttachOptions{})
+	if err != nil {
+		return "", cosy.WrapErrorWithParams(ErrFailedToAttach, err.Error())
+	}
+	defer hijackedResp.Close()
+
+	// Read the output
+	var outBuf, errBuf bytes.Buffer
+	outputDone := make(chan error)
+
+	go func() {
+		// stdcopy.StdCopy demultiplexes the stream into two buffers
+		_, err = stdcopy.StdCopy(&outBuf, &errBuf, hijackedResp.Reader)
+		outputDone <- err
+	}()
+
+	select {
+	case err := <-outputDone:
+		if err != nil && err != io.EOF { // io.EOF is expected when the stream finishes
+			return "", cosy.WrapErrorWithParams(ErrReadOutput, err.Error())
+		}
+	case <-ctx.Done():
+		return "", cosy.WrapErrorWithParams(ErrReadOutput, ctx.Err().Error())
+	}
+
+	// Optionally inspect the exec process to check the exit code
+	execInspectResp, err := cli.ContainerExecInspect(ctx, execID)
+	logger.Debug("docker exec result", outBuf.String(), errBuf.String())
+
+	if err != nil {
+		return "", cosy.WrapErrorWithParams(ErrExitUnexpected, err.Error())
+	} else if execInspectResp.ExitCode != 0 {
+		// Command exited with a non-zero status code. Return stderr as part of the error.
+		return outBuf.String(), cosy.WrapErrorWithParams(ErrExitUnexpected, strconv.Itoa(execInspectResp.ExitCode), errBuf.String())
+	}
+
+	// Return stdout if successful
+	return outBuf.String(), nil
+}

+ 29 - 0
internal/docker/stat_path.go

@@ -0,0 +1,29 @@
+package docker
+
+import (
+	"context"
+
+	"github.com/0xJacky/Nginx-UI/settings"
+	"github.com/uozi-tech/cosy/logger"
+)
+
+// StatPath checks if a path exists in the container
+func StatPath(path string) bool {
+	if !settings.NginxSettings.RunningInAnotherContainer() {
+		return false
+	}
+
+	cli, err := initClient()
+	if err != nil {
+		return false
+	}
+	defer cli.Close()
+
+	_, err = cli.ContainerStatPath(context.Background(), settings.NginxSettings.ContainerName, path)
+	if err != nil {
+		logger.Error("Failed to stat path", "error", err)
+		return false
+	}
+
+	return true
+}

+ 58 - 0
internal/docker/status.go

@@ -0,0 +1,58 @@
+package docker
+
+import (
+	"context"
+
+	"github.com/docker/docker/client"
+	"github.com/uozi-tech/cosy"
+)
+
+type ContainerStatus int
+
+const (
+	ContainerStatusCreated ContainerStatus = iota
+	ContainerStatusRunning
+	ContainerStatusPaused
+	ContainerStatusRestarting
+	ContainerStatusRemoving
+	ContainerStatusExited
+	ContainerStatusDead
+	ContainerStatusUnknown
+	ContainerStatusNotFound
+)
+
+var (
+	containerStatusMap = map[string]ContainerStatus{
+		"created":    ContainerStatusCreated,
+		"running":    ContainerStatusRunning,
+		"paused":     ContainerStatusPaused,
+		"restarting": ContainerStatusRestarting,
+		"removing":   ContainerStatusRemoving,
+		"exited":     ContainerStatusExited,
+		"dead":       ContainerStatusDead,
+	}
+)
+
+// GetContainerStatus checks the status of a given container.
+func GetContainerStatus(ctx context.Context, containerID string) (ContainerStatus, error) {
+	cli, err := initClient()
+	if err != nil {
+		return ContainerStatusUnknown, cosy.WrapErrorWithParams(ErrClientNotInitialized, err.Error())
+	}
+	defer cli.Close()
+
+	containerJSON, err := cli.ContainerInspect(ctx, containerID)
+	if err != nil {
+		if client.IsErrNotFound(err) {
+			return ContainerStatusNotFound, nil // Container doesn't exist
+		}
+		return ContainerStatusUnknown, cosy.WrapErrorWithParams(ErrInspectContainer, err.Error())
+	}
+
+	// Can be one of "created", "running", "paused", "restarting", "removing", "exited", or "dead"
+	status, ok := containerStatusMap[containerJSON.State.Status]
+	if !ok {
+		return ContainerStatusUnknown, ErrContainerStatusUnknown
+	}
+	return status, nil
+}

+ 1 - 0
internal/nginx/errors.go

@@ -5,4 +5,5 @@ import "github.com/uozi-tech/cosy"
 var (
 var (
 	e             = cosy.NewErrorScope("nginx")
 	e             = cosy.NewErrorScope("nginx")
 	ErrBlockIsNil = e.New(50001, "block is nil")
 	ErrBlockIsNil = e.New(50001, "block is nil")
+	ErrReloadFailed = e.New(50002, "reload nginx failed: {0}")
 )
 )

+ 28 - 0
internal/nginx/exec.go

@@ -0,0 +1,28 @@
+package nginx
+
+import (
+	"context"
+	"os/exec"
+
+	"github.com/0xJacky/Nginx-UI/internal/docker"
+	"github.com/0xJacky/Nginx-UI/settings"
+)
+
+func execShell(cmd string) (stdOut string, stdErr error) {
+	return execCommand("/bin/sh", "-c", cmd)
+}
+
+func execCommand(name string, cmd ...string) (stdOut string, stdErr error) {
+	switch settings.NginxSettings.RunningInAnotherContainer() {
+	case true:
+		cmd = append([]string{name}, cmd...)
+		stdOut, stdErr = docker.Exec(context.Background(), cmd)
+	case false:
+		bytes, err := exec.Command(name, cmd...).CombinedOutput()
+		stdOut = string(bytes)
+		if err != nil {
+			stdErr = err
+		}
+	}
+	return
+}

+ 38 - 51
internal/nginx/nginx.go

@@ -2,46 +2,41 @@ package nginx
 
 
 import (
 import (
 	"os"
 	"os"
-	"os/exec"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"github.com/0xJacky/Nginx-UI/internal/docker"
 	"github.com/0xJacky/Nginx-UI/settings"
 	"github.com/0xJacky/Nginx-UI/settings"
 )
 )
 
 
 var (
 var (
 	mutex      sync.Mutex
 	mutex      sync.Mutex
-	lastOutput string
+	lastStdOut string
+	lastStdErr error
 )
 )
 
 
-func TestConf() (out string) {
+// TestConfig tests the nginx config
+func TestConfig() (stdOut string, stdErr error) {
 	mutex.Lock()
 	mutex.Lock()
 	defer mutex.Unlock()
 	defer mutex.Unlock()
 	if settings.NginxSettings.TestConfigCmd != "" {
 	if settings.NginxSettings.TestConfigCmd != "" {
-		out = execShell(settings.NginxSettings.TestConfigCmd)
-
-		return
+		return execShell(settings.NginxSettings.TestConfigCmd)
 	}
 	}
-
-	out = execCommand("nginx", "-t")
-
-	return
+	return execCommand("nginx", "-t")
 }
 }
 
 
-func Reload() (out string) {
+// Reload reloads the nginx
+func Reload() (stdOut string, stdErr error) {
 	mutex.Lock()
 	mutex.Lock()
 	defer mutex.Unlock()
 	defer mutex.Unlock()
 	if settings.NginxSettings.ReloadCmd != "" {
 	if settings.NginxSettings.ReloadCmd != "" {
-		out = execShell(settings.NginxSettings.ReloadCmd)
-		return
+		return execShell(settings.NginxSettings.ReloadCmd)
 	}
 	}
-
-	out = execCommand("nginx", "-s", "reload")
-
-	return
+	return execCommand("nginx", "-s", "reload")
 }
 }
 
 
+// Restart restarts the nginx
 func Restart() {
 func Restart() {
 	mutex.Lock()
 	mutex.Lock()
 	defer mutex.Unlock()
 	defer mutex.Unlock()
@@ -50,41 +45,45 @@ func Restart() {
 	time.Sleep(500 * time.Millisecond)
 	time.Sleep(500 * time.Millisecond)
 
 
 	if settings.NginxSettings.RestartCmd != "" {
 	if settings.NginxSettings.RestartCmd != "" {
-		lastOutput = execShell(settings.NginxSettings.RestartCmd)
-
+		lastStdOut, lastStdErr = execShell(settings.NginxSettings.RestartCmd)
 		return
 		return
 	}
 	}
 
 
 	pidPath := GetPIDPath()
 	pidPath := GetPIDPath()
 	daemon := GetSbinPath()
 	daemon := GetSbinPath()
 
 
-	lastOutput = execCommand("start-stop-daemon", "--stop", "--quiet", "--oknodo", "--retry=TERM/30/KILL/5", "--pidfile", pidPath)
+	lastStdOut, lastStdErr = execCommand("start-stop-daemon", "--stop", "--quiet", "--oknodo", "--retry=TERM/30/KILL/5", "--pidfile", pidPath)
+	if lastStdErr != nil {
+		return
+	}
 
 
 	if daemon == "" {
 	if daemon == "" {
-		lastOutput += execCommand("nginx")
-
+		lastStdOut, lastStdErr = execCommand("nginx")
 		return
 		return
 	}
 	}
 
 
-	lastOutput += execCommand("start-stop-daemon", "--start", "--quiet", "--pidfile", pidPath, "--exec", daemon)
-
+	lastStdOut, lastStdErr = execCommand("start-stop-daemon", "--start", "--quiet", "--pidfile", pidPath, "--exec", daemon)
 	return
 	return
 }
 }
 
 
-func GetLastOutput() string {
+// GetLastOutput returns the last output of the nginx command
+func GetLastOutput() (stdOut string, stdErr error) {
 	mutex.Lock()
 	mutex.Lock()
 	defer mutex.Unlock()
 	defer mutex.Unlock()
-	return lastOutput
+	return lastStdOut, lastStdErr
 }
 }
 
 
 // GetModulesPath returns the nginx modules path
 // GetModulesPath returns the nginx modules path
 func GetModulesPath() string {
 func GetModulesPath() string {
 	// First try to get from nginx -V output
 	// First try to get from nginx -V output
-	output := execCommand("nginx", "-V")
-	if output != "" {
+	stdOut, stdErr := execCommand("nginx", "-V")
+	if stdErr != nil {
+		return ""
+	}
+	if stdOut != "" {
 		// Look for --modules-path in the output
 		// Look for --modules-path in the output
-		if strings.Contains(output, "--modules-path=") {
-			parts := strings.Split(output, "--modules-path=")
+		if strings.Contains(stdOut, "--modules-path=") {
+			parts := strings.Split(stdOut, "--modules-path=")
 			if len(parts) > 1 {
 			if len(parts) > 1 {
 				// Extract the path
 				// Extract the path
 				path := strings.Split(parts[1], " ")[0]
 				path := strings.Split(parts[1], " ")[0]
@@ -99,28 +98,16 @@ func GetModulesPath() string {
 	return "/usr/lib/nginx/modules"
 	return "/usr/lib/nginx/modules"
 }
 }
 
 
-func execShell(cmd string) (out string) {
-	bytes, err := exec.Command("/bin/sh", "-c", cmd).CombinedOutput()
-	out = string(bytes)
-	if err != nil {
-		out += " " + err.Error()
-	}
-	return
-}
-
-func execCommand(name string, cmd ...string) (out string) {
-	bytes, err := exec.Command(name, cmd...).CombinedOutput()
-	out = string(bytes)
-	if err != nil {
-		out += " " + err.Error()
-	}
-	return
-}
-
 func IsNginxRunning() bool {
 func IsNginxRunning() bool {
 	pidPath := GetPIDPath()
 	pidPath := GetPIDPath()
-	if fileInfo, err := os.Stat(pidPath); err != nil || fileInfo.Size() == 0 {
-		return false
+	switch settings.NginxSettings.RunningInAnotherContainer() {
+	case true:
+		return docker.StatPath(pidPath)
+	case false:
+		if fileInfo, err := os.Stat(pidPath); err != nil || fileInfo.Size() == 0 {
+			return false
+		}
+		return true
 	}
 	}
-	return true
+	return false
 }
 }

+ 4 - 1
internal/site/disable.go

@@ -35,7 +35,10 @@ func Disable(name string) (err error) {
 		return
 		return
 	}
 	}
 
 
-	output := nginx.Reload()
+	output, err := nginx.Reload()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 	}
 	}

+ 8 - 2
internal/site/enable.go

@@ -35,13 +35,19 @@ func Enable(name string) (err error) {
 	}
 	}
 
 
 	// Test nginx config, if not pass, then disable the site.
 	// Test nginx config, if not pass, then disable the site.
-	output := nginx.TestConf()
+	output, err := nginx.TestConfig()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		_ = os.Remove(enabledConfigFilePath)
 		_ = os.Remove(enabledConfigFilePath)
 		return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 	}
 	}
 
 
-	output = nginx.Reload()
+	output, err = nginx.Reload()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 	}
 	}

+ 16 - 4
internal/site/maintenance.go

@@ -76,7 +76,10 @@ func EnableMaintenance(name string) (err error) {
 	}
 	}
 
 
 	// Test nginx config, if not pass, then restore original configuration
 	// Test nginx config, if not pass, then restore original configuration
-	output := nginx.TestConf()
+	output, err := nginx.TestConfig()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		// Configuration error, cleanup and revert
 		// Configuration error, cleanup and revert
 		_ = os.Remove(maintenanceConfigPath)
 		_ = os.Remove(maintenanceConfigPath)
@@ -87,7 +90,10 @@ func EnableMaintenance(name string) (err error) {
 	}
 	}
 
 
 	// Reload nginx
 	// Reload nginx
-	output = nginx.Reload()
+	output, err = nginx.Reload()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 	}
 	}
@@ -132,7 +138,10 @@ func DisableMaintenance(name string) (err error) {
 	}
 	}
 
 
 	// Test nginx config, if not pass, then revert
 	// Test nginx config, if not pass, then revert
-	output := nginx.TestConf()
+	output, err := nginx.TestConfig()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		// Configuration error, cleanup and revert
 		// Configuration error, cleanup and revert
 		_ = os.Remove(enabledConfigFilePath)
 		_ = os.Remove(enabledConfigFilePath)
@@ -141,7 +150,10 @@ func DisableMaintenance(name string) (err error) {
 	}
 	}
 
 
 	// Reload nginx
 	// Reload nginx
-	output = nginx.Reload()
+	output, err = nginx.Reload()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return fmt.Errorf("%s", output)
 		return fmt.Errorf("%s", output)
 	}
 	}

+ 13 - 6
internal/site/rename.go

@@ -2,16 +2,17 @@ package site
 
 
 import (
 import (
 	"fmt"
 	"fmt"
+	"net/http"
+	"os"
+	"runtime"
+	"sync"
+
 	"github.com/0xJacky/Nginx-UI/internal/helper"
 	"github.com/0xJacky/Nginx-UI/internal/helper"
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
 	"github.com/0xJacky/Nginx-UI/internal/nginx"
 	"github.com/0xJacky/Nginx-UI/internal/notification"
 	"github.com/0xJacky/Nginx-UI/internal/notification"
 	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/go-resty/resty/v2"
 	"github.com/go-resty/resty/v2"
 	"github.com/uozi-tech/cosy/logger"
 	"github.com/uozi-tech/cosy/logger"
-	"net/http"
-	"os"
-	"runtime"
-	"sync"
 )
 )
 
 
 func Rename(oldName string, newName string) (err error) {
 func Rename(oldName string, newName string) (err error) {
@@ -47,13 +48,19 @@ func Rename(oldName string, newName string) (err error) {
 	}
 	}
 
 
 	// test nginx configuration
 	// test nginx configuration
-	output := nginx.TestConf()
+	output, err := nginx.TestConfig()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return fmt.Errorf("%s", output)
 		return fmt.Errorf("%s", output)
 	}
 	}
 
 
 	// reload nginx
 	// reload nginx
-	output = nginx.Reload()
+	output, err = nginx.Reload()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return fmt.Errorf("%s", output)
 		return fmt.Errorf("%s", output)
 	}
 	}

+ 9 - 2
internal/site/save.go

@@ -38,14 +38,21 @@ func Save(name string, content string, overwrite bool, envGroupId uint64, syncNo
 	enabledConfigFilePath := nginx.GetConfPath("sites-enabled", name)
 	enabledConfigFilePath := nginx.GetConfPath("sites-enabled", name)
 	if helper.FileExists(enabledConfigFilePath) {
 	if helper.FileExists(enabledConfigFilePath) {
 		// Test nginx configuration
 		// Test nginx configuration
-		output := nginx.TestConf()
+		var output string
+		output, err = nginx.TestConfig()
+		if err != nil {
+			return
+		}
 
 
 		if nginx.GetLogLevel(output) > nginx.Warn {
 		if nginx.GetLogLevel(output) > nginx.Warn {
 			return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 			return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 		}
 		}
 
 
 		if postAction == model.PostSyncActionReloadNginx {
 		if postAction == model.PostSyncActionReloadNginx {
-			output = nginx.Reload()
+			output, err = nginx.Reload()
+			if err != nil {
+				return
+			}
 			if nginx.GetLogLevel(output) > nginx.Warn {
 			if nginx.GetLogLevel(output) > nginx.Warn {
 				return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 				return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 			}
 			}

+ 4 - 1
internal/stream/disable.go

@@ -35,7 +35,10 @@ func Disable(name string) (err error) {
 		return
 		return
 	}
 	}
 
 
-	output := nginx.Reload()
+	output, err := nginx.Reload()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 	}
 	}

+ 8 - 2
internal/stream/enable.go

@@ -35,13 +35,19 @@ func Enable(name string) (err error) {
 	}
 	}
 
 
 	// Test nginx config, if not pass, then disable the site.
 	// Test nginx config, if not pass, then disable the site.
-	output := nginx.TestConf()
+	output, err := nginx.TestConfig()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		_ = os.Remove(enabledConfigFilePath)
 		_ = os.Remove(enabledConfigFilePath)
 		return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 	}
 	}
 
 
-	output = nginx.Reload()
+	output, err = nginx.Reload()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 	}
 	}

+ 8 - 2
internal/stream/rename.go

@@ -49,13 +49,19 @@ func Rename(oldName string, newName string) (err error) {
 	}
 	}
 
 
 	// test nginx configuration
 	// test nginx configuration
-	output := nginx.TestConf()
+	output, err := nginx.TestConfig()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 	}
 	}
 
 
 	// reload nginx
 	// reload nginx
-	output = nginx.Reload()
+	output, err = nginx.Reload()
+	if err != nil {
+		return
+	}
 	if nginx.GetLogLevel(output) > nginx.Warn {
 	if nginx.GetLogLevel(output) > nginx.Warn {
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 		return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 	}
 	}

+ 9 - 2
internal/stream/save.go

@@ -37,15 +37,22 @@ func Save(name string, content string, overwrite bool, syncNodeIds []uint64, pos
 
 
 	enabledConfigFilePath := nginx.GetConfPath("streams-enabled", name)
 	enabledConfigFilePath := nginx.GetConfPath("streams-enabled", name)
 	if helper.FileExists(enabledConfigFilePath) {
 	if helper.FileExists(enabledConfigFilePath) {
+		var output string
 		// Test nginx configuration
 		// Test nginx configuration
-		output := nginx.TestConf()
+		output, err = nginx.TestConfig()
+		if err != nil {
+			return
+		}
 
 
 		if nginx.GetLogLevel(output) > nginx.Warn {
 		if nginx.GetLogLevel(output) > nginx.Warn {
 			return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 			return cosy.WrapErrorWithParams(ErrNginxTestFailed, output)
 		}
 		}
 
 
 		if postAction == model.PostSyncActionReloadNginx {
 		if postAction == model.PostSyncActionReloadNginx {
-			output = nginx.Reload()
+			output, err = nginx.Reload()
+			if err != nil {
+				return
+			}
 			if nginx.GetLogLevel(output) > nginx.Warn {
 			if nginx.GetLogLevel(output) > nginx.Warn {
 				return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 				return cosy.WrapErrorWithParams(ErrNginxReloadFailed, output)
 			}
 			}

+ 5 - 0
settings/nginx.go

@@ -11,6 +11,7 @@ type Nginx struct {
 	ReloadCmd       string   `json:"reload_cmd" protected:"true"`
 	ReloadCmd       string   `json:"reload_cmd" protected:"true"`
 	RestartCmd      string   `json:"restart_cmd" protected:"true"`
 	RestartCmd      string   `json:"restart_cmd" protected:"true"`
 	StubStatusPort  uint     `json:"stub_status_port" binding:"omitempty,min=1,max=65535"`
 	StubStatusPort  uint     `json:"stub_status_port" binding:"omitempty,min=1,max=65535"`
+	ContainerName   string   `json:"container_name" protected:"true"`
 }
 }
 
 
 var NginxSettings = &Nginx{}
 var NginxSettings = &Nginx{}
@@ -21,3 +22,7 @@ func (n *Nginx) GetStubStatusPort() uint {
 	}
 	}
 	return n.StubStatusPort
 	return n.StubStatusPort
 }
 }
+
+func (n *Nginx) RunningInAnotherContainer() bool {
+	return n.ContainerName != ""
+}