diff --git a/.gitignore b/.gitignore index 82995009..b9f700a9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ lazydocker* TODO.md Lazydocker.code-workspace .vscode +.idea diff --git a/README.md b/README.md index c53b15f8..1485464c 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ A simple terminal UI for both docker and docker-compose, written in Go with the

- +

## Elevator Pitch diff --git a/docs/keybindings/Keybindings_de.md b/docs/keybindings/Keybindings_de.md index 913d8817..f463e21b 100644 --- a/docs/keybindings/Keybindings_de.md +++ b/docs/keybindings/Keybindings_de.md @@ -81,6 +81,18 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct /: filter list +## Netzwerk + +
+  c: führe vordefinierten benutzerdefinierten Befehl aus
+  d: entferne Netzwerk
+  b: view bulk commands
+  enter: fokussieren aufs Hauptpanel
+  [: vorheriges Tab
+  ]: nächstes Tab
+  /: filter list
+
+ ## Haupt
diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md
index fe99e262..a5a8ff3f 100644
--- a/docs/keybindings/Keybindings_en.md
+++ b/docs/keybindings/Keybindings_en.md
@@ -81,6 +81,18 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
   /: filter list
 
+## Networks + +
+  c: run predefined custom command
+  d: remove network
+  b: view bulk commands
+  enter: focus main panel
+  [: previous tab
+  ]: next tab
+  /: filter list
+
+ ## Main
diff --git a/docs/keybindings/Keybindings_fr.md b/docs/keybindings/Keybindings_fr.md
index 07c1eac3..dcdbe19e 100644
--- a/docs/keybindings/Keybindings_fr.md
+++ b/docs/keybindings/Keybindings_fr.md
@@ -81,6 +81,18 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
   /: filter list
 
+## Réseaux + +
+  c: executer une commande prédéfinie
+  d: supprimer le réseau
+  b: voir les commandes groupés
+  enter: focus paneau principal
+  [: onglet précédent
+  ]: onglet suivant
+  /: filter list
+
+ ## Principal
diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md
index 7f134edb..3de0c93e 100644
--- a/docs/keybindings/Keybindings_nl.md
+++ b/docs/keybindings/Keybindings_nl.md
@@ -81,6 +81,18 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
   /: filter list
 
+## Networks + +
+  c: draai een vooraf bedacht aangepaste opdracht
+  d: verwijder network
+  b: view bulk commands
+  enter: focus hoofdpaneel
+  [: vorige tab
+  ]: volgende tab
+  /: filter list
+
+ ## Hoofd
diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md
index b14a9b34..0983b8e2 100644
--- a/docs/keybindings/Keybindings_pl.md
+++ b/docs/keybindings/Keybindings_pl.md
@@ -81,6 +81,18 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
   /: filter list
 
+## Seici + +
+  c: wykonaj predefiniowaną własną komende
+  d: usuń seici
+  b: view bulk commands
+  enter: skup na głównym panelu
+  [: poprzednia zakładka
+  ]: następna zakładka
+  /: filter list
+
+ ## Główne
diff --git a/docs/keybindings/Keybindings_tr.md b/docs/keybindings/Keybindings_tr.md
index bcb7ac1c..018f68c2 100644
--- a/docs/keybindings/Keybindings_tr.md
+++ b/docs/keybindings/Keybindings_tr.md
@@ -81,6 +81,18 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
   /: filter list
 
+## Ağları + +
+  c: önceden tanımlanmış özel komutu çalıştır
+  d: ağı kaldır
+  b: view bulk commands
+  enter: ana panele odaklan
+  [: önceki sekme
+  ]: sonraki sekme
+  /: filter list
+
+ ## Ana
diff --git a/go.mod b/go.mod
index fb69eded..511999bb 100644
--- a/go.mod
+++ b/go.mod
@@ -32,12 +32,12 @@ require (
 require (
 	github.com/Microsoft/go-winio v0.4.14 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
-	github.com/docker/distribution v2.7.1+incompatible // indirect
+	github.com/docker/distribution v2.8.0+incompatible // indirect
 	github.com/docker/go-connections v0.4.0 // indirect
 	github.com/docker/go-units v0.4.0 // indirect
 	github.com/gdamore/encoding v1.0.0 // indirect
 	github.com/gdamore/tcell/v2 v2.5.3 // indirect
-	github.com/gogo/protobuf v1.3.1 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
 	github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
 	github.com/mattn/go-colorable v0.1.4 // indirect
@@ -47,7 +47,7 @@ require (
 	github.com/onsi/ginkgo v1.8.0 // indirect
 	github.com/onsi/gomega v1.5.0 // indirect
 	github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
-	github.com/opencontainers/image-spec v1.0.1 // indirect
+	github.com/opencontainers/image-spec v1.0.2 // indirect
 	github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/rivo/uniseg v0.4.2 // indirect
diff --git a/go.sum b/go.sum
index ebcf084b..3132988d 100644
--- a/go.sum
+++ b/go.sum
@@ -12,8 +12,8 @@ github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
-github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
+github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docker/docker v20.10.15+incompatible h1:dk9FewY/9Xwm4ay/HViEEHSQuM/kL4F+JaG6GQdgmGo=
 github.com/docker/docker v20.10.15+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
@@ -31,8 +31,8 @@ github.com/gdamore/tcell/v2 v2.5.3/go.mod h1:wSkrPaXoiIWZqW/g7Px4xc79di6FTcpB8tv
 github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
 github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
 github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
-github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
-github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -56,7 +56,7 @@ github.com/jesseduffield/lazycore v0.0.0-20221023210126-718a4caea996 h1:CH1en6Gp
 github.com/jesseduffield/lazycore v0.0.0-20221023210126-718a4caea996/go.mod h1:qxN4mHOAyeIDLP7IK7defgPClM/z1Kze8VVQiaEjzsQ=
 github.com/jesseduffield/yaml v0.0.0-20190702115811-b900b7e08b56 h1:33wSxJWU/f2TAozHYtJ8zqBxEnEVYM+22moLoiAkxvg=
 github.com/jesseduffield/yaml v0.0.0-20190702115811-b900b7e08b56/go.mod h1:FZJBwOhE+RXz8EVZfY+xnbCw2cVOwxlK3/aIi581z/s=
-github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
@@ -90,8 +90,8 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
 github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
-github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
-github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
+github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
 github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -125,21 +125,25 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
 github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
 github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
 github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4=
 golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -168,9 +172,10 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/pkg/cheatsheet/generate.go b/pkg/cheatsheet/generate.go
index bd9d230c..76e9875d 100644
--- a/pkg/cheatsheet/generate.go
+++ b/pkg/cheatsheet/generate.go
@@ -96,6 +96,7 @@ func getBindingSections(mApp *app.App) []*bindingSection {
 			"containers": mApp.Tr.ContainersTitle,
 			"images":     mApp.Tr.ImagesTitle,
 			"volumes":    mApp.Tr.VolumesTitle,
+			"networks":   mApp.Tr.NetworksTitle,
 		}
 
 		bindingSections = addBinding(titleMap[viewName], bindingSections, binding)
diff --git a/pkg/commands/docker.go b/pkg/commands/docker.go
index 2c802bee..10270c0d 100644
--- a/pkg/commands/docker.go
+++ b/pkg/commands/docker.go
@@ -55,6 +55,7 @@ type CommandObject struct {
 	Container     *Container
 	Image         *Image
 	Volume        *Volume
+	Network       *Network
 }
 
 type ComposeProject struct {
diff --git a/pkg/commands/network.go b/pkg/commands/network.go
new file mode 100644
index 00000000..c1c18593
--- /dev/null
+++ b/pkg/commands/network.go
@@ -0,0 +1,54 @@
+package commands
+
+import (
+	"context"
+
+	dockerTypes "github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/client"
+	"github.com/sirupsen/logrus"
+)
+
+// Network : A docker Network
+type Network struct {
+	Name          string
+	Network       dockerTypes.NetworkResource
+	Client        *client.Client
+	OSCommand     *OSCommand
+	Log           *logrus.Entry
+	DockerCommand LimitedDockerCommand
+}
+
+// RefreshNetworks gets the networks and stores them
+func (c *DockerCommand) RefreshNetworks() ([]*Network, error) {
+	networks, err := c.Client.NetworkList(context.Background(), dockerTypes.NetworkListOptions{})
+	if err != nil {
+		return nil, err
+	}
+
+	ownNetworks := make([]*Network, len(networks))
+
+	for i, network := range networks {
+		ownNetworks[i] = &Network{
+			Name:          network.Name,
+			Network:       network,
+			Client:        c.Client,
+			OSCommand:     c.OSCommand,
+			Log:           c.Log,
+			DockerCommand: c,
+		}
+	}
+
+	return ownNetworks, nil
+}
+
+// PruneNetworks prunes networks
+func (c *DockerCommand) PruneNetworks() error {
+	_, err := c.Client.NetworksPrune(context.Background(), filters.Args{})
+	return err
+}
+
+// Remove removes the network
+func (v *Network) Remove() error {
+	return v.Client.NetworkRemove(context.Background(), v.Name)
+}
diff --git a/pkg/commands/os.go b/pkg/commands/os.go
index 5a8e6406..36984114 100644
--- a/pkg/commands/os.go
+++ b/pkg/commands/os.go
@@ -103,7 +103,7 @@ func (c *OSCommand) ExecutableFromStringContext(ctx context.Context, commandStr
 }
 
 func (c *OSCommand) NewCommandStringWithShell(commandStr string) string {
-	quotedCommand := ""
+	var quotedCommand string
 	// Windows does not seem to like quotes around the command
 	if c.Platform.os == "windows" {
 		quotedCommand = strings.NewReplacer(
diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go
index 87bc4f2c..c3a0994a 100644
--- a/pkg/config/app_config.go
+++ b/pkg/config/app_config.go
@@ -286,6 +286,9 @@ type CustomCommands struct {
 
 	// Volumes contains the custom commands for volumes
 	Volumes []CustomCommand `yaml:"volumes,omitempty"`
+
+	// Networks contains the custom commands for networks
+	Networks []CustomCommand `yaml:"networks,omitempty"`
 }
 
 // Replacements contains the stuff relating to rendering a container's info
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index 6a24254e..b15cbd72 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -56,6 +56,7 @@ type Panels struct {
 	Containers *panels.SideListPanel[*commands.Container]
 	Images     *panels.SideListPanel[*commands.Image]
 	Volumes    *panels.SideListPanel[*commands.Volume]
+	Networks   *panels.SideListPanel[*commands.Network]
 	Menu       *panels.SideListPanel[*types.MenuItem]
 }
 
@@ -273,6 +274,7 @@ func (gui *Gui) setPanels() {
 		Containers: gui.getContainersPanel(),
 		Images:     gui.getImagesPanel(),
 		Volumes:    gui.getVolumesPanel(),
+		Networks:   gui.getNetworksPanel(),
 		Menu:       gui.getMenuPanel(),
 	}
 }
@@ -297,6 +299,11 @@ func (gui *Gui) refresh() {
 			gui.Log.Error(err)
 		}
 	}()
+	go func() {
+		if err := gui.reloadNetworks(); err != nil {
+			gui.Log.Error(err)
+		}
+	}()
 	go func() {
 		if err := gui.reloadImages(); err != nil {
 			gui.Log.Error(err)
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index 307ca16c..196819b2 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -415,6 +415,27 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
 			Handler:     gui.handleVolumesBulkCommand,
 			Description: gui.Tr.ViewBulkCommands,
 		},
+		{
+			ViewName:    "networks",
+			Key:         'c',
+			Modifier:    gocui.ModNone,
+			Handler:     gui.handleNetworksCustomCommand,
+			Description: gui.Tr.RunCustomCommand,
+		},
+		{
+			ViewName:    "networks",
+			Key:         'd',
+			Modifier:    gocui.ModNone,
+			Handler:     gui.handleNetworksRemoveMenu,
+			Description: gui.Tr.RemoveNetwork,
+		},
+		{
+			ViewName:    "networks",
+			Key:         'b',
+			Modifier:    gocui.ModNone,
+			Handler:     gui.handleNetworksBulkCommand,
+			Description: gui.Tr.ViewBulkCommands,
+		},
 		{
 			ViewName:    "main",
 			Key:         gocui.KeyEsc,
diff --git a/pkg/gui/networks_panel.go b/pkg/gui/networks_panel.go
new file mode 100644
index 00000000..4702d35d
--- /dev/null
+++ b/pkg/gui/networks_panel.go
@@ -0,0 +1,179 @@
+package gui
+
+import (
+	"strconv"
+
+	"github.com/fatih/color"
+	"github.com/jesseduffield/gocui"
+	"github.com/jesseduffield/lazydocker/pkg/commands"
+	"github.com/jesseduffield/lazydocker/pkg/config"
+	"github.com/jesseduffield/lazydocker/pkg/gui/panels"
+	"github.com/jesseduffield/lazydocker/pkg/gui/presentation"
+	"github.com/jesseduffield/lazydocker/pkg/gui/types"
+	"github.com/jesseduffield/lazydocker/pkg/tasks"
+	"github.com/jesseduffield/lazydocker/pkg/utils"
+	"github.com/samber/lo"
+)
+
+func (gui *Gui) getNetworksPanel() *panels.SideListPanel[*commands.Network] {
+	return &panels.SideListPanel[*commands.Network]{
+		ContextState: &panels.ContextState[*commands.Network]{
+			GetMainTabs: func() []panels.MainTab[*commands.Network] {
+				return []panels.MainTab[*commands.Network]{
+					{
+						Key:    "config",
+						Title:  gui.Tr.ConfigTitle,
+						Render: gui.renderNetworkConfig,
+					},
+				}
+			},
+			GetItemContextCacheKey: func(network *commands.Network) string {
+				return "networks-" + network.Name
+			},
+		},
+		ListPanel: panels.ListPanel[*commands.Network]{
+			List: panels.NewFilteredList[*commands.Network](),
+			View: gui.Views.Networks,
+		},
+		NoItemsMessage: gui.Tr.NoNetworks,
+		Gui:            gui.intoInterface(),
+		// we're sorting these networks based on whether they have labels defined,
+		// because those are the ones you typically care about.
+		// Within that, we also sort them alphabetically
+		Sort: func(a *commands.Network, b *commands.Network) bool {
+			return a.Name < b.Name
+		},
+		GetTableCells: presentation.GetNetworkDisplayStrings,
+	}
+}
+
+func (gui *Gui) renderNetworkConfig(network *commands.Network) tasks.TaskFunc {
+	return gui.NewSimpleRenderStringTask(func() string { return gui.networkConfigStr(network) })
+}
+
+func (gui *Gui) networkConfigStr(network *commands.Network) string {
+	padding := 15
+	output := ""
+	output += utils.WithPadding("ID: ", padding) + network.Network.ID + "\n"
+	output += utils.WithPadding("Name: ", padding) + network.Name + "\n"
+	output += utils.WithPadding("Driver: ", padding) + network.Network.Driver + "\n"
+	output += utils.WithPadding("Scope: ", padding) + network.Network.Scope + "\n"
+	output += utils.WithPadding("EnabledIPV6: ", padding) + strconv.FormatBool(network.Network.EnableIPv6) + "\n"
+	output += utils.WithPadding("Internal: ", padding) + strconv.FormatBool(network.Network.Internal) + "\n"
+	output += utils.WithPadding("Attachable: ", padding) + strconv.FormatBool(network.Network.Attachable) + "\n"
+	output += utils.WithPadding("Ingress: ", padding) + strconv.FormatBool(network.Network.Ingress) + "\n"
+
+	output += utils.WithPadding("Containers: ", padding)
+	if len(network.Network.Containers) > 0 {
+		output += "\n"
+		for _, v := range network.Network.Containers {
+			output += utils.FormatMapItem(padding, v.Name, v.EndpointID)
+		}
+	} else {
+		output += "none\n"
+	}
+
+	output += "\n"
+	output += utils.WithPadding("Labels: ", padding) + utils.FormatMap(padding, network.Network.Labels) + "\n"
+	output += utils.WithPadding("Options: ", padding) + utils.FormatMap(padding, network.Network.Options)
+
+	return output
+}
+
+func (gui *Gui) reloadNetworks() error {
+	if err := gui.refreshStateNetworks(); err != nil {
+		return err
+	}
+
+	return gui.Panels.Networks.RerenderList()
+}
+
+func (gui *Gui) refreshStateNetworks() error {
+	networks, err := gui.DockerCommand.RefreshNetworks()
+	if err != nil {
+		return err
+	}
+
+	gui.Panels.Networks.SetItems(networks)
+
+	return nil
+}
+
+func (gui *Gui) handleNetworksRemoveMenu(g *gocui.Gui, v *gocui.View) error {
+	network, err := gui.Panels.Networks.GetSelectedItem()
+	if err != nil {
+		return nil
+	}
+
+	type removeNetworkOption struct {
+		description string
+		command     string
+	}
+
+	options := []*removeNetworkOption{
+		{
+			description: gui.Tr.Remove,
+			command:     utils.WithShortSha("docker network rm " + network.Name),
+		},
+	}
+
+	menuItems := lo.Map(options, func(option *removeNetworkOption, _ int) *types.MenuItem {
+		return &types.MenuItem{
+			LabelColumns: []string{option.description, color.New(color.FgRed).Sprint(option.command)},
+			OnPress: func() error {
+				return gui.WithWaitingStatus(gui.Tr.RemovingStatus, func() error {
+					if err := network.Remove(); err != nil {
+						return gui.createErrorPanel(err.Error())
+					}
+					return nil
+				})
+			},
+		}
+	})
+
+	return gui.Menu(CreateMenuOptions{
+		Title: "",
+		Items: menuItems,
+	})
+}
+
+func (gui *Gui) handlePruneNetworks() error {
+	return gui.createConfirmationPanel(gui.Tr.Confirm, gui.Tr.ConfirmPruneNetworks, func(g *gocui.Gui, v *gocui.View) error {
+		return gui.WithWaitingStatus(gui.Tr.PruningStatus, func() error {
+			err := gui.DockerCommand.PruneNetworks()
+			if err != nil {
+				return gui.createErrorPanel(err.Error())
+			}
+			return nil
+		})
+	}, nil)
+}
+
+func (gui *Gui) handleNetworksCustomCommand(g *gocui.Gui, v *gocui.View) error {
+	network, err := gui.Panels.Networks.GetSelectedItem()
+	if err != nil {
+		return nil
+	}
+
+	commandObject := gui.DockerCommand.NewCommandObject(commands.CommandObject{
+		Network: network,
+	})
+
+	customCommands := gui.Config.UserConfig.CustomCommands.Networks
+
+	return gui.createCustomCommandMenu(customCommands, commandObject)
+}
+
+func (gui *Gui) handleNetworksBulkCommand(g *gocui.Gui, v *gocui.View) error {
+	baseBulkCommands := []config.CustomCommand{
+		{
+			Name:             gui.Tr.PruneNetworks,
+			InternalFunction: gui.handlePruneNetworks,
+		},
+	}
+
+	bulkCommands := append(baseBulkCommands, gui.Config.UserConfig.BulkCommands.Networks...)
+	commandObject := gui.DockerCommand.NewCommandObject(commands.CommandObject{})
+
+	return gui.createBulkCommandMenu(bulkCommands, commandObject)
+}
diff --git a/pkg/gui/presentation/networks.go b/pkg/gui/presentation/networks.go
new file mode 100644
index 00000000..88a29fc9
--- /dev/null
+++ b/pkg/gui/presentation/networks.go
@@ -0,0 +1,7 @@
+package presentation
+
+import "github.com/jesseduffield/lazydocker/pkg/commands"
+
+func GetNetworkDisplayStrings(network *commands.Network) []string {
+	return []string{network.Network.Driver, network.Name}
+}
diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go
index 8ddae589..5e2b72fb 100644
--- a/pkg/gui/view_helpers.go
+++ b/pkg/gui/view_helpers.go
@@ -362,6 +362,7 @@ func (gui *Gui) allSidePanels() []panels.ISideListPanel {
 		gui.Panels.Containers,
 		gui.Panels.Images,
 		gui.Panels.Volumes,
+		gui.Panels.Networks,
 	}
 }
 
diff --git a/pkg/gui/views.go b/pkg/gui/views.go
index 04955308..c83fd6db 100644
--- a/pkg/gui/views.go
+++ b/pkg/gui/views.go
@@ -32,6 +32,7 @@ type Views struct {
 	Containers *gocui.View
 	Images     *gocui.View
 	Volumes    *gocui.View
+	Networks   *gocui.View
 
 	// main panel
 	Main *gocui.View
@@ -70,6 +71,7 @@ func (gui *Gui) orderedViewNameMappings() []viewNameMapping {
 		{viewPtr: &gui.Views.Containers, name: "containers", autoPosition: true},
 		{viewPtr: &gui.Views.Images, name: "images", autoPosition: true},
 		{viewPtr: &gui.Views.Volumes, name: "volumes", autoPosition: true},
+		{viewPtr: &gui.Views.Networks, name: "networks", autoPosition: true},
 
 		{viewPtr: &gui.Views.Main, name: "main", autoPosition: true},
 
@@ -129,6 +131,10 @@ func (gui *Gui) createAllViews() error {
 	gui.Views.Volumes.Title = gui.Tr.VolumesTitle
 	gui.Views.Volumes.SelBgColor = selectedLineBgColor
 
+	gui.Views.Networks.Highlight = true
+	gui.Views.Networks.Title = gui.Tr.NetworksTitle
+	gui.Views.Networks.SelBgColor = selectedLineBgColor
+
 	gui.Views.Options.Frame = false
 	gui.Views.Options.FgColor = gui.GetOptionsPanelTextColor()
 
diff --git a/pkg/i18n/dutch.go b/pkg/i18n/dutch.go
index 2508f2f0..1c592fdc 100644
--- a/pkg/i18n/dutch.go
+++ b/pkg/i18n/dutch.go
@@ -45,9 +45,11 @@ func dutchSet() TranslationSet {
 		ViewLogs:           "bekijk logs",
 		RemoveImage:        "verwijder image",
 		RemoveVolume:       "verwijder volume",
+		RemoveNetwork:      "verwijder network",
 		RemoveWithoutPrune: "verwijder zonder de ongelabeld ouders te verwijderen",
 		PruneContainers:    "vernietig bestaande containers",
 		PruneVolumes:       "vernietig ongebruikte volumes",
+		PruneNetworks:      "vernietig ongebruikte networks",
 		PruneImages:        "vernietig ongebruikte images",
 		ViewRestartOptions: "bekijk herstart opties",
 		RunCustomCommand:   "draai een vooraf bedacht aangepaste opdracht",
@@ -60,6 +62,7 @@ func dutchSet() TranslationSet {
 		StandaloneContainersTitle: "Alleenstaande Containers",
 		ImagesTitle:               "Images",
 		VolumesTitle:              "Volumes",
+		NetworksTitle:             "Networks",
 		CustomCommandTitle:        "Aangepast commando:",
 		ErrorTitle:                "Fout",
 		LogsTitle:                 "Logs",
@@ -78,6 +81,7 @@ func dutchSet() TranslationSet {
 		NoContainer:  "Geen container",
 		NoImages:     "Geen images",
 		NoVolumes:    "Geen volumes",
+		NoNetworks:   "Geen networks",
 
 		ConfirmQuit:                "Weet je zeker dat je weg wil gaan?",
 		MustForceToRemoveContainer: "Je kan geen draaiende container verwijderen tenzij je het forceert, Wil je het forceren?",
@@ -85,6 +89,7 @@ func dutchSet() TranslationSet {
 		ConfirmPruneImages:         "Weet je zeker dat je alle niet gebruikte images wil vernietigen?",
 		ConfirmPruneContainers:     "Weet je zeker dat je alle niet gestopte containers wil vernietigen?",
 		ConfirmPruneVolumes:        "Weet je zeker dat je alle niet gebruikte volumes wil vernietigen?",
+		ConfirmPruneNetworks:       "Weet je zeker dat je alle niet gebruikte networks wil vernietigen?",
 		StopService:                "Weet je zeker dat je deze service zijn containers wil stoppen?",
 		StopContainer:              "Weet je zeker dat je deze container wil stoppen?",
 		PressEnterToReturn:         "Druk op enter om terug te gaan naar lazydocker (Deze popup kan uit gezet worden door in de config dit neer te zetten `gui.returnImmediately: true`)",
diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go
index 46f0c543..62892182 100644
--- a/pkg/i18n/english.go
+++ b/pkg/i18n/english.go
@@ -73,24 +73,29 @@ type TranslationSet struct {
 	TopTitle                    string
 	ImagesTitle                 string
 	VolumesTitle                string
+	NetworksTitle               string
 	NoContainers                string
 	NoContainer                 string
 	NoImages                    string
 	NoVolumes                   string
+	NoNetworks                  string
 	NoServices                  string
 	RemoveImage                 string
 	RemoveVolume                string
+	RemoveNetwork               string
 	RemoveWithoutPrune          string
 	RemoveWithoutPruneWithForce string
 	RemoveWithForce             string
 	PruneImages                 string
 	PruneContainers             string
 	PruneVolumes                string
+	PruneNetworks               string
 	ConfirmPruneContainers      string
 	ConfirmStopContainers       string
 	ConfirmRemoveContainers     string
 	ConfirmPruneImages          string
 	ConfirmPruneVolumes         string
+	ConfirmPruneNetworks        string
 	PruningStatus               string
 	StopService                 string
 	PressEnterToReturn          string
@@ -186,11 +191,13 @@ func englishSet() TranslationSet {
 		DownProject:                 "down project",
 		RemoveImage:                 "remove image",
 		RemoveVolume:                "remove volume",
+		RemoveNetwork:               "remove network",
 		RemoveWithoutPrune:          "remove without deleting untagged parents",
 		RemoveWithoutPruneWithForce: "remove (forced) without deleting untagged parents",
 		RemoveWithForce:             "remove (forced)",
 		PruneContainers:             "prune exited containers",
 		PruneVolumes:                "prune unused volumes",
+		PruneNetworks:               "prune unused networks",
 		PruneImages:                 "prune unused images",
 		StopAllContainers:           "stop all containers",
 		RemoveAllContainers:         "remove all containers (forced)",
@@ -210,6 +217,7 @@ func englishSet() TranslationSet {
 		StandaloneContainersTitle: "Standalone Containers",
 		ImagesTitle:               "Images",
 		VolumesTitle:              "Volumes",
+		NetworksTitle:             "Networks",
 		CustomCommandTitle:        "Custom Command:",
 		BulkCommandTitle:          "Bulk Command:",
 		ErrorTitle:                "Error",
@@ -230,6 +238,7 @@ func englishSet() TranslationSet {
 		NoContainer:  "No container",
 		NoImages:     "No images",
 		NoVolumes:    "No volumes",
+		NoNetworks:   "No networks",
 		NoServices:   "No services",
 
 		ConfirmQuit:                "Are you sure you want to quit?",
@@ -241,6 +250,7 @@ func englishSet() TranslationSet {
 		ConfirmStopContainers:      "Are you sure you want to stop all containers?",
 		ConfirmRemoveContainers:    "Are you sure you want to remove all containers?",
 		ConfirmPruneVolumes:        "Are you sure you want to prune all unused volumes?",
+		ConfirmPruneNetworks:       "Are you sure you want to prune all unused networks?",
 		StopService:                "Are you sure you want to stop this service's containers?",
 		StopContainer:              "Are you sure you want to stop this container?",
 		PressEnterToReturn:         "Press enter to return to lazydocker (this prompt can be disabled in your config by setting `gui.returnImmediately: true`)",
diff --git a/pkg/i18n/french.go b/pkg/i18n/french.go
index 1cd79a8a..c2b826a6 100644
--- a/pkg/i18n/french.go
+++ b/pkg/i18n/french.go
@@ -53,11 +53,13 @@ func frenchSet() TranslationSet {
 		ViewLogs:                    "voir les enregistrements",
 		RemoveImage:                 "supprimer l'image",
 		RemoveVolume:                "supprimer le volume",
+		RemoveNetwork:               "supprimer le réseau",
 		RemoveWithoutPrune:          "supprimer sans effacer les parents non étiqueté",
 		RemoveWithoutPruneWithForce: "supprimer (forcer) sans effacer les parents non étiqueté",
 		RemoveWithForce:             "supprimer (forcer)",
 		PruneContainers:             "détruire les conteneurs arrêtes",
 		PruneVolumes:                "détruire les volumes non utilisés",
+		PruneNetworks:               "détruire les réseaux non utilisés",
 		PruneImages:                 "détruire les images non utilisés",
 		StopAllContainers:           "arrêter tous les conteneurs",
 		RemoveAllContainers:         "supprimer tous les conteneurs (forcer)",
@@ -76,6 +78,7 @@ func frenchSet() TranslationSet {
 		StandaloneContainersTitle: "Conteneurs Autonomes",
 		ImagesTitle:               "Images",
 		VolumesTitle:              "Volumes",
+		NetworksTitle:             "Réseaux",
 		CustomCommandTitle:        "Commande personalisé:",
 		BulkCommandTitle:          "Commande groupée:",
 		ErrorTitle:                "Erreur",
@@ -95,6 +98,7 @@ func frenchSet() TranslationSet {
 		NoContainer:  "Aucun conteneur",
 		NoImages:     "Aucune images",
 		NoVolumes:    "Aucun volumes",
+		NoNetworks:   "Aucun réseaux",
 
 		ConfirmQuit:                "Êtes vous certain de vouloir quitter?",
 		MustForceToRemoveContainer: "Vous ne pouvez pas supprimer un conteneur qui tourne sans le forcer. Voulez-vous le forcer ?",
@@ -104,6 +108,7 @@ func frenchSet() TranslationSet {
 		ConfirmStopContainers:      "Êtes-vous certain de vouloir arrêter tous les conteneurs ?",
 		ConfirmRemoveContainers:    "Êtes-vous certain de vouloir supprimer tous les conteneurs ?",
 		ConfirmPruneVolumes:        "Êtes-vous certain de vouloir détruire tous les volumes non utilisés ?",
+		ConfirmPruneNetworks:       "Êtes-vous certain de vouloir détruire tous les réseaux non utilisés ?",
 		StopService:                "Êtes-vous certain de vouloir arrêter le conteneur de ce service ?",
 		StopContainer:              "Êtes-vous certain de vouloir arrêter ce conteneur ?",
 		PressEnterToReturn:         "Appuiez sur Enter pour revenir à lazydocker (ce message peut être désactivé dans vos configurations en appliquant `gui.returnImmediately: true`)",
diff --git a/pkg/i18n/german.go b/pkg/i18n/german.go
index 4a205aa2..687e3eaa 100644
--- a/pkg/i18n/german.go
+++ b/pkg/i18n/german.go
@@ -44,9 +44,11 @@ func germanSet() TranslationSet {
 		ViewLogs:           "zeige Protokolle",
 		RemoveImage:        "entferne Image",
 		RemoveVolume:       "entferne Volume",
+		RemoveNetwork:      "entferne Netzwerk",
 		RemoveWithoutPrune: "entfernen, ohne die unmarkierten Eltern zu entfernen",
 		PruneContainers:    "entferne verlassene Container",
 		PruneVolumes:       "entferne unbenutzte Volumes",
+		PruneNetworks:      "entferne unbenutzte Netzwerk",
 		PruneImages:        "entferne unbenutzte Images",
 		ViewRestartOptions: "zeige Neustartoptionen",
 		RunCustomCommand:   "führe vordefinierten benutzerdefinierten Befehl aus",
@@ -59,6 +61,7 @@ func germanSet() TranslationSet {
 		StandaloneContainersTitle: "Alleinstehende Container",
 		ImagesTitle:               "Images",
 		VolumesTitle:              "Volumes",
+		NetworksTitle:             "Netzwerk",
 		CustomCommandTitle:        "Benutzerdefinierter Befehl",
 		ErrorTitle:                "Fehler",
 		LogsTitle:                 "Protokoll",
@@ -77,6 +80,7 @@ func germanSet() TranslationSet {
 		NoContainer:  "Kein Container",
 		NoImages:     "Keine Images",
 		NoVolumes:    "Keine Volumes",
+		NoNetworks:   "Keine Netzwerk",
 
 		ConfirmQuit:                "Bist du dir sicher, dass du verlassen möchtest?",
 		MustForceToRemoveContainer: "Du kannst keinen Container entfernen, der noch ausgeführt wird außer du erzwingst es. Möchtest du es erzwingen?",
@@ -84,6 +88,7 @@ func germanSet() TranslationSet {
 		ConfirmPruneImages:         "Bist du dir sicher, dass du alle unbenutzten Images entfernen möchtest?",
 		ConfirmPruneContainers:     "Bist du dir sicher, dass du alle angehaltenen Container entfernen möchtes?",
 		ConfirmPruneVolumes:        "Bist du dir sicher, dass du alle unbenutzen Volumes entfernen möchtest?",
+		ConfirmPruneNetworks:       "Bist du dir sicher, dass du alle unbenutzen Netzwerk entfernen möchtest?",
 		StopService:                "Bist du dir sicher, dass du den Dienst dieses Containers anhalten möchtest?",
 		StopContainer:              "Bist du dir sicher, dass du den Container anhalten möchtest?",
 		PressEnterToReturn:         "Drücke Eingabe um zu lazydocker zurückzukehren. (Diese Nachfrage kann in Deiner Konfiguration deaktiviert werden, indem du folgenden Wert setzt: `gui.returnImmediately: true`)",
diff --git a/pkg/i18n/polish.go b/pkg/i18n/polish.go
index 2cf12dd0..f3592745 100644
--- a/pkg/i18n/polish.go
+++ b/pkg/i18n/polish.go
@@ -44,9 +44,11 @@ func polishSet() TranslationSet {
 		ViewLogs:           "pokaż logi",
 		RemoveImage:        "usuń obraz",
 		RemoveVolume:       "usuń wolumen",
+		RemoveNetwork:      "usuń seici",
 		RemoveWithoutPrune: "usuń bez kasowania nieoznaczonych rodziców",
 		PruneContainers:    "wyczyść kontenery",
 		PruneVolumes:       "wyczyść nieużywane wolumeny",
+		PruneNetworks:      "wyczyść nieużywane sieci",
 		PruneImages:        "wyczyść nieużywane obrazy",
 		ViewRestartOptions: "pokaż opcje restartu",
 		RunCustomCommand:   "wykonaj predefiniowaną własną komende",
@@ -59,6 +61,7 @@ func polishSet() TranslationSet {
 		StandaloneContainersTitle: "Kontenery samodzielne",
 		ImagesTitle:               "Obrazy",
 		VolumesTitle:              "Wolumeny",
+		NetworksTitle:             "Seici",
 		CustomCommandTitle:        "Własna komenda:",
 		ErrorTitle:                "Błąd",
 		LogsTitle:                 "Logi",
@@ -77,6 +80,7 @@ func polishSet() TranslationSet {
 		NoContainer:  "Brak kontenera",
 		NoImages:     "Brak obrazów",
 		NoVolumes:    "Brak wolumenów",
+		NoNetworks:   "Brak sieci",
 
 		ConfirmQuit:                "Na pewno chcesz wyjść?",
 		MustForceToRemoveContainer: "Nie możesz usunąć uruchomionego kontenera dopóki nie zrobisz tego siłą. Chcesz wykonać to z siłą?",
@@ -84,6 +88,7 @@ func polishSet() TranslationSet {
 		ConfirmPruneImages:         "Na pewno wyczyścić wszystkie nieużywane obrazy?",
 		ConfirmPruneContainers:     "Na pewno wyczyścić wszystkie nieuruchomione kontenery?",
 		ConfirmPruneVolumes:        "Na pewno wyczyścić wszystkie nieużywane wolumeny?",
+		ConfirmPruneNetworks:       "Na pewno wyczyścić wszystkie nieużywane seici?",
 		StopService:                "Na pewno zatrzymać kontenery tego serwisu?",
 		StopContainer:              "Na pewno zatrzymać ten kontener?",
 		PressEnterToReturn:         "Wciśnij enter aby powrócić do lazydockera (ten komunikat może być wyłączony w konfiguracji poprzez ustawienie `gui.returnImmediately: true`)",
diff --git a/pkg/i18n/turkish.go b/pkg/i18n/turkish.go
index 4a378b7a..1e1bf47d 100644
--- a/pkg/i18n/turkish.go
+++ b/pkg/i18n/turkish.go
@@ -44,9 +44,11 @@ func turkishSet() TranslationSet {
 		ViewLogs:           "kayıt defterini görüntüle",
 		RemoveImage:        "imajı kaldır",
 		RemoveVolume:       "alanı kaldır",
+		RemoveNetwork:      "ağı kaldır",
 		RemoveWithoutPrune: "etkisiz ebeveynleri silmeden kaldır",
 		PruneContainers:    "çalışmayan konteynerleri temizle",
 		PruneVolumes:       "kullanılmayan alanları temizle",
+		PruneNetworks:      "kullanılmayan ağları temizle",
 		PruneImages:        "kullanılmayan imajları temizle",
 		ViewRestartOptions: "yeniden başlatma seçeneklerini görüntüle",
 		RunCustomCommand:   "önceden tanımlanmış özel komutu çalıştır",
@@ -59,6 +61,7 @@ func turkishSet() TranslationSet {
 		StandaloneContainersTitle: "Bağımsız Konteynerler",
 		ImagesTitle:               "Imajlar",
 		VolumesTitle:              "Alanlar",
+		NetworksTitle:             "Ağları",
 		CustomCommandTitle:        "Özel Komut:",
 		ErrorTitle:                "Hata",
 		LogsTitle:                 "Kayitlar",
@@ -77,6 +80,7 @@ func turkishSet() TranslationSet {
 		NoContainer:  "Konteyner yok",
 		NoImages:     "Imajlar yok",
 		NoVolumes:    "Alanlar yok",
+		NoNetworks:   "Ağları yok",
 
 		ConfirmQuit:                "Çıkmak istediğine emin misin?",
 		MustForceToRemoveContainer: "Zorlamadan çalışan bir konteyneri kaldıramazsınız. Zorlamak ister misin?",
@@ -84,6 +88,7 @@ func turkishSet() TranslationSet {
 		ConfirmPruneImages:         "Kullanılmayan tüm görüntüleri temizlemek istediğinize emin misiniz?",
 		ConfirmPruneContainers:     "Durdurulan tüm konteynerları temizlemek istediğinizden emin misiniz?",
 		ConfirmPruneVolumes:        "Kullanılmayan tüm alanları temizlemek istediğinizden emin misiniz?",
+		ConfirmPruneNetworks:       "Kullanılmayan tüm ağları temizlemek istediğinizden emin misiniz?",
 		StopService:                "Bu servisin konteynerlerini durdurmak istediğinize emin misiniz?",
 		StopContainer:              "Bu konteyneri durdurmak istediğinize emin misiniz?",
 		PressEnterToReturn:         "lazydocker' a geri dönmek için enter tuşuna basın ( Bu uyarı, `gui.return Immediately: true` ayarıyla devre dışı bırakılabilir)",
diff --git a/vendor/github.com/docker/distribution/reference/normalize.go b/vendor/github.com/docker/distribution/reference/normalize.go
index 2d71fc5e..b3dfb7a6 100644
--- a/vendor/github.com/docker/distribution/reference/normalize.go
+++ b/vendor/github.com/docker/distribution/reference/normalize.go
@@ -56,6 +56,35 @@ func ParseNormalizedNamed(s string) (Named, error) {
 	return named, nil
 }
 
+// ParseDockerRef normalizes the image reference following the docker convention. This is added
+// mainly for backward compatibility.
+// The reference returned can only be either tagged or digested. For reference contains both tag
+// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
+// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
+// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
+func ParseDockerRef(ref string) (Named, error) {
+	named, err := ParseNormalizedNamed(ref)
+	if err != nil {
+		return nil, err
+	}
+	if _, ok := named.(NamedTagged); ok {
+		if canonical, ok := named.(Canonical); ok {
+			// The reference is both tagged and digested, only
+			// return digested.
+			newNamed, err := WithName(canonical.Name())
+			if err != nil {
+				return nil, err
+			}
+			newCanonical, err := WithDigest(newNamed, canonical.Digest())
+			if err != nil {
+				return nil, err
+			}
+			return newCanonical, nil
+		}
+	}
+	return TagNameOnly(named), nil
+}
+
 // splitDockerDomain splits a repository name to domain and remotename string.
 // If no valid domain is found, the default domain is used. Repository name
 // needs to be already validated before.
diff --git a/vendor/github.com/docker/distribution/reference/reference.go b/vendor/github.com/docker/distribution/reference/reference.go
index 2f66cca8..8c0c23b2 100644
--- a/vendor/github.com/docker/distribution/reference/reference.go
+++ b/vendor/github.com/docker/distribution/reference/reference.go
@@ -205,7 +205,7 @@ func Parse(s string) (Reference, error) {
 	var repo repository
 
 	nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
-	if nameMatch != nil && len(nameMatch) == 3 {
+	if len(nameMatch) == 3 {
 		repo.domain = nameMatch[1]
 		repo.path = nameMatch[2]
 	} else {
diff --git a/vendor/github.com/gogo/protobuf/proto/text_parser.go b/vendor/github.com/gogo/protobuf/proto/text_parser.go
index 1ce0be2f..f85c0cc8 100644
--- a/vendor/github.com/gogo/protobuf/proto/text_parser.go
+++ b/vendor/github.com/gogo/protobuf/proto/text_parser.go
@@ -318,7 +318,7 @@ func unescape(s string) (ch string, tail string, err error) {
 		if i > utf8.MaxRune {
 			return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
 		}
-		return string(i), s, nil
+		return string(rune(i)), s, nil
 	}
 	return "", "", fmt.Errorf(`unknown escape \%c`, r)
 }
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
index 4e6c4b23..82da6c6a 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go
@@ -21,6 +21,9 @@ import "github.com/opencontainers/image-spec/specs-go"
 type Index struct {
 	specs.Versioned
 
+	// MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json`
+	MediaType string `json:"mediaType,omitempty"`
+
 	// Manifests references platform specific manifests.
 	Manifests []Descriptor `json:"manifests"`
 
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
index 7ff32c40..d72d15ce 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go
@@ -20,6 +20,9 @@ import "github.com/opencontainers/image-spec/specs-go"
 type Manifest struct {
 	specs.Versioned
 
+	// MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json`
+	MediaType string `json:"mediaType,omitempty"`
+
 	// Config references a configuration object for a container, by digest.
 	// The referenced configuration object is a JSON blob that the runtime uses to set up the container.
 	Config Descriptor `json:"config"`
diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/version.go b/vendor/github.com/opencontainers/image-spec/specs-go/version.go
index 5d493df2..0d9543f1 100644
--- a/vendor/github.com/opencontainers/image-spec/specs-go/version.go
+++ b/vendor/github.com/opencontainers/image-spec/specs-go/version.go
@@ -22,7 +22,7 @@ const (
 	// VersionMinor is for functionality in a backwards-compatible manner
 	VersionMinor = 0
 	// VersionPatch is for backwards-compatible bug fixes
-	VersionPatch = 1
+	VersionPatch = 2
 
 	// VersionDev indicates development branch. Releases will be empty string.
 	VersionDev = ""
diff --git a/vendor/modules.txt b/vendor/modules.txt
index a135a6d7..4812056c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -14,7 +14,7 @@ github.com/cloudfoundry/jibber_jabber
 # github.com/davecgh/go-spew v1.1.1
 ## explicit
 github.com/davecgh/go-spew/spew
-# github.com/docker/distribution v2.7.1+incompatible
+# github.com/docker/distribution v2.8.0+incompatible
 ## explicit
 github.com/docker/distribution/digestset
 github.com/docker/distribution/reference
@@ -97,8 +97,8 @@ github.com/gdamore/tcell/v2/terminfo/x/xterm_termite
 # github.com/go-errors/errors v1.4.2
 ## explicit; go 1.14
 github.com/go-errors/errors
-# github.com/gogo/protobuf v1.3.1
-## explicit
+# github.com/gogo/protobuf v1.3.2
+## explicit; go 1.15
 github.com/gogo/protobuf/proto
 # github.com/gookit/color v1.5.0
 ## explicit; go 1.13
@@ -157,7 +157,7 @@ github.com/mgutz/str
 # github.com/opencontainers/go-digest v1.0.0-rc1
 ## explicit
 github.com/opencontainers/go-digest
-# github.com/opencontainers/image-spec v1.0.1
+# github.com/opencontainers/image-spec v1.0.2
 ## explicit
 github.com/opencontainers/image-spec/specs-go
 github.com/opencontainers/image-spec/specs-go/v1