diff --git a/docs/Config.md b/docs/Config.md
index 6e77a94a..b1d0c4d7 100644
--- a/docs/Config.md
+++ b/docs/Config.md
@@ -42,8 +42,11 @@ logs:
commandTemplates:
dockerCompose: docker-compose
restartService: '{{ .DockerCompose }} restart {{ .Service.Name }}'
- startService: '{{ .DockerCompose }} start {{ .Service.Name }}'
+ up: '{{ .DockerCompose }} up -d'
+ down: '{{ .DockerCompose }} down'
+ downWithVolumes: '{{ .DockerCompose }} down --volumes'
upService: '{{ .DockerCompose }} up -d {{ .Service.Name }}'
+ startService: '{{ .DockerCompose }} start {{ .Service.Name }}'
stopService: '{{ .DockerCompose }} stop {{ .Service.Name }}'
serviceLogs: '{{ .DockerCompose }} logs --since=60m --follow {{ .Service.Name }}'
viewServiceLogs: '{{ .DockerCompose }} logs --follow {{ .Service.Name }}'
diff --git a/docs/keybindings/Keybindings_de.md b/docs/keybindings/Keybindings_de.md
index b28837b1..898317b4 100644
--- a/docs/keybindings/Keybindings_de.md
+++ b/docs/keybindings/Keybindings_de.md
@@ -43,6 +43,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
S: start
a: anbinden
m: zeige Protokolle
+ U: up project
+ D: down project
[: vorheriges Tab
]: nächstes Tab
R: zeige Neustartoptionen
diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md
index 86f1b8cf..8cfab0de 100644
--- a/docs/keybindings/Keybindings_en.md
+++ b/docs/keybindings/Keybindings_en.md
@@ -43,6 +43,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
S: start
a: attach
m: view logs
+ U: up project
+ D: down project
[: previous tab
]: next tab
R: view restart options
diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md
index 17077899..f606b880 100644
--- a/docs/keybindings/Keybindings_nl.md
+++ b/docs/keybindings/Keybindings_nl.md
@@ -43,6 +43,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
S: start
a: verbinden
m: bekijk logs
+ U: up project
+ D: down project
[: vorige tab
]: volgende tab
R: bekijk herstart opties
diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md
index 08b89c5b..a8ab2a1b 100644
--- a/docs/keybindings/Keybindings_pl.md
+++ b/docs/keybindings/Keybindings_pl.md
@@ -43,6 +43,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
S: start
a: przyczep
m: pokaż logi
+ U: up project
+ D: down project
[: poprzednia zakładka
]: następna zakładka
R: pokaż opcje restartu
diff --git a/docs/keybindings/Keybindings_tr.md b/docs/keybindings/Keybindings_tr.md
index 263db57b..0124bb1f 100644
--- a/docs/keybindings/Keybindings_tr.md
+++ b/docs/keybindings/Keybindings_tr.md
@@ -43,6 +43,8 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
S: start
a: bağlan/iliştir
m: kayıt defterini görüntüle
+ U: up project
+ D: down project
[: önceki sekme
]: sonraki sekme
R: yeniden başlatma seçeneklerini görüntüle
diff --git a/pkg/commands/container.go b/pkg/commands/container.go
index c239640d..39cece20 100644
--- a/pkg/commands/container.go
+++ b/pkg/commands/container.go
@@ -57,6 +57,10 @@ func (c *Container) GetDisplayStrings(isFocused bool) []string {
func (c *Container) displayPorts() string {
portStrings := lo.Map(c.Container.Ports, func(port types.Port, _ int) string {
+ if port.PublicPort == 0 {
+ return fmt.Sprintf("%d\\%s", port.PrivatePort, port.Type)
+ }
+
// docker ps will show '0.0.0.0:80->80/tcp' but we'll show
// '80->80/tcp' instead to save space (unless the IP is something other than
// 0.0.0.0)
diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go
index a68cb444..104c55ca 100644
--- a/pkg/config/app_config.go
+++ b/pkg/config/app_config.go
@@ -141,6 +141,14 @@ type CommandTemplatesConfig struct {
// UpService ups the service (creates and starts)
UpService string `yaml:"upService,omitempty"`
+ // Runs "docker-compose up -d"
+ Up string `yaml:"up,omitempty"`
+
+ // downs everything
+ Down string `yaml:"down,omitempty"`
+ // downs and removes volumes
+ DownWithVolumes string `yaml:"downWithVolumes,omitempty"`
+
// DockerCompose is for your docker-compose command. You may want to combine a
// few different docker-compose.yml files together, in which case you can set
// this to "docker-compose -f foo/docker-compose.yml -f
@@ -351,6 +359,9 @@ func GetDefaultConfig() UserConfig {
DockerCompose: "docker-compose",
RestartService: "{{ .DockerCompose }} restart {{ .Service.Name }}",
StartService: "{{ .DockerCompose }} start {{ .Service.Name }}",
+ Up: "{{ .DockerCompose }} up -d",
+ Down: "{{ .DockerCompose }} down",
+ DownWithVolumes: "{{ .DockerCompose }} down --volumes",
UpService: "{{ .DockerCompose }} up -d {{ .Service.Name }}",
RebuildService: "{{ .DockerCompose }} up -d --build {{ .Service.Name }}",
RecreateService: "{{ .DockerCompose }} up -d --force-recreate {{ .Service.Name }}",
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index 54a6b7e7..3f8ac500 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -109,6 +109,12 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Modifier: gocui.ModNone,
Handler: gui.autoScrollMain,
},
+ {
+ ViewName: "",
+ Key: gocui.KeyHome,
+ Modifier: gocui.ModNone,
+ Handler: gui.jumpToTopMain,
+ },
{
ViewName: "",
Key: 'x',
@@ -339,6 +345,20 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleServiceRenderLogsToMain,
Description: gui.Tr.ViewLogs,
},
+ {
+ ViewName: "services",
+ Key: 'U',
+ Modifier: gocui.ModNone,
+ Handler: gui.handleProjectUp,
+ Description: gui.Tr.UpProject,
+ },
+ {
+ ViewName: "services",
+ Key: 'D',
+ Modifier: gocui.ModNone,
+ Handler: gui.handleProjectDown,
+ Description: gui.Tr.DownProject,
+ },
{
ViewName: "services",
Key: '[',
diff --git a/pkg/gui/main_panel.go b/pkg/gui/main_panel.go
index e8675df4..bf985d8c 100644
--- a/pkg/gui/main_panel.go
+++ b/pkg/gui/main_panel.go
@@ -66,6 +66,13 @@ func (gui *Gui) autoScrollMain(g *gocui.Gui, v *gocui.View) error {
return nil
}
+func (gui *Gui) jumpToTopMain(g *gocui.Gui, v *gocui.View) error {
+ gui.getMainView().Autoscroll = false
+ _ = gui.getMainView().SetOrigin(0, 0)
+ _ = gui.getMainView().SetCursor(0, 0)
+ return nil
+}
+
func (gui *Gui) onMainTabClick(tabIndex int) error {
gui.Log.Warn(tabIndex)
diff --git a/pkg/gui/services_panel.go b/pkg/gui/services_panel.go
index af95e925..c0361e1a 100644
--- a/pkg/gui/services_panel.go
+++ b/pkg/gui/services_panel.go
@@ -254,7 +254,7 @@ func (gui *Gui) handleServiceUp(g *gocui.Gui, v *gocui.View) error {
return nil
}
- return gui.WithWaitingStatus(gui.Tr.UppingStatus, func() error {
+ return gui.WithWaitingStatus(gui.Tr.UppingServiceStatus, func() error {
if err := service.Up(); err != nil {
return gui.createErrorPanel(err.Error())
}
@@ -325,6 +325,69 @@ func (gui *Gui) handleServiceRenderLogsToMain(g *gocui.Gui, v *gocui.View) error
return gui.runSubprocess(c)
}
+func (gui *Gui) handleProjectUp(g *gocui.Gui, v *gocui.View) error {
+ return gui.createConfirmationPanel(gui.Tr.Confirm, gui.Tr.ConfirmUpProject, func(g *gocui.Gui, v *gocui.View) error {
+ cmdStr := utils.ApplyTemplate(
+ gui.Config.UserConfig.CommandTemplates.Up,
+ gui.DockerCommand.NewCommandObject(commands.CommandObject{}),
+ )
+
+ return gui.WithWaitingStatus(gui.Tr.UppingProjectStatus, func() error {
+ if err := gui.OSCommand.RunCommand(cmdStr); err != nil {
+ return gui.createErrorPanel(err.Error())
+ }
+ return nil
+ })
+ }, nil)
+}
+
+func (gui *Gui) handleProjectDown(g *gocui.Gui, v *gocui.View) error {
+ downCommand := utils.ApplyTemplate(
+ gui.Config.UserConfig.CommandTemplates.Down,
+ gui.DockerCommand.NewCommandObject(commands.CommandObject{}),
+ )
+
+ downWithVolumesCommand := utils.ApplyTemplate(
+ gui.Config.UserConfig.CommandTemplates.DownWithVolumes,
+ gui.DockerCommand.NewCommandObject(commands.CommandObject{}),
+ )
+
+ options := []*commandOption{
+ {
+ description: gui.Tr.Down,
+ command: downCommand,
+ f: func() error {
+ return gui.WithWaitingStatus(gui.Tr.DowningStatus, func() error {
+ if err := gui.OSCommand.RunCommand(downCommand); err != nil {
+ return gui.createErrorPanel(err.Error())
+ }
+ return nil
+ })
+ },
+ },
+ {
+ description: gui.Tr.DownWithVolumes,
+ command: downWithVolumesCommand,
+ f: func() error {
+ return gui.WithWaitingStatus(gui.Tr.DowningStatus, func() error {
+ if err := gui.OSCommand.RunCommand(downWithVolumesCommand); err != nil {
+ return gui.createErrorPanel(err.Error())
+ }
+ return nil
+ })
+ },
+ },
+ {
+ description: gui.Tr.Cancel,
+ f: func() error { return nil },
+ },
+ }
+
+ handleMenuPress := func(index int) error { return options[index].f() }
+
+ return gui.createMenu("", options, len(options), handleMenuPress)
+}
+
func (gui *Gui) handleServiceRestartMenu(g *gocui.Gui, v *gocui.View) error {
service, err := gui.getSelectedService()
if err != nil {
diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go
index cc11470f..f747b5f5 100644
--- a/pkg/i18n/english.go
+++ b/pkg/i18n/english.go
@@ -17,6 +17,7 @@ type TranslationSet struct {
OpenConfig string
EditConfig string
ConfirmQuit string
+ ConfirmUpProject string
ErrorOccurred string
ConnectionFailed string
UnattachableContainerError string
@@ -41,9 +42,11 @@ type TranslationSet struct {
RestartingStatus string
StartingStatus string
StoppingStatus string
- UppingStatus string
+ UppingProjectStatus string
+ UppingServiceStatus string
PausingStatus string
RemovingStatus string
+ DowningStatus string
RunningCustomCommandStatus string
RunningBulkCommandStatus string
RemoveService string
@@ -51,6 +54,8 @@ type TranslationSet struct {
Stop string
Pause string
Restart string
+ Down string
+ DownWithVolumes string
Start string
Rebuild string
Recreate string
@@ -58,6 +63,8 @@ type TranslationSet struct {
NextContext string
Attach string
ViewLogs string
+ UpProject string
+ DownProject string
ServicesTitle string
ContainersTitle string
StandaloneContainersTitle string
@@ -118,7 +125,9 @@ func englishSet() TranslationSet {
RestartingStatus: "restarting",
StartingStatus: "starting",
StoppingStatus: "stopping",
- UppingStatus: "upping",
+ UppingServiceStatus: "upping service",
+ UppingProjectStatus: "upping project",
+ DowningStatus: "downing",
PausingStatus: "pausing",
RunningCustomCommandStatus: "running custom command",
RunningBulkCommandStatus: "running bulk command",
@@ -156,6 +165,8 @@ func englishSet() TranslationSet {
Stop: "stop",
Pause: "pause",
Restart: "restart",
+ Down: "down project",
+ DownWithVolumes: "down project with volumes",
Start: "start",
Rebuild: "rebuild",
Recreate: "recreate",
@@ -163,6 +174,8 @@ func englishSet() TranslationSet {
NextContext: "next tab",
Attach: "attach",
ViewLogs: "view logs",
+ UpProject: "up project",
+ DownProject: "down project",
RemoveImage: "remove image",
RemoveVolume: "remove volume",
RemoveWithoutPrune: "remove without deleting untagged parents",
@@ -209,6 +222,7 @@ func englishSet() TranslationSet {
NoVolumes: "No volumes",
ConfirmQuit: "Are you sure you want to quit?",
+ ConfirmUpProject: "Are you sure you want to 'up' your docker compose project?",
MustForceToRemoveContainer: "You cannot remove a running container unless you force it. Do you want to force it?",
NotEnoughSpace: "Not enough space to render panels",
ConfirmPruneImages: "Are you sure you want to prune all unused images?",