From 5cfbe0b78e3672dd67cd028b85d816fc19d6a614 Mon Sep 17 00:00:00 2001
From: jortkoopmans <jort@jabo-solutions.eu>
Date: Wed, 25 Nov 2020 18:26:22 +0100
Subject: squash

Signed-off-by: jortkoopmans <jort@jabo-solutions.eu>
---
 changelog.txt                                      |  30 ++
 cmd/podman/common/completion.go                    | 251 +++++++++---
 cmd/podman/common/create.go                        |  18 +-
 cmd/podman/common/create_opts.go                   | 153 +++++--
 cmd/podman/common/createparse.go                   |   2 +-
 cmd/podman/common/netflags.go                      |  34 +-
 cmd/podman/common/volumes.go                       | 102 +----
 cmd/podman/containers/ps.go                        |  20 +-
 cmd/podman/containers/top.go                       |  10 +-
 cmd/podman/images/list.go                          |   3 +-
 cmd/podman/images/load.go                          |   2 +-
 cmd/podman/networks/connect.go                     |   2 +-
 cmd/podman/networks/disconnect.go                  |   2 +-
 cmd/podman/networks/list.go                        |   2 +-
 cmd/podman/networks/rm.go                          |   1 +
 cmd/podman/pods/create.go                          |  30 +-
 cmd/podman/pods/top.go                             |   2 +-
 cmd/podman/root.go                                 |  52 ++-
 cmd/podman/volumes/list.go                         |   2 +-
 contrib/systemd/system/podman.service              |   3 +-
 docs/source/Tutorials.rst                          |   2 +-
 docs/source/conf.py                                |   4 +-
 docs/source/managecontainers.rst                   |   2 +
 docs/source/markdown/links/podman-list.1           |   1 -
 docs/source/markdown/links/podman-ls.1             |   1 -
 docs/source/markdown/podman-container.1.md         |   1 +
 docs/source/markdown/podman-create.1.md            |   9 +-
 docs/source/markdown/podman-export.1.md            |   2 +
 docs/source/markdown/podman-import.1.md            |   1 +
 docs/source/markdown/podman-load.1.md              |   3 +-
 docs/source/markdown/podman-ps.1.md                |   8 +-
 docs/source/markdown/podman-run.1.md               |   9 +-
 docs/source/markdown/podman-save.1.md              |   4 +-
 docs/source/markdown/podman-system-service.1.md    |   5 +-
 docs/source/markdown/podman-top.1.md               |   2 +-
 docs/source/markdown/podman.1.md                   |  12 +-
 docs/tutorials/mac_win_client.md                   |   2 +-
 go.mod                                             |   6 +-
 go.sum                                             |  12 +-
 libpod/container.go                                |  55 ++-
 libpod/container_api.go                            |  14 +
 libpod/container_internal.go                       |  37 +-
 libpod/healthcheck_linux.go                        |   4 +
 libpod/image/manifests.go                          |  36 +-
 libpod/network/config.go                           |  10 +
 libpod/network/create.go                           |   1 +
 libpod/network/netconflist.go                      |   7 +
 libpod/network/subnet.go                           |  14 +-
 libpod/network/subnet_test.go                      |  62 +++
 libpod/networking_linux.go                         |  28 +-
 libpod/rootless_cni_linux.go                       |   4 +-
 pkg/api/handlers/compat/containers.go              |  15 +-
 pkg/api/handlers/compat/containers_create.go       |  21 +-
 pkg/api/handlers/compat/info.go                    |   3 +-
 pkg/api/handlers/libpod/containers.go              |  24 ++
 pkg/api/handlers/types.go                          |  13 +-
 pkg/api/server/handler_api.go                      |   7 +-
 pkg/api/server/listener_api.go                     |   1 +
 pkg/api/server/server.go                           |   6 +-
 pkg/bindings/containers/containers.go              |  12 +
 pkg/domain/entities/images.go                      |   8 +-
 pkg/domain/infra/abi/containers.go                 |  15 +-
 pkg/domain/infra/tunnel/containers.go              |  25 +-
 pkg/specgen/generate/container_create.go           |  12 +-
 pkg/specgen/generate/storage.go                    |  61 ++-
 pkg/specgen/namespaces.go                          |   6 -
 pkg/specgen/specgen.go                             |  38 +-
 pkg/specgen/volumes.go                             | 149 +++++++
 test/apiv2/rest_api/__init__.py                    |  15 +-
 test/apiv2/rest_api/test_rest_v2_0_0.py            |  90 +++-
 test/apiv2/rest_api/v1_test_rest_v1_0_0.py         |   4 +-
 test/e2e/config/containers-remote.conf             |  51 +++
 test/e2e/containers_conf_test.go                   |  68 +++
 test/e2e/create_staticmac_test.go                  |  18 +
 test/e2e/network_test.go                           |  55 +--
 test/e2e/pod_create_test.go                        |  20 +
 test/e2e/ps_test.go                                |   6 +
 test/e2e/run_networking_test.go                    |  29 ++
 test/e2e/run_test.go                               |   4 +-
 test/python/docker/__init__.py                     |  14 +-
 test/python/docker/common.py                       |   4 +-
 test/python/docker/test_containers.py              |   2 +-
 test/python/docker/test_images.py                  |   4 +-
 .../containers/common/pkg/config/config.go         |   4 +
 .../containers/common/pkg/config/containers.conf   |  10 +-
 .../containers/common/pkg/config/default.go        |   4 +-
 .../containers/common/pkg/retry/retry.go           |   2 +-
 .../containers/common/pkg/seccomp/default_linux.go |   2 +
 .../containers/common/pkg/seccomp/supported.go     |   2 +
 .../containers/common/version/version.go           |   2 +-
 .../image/v5/pkg/sysregistriesv2/shortnames.go     |   2 +-
 .../containers/image/v5/version/version.go         |   2 +-
 vendor/github.com/containers/storage/VERSION       |   2 +-
 vendor/github.com/containers/storage/go.mod        |   2 +-
 vendor/github.com/containers/storage/go.sum        |   4 +-
 .../containers/storage/pkg/unshare/unshare.go      |   1 +
 .../klauspost/compress/flate/gen_inflate.go        | 114 +++---
 .../github.com/klauspost/compress/flate/inflate.go |   7 +
 .../klauspost/compress/flate/inflate_gen.go        | 456 ++++++++++++---------
 .../github.com/klauspost/compress/zstd/README.md   |   4 +-
 .../github.com/klauspost/compress/zstd/decoder.go  |  10 +-
 vendor/modules.txt                                 |   8 +-
 102 files changed, 1687 insertions(+), 830 deletions(-)
 delete mode 100644 docs/source/markdown/links/podman-list.1
 delete mode 100644 docs/source/markdown/links/podman-ls.1
 create mode 100644 pkg/specgen/volumes.go
 create mode 100644 test/e2e/config/containers-remote.conf

diff --git a/changelog.txt b/changelog.txt
index 4d423ca44..326f52718 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,33 @@
+- Changelog for HEAD (2020-11-24):
+  * Set PATH env in systemd timer.
+  * Docker compat API fixes
+  * shell completions: remove usage of ShellCompDirectiveError
+  * more shell completion improvements
+  * Fix ip-range for classless subnet masks
+  * Bump github.com/containers/common from 0.27.0 to 0.29.0
+  * Add podman container ps command
+  * clarify ps(1) fallback of `podman top`
+  * APIv2 - create container sets wrong entrypoint
+  * Enable remote shell completion without a running endpoint
+  * Specify what the replace flag replaces in help text
+  * APIv2 - strip CAP_ prefix from capabilities in json
+  * Make c.networks() list include the default network
+  * Allow containers to --restart on-failure with --rm
+  * REST API v2 - list of images - mandatory Created attribute
+  * Allow multiple --network flags for podman run/create
+  * fix container cgroup lookup
+  * Make podman service log events
+  * vendor in containers/storage v1.24.1 containers/image v5.8.1
+  * Document containers.conf settings for remote connections
+  * Shell completion for podman ps and podman pod ps --filter
+  * Add alias for podman network rm -> remove
+  * add network connect|disconnect compat endpoints
+  * Fix sed regex to update version in version/version.go
+  * Github-Actions: Send e-mail on Cirrus cron failure
+  * Align the podman pod ps --filter behavior with podman ps
+  * podman-remote network rm --force is broken
+  * Remove build \!remote flags from test
+
 - Changelog for v2.2.0-rc1 (2020-11-18):
   * Add release notes for v2.2.0-RC1
   * correct numbering typo
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index db4d3d0d3..9856e46ef 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -12,7 +12,9 @@ import (
 	"github.com/containers/podman/v2/libpod/define"
 	"github.com/containers/podman/v2/pkg/domain/entities"
 	"github.com/containers/podman/v2/pkg/registries"
+	"github.com/containers/podman/v2/pkg/rootless"
 	systemdGen "github.com/containers/podman/v2/pkg/systemd/generate"
+	"github.com/containers/podman/v2/pkg/util"
 	"github.com/spf13/cobra"
 )
 
@@ -36,7 +38,35 @@ const (
 
 type keyValueCompletion map[string]func(s string) ([]string, cobra.ShellCompDirective)
 
-func getContainers(toComplete string, cType completeType, statuses ...string) ([]string, cobra.ShellCompDirective) {
+func setupContainerEngine(cmd *cobra.Command) (entities.ContainerEngine, error) {
+	containerEngine, err := registry.NewContainerEngine(cmd, []string{})
+	if err != nil {
+		cobra.CompErrorln(err.Error())
+		return nil, err
+	}
+	if !registry.IsRemote() && rootless.IsRootless() {
+		err := containerEngine.SetupRootless(registry.Context(), cmd)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return containerEngine, nil
+}
+
+func setupImageEngine(cmd *cobra.Command) (entities.ImageEngine, error) {
+	imageEngine, err := registry.NewImageEngine(cmd, []string{})
+	if err != nil {
+		return nil, err
+	}
+	// we also need to set up the container engine since this
+	// is required to setup the rootless namespace
+	if _, err = setupContainerEngine(cmd); err != nil {
+		return nil, err
+	}
+	return imageEngine, nil
+}
+
+func getContainers(cmd *cobra.Command, toComplete string, cType completeType, statuses ...string) ([]string, cobra.ShellCompDirective) {
 	suggestions := []string{}
 	listOpts := entities.ContainerListOptions{
 		Filters: make(map[string][]string),
@@ -47,10 +77,15 @@ func getContainers(toComplete string, cType completeType, statuses ...string) ([
 		listOpts.Filters["status"] = statuses
 	}
 
-	containers, err := registry.ContainerEngine().ContainerList(registry.GetContext(), listOpts)
+	engine, err := setupContainerEngine(cmd)
+	if err != nil {
+		cobra.CompErrorln(err.Error())
+		return nil, cobra.ShellCompDirectiveNoFileComp
+	}
+	containers, err := engine.ContainerList(registry.GetContext(), listOpts)
 	if err != nil {
 		cobra.CompErrorln(err.Error())
-		return nil, cobra.ShellCompDirectiveError
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 
 	for _, c := range containers {
@@ -68,7 +103,7 @@ func getContainers(toComplete string, cType completeType, statuses ...string) ([
 	return suggestions, cobra.ShellCompDirectiveNoFileComp
 }
 
-func getPods(toComplete string, cType completeType, statuses ...string) ([]string, cobra.ShellCompDirective) {
+func getPods(cmd *cobra.Command, toComplete string, cType completeType, statuses ...string) ([]string, cobra.ShellCompDirective) {
 	suggestions := []string{}
 	listOpts := entities.PodPSOptions{
 		Filters: make(map[string][]string),
@@ -77,10 +112,15 @@ func getPods(toComplete string, cType completeType, statuses ...string) ([]strin
 		listOpts.Filters["status"] = statuses
 	}
 
-	pods, err := registry.ContainerEngine().PodPs(registry.GetContext(), listOpts)
+	engine, err := setupContainerEngine(cmd)
 	if err != nil {
 		cobra.CompErrorln(err.Error())
-		return nil, cobra.ShellCompDirectiveError
+		return nil, cobra.ShellCompDirectiveNoFileComp
+	}
+	pods, err := engine.PodPs(registry.GetContext(), listOpts)
+	if err != nil {
+		cobra.CompErrorln(err.Error())
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 
 	for _, pod := range pods {
@@ -98,14 +138,19 @@ func getPods(toComplete string, cType completeType, statuses ...string) ([]strin
 	return suggestions, cobra.ShellCompDirectiveNoFileComp
 }
 
-func getVolumes(toComplete string) ([]string, cobra.ShellCompDirective) {
+func getVolumes(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
 	suggestions := []string{}
 	lsOpts := entities.VolumeListOptions{}
 
-	volumes, err := registry.ContainerEngine().VolumeList(registry.GetContext(), lsOpts)
+	engine, err := setupContainerEngine(cmd)
+	if err != nil {
+		cobra.CompErrorln(err.Error())
+		return nil, cobra.ShellCompDirectiveNoFileComp
+	}
+	volumes, err := engine.VolumeList(registry.GetContext(), lsOpts)
 	if err != nil {
 		cobra.CompErrorln(err.Error())
-		return nil, cobra.ShellCompDirectiveError
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 
 	for _, v := range volumes {
@@ -116,14 +161,19 @@ func getVolumes(toComplete string) ([]string, cobra.ShellCompDirective) {
 	return suggestions, cobra.ShellCompDirectiveNoFileComp
 }
 
-func getImages(toComplete string) ([]string, cobra.ShellCompDirective) {
+func getImages(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
 	suggestions := []string{}
 	listOptions := entities.ImageListOptions{}
 
-	images, err := registry.ImageEngine().List(registry.GetContext(), listOptions)
+	engine, err := setupImageEngine(cmd)
+	if err != nil {
+		cobra.CompErrorln(err.Error())
+		return nil, cobra.ShellCompDirectiveNoFileComp
+	}
+	images, err := engine.List(registry.GetContext(), listOptions)
 	if err != nil {
 		cobra.CompErrorln(err.Error())
-		return nil, cobra.ShellCompDirectiveError
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 
 	for _, image := range images {
@@ -166,19 +216,24 @@ func getRegistries() ([]string, cobra.ShellCompDirective) {
 	regs, err := registries.GetRegistries()
 	if err != nil {
 		cobra.CompErrorln(err.Error())
-		return nil, cobra.ShellCompDirectiveError
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 	return regs, cobra.ShellCompDirectiveNoFileComp
 }
 
-func getNetworks(toComplete string) ([]string, cobra.ShellCompDirective) {
+func getNetworks(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
 	suggestions := []string{}
 	networkListOptions := entities.NetworkListOptions{}
 
-	networks, err := registry.ContainerEngine().NetworkList(registry.Context(), networkListOptions)
+	engine, err := setupContainerEngine(cmd)
+	if err != nil {
+		cobra.CompErrorln(err.Error())
+		return nil, cobra.ShellCompDirectiveNoFileComp
+	}
+	networks, err := engine.NetworkList(registry.Context(), networkListOptions)
 	if err != nil {
 		cobra.CompErrorln(err.Error())
-		return nil, cobra.ShellCompDirectiveError
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 
 	for _, n := range networks {
@@ -266,7 +321,7 @@ func AutocompleteContainers(cmd *cobra.Command, args []string, toComplete string
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getContainers(toComplete, completeDefault)
+	return getContainers(cmd, toComplete, completeDefault)
 }
 
 // AutocompleteContainersCreated - Autocomplete only created container names.
@@ -274,7 +329,7 @@ func AutocompleteContainersCreated(cmd *cobra.Command, args []string, toComplete
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getContainers(toComplete, completeDefault, "created")
+	return getContainers(cmd, toComplete, completeDefault, "created")
 }
 
 // AutocompleteContainersExited - Autocomplete only exited container names.
@@ -282,7 +337,7 @@ func AutocompleteContainersExited(cmd *cobra.Command, args []string, toComplete
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getContainers(toComplete, completeDefault, "exited")
+	return getContainers(cmd, toComplete, completeDefault, "exited")
 }
 
 // AutocompleteContainersPaused - Autocomplete only paused container names.
@@ -290,7 +345,7 @@ func AutocompleteContainersPaused(cmd *cobra.Command, args []string, toComplete
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getContainers(toComplete, completeDefault, "paused")
+	return getContainers(cmd, toComplete, completeDefault, "paused")
 }
 
 // AutocompleteContainersRunning - Autocomplete only running container names.
@@ -298,7 +353,7 @@ func AutocompleteContainersRunning(cmd *cobra.Command, args []string, toComplete
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getContainers(toComplete, completeDefault, "running")
+	return getContainers(cmd, toComplete, completeDefault, "running")
 }
 
 // AutocompleteContainersStartable - Autocomplete only created and exited container names.
@@ -306,7 +361,7 @@ func AutocompleteContainersStartable(cmd *cobra.Command, args []string, toComple
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getContainers(toComplete, completeDefault, "created", "exited")
+	return getContainers(cmd, toComplete, completeDefault, "created", "exited")
 }
 
 // AutocompletePods - Autocomplete all pod names.
@@ -314,7 +369,7 @@ func AutocompletePods(cmd *cobra.Command, args []string, toComplete string) ([]s
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getPods(toComplete, completeDefault)
+	return getPods(cmd, toComplete, completeDefault)
 }
 
 // AutocompletePodsRunning - Autocomplete only running pod names.
@@ -323,7 +378,7 @@ func AutocompletePodsRunning(cmd *cobra.Command, args []string, toComplete strin
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getPods(toComplete, completeDefault, "running", "degraded")
+	return getPods(cmd, toComplete, completeDefault, "running", "degraded")
 }
 
 // AutocompleteContainersAndPods - Autocomplete container names and pod names.
@@ -331,8 +386,8 @@ func AutocompleteContainersAndPods(cmd *cobra.Command, args []string, toComplete
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	containers, _ := getContainers(toComplete, completeDefault)
-	pods, _ := getPods(toComplete, completeDefault)
+	containers, _ := getContainers(cmd, toComplete, completeDefault)
+	pods, _ := getPods(cmd, toComplete, completeDefault)
 	return append(containers, pods...), cobra.ShellCompDirectiveNoFileComp
 }
 
@@ -341,8 +396,8 @@ func AutocompleteContainersAndImages(cmd *cobra.Command, args []string, toComple
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	containers, _ := getContainers(toComplete, completeDefault)
-	images, _ := getImages(toComplete)
+	containers, _ := getContainers(cmd, toComplete, completeDefault)
+	images, _ := getImages(cmd, toComplete)
 	return append(containers, images...), cobra.ShellCompDirectiveNoFileComp
 }
 
@@ -351,7 +406,7 @@ func AutocompleteVolumes(cmd *cobra.Command, args []string, toComplete string) (
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getVolumes(toComplete)
+	return getVolumes(cmd, toComplete)
 }
 
 // AutocompleteImages - Autocomplete images.
@@ -359,7 +414,7 @@ func AutocompleteImages(cmd *cobra.Command, args []string, toComplete string) ([
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getImages(toComplete)
+	return getImages(cmd, toComplete)
 }
 
 // AutocompleteCreateRun - Autocomplete only the fist argument as image and then do file completion.
@@ -368,7 +423,7 @@ func AutocompleteCreateRun(cmd *cobra.Command, args []string, toComplete string)
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 	if len(args) < 1 {
-		return getImages(toComplete)
+		return getImages(cmd, toComplete)
 	}
 	// TODO: add path completion for files in the image
 	return nil, cobra.ShellCompDirectiveDefault
@@ -387,7 +442,7 @@ func AutocompleteNetworks(cmd *cobra.Command, args []string, toComplete string)
 	if !validCurrentCmdLine(cmd, args, toComplete) {
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
-	return getNetworks(toComplete)
+	return getNetworks(cmd, toComplete)
 }
 
 // AutocompleteCpCommand - Autocomplete podman cp command args.
@@ -396,7 +451,7 @@ func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string)
 		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 	if len(args) < 2 {
-		containers, _ := getContainers(toComplete, completeDefault)
+		containers, _ := getContainers(cmd, toComplete, completeDefault)
 		for _, container := range containers {
 			// TODO: Add path completion for inside the container if possible
 			if strings.HasPrefix(container, toComplete) {
@@ -410,6 +465,37 @@ func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string)
 	return nil, cobra.ShellCompDirectiveNoFileComp
 }
 
+// AutocompleteNetworkConnectCmd - Autocomplete podman network connect/disconnect command args.
+func AutocompleteNetworkConnectCmd(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+	if len(args) == 0 {
+		return getNetworks(cmd, toComplete)
+	}
+	if len(args) == 1 {
+		return getContainers(cmd, toComplete, completeDefault)
+	}
+	// don't complete more than 2 args
+	return nil, cobra.ShellCompDirectiveNoFileComp
+}
+
+// AutocompleteTopCmd - Autocomplete podman top/pod top command args.
+func AutocompleteTopCmd(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+	latest := cmd.Flags().Lookup("latest")
+	// only complete containers/pods as first arg if latest is not set
+	if len(args) == 0 && (latest == nil || !latest.Changed) {
+		if cmd.Parent().Name() == "pod" {
+			// need to complete pods since we are using pod top
+			return getPods(cmd, toComplete, completeDefault)
+		}
+		return getContainers(cmd, toComplete, completeDefault)
+	}
+	descriptors, err := util.GetContainerPidInformationDescriptors()
+	if err != nil {
+		cobra.CompErrorln(err.Error())
+		return nil, cobra.ShellCompDirectiveNoFileComp
+	}
+	return descriptors, cobra.ShellCompDirectiveNoFileComp
+}
+
 // AutocompleteSystemConnections - Autocomplete system connections.
 func AutocompleteSystemConnections(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
 	if !validCurrentCmdLine(cmd, args, toComplete) {
@@ -419,7 +505,7 @@ func AutocompleteSystemConnections(cmd *cobra.Command, args []string, toComplete
 	cfg, err := config.ReadCustomConfig()
 	if err != nil {
 		cobra.CompErrorln(err.Error())
-		return nil, cobra.ShellCompDirectiveError
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 
 	for k, v := range cfg.Engine.ServiceDestinations {
@@ -464,7 +550,7 @@ func AutocompleteCreateAttach(cmd *cobra.Command, args []string, toComplete stri
 // -> host,container:[name],ns:[path],private
 func AutocompleteNamespace(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
 	kv := keyValueCompletion{
-		"container:": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeDefault) },
+		"container:": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
 		"ns:":        func(s string) ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveDefault },
 		"host":       nil,
 		"private":    nil,
@@ -567,7 +653,8 @@ func AutocompleteUserFlag(cmd *cobra.Command, args []string, toComplete string)
 		// but at this point we don't know the image.
 		file, err := os.Open("/etc/group")
 		if err != nil {
-			return nil, cobra.ShellCompDirectiveError
+			cobra.CompErrorln(err.Error())
+			return nil, cobra.ShellCompDirectiveNoFileComp
 		}
 		defer file.Close()
 
@@ -583,7 +670,8 @@ func AutocompleteUserFlag(cmd *cobra.Command, args []string, toComplete string)
 			}
 		}
 		if err = scanner.Err(); err != nil {
-			return nil, cobra.ShellCompDirectiveError
+			cobra.CompErrorln(err.Error())
+			return nil, cobra.ShellCompDirectiveNoFileComp
 		}
 		return groups, cobra.ShellCompDirectiveNoFileComp
 	}
@@ -592,7 +680,8 @@ func AutocompleteUserFlag(cmd *cobra.Command, args []string, toComplete string)
 	// but at this point we don't know the image.
 	file, err := os.Open("/etc/passwd")
 	if err != nil {
-		return nil, cobra.ShellCompDirectiveError
+		cobra.CompErrorln(err.Error())
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 	defer file.Close()
 
@@ -607,7 +696,7 @@ func AutocompleteUserFlag(cmd *cobra.Command, args []string, toComplete string)
 		}
 	}
 	if err = scanner.Err(); err != nil {
-		return nil, cobra.ShellCompDirectiveError
+		return nil, cobra.ShellCompDirectiveNoFileComp
 	}
 	return users, cobra.ShellCompDirectiveNoSpace
 }
@@ -623,7 +712,7 @@ func AutocompleteMountFlag(cmd *cobra.Command, args []string, toComplete string)
 // AutocompleteVolumeFlag - Autocomplete volume flag options.
 // -> volumes and paths
 func AutocompleteVolumeFlag(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
-	volumes, _ := getVolumes(toComplete)
+	volumes, _ := getVolumes(cmd, toComplete)
 	directive := cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveDefault
 	if strings.Contains(toComplete, ":") {
 		// add space after second path
@@ -641,8 +730,22 @@ func AutocompleteJSONFormat(cmd *cobra.Command, args []string, toComplete string
 // AutocompleteEventFilter - Autocomplete event filter flag options.
 // -> "container=", "event=", "image=", "pod=", "volume=", "type="
 func AutocompleteEventFilter(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
-	filters := []string{"container=", "event=", "image=", "pod=", "volume=", "type="}
-	return filters, cobra.ShellCompDirectiveNoSpace
+	eventTypes := func(_ string) ([]string, cobra.ShellCompDirective) {
+		return []string{"attach", "checkpoint", "cleanup", "commit", "create", "exec",
+			"export", "import", "init", "kill", "mount", "pause", "prune", "remove",
+			"restart", "restore", "start", "stop", "sync", "unmount", "unpause",
+			"pull", "push", "save", "tag", "untag", "refresh", "renumber",
+		}, cobra.ShellCompDirectiveNoFileComp
+	}
+	kv := keyValueCompletion{
+		"container=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
+		"image=":     func(s string) ([]string, cobra.ShellCompDirective) { return getImages(cmd, s) },
+		"pod=":       func(s string) ([]string, cobra.ShellCompDirective) { return getPods(cmd, s, completeDefault) },
+		"volume=":    func(s string) ([]string, cobra.ShellCompDirective) { return getVolumes(cmd, s) },
+		"event=":     eventTypes,
+		"type=":      eventTypes,
+	}
+	return completeKeyValues(toComplete, kv)
 }
 
 // AutocompleteSystemdRestartOptions - Autocomplete systemd restart options.
@@ -753,15 +856,15 @@ var containerStatuses = []string{"created", "running", "paused", "stopped", "exi
 // AutocompletePsFilters - Autocomplete ps filter options.
 func AutocompletePsFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
 	kv := keyValueCompletion{
-		"id=":   func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeIDs) },
-		"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeNames) },
+		"id=":   func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeIDs) },
+		"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeNames) },
 		"status=": func(_ string) ([]string, cobra.ShellCompDirective) {
 			return containerStatuses, cobra.ShellCompDirectiveNoFileComp
 		},
-		"ancestor": func(s string) ([]string, cobra.ShellCompDirective) { return getImages(s) },
-		"before=":  func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeDefault) },
-		"since=":   func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeDefault) },
-		"volume=":  func(s string) ([]string, cobra.ShellCompDirective) { return getVolumes(s) },
+		"ancestor": func(s string) ([]string, cobra.ShellCompDirective) { return getImages(cmd, s) },
+		"before=":  func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
+		"since=":   func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
+		"volume=":  func(s string) ([]string, cobra.ShellCompDirective) { return getVolumes(cmd, s) },
 		"health=": func(_ string) ([]string, cobra.ShellCompDirective) {
 			return []string{define.HealthCheckHealthy,
 				define.HealthCheckUnhealthy}, cobra.ShellCompDirectiveNoFileComp
@@ -776,14 +879,14 @@ func AutocompletePsFilters(cmd *cobra.Command, args []string, toComplete string)
 // AutocompletePodPsFilters - Autocomplete pod ps filter options.
 func AutocompletePodPsFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
 	kv := keyValueCompletion{
-		"id=":   func(s string) ([]string, cobra.ShellCompDirective) { return getPods(s, completeIDs) },
-		"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getPods(s, completeNames) },
+		"id=":   func(s string) ([]string, cobra.ShellCompDirective) { return getPods(cmd, s, completeIDs) },
+		"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getPods(cmd, s, completeNames) },
 		"status=": func(_ string) ([]string, cobra.ShellCompDirective) {
 			return []string{"stopped", "running",
 				"paused", "exited", "dead", "created", "degraded"}, cobra.ShellCompDirectiveNoFileComp
 		},
-		"ctr-ids=":    func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeIDs) },
-		"ctr-names=":  func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeNames) },
+		"ctr-ids=":    func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeIDs) },
+		"ctr-names=":  func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeNames) },
 		"ctr-number=": nil,
 		"ctr-status=": func(_ string) ([]string, cobra.ShellCompDirective) {
 			return containerStatuses, cobra.ShellCompDirectiveNoFileComp
@@ -792,3 +895,47 @@ func AutocompletePodPsFilters(cmd *cobra.Command, args []string, toComplete stri
 	}
 	return completeKeyValues(toComplete, kv)
 }
+
+// AutocompleteImageFilters - Autocomplete image ls --filter options.
+func AutocompleteImageFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+	getBool := func(_ string) ([]string, cobra.ShellCompDirective) {
+		return []string{"true", "false"}, cobra.ShellCompDirectiveNoFileComp
+	}
+	getImg := func(s string) ([]string, cobra.ShellCompDirective) { return getImages(cmd, s) }
+	kv := keyValueCompletion{
+		"before=":    getImg,
+		"since=":     getImg,
+		"label=":     nil,
+		"reference=": nil,
+		"dangling=":  getBool,
+		"readonly=":  getBool,
+	}
+	return completeKeyValues(toComplete, kv)
+}
+
+// AutocompleteNetworkFilters - Autocomplete network ls --filter options.
+func AutocompleteNetworkFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+	kv := keyValueCompletion{
+		"name=":   func(s string) ([]string, cobra.ShellCompDirective) { return getNetworks(cmd, s) },
+		"plugin=": nil,
+	}
+	return completeKeyValues(toComplete, kv)
+}
+
+// AutocompleteVolumeFilters - Autocomplete volume ls --filter options.
+func AutocompleteVolumeFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+	local := func(_ string) ([]string, cobra.ShellCompDirective) {
+		return []string{"local"}, cobra.ShellCompDirectiveNoFileComp
+	}
+	kv := keyValueCompletion{
+		"name=":   func(s string) ([]string, cobra.ShellCompDirective) { return getVolumes(cmd, s) },
+		"driver=": local,
+		"scope=":  local,
+		"label=":  nil,
+		"opt=":    nil,
+		"dangling=": func(_ string) ([]string, cobra.ShellCompDirective) {
+			return []string{"true", "false"}, cobra.ShellCompDirectiveNoFileComp
+		},
+	}
+	return completeKeyValues(toComplete, kv)
+}
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index ab3a984f0..599b430ea 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -84,7 +84,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 	cgroupsFlagName := "cgroups"
 	createFlags.StringVar(
 		&cf.CGroupsMode,
-		cgroupsFlagName, containerConfig.Cgroups(),
+		cgroupsFlagName, cgroupConfig(),
 		`control container cgroup configuration ("enabled"|"disabled"|"no-conmon"|"split")`,
 	)
 	_ = cmd.RegisterFlagCompletionFunc(cgroupsFlagName, AutocompleteCgroupMode)
@@ -180,7 +180,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 	deviceFlagName := "device"
 	createFlags.StringSliceVar(
 		&cf.Devices,
-		deviceFlagName, containerConfig.Devices(),
+		deviceFlagName, devices(),
 		fmt.Sprintf("Add a host device to the container"),
 	)
 	_ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
@@ -238,7 +238,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 
 	envFlagName := "env"
 	createFlags.StringArrayP(
-		envFlagName, "e", containerConfig.Env(),
+		envFlagName, "e", env(),
 		"Set environment variables in container",
 	)
 	_ = cmd.RegisterFlagCompletionFunc(envFlagName, completion.AutocompleteNone)
@@ -357,7 +357,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 	initPathFlagName := "init-path"
 	createFlags.StringVar(
 		&cf.InitPath,
-		initPathFlagName, containerConfig.InitPath(),
+		initPathFlagName, initPath(),
 		// Do not use  the Value field for setting the default value to determine user input (i.e., non-empty string)
 		fmt.Sprintf("Path to the container-init binary"),
 	)
@@ -508,7 +508,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 
 	pidsLimitFlagName := "pids-limit"
 	createFlags.Int64(
-		pidsLimitFlagName, containerConfig.PidsLimit(),
+		pidsLimitFlagName, pidsLimit(),
 		"Tune container pids limit (set 0 for unlimited, -1 for server defaults)",
 	)
 	_ = cmd.RegisterFlagCompletionFunc(pidsLimitFlagName, completion.AutocompleteNone)
@@ -543,7 +543,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 	pullFlagName := "pull"
 	createFlags.StringVar(
 		&cf.Pull,
-		pullFlagName, containerConfig.Engine.PullPolicy,
+		pullFlagName, policy(),
 		`Pull image before creating ("always"|"missing"|"never")`,
 	)
 	_ = cmd.RegisterFlagCompletionFunc(pullFlagName, AutocompletePullOption)
@@ -606,7 +606,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 
 	shmSizeFlagName := "shm-size"
 	createFlags.String(
-		shmSizeFlagName, containerConfig.ShmSize(),
+		shmSizeFlagName, shmSize(),
 		"Size of /dev/shm "+sizeWithUnitFormat,
 	)
 	_ = cmd.RegisterFlagCompletionFunc(shmSizeFlagName, completion.AutocompleteNone)
@@ -715,7 +715,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 	ulimitFlagName := "ulimit"
 	createFlags.StringSliceVar(
 		&cf.Ulimit,
-		ulimitFlagName, containerConfig.Ulimits(),
+		ulimitFlagName, ulimits(),
 		"Ulimit options",
 	)
 	_ = cmd.RegisterFlagCompletionFunc(ulimitFlagName, completion.AutocompleteNone)
@@ -753,7 +753,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
 	volumeFlagName := "volume"
 	createFlags.StringArrayVarP(
 		&cf.Volume,
-		volumeFlagName, "v", containerConfig.Volumes(),
+		volumeFlagName, "v", volumes(),
 		"Bind mount a volume into the container",
 	)
 	_ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag)
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go
index 4b52663c3..6dc43dbc6 100644
--- a/cmd/podman/common/create_opts.go
+++ b/cmd/podman/common/create_opts.go
@@ -6,6 +6,7 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/containers/podman/v2/cmd/podman/registry"
 	"github.com/containers/podman/v2/pkg/api/handlers"
 	"github.com/containers/podman/v2/pkg/cgroups"
 	"github.com/containers/podman/v2/pkg/domain/entities"
@@ -133,10 +134,9 @@ func stringMaptoArray(m map[string]string) []string {
 // a specgen spec.
 func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroupsManager string) (*ContainerCLIOpts, []string, error) {
 	var (
-		aliases    []string
 		capAdd     []string
 		cappDrop   []string
-		entrypoint string
+		entrypoint *string
 		init       bool
 		specPorts  []specgen.PortMapping
 	)
@@ -180,13 +180,14 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
 	// marshall it to json; otherwise it should just be the string
 	// value
 	if len(cc.Config.Entrypoint) > 0 {
-		entrypoint = cc.Config.Entrypoint[0]
+		entrypoint = &cc.Config.Entrypoint[0]
 		if len(cc.Config.Entrypoint) > 1 {
 			b, err := json.Marshal(cc.Config.Entrypoint)
 			if err != nil {
 				return nil, nil, err
 			}
-			entrypoint = string(b)
+			var jsonString = string(b)
+			entrypoint = &jsonString
 		}
 	}
 
@@ -210,7 +211,7 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
 		mounts = append(mounts, mount)
 	}
 
-	//volumes
+	// volumes
 	volumes := make([]string, 0, len(cc.Config.Volumes))
 	for v := range cc.Config.Volumes {
 		volumes = append(volumes, v)
@@ -240,16 +241,6 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
 		}
 	}
 
-	// network names
-	endpointsConfig := cc.NetworkingConfig.EndpointsConfig
-	cniNetworks := make([]string, 0, len(endpointsConfig))
-	for netName, endpoint := range endpointsConfig {
-		cniNetworks = append(cniNetworks, netName)
-		if len(endpoint.Aliases) > 0 {
-			aliases = append(aliases, endpoint.Aliases...)
-		}
-	}
-
 	// netMode
 	nsmode, _, err := specgen.ParseNetworkNamespace(cc.HostConfig.NetworkMode.NetworkName())
 	if err != nil {
@@ -266,8 +257,6 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
 	// defined when there is only one network.
 	netInfo := entities.NetOptions{
 		AddHosts:     cc.HostConfig.ExtraHosts,
-		Aliases:      aliases,
-		CNINetworks:  cniNetworks,
 		DNSOptions:   cc.HostConfig.DNSOptions,
 		DNSSearch:    cc.HostConfig.DNSSearch,
 		DNSServers:   dns,
@@ -275,31 +264,58 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
 		PublishPorts: specPorts,
 	}
 
-	// static IP and MAC
-	if len(endpointsConfig) == 1 {
-		for _, ep := range endpointsConfig {
-			// if IP address is provided
-			if len(ep.IPAddress) > 0 {
-				staticIP := net.ParseIP(ep.IPAddress)
-				netInfo.StaticIP = &staticIP
+	// network names
+	switch {
+	case len(cc.NetworkingConfig.EndpointsConfig) > 0:
+		var aliases []string
+
+		endpointsConfig := cc.NetworkingConfig.EndpointsConfig
+		cniNetworks := make([]string, 0, len(endpointsConfig))
+		for netName, endpoint := range endpointsConfig {
+
+			cniNetworks = append(cniNetworks, netName)
+
+			if endpoint == nil {
+				continue
 			}
-			// If MAC address is provided
-			if len(ep.MacAddress) > 0 {
-				staticMac, err := net.ParseMAC(ep.MacAddress)
-				if err != nil {
-					return nil, nil, err
+			if len(endpoint.Aliases) > 0 {
+				aliases = append(aliases, endpoint.Aliases...)
+			}
+		}
+
+		// static IP and MAC
+		if len(endpointsConfig) == 1 {
+			for _, ep := range endpointsConfig {
+				if ep == nil {
+					continue
+				}
+				// if IP address is provided
+				if len(ep.IPAddress) > 0 {
+					staticIP := net.ParseIP(ep.IPAddress)
+					netInfo.StaticIP = &staticIP
+				}
+				// If MAC address is provided
+				if len(ep.MacAddress) > 0 {
+					staticMac, err := net.ParseMAC(ep.MacAddress)
+					if err != nil {
+						return nil, nil, err
+					}
+					netInfo.StaticMAC = &staticMac
 				}
-				netInfo.StaticMAC = &staticMac
+				break
 			}
-			break
 		}
+		netInfo.Aliases = aliases
+		netInfo.CNINetworks = cniNetworks
+	case len(cc.HostConfig.NetworkMode) > 0:
+		netInfo.CNINetworks = []string{string(cc.HostConfig.NetworkMode)}
 	}
 
 	// Note: several options here are marked as "don't need". this is based
 	// on speculation by Matt and I. We think that these come into play later
 	// like with start. We believe this is just a difference in podman/compat
 	cliOpts := ContainerCLIOpts{
-		//Attach:            nil, // dont need?
+		// Attach:            nil, // dont need?
 		Authfile:     "",
 		CapAdd:       append(capAdd, cc.HostConfig.CapAdd...),
 		CapDrop:      append(cappDrop, cc.HostConfig.CapDrop...),
@@ -310,18 +326,18 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
 		CPURTPeriod:  uint64(cc.HostConfig.CPURealtimePeriod),
 		CPURTRuntime: cc.HostConfig.CPURealtimeRuntime,
 		CPUShares:    uint64(cc.HostConfig.CPUShares),
-		//CPUS:              0, // dont need?
+		// CPUS:              0, // dont need?
 		CPUSetCPUs: cc.HostConfig.CpusetCpus,
 		CPUSetMems: cc.HostConfig.CpusetMems,
-		//Detach:            false, // dont need
-		//DetachKeys:        "",    // dont need
+		// Detach:            false, // dont need
+		// DetachKeys:        "",    // dont need
 		Devices:          devices,
 		DeviceCGroupRule: nil,
 		DeviceReadBPs:    readBps,
 		DeviceReadIOPs:   readIops,
 		DeviceWriteBPs:   writeBps,
 		DeviceWriteIOPs:  writeIops,
-		Entrypoint:       &entrypoint,
+		Entrypoint:       entrypoint,
 		Env:              cc.Config.Env,
 		Expose:           expose,
 		GroupAdd:         cc.HostConfig.GroupAdd,
@@ -436,7 +452,70 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
 	}
 
 	// specgen assumes the image name is arg[0]
-	cmd := []string{cc.Image}
+	cmd := []string{cc.Config.Image}
 	cmd = append(cmd, cc.Config.Cmd...)
 	return &cliOpts, cmd, nil
 }
+
+func ulimits() []string {
+	if !registry.IsRemote() {
+		return containerConfig.Ulimits()
+	}
+	return nil
+}
+
+func cgroupConfig() string {
+	if !registry.IsRemote() {
+		return containerConfig.Cgroups()
+	}
+	return ""
+}
+
+func devices() []string {
+	if !registry.IsRemote() {
+		return containerConfig.Devices()
+	}
+	return nil
+}
+
+func env() []string {
+	if !registry.IsRemote() {
+		return containerConfig.Env()
+	}
+	return nil
+}
+
+func initPath() string {
+	if !registry.IsRemote() {
+		return containerConfig.InitPath()
+	}
+	return ""
+}
+
+func pidsLimit() int64 {
+	if !registry.IsRemote() {
+		return containerConfig.PidsLimit()
+	}
+	return -1
+}
+
+func policy() string {
+	if !registry.IsRemote() {
+		return containerConfig.Engine.PullPolicy
+	}
+	return ""
+}
+
+func shmSize() string {
+	if !registry.IsRemote() {
+		return containerConfig.ShmSize()
+	}
+	return ""
+}
+
+func volumes() []string {
+	if !registry.IsRemote() {
+		return containerConfig.Volumes()
+	}
+	return nil
+}
diff --git a/cmd/podman/common/createparse.go b/cmd/podman/common/createparse.go
index 09ee5aa0c..3a69f11b6 100644
--- a/cmd/podman/common/createparse.go
+++ b/cmd/podman/common/createparse.go
@@ -9,7 +9,7 @@ import (
 // by validate must not need any state information on the flag (i.e. changed)
 func (c *ContainerCLIOpts) validate() error {
 	var ()
-	if c.Rm && c.Restart != "" && c.Restart != "no" {
+	if c.Rm && (c.Restart != "" && c.Restart != "no" && c.Restart != "on-failure") {
 		return errors.Errorf(`the --rm option conflicts with --restart, when the restartPolicy is not "" and "no"`)
 	}
 
diff --git a/cmd/podman/common/netflags.go b/cmd/podman/common/netflags.go
index cae52ccaa..898d65bd0 100644
--- a/cmd/podman/common/netflags.go
+++ b/cmd/podman/common/netflags.go
@@ -59,8 +59,8 @@ func DefineNetFlags(cmd *cobra.Command) {
 	_ = cmd.RegisterFlagCompletionFunc(macAddressFlagName, completion.AutocompleteNone)
 
 	networkFlagName := "network"
-	netFlags.String(
-		networkFlagName, containerConfig.NetNS(),
+	netFlags.StringArray(
+		networkFlagName, []string{containerConfig.NetNS()},
 		"Connect a container to a network",
 	)
 	_ = cmd.RegisterFlagCompletionFunc(networkFlagName, AutocompleteNetworks)
@@ -194,25 +194,29 @@ func NetFlagsToNetOptions(cmd *cobra.Command) (*entities.NetOptions, error) {
 	}
 
 	if cmd.Flags().Changed("network") {
-		network, err := cmd.Flags().GetString("network")
+		networks, err := cmd.Flags().GetStringArray("network")
 		if err != nil {
 			return nil, err
 		}
+		for i, network := range networks {
+			parts := strings.SplitN(network, ":", 2)
 
-		parts := strings.SplitN(network, ":", 2)
-
-		ns, cniNets, err := specgen.ParseNetworkNamespace(network)
-		if err != nil {
-			return nil, err
-		}
+			ns, cniNets, err := specgen.ParseNetworkNamespace(network)
+			if err != nil {
+				return nil, err
+			}
+			if i > 0 && (len(cniNets) == 0 || len(opts.CNINetworks) == 0) {
+				return nil, errors.Errorf("network conflict between type %s and %s", opts.Network.NSMode, ns.NSMode)
+			}
 
-		if len(parts) > 1 {
-			opts.NetworkOptions = make(map[string][]string)
-			opts.NetworkOptions[parts[0]] = strings.Split(parts[1], ",")
-			cniNets = nil
+			if len(parts) > 1 {
+				opts.NetworkOptions = make(map[string][]string)
+				opts.NetworkOptions[parts[0]] = strings.Split(parts[1], ",")
+				cniNets = nil
+			}
+			opts.Network = ns
+			opts.CNINetworks = append(opts.CNINetworks, cniNets...)
 		}
-		opts.Network = ns
-		opts.CNINetworks = cniNets
 	}
 
 	aliases, err := cmd.Flags().GetStringSlice("network-alias")
diff --git a/cmd/podman/common/volumes.go b/cmd/podman/common/volumes.go
index b3c160ddf..0468f15e0 100644
--- a/cmd/podman/common/volumes.go
+++ b/cmd/podman/common/volumes.go
@@ -10,7 +10,6 @@ import (
 	"github.com/containers/podman/v2/pkg/util"
 	spec "github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/pkg/errors"
-	"github.com/sirupsen/logrus"
 )
 
 const (
@@ -45,7 +44,7 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo
 	}
 
 	// Next --volumes flag.
-	volumeMounts, volumeVolumes, overlayVolumes, err := getVolumeMounts(volumeFlag)
+	volumeMounts, volumeVolumes, overlayVolumes, err := specgen.GenVolumeMounts(volumeFlag)
 	if err != nil {
 		return nil, nil, nil, nil, err
 	}
@@ -594,105 +593,6 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) {
 	return newVolume, nil
 }
 
-func getVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*specgen.NamedVolume, map[string]*specgen.OverlayVolume, error) {
-	mounts := make(map[string]spec.Mount)
-	volumes := make(map[string]*specgen.NamedVolume)
-	overlayVolumes := make(map[string]*specgen.OverlayVolume)
-
-	volumeFormatErr := errors.Errorf("incorrect volume format, should be [host-dir:]ctr-dir[:option]")
-
-	for _, vol := range volumeFlag {
-		var (
-			options []string
-			src     string
-			dest    string
-			err     error
-		)
-
-		splitVol := strings.Split(vol, ":")
-		if len(splitVol) > 3 {
-			return nil, nil, nil, errors.Wrapf(volumeFormatErr, vol)
-		}
-
-		src = splitVol[0]
-		if len(splitVol) == 1 {
-			// This is an anonymous named volume. Only thing given
-			// is destination.
-			// Name/source will be blank, and populated by libpod.
-			src = ""
-			dest = splitVol[0]
-		} else if len(splitVol) > 1 {
-			dest = splitVol[1]
-		}
-		if len(splitVol) > 2 {
-			if options, err = parse.ValidateVolumeOpts(strings.Split(splitVol[2], ",")); err != nil {
-				return nil, nil, nil, err
-			}
-		}
-
-		// Do not check source dir for anonymous volumes
-		if len(splitVol) > 1 {
-			if err := parse.ValidateVolumeHostDir(src); err != nil {
-				return nil, nil, nil, err
-			}
-		}
-		if err := parse.ValidateVolumeCtrDir(dest); err != nil {
-			return nil, nil, nil, err
-		}
-
-		cleanDest := filepath.Clean(dest)
-
-		if strings.HasPrefix(src, "/") || strings.HasPrefix(src, ".") {
-			// This is not a named volume
-			overlayFlag := false
-			for _, o := range options {
-				if o == "O" {
-					overlayFlag = true
-					if len(options) > 1 {
-						return nil, nil, nil, errors.New("can't use 'O' with other options")
-					}
-				}
-			}
-			if overlayFlag {
-				// This is a overlay volume
-				newOverlayVol := new(specgen.OverlayVolume)
-				newOverlayVol.Destination = cleanDest
-				newOverlayVol.Source = src
-				if _, ok := overlayVolumes[newOverlayVol.Destination]; ok {
-					return nil, nil, nil, errors.Wrapf(errDuplicateDest, newOverlayVol.Destination)
-				}
-				overlayVolumes[newOverlayVol.Destination] = newOverlayVol
-			} else {
-				newMount := spec.Mount{
-					Destination: cleanDest,
-					Type:        string(TypeBind),
-					Source:      src,
-					Options:     options,
-				}
-				if _, ok := mounts[newMount.Destination]; ok {
-					return nil, nil, nil, errors.Wrapf(errDuplicateDest, newMount.Destination)
-				}
-				mounts[newMount.Destination] = newMount
-			}
-		} else {
-			// This is a named volume
-			newNamedVol := new(specgen.NamedVolume)
-			newNamedVol.Name = src
-			newNamedVol.Dest = cleanDest
-			newNamedVol.Options = options
-
-			if _, ok := volumes[newNamedVol.Dest]; ok {
-				return nil, nil, nil, errors.Wrapf(errDuplicateDest, newNamedVol.Dest)
-			}
-			volumes[newNamedVol.Dest] = newNamedVol
-		}
-
-		logrus.Debugf("User mount %s:%s options %v", src, dest, options)
-	}
-
-	return mounts, volumes, overlayVolumes, nil
-}
-
 // GetTmpfsMounts creates spec.Mount structs for user-requested tmpfs mounts
 func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) {
 	m := make(map[string]spec.Mount)
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go
index a1a41ae08..6f84cf9b8 100644
--- a/cmd/podman/containers/ps.go
+++ b/cmd/podman/containers/ps.go
@@ -29,15 +29,25 @@ var (
 	psDescription = "Prints out information about the containers"
 	psCommand     = &cobra.Command{
 		Use:               "ps [options]",
-		Args:              validate.NoArgs,
 		Short:             "List containers",
 		Long:              psDescription,
 		RunE:              ps,
+		Args:              validate.NoArgs,
 		ValidArgsFunction: completion.AutocompleteNone,
 		Example: `podman ps -a
   podman ps -a --format "{{.ID}}  {{.Image}}  {{.Labels}}  {{.Mounts}}"
   podman ps --size --sort names`,
 	}
+
+	psContainerCommand = &cobra.Command{
+		Use:               psCommand.Use,
+		Short:             psCommand.Short,
+		Long:              psCommand.Long,
+		RunE:              psCommand.RunE,
+		Args:              psCommand.Args,
+		ValidArgsFunction: psCommand.ValidArgsFunction,
+		Example:           strings.ReplaceAll(psCommand.Example, "podman ps", "podman container ps"),
+	}
 )
 var (
 	listOpts = entities.ContainerListOptions{
@@ -54,6 +64,14 @@ func init() {
 	})
 	listFlagSet(psCommand)
 	validate.AddLatestFlag(psCommand, &listOpts.Latest)
+
+	registry.Commands = append(registry.Commands, registry.CliCommand{
+		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+		Command: psContainerCommand,
+		Parent:  containerCmd,
+	})
+	listFlagSet(psContainerCommand)
+	validate.AddLatestFlag(psContainerCommand, &listOpts.Latest)
 }
 
 func listFlagSet(cmd *cobra.Command) {
diff --git a/cmd/podman/containers/top.go b/cmd/podman/containers/top.go
index 3eb6d2af2..e691f527a 100644
--- a/cmd/podman/containers/top.go
+++ b/cmd/podman/containers/top.go
@@ -18,12 +18,10 @@ import (
 )
 
 var (
-	topDescription = `Similar to system "top" command.
-
-  Specify format descriptors to alter the output.
-
-  Running "podman top -l pid pcpu seccomp" will print the process ID, the CPU percentage and the seccomp mode of each process of the latest container.`
+	topDescription = `Display the running processes of a container.
 
+  The top command extends the ps(1) compatible AIX descriptors with container-specific ones as shown below.  In the presence of ps(1) specific flags (e.g, -eo), Podman will execute ps(1) inside the container.
+`
 	topOptions = entities.TopOptions{}
 
 	topCommand = &cobra.Command{
@@ -32,7 +30,7 @@ var (
 		Long:              topDescription,
 		RunE:              top,
 		Args:              cobra.ArbitraryArgs,
-		ValidArgsFunction: common.AutocompleteContainersRunning,
+		ValidArgsFunction: common.AutocompleteTopCmd,
 		Example: `podman top ctrID
 podman top --latest
 podman top ctrID pid seccomp args %C
diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go
index 4692699f2..bcb31e6ee 100644
--- a/cmd/podman/images/list.go
+++ b/cmd/podman/images/list.go
@@ -79,8 +79,7 @@ func imageListFlagSet(cmd *cobra.Command) {
 
 	filterFlagName := "filter"
 	flags.StringSliceVarP(&listOptions.Filter, filterFlagName, "f", []string{}, "Filter output based on conditions provided (default [])")
-	// TODO: add completion function for filters
-	_ = cmd.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone)
+	_ = cmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteImageFilters)
 
 	formatFlagName := "format"
 	flags.StringVar(&listFlag.format, formatFlagName, "", "Change the output format to JSON or a Go template")
diff --git a/cmd/podman/images/load.go b/cmd/podman/images/load.go
index a7884f4c5..a24f46781 100644
--- a/cmd/podman/images/load.go
+++ b/cmd/podman/images/load.go
@@ -23,7 +23,7 @@ var (
 	loadDescription = "Loads an image from a locally stored archive (tar file) into container storage."
 	loadCommand     = &cobra.Command{
 		Use:               "load [options] [NAME[:TAG]]",
-		Short:             "Load an image from container archive",
+		Short:             "Load image(s) from a tar archive",
 		Long:              loadDescription,
 		RunE:              load,
 		Args:              cobra.MaximumNArgs(1),
diff --git a/cmd/podman/networks/connect.go b/cmd/podman/networks/connect.go
index a7636688c..8afc0c7c0 100644
--- a/cmd/podman/networks/connect.go
+++ b/cmd/podman/networks/connect.go
@@ -17,7 +17,7 @@ var (
 		RunE:              networkConnect,
 		Example:           `podman network connect web secondary`,
 		Args:              cobra.ExactArgs(2),
-		ValidArgsFunction: common.AutocompleteNetworks,
+		ValidArgsFunction: common.AutocompleteNetworkConnectCmd,
 	}
 )
 
diff --git a/cmd/podman/networks/disconnect.go b/cmd/podman/networks/disconnect.go
index 598c23a1c..a30315774 100644
--- a/cmd/podman/networks/disconnect.go
+++ b/cmd/podman/networks/disconnect.go
@@ -17,7 +17,7 @@ var (
 		RunE:              networkDisconnect,
 		Example:           `podman network disconnect web secondary`,
 		Args:              cobra.ExactArgs(2),
-		ValidArgsFunction: common.AutocompleteNetworks,
+		ValidArgsFunction: common.AutocompleteNetworkConnectCmd,
 	}
 )
 
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index f2a5a431a..dcba3f186 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -46,7 +46,7 @@ func networkListFlags(flags *pflag.FlagSet) {
 
 	filterFlagName := "filter"
 	flags.StringVarP(&networkListOptions.Filter, filterFlagName, "", "", "Provide filter values (e.g. 'name=podman')")
-	_ = networklistCommand.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone)
+	_ = networklistCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteNetworkFilters)
 
 }
 
diff --git a/cmd/podman/networks/rm.go b/cmd/podman/networks/rm.go
index 34e756a3a..1504d9385 100644
--- a/cmd/podman/networks/rm.go
+++ b/cmd/podman/networks/rm.go
@@ -18,6 +18,7 @@ var (
 	networkrmDescription = `Remove networks`
 	networkrmCommand     = &cobra.Command{
 		Use:               "rm [options] NETWORK [NETWORK...]",
+		Aliases:           []string{"remove"},
 		Short:             "network rm",
 		Long:              networkrmDescription,
 		RunE:              networkRm,
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 449d60bb9..5b0aa2fe4 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -94,7 +94,7 @@ func init() {
 	flags.StringVar(&podIDFile, podIDFileFlagName, "", "Write the pod ID to the file")
 	_ = createCommand.RegisterFlagCompletionFunc(podIDFileFlagName, completion.AutocompleteDefault)
 
-	flags.BoolVar(&replace, "replace", false, "If a pod with the same exists, replace it")
+	flags.BoolVar(&replace, "replace", false, "If a pod with the same name exists, replace it")
 
 	shareFlagName := "share"
 	flags.StringVar(&share, shareFlagName, specgen.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
@@ -171,33 +171,7 @@ func create(cmd *cobra.Command, args []string) error {
 	if err != nil {
 		return err
 	}
-	createOptions.Net.Network = specgen.Namespace{}
-	if cmd.Flag("network").Changed {
-		netInput, err := cmd.Flags().GetString("network")
-		if err != nil {
-			return err
-		}
-		parts := strings.SplitN(netInput, ":", 2)
-
-		n := specgen.Namespace{}
-		switch {
-		case netInput == "bridge":
-			n.NSMode = specgen.Bridge
-		case netInput == "host":
-			n.NSMode = specgen.Host
-		case netInput == "slirp4netns", strings.HasPrefix(netInput, "slirp4netns:"):
-			n.NSMode = specgen.Slirp
-			if len(parts) > 1 {
-				createOptions.Net.NetworkOptions = make(map[string][]string)
-				createOptions.Net.NetworkOptions[parts[0]] = strings.Split(parts[1], ",")
-			}
-		default:
-			// Container and NS mode are presently unsupported
-			n.NSMode = specgen.Bridge
-			createOptions.Net.CNINetworks = strings.Split(netInput, ",")
-		}
-		createOptions.Net.Network = n
-	}
+
 	if len(createOptions.Net.PublishPorts) > 0 {
 		if !createOptions.Infra {
 			return errors.Errorf("you must have an infra container to publish port bindings to the host")
diff --git a/cmd/podman/pods/top.go b/cmd/podman/pods/top.go
index 45ef1e7c2..829882080 100644
--- a/cmd/podman/pods/top.go
+++ b/cmd/podman/pods/top.go
@@ -29,7 +29,7 @@ var (
 		Long:              topDescription,
 		RunE:              top,
 		Args:              cobra.ArbitraryArgs,
-		ValidArgsFunction: common.AutocompletePodsRunning,
+		ValidArgsFunction: common.AutocompleteTopCmd,
 		Example: `podman pod top podID
 podman pod top --latest
 podman pod top podID pid seccomp args %C
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 34d92cd0f..7840e6100 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -113,33 +113,9 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error {
 		return nil
 	}
 
-	// Special case if command is hidden completion command ("__complete","__completeNoDesc")
-	// Since __completeNoDesc is an alias the cm.Name is always __complete
-	if cmd.Name() == cobra.ShellCompRequestCmd {
-		// Parse the cli arguments after the the completion cmd (always called as second argument)
-		// This ensures that the --url, --identity and --connection flags are properly set
-		compCmd, _, err := cmd.Root().Traverse(os.Args[2:])
-		if err != nil {
-			return err
-		}
-		// If we don't complete the root cmd hide all root flags
-		// so they won't show up in the completions on subcommands.
-		if compCmd != compCmd.Root() {
-			compCmd.Root().Flags().VisitAll(func(flag *pflag.Flag) {
-				flag.Hidden = true
-			})
-		}
-		// No need for further setup when completing commands with subcommands.
-		if compCmd.HasSubCommands() {
-			requireCleanup = false
-			return nil
-		}
-	}
-
 	cfg := registry.PodmanConfig()
 
 	// --connection is not as "special" as --remote so we can wait and process it here
-	var connErr error
 	conn := cmd.Root().LocalFlags().Lookup("connection")
 	if conn != nil && conn.Changed {
 		cfg.Engine.ActiveService = conn.Value.String()
@@ -147,19 +123,37 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error {
 		var err error
 		cfg.URI, cfg.Identity, err = cfg.ActiveDestination()
 		if err != nil {
-			connErr = errors.Wrap(err, "failed to resolve active destination")
+			return errors.Wrap(err, "failed to resolve active destination")
 		}
 
 		if err := cmd.Root().LocalFlags().Set("url", cfg.URI); err != nil {
-			connErr = errors.Wrap(err, "failed to override --url flag")
+			return errors.Wrap(err, "failed to override --url flag")
 		}
 
 		if err := cmd.Root().LocalFlags().Set("identity", cfg.Identity); err != nil {
-			connErr = errors.Wrap(err, "failed to override --identity flag")
+			return errors.Wrap(err, "failed to override --identity flag")
 		}
 	}
-	if connErr != nil {
-		return connErr
+
+	// Special case if command is hidden completion command ("__complete","__completeNoDesc")
+	// Since __completeNoDesc is an alias the cm.Name is always __complete
+	if cmd.Name() == cobra.ShellCompRequestCmd {
+		// Parse the cli arguments after the the completion cmd (always called as second argument)
+		// This ensures that the --url, --identity and --connection flags are properly set
+		compCmd, _, err := cmd.Root().Traverse(os.Args[2:])
+		if err != nil {
+			return err
+		}
+		// If we don't complete the root cmd hide all root flags
+		// so they won't show up in the completions on subcommands.
+		if compCmd != compCmd.Root() {
+			compCmd.Root().Flags().VisitAll(func(flag *pflag.Flag) {
+				flag.Hidden = true
+			})
+		}
+		// No need for further setup the completion logic setups the engines as needed.
+		requireCleanup = false
+		return nil
 	}
 
 	// Prep the engines
diff --git a/cmd/podman/volumes/list.go b/cmd/podman/volumes/list.go
index b0d999765..7e54de38a 100644
--- a/cmd/podman/volumes/list.go
+++ b/cmd/podman/volumes/list.go
@@ -56,7 +56,7 @@ func init() {
 
 	filterFlagName := "filter"
 	flags.StringSliceVarP(&cliOpts.Filter, filterFlagName, "f", []string{}, "Filter volume output")
-	_ = lsCommand.RegisterFlagCompletionFunc(filterFlagName, completion.AutocompleteNone)
+	_ = lsCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteVolumeFilters)
 
 	formatFlagName := "format"
 	flags.StringVar(&cliOpts.Format, formatFlagName, "{{.Driver}}\t{{.Name}}\n", "Format volume output using Go template")
diff --git a/contrib/systemd/system/podman.service b/contrib/systemd/system/podman.service
index e14bbe078..9b5a1a87f 100644
--- a/contrib/systemd/system/podman.service
+++ b/contrib/systemd/system/podman.service
@@ -8,4 +8,5 @@ StartLimitIntervalSec=0
 [Service]
 Type=notify
 KillMode=process
-ExecStart=/usr/bin/podman system service
+Environment=LOGGING="--log-level=info"
+ExecStart=/usr/bin/podman $LOGGING system service
diff --git a/docs/source/Tutorials.rst b/docs/source/Tutorials.rst
index 83818e3ae..e3e869d5b 100644
--- a/docs/source/Tutorials.rst
+++ b/docs/source/Tutorials.rst
@@ -2,7 +2,7 @@
 
 Tutorials
 =========
-Here are a number of useful tutorials to get you up and running with Podman. If you are familiar with the Docker `Container Engine`_ the command in Podman_ should be quite familiar. If are brand new to containers, take a look at our `Introduction`.
+Here are a number of useful tutorials to get you up and running with Podman. If you are familiar with the Docker `Container Engine`_ the command in Podman_ should be quite familiar. If you are brand new to containers, take a look at our `Introduction`.
 
 * `Basic Setup and Use of Podman <https://github.com/containers/podman/blob/master/docs/tutorials/podman_tutorial.md>`_: Learn how to setup Podman and perform some basic commands with the utility.
 * `Basic Setup and Use of Podman in a Rootless environment <https://github.com/containers/podman/blob/master/docs/tutorials/rootless_tutorial.md>`_: The steps required to setup rootless Podman are enumerated.
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 368d7cc29..e3715937d 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -28,11 +28,11 @@ author = "team"
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = [
-    'sphinx_markdown_tables',
+    "sphinx_markdown_tables",
 ]
 
 source_parsers = {
-    '.md': 'recommonmark.parser.CommonMarkParser',
+    ".md": "recommonmark.parser.CommonMarkParser",
 }
 
 
diff --git a/docs/source/managecontainers.rst b/docs/source/managecontainers.rst
index 849fd1d25..9926f9996 100644
--- a/docs/source/managecontainers.rst
+++ b/docs/source/managecontainers.rst
@@ -39,6 +39,8 @@ Manage Containers
 
 :doc:`prune <markdown/podman-container-prune.1>` Remove all stopped containers
 
+:doc:`ps <markdown/podman-ps.1>` List containers
+
 :doc:`restart <markdown/podman-restart.1>` Restart one or more containers
 
 :doc:`restore <markdown/podman-container-restore.1>` Restores one or more containers from a checkpoint
diff --git a/docs/source/markdown/links/podman-list.1 b/docs/source/markdown/links/podman-list.1
deleted file mode 100644
index f7f44c704..000000000
--- a/docs/source/markdown/links/podman-list.1
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/podman-ps.1
diff --git a/docs/source/markdown/links/podman-ls.1 b/docs/source/markdown/links/podman-ls.1
deleted file mode 100644
index f7f44c704..000000000
--- a/docs/source/markdown/links/podman-ls.1
+++ /dev/null
@@ -1 +0,0 @@
-.so man1/podman-ps.1
diff --git a/docs/source/markdown/podman-container.1.md b/docs/source/markdown/podman-container.1.md
index 0a6ceea33..9da5db601 100644
--- a/docs/source/markdown/podman-container.1.md
+++ b/docs/source/markdown/podman-container.1.md
@@ -32,6 +32,7 @@ The container command allows you to manage containers
 | pause      | [podman-pause(1)](podman-pause.1.md)                | Pause one or more containers.                                                |
 | port       | [podman-port(1)](podman-port.1.md)                  | List port mappings for the container.                                        |
 | prune      | [podman-container-prune(1)](podman-container-prune.1.md)| Remove all stopped containers from local storage.                        |
+| ps         | [podman-ps(1)](podman-ps.1.md)                      | Prints out information about containers.                                     |
 | restart    | [podman-restart(1)](podman-restart.1.md)            | Restart one or more containers.                                              |
 | restore    | [podman-container-restore(1)](podman-container-restore.1.md)  | Restores one or more containers from a checkpoint.                 |
 | rm         | [podman-rm(1)](podman-rm.1.md)                      | Remove one or more containers.                                               |
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 749af8a66..eb73609d4 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -18,6 +18,10 @@ any point.
 
 The initial status of the container created with **podman create** is 'created'.
 
+Default settings for flags are defined in `containers.conf`. Most settings for
+remote connections use the server's containers.conf, except when documented in
+man pages.
+
 ## OPTIONS
 #### **--add-host**=*host*
 
@@ -584,7 +588,7 @@ Valid _mode_ values are:
 - **none**: no networking;
 - **container:**_id_: reuse another container's network stack;
 - **host**: use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure;
-- _network-id_: connect to a user-defined network, multiple networks should be comma separated;
+- **cni-network**: connect to a user-defined network, multiple networks should be comma-separated or they can be specified with multiple uses of the **--network** option;
 - **ns:**_path_: path to a network namespace to join;
 - **private**: create a new namespace for the container (default)
 - **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack.  This is the default for rootless containers.  It is possible to specify these additional options:
@@ -817,6 +821,7 @@ Signal to stop a container. Default is SIGTERM.
 #### **--stop-timeout**=*seconds*
 
 Timeout (in seconds) to stop a container. Default is 10.
+Remote connections use local containers.conf for defaults
 
 #### **--subgidname**=*name*
 
@@ -893,10 +898,12 @@ standard input.
 #### **--tz**=*timezone*
 
 Set timezone in container. This flag takes area-based timezones, GMT time, as well as `local`, which sets the timezone in the container to match the host machine. See `/usr/share/zoneinfo/` for valid timezones.
+Remote connections use local containers.conf for defaults
 
 #### **--umask**=*umask*
 
 Set the umask inside the container. Defaults to `0022`.
+Remote connections use local containers.conf for defaults
 
 #### **--uidmap**=*container_uid:host_uid:amount*
 
diff --git a/docs/source/markdown/podman-export.1.md b/docs/source/markdown/podman-export.1.md
index 647c25770..63989a4db 100644
--- a/docs/source/markdown/podman-export.1.md
+++ b/docs/source/markdown/podman-export.1.md
@@ -12,6 +12,8 @@ podman\-export - Export a container's filesystem contents as a tar archive
 **podman export** exports the filesystem of a container and saves it as a tarball
 on the local machine. **podman export** writes to STDOUT by default and can be
 redirected to a file using the `--output` flag.
+The image of the container exported by **podman export** can be imported by **podman import**.
+To export image(s) with parent layers, use **podman save**.
 Note: `:` is a restricted character and cannot be part of the file name.
 
 **podman [GLOBAL OPTIONS]**
diff --git a/docs/source/markdown/podman-import.1.md b/docs/source/markdown/podman-import.1.md
index ebedf90b4..427c67da4 100644
--- a/docs/source/markdown/podman-import.1.md
+++ b/docs/source/markdown/podman-import.1.md
@@ -14,6 +14,7 @@ and saves it as a filesystem image. Remote tarballs can be specified using a URL
 Various image instructions can be configured with the **--change** flag and
 a commit message can be set using the **--message** flag.
 **reference**, if present, is a tag to assign to the image.
+**podman import** is used for importing from the archive generated by **podman export**, that includes the container's filesystem. To import the archive of image layers created by **podman save**, use **podman load**.
 Note: `:` is a restricted character and cannot be part of the file name.
 
 ## OPTIONS
diff --git a/docs/source/markdown/podman-load.1.md b/docs/source/markdown/podman-load.1.md
index cdc99fbf2..177709a43 100644
--- a/docs/source/markdown/podman-load.1.md
+++ b/docs/source/markdown/podman-load.1.md
@@ -1,7 +1,7 @@
 % podman-load(1)
 
 ## NAME
-podman\-load - Load an image from a container image archive into container storage
+podman\-load - Load image(s) from a tar archive into container storage
 
 ## SYNOPSIS
 **podman load** [*options*] [*name*[:*tag*]]
@@ -11,6 +11,7 @@ podman\-load - Load an image from a container image archive into container stora
 ## DESCRIPTION
 **podman load** loads an image from either an **oci-archive** or a **docker-archive** stored on the local machine into container storage. **podman load** reads from stdin by default or a file if the **input** option is set.
 You can also specify a name for the image if the archive does not contain a named reference, of if you want an additional name for the local image.
+**podman load** is used for loading from the archive generated by **podman save**, that includes the image parent layers. To load the archive of container's filesystem created by **podman export**, use **podman import**.
 
 The local client further supports loading an **oci-dir** or a **docker-dir** as created with **podman save** (1).
 
diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md
index f542daf4c..b94964f6c 100644
--- a/docs/source/markdown/podman-ps.1.md
+++ b/docs/source/markdown/podman-ps.1.md
@@ -6,15 +6,11 @@ podman\-ps - Prints out information about containers
 ## SYNOPSIS
 **podman ps** [*options*]
 
-**podman container list** [*options*]
-
-**podman container ls** [*options*]
-
 **podman container ps** [*options*]
 
-**podman list** [*options*]
+**podman container list** [*options*]
 
-**podman ls** [*options*]
+**podman container ls** [*options*]
 
 ## DESCRIPTION
 **podman ps** lists the running containers on the system. Use the **--all** flag to view
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 5b2cdd6a5..184c12acd 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -33,6 +33,10 @@ is located at _/run/.containerenv_.
 When running from a user defined network namespace, the _/etc/netns/NSNAME/resolv.conf_
 will be used if it exists, otherwise _/etc/resolv.conf_ will be used.
 
+Default settings are defined in `containers.conf`. Most settings for remote
+connections use the servers containers.conf, except when documented in man
+pages.
+
 ## OPTIONS
 #### **--add-host**=_host_:_ip_
 
@@ -610,7 +614,7 @@ Valid _mode_ values are:
 - **none**: no networking;
 - **container:**_id_: reuse another container's network stack;
 - **host**: use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure;
-- _network-id_: connect to a user-defined network, multiple networks should be comma separated;
+- **cni-network**: connect to a user-defined network, multiple networks should be comma-separated or they can be specified with multiple uses of the **--network** option;
 - **ns:**_path_: path to a network namespace to join;
 - **private**: create a new namespace for the container (default)
 - **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack.  This is the default for rootless containers.  It is possible to specify these additional options:
@@ -857,6 +861,7 @@ Signal to stop a container. Default is **SIGTERM**.
 #### **--stop-timeout**=*seconds*
 
 Timeout to stop a container. Default is **10**.
+Remote connections use local containers.conf for defaults
 
 #### **--subgidname**=*name*
 
@@ -952,10 +957,12 @@ standard input.
 #### **--tz**=*timezone*
 
 Set timezone in container. This flag takes area-based timezones, GMT time, as well as `local`, which sets the timezone in the container to match the host machine. See `/usr/share/zoneinfo/` for valid timezones.
+Remote connections use local containers.conf for defaults
 
 #### **--umask**=*umask*
 
 Set the umask inside the container. Defaults to `0022`.
+Remote connections use local containers.conf for defaults
 
 #### **--uidmap**=*container_uid*:*host_uid*:*amount*
 
diff --git a/docs/source/markdown/podman-save.1.md b/docs/source/markdown/podman-save.1.md
index bfb52e7f8..fb79cfd2a 100644
--- a/docs/source/markdown/podman-save.1.md
+++ b/docs/source/markdown/podman-save.1.md
@@ -1,7 +1,7 @@
 % podman-save(1)
 
 ## NAME
-podman\-save - Save an image to a container archive
+podman\-save - Save image(s) to an archive
 
 ## SYNOPSIS
 **podman save** [*options*] *name*[:*tag*]
@@ -12,6 +12,8 @@ podman\-save - Save an image to a container archive
 **podman save** saves an image to either **docker-archive**, **oci-archive**, **oci-dir** (directory with oci manifest type), or **docker-dir** (directory with v2s2 manifest type) on the local machine,
 default is **docker-archive**. **podman save** writes to STDOUT by default and can be redirected to a
 file using the **output** flag. The **quiet** flag suppresses the output when set.
+**podman save** will save parent layers of the image(s) and the image(s) can be loaded using **podman load**.
+To export the containers, use the **podman export**.
 Note: `:` is a restricted character and cannot be part of the file name.
 
 **podman [GLOBAL OPTIONS]**
diff --git a/docs/source/markdown/podman-system-service.1.md b/docs/source/markdown/podman-system-service.1.md
index 39e30ec02..1fdecfa5c 100644
--- a/docs/source/markdown/podman-system-service.1.md
+++ b/docs/source/markdown/podman-system-service.1.md
@@ -17,12 +17,14 @@ The REST API provided by **podman system service** is split into two parts: a co
 Documentation for the latter is available at *https://docs.podman.io/en/latest/_static/api.html*.
 Both APIs are versioned, but the server will not reject requests with an unsupported version set.
 
+Note: The default systemd unit files (system and user) change the log-level option to *info* from *error*. This change provides additional information on each API call.
+
 ## OPTIONS
 
 #### **--time**, **-t**
 
 The time until the session expires in _seconds_. The default is 5
-seconds. A value of `0` means no timeout and the session will not expire.
+seconds. A value of `0` means no timeout, therefore the session will not expire.
 
 #### **--help**, **-h**
 
@@ -40,3 +42,4 @@ podman(1), podman-system-service(1), podman-system-connection(1)
 
 ## HISTORY
 January 2020, Originally compiled by Brent Baude<bbaude@redhat.com>
+November 2020, Updated by Jhon Honce <jhonce at redhat.com>
diff --git a/docs/source/markdown/podman-top.1.md b/docs/source/markdown/podman-top.1.md
index f307f96da..cfb89567c 100644
--- a/docs/source/markdown/podman-top.1.md
+++ b/docs/source/markdown/podman-top.1.md
@@ -9,7 +9,7 @@ podman\-top - Display the running processes of a container
 **podman container top** [*options*] *container* [*format-descriptors*]
 
 ## DESCRIPTION
-Display the running processes of the container. The *format-descriptors* are ps (1) compatible AIX format descriptors but extended to print additional information, such as the seccomp mode or the effective capabilities of a given process. The descriptors can either be passed as separated arguments or as a single comma-separated argument. Note that you can also specify options and or flags of ps(1); in this case, Podman will fallback to executing ps with the specified arguments and flags in the container.
+Display the running processes of the container. The *format-descriptors* are ps (1) compatible AIX format descriptors but extended to print additional information, such as the seccomp mode or the effective capabilities of a given process. The descriptors can either be passed as separated arguments or as a single comma-separated argument. Note that you can also specify options and or flags of ps(1); in this case, Podman will fallback to executing ps with the specified arguments and flags in the container.  Please use the "h*" descriptors if you want to extract host-related information.  For instance, `podman top $name hpid huser` to display the PID and user of the processes in the host context.
 
 ## OPTIONS
 
diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md
index 1954ca2aa..7da01d389 100644
--- a/docs/source/markdown/podman.1.md
+++ b/docs/source/markdown/podman.1.md
@@ -17,6 +17,10 @@ Podman uses Buildah(1) internally to create container images. Both tools share i
 (not container) storage, hence each can use or manipulate images (but not containers)
 created by the other.
 
+Default settings for flags are defined in `containers.conf`. Most settings for
+Remote connections use the server's containers.conf, except when documented in
+man pages.
+
 **podman [GLOBAL OPTIONS]**
 
 ## GLOBAL OPTIONS
@@ -33,6 +37,7 @@ Path of the configuration directory for CNI networks.  (Default: `/etc/cni/net.d
 
 #### **--connection**, **-c**
 Connection to use for remote podman (Default connection is configured in `containers.conf`)
+Remote connections use local containers.conf for default.
 
 #### **--conmon**
 Path of the conmon binary (Default path is configured in `containers.conf`)
@@ -71,6 +76,7 @@ Identity value resolution precedence:
  - command line value
  - environment variable `CONTAINER_SSHKEY`, if `CONTAINER_HOST` is found
  - `containers.conf`
+Remote connections use local containers.conf for default.
 
 #### **--log-level**=*level*
 
@@ -86,6 +92,7 @@ Path to the command binary to use for setting up a network.  It is currently onl
 
 #### **--remote**, **-r**
 Access Podman service will be remote
+Remote connections use local containers.conf for default.
 
 #### **--url**=*value*
 URL to access Podman service (default from `containers.conf`, rootless `unix://run/user/$UID/podman/podman.sock` or as root `unix://run/podman/podman.sock`).
@@ -104,6 +111,7 @@ URL value resolution precedence:
  - environment variable `CONTAINER_HOST`
  - `containers.conf`
  - `unix://run/podman/podman.sock`
+Remote connections use local containers.conf for default.
 
 #### **--root**=*value*
 
@@ -223,7 +231,7 @@ the exit codes follow the `chroot` standard, see below:
 | [podman-init(1)](podman-init.1.md)               | Initialize one or more containers                                           |
 | [podman-inspect(1)](podman-inspect.1.md)         | Display a container, image, volume, network, or pod's configuration.        |
 | [podman-kill(1)](podman-kill.1.md)               | Kill the main process in one or more containers.                            |
-| [podman-load(1)](podman-load.1.md)               | Load an image from a container image archive into container storage.        |
+| [podman-load(1)](podman-load.1.md)               | Load image(s) from a tar archive into container storage.                    |
 | [podman-login(1)](podman-login.1.md)             | Login to a container registry.                                              |
 | [podman-logout(1)](podman-logout.1.md)           | Logout of a container registry.                                             |
 | [podman-logs(1)](podman-logs.1.md)               | Display the logs of one or more containers.                                 |
@@ -241,7 +249,7 @@ the exit codes follow the `chroot` standard, see below:
 | [podman-rm(1)](podman-rm.1.md)                   | Remove one or more containers.                                              |
 | [podman-rmi(1)](podman-rmi.1.md)                 | Removes one or more locally stored images.                                  |
 | [podman-run(1)](podman-run.1.md)                 | Run a command in a new container.                                           |
-| [podman-save(1)](podman-save.1.md)               | Save an image to a container archive.                                       |
+| [podman-save(1)](podman-save.1.md)               | Save image(s) to an archive.                                                |
 | [podman-search(1)](podman-search.1.md)           | Search a registry for an image.                                             |
 | [podman-start(1)](podman-start.1.md)             | Start one or more containers.                                               |
 | [podman-stats(1)](podman-stats.1.md)             | Display a live stream of one or more container's resource usage statistics. |
diff --git a/docs/tutorials/mac_win_client.md b/docs/tutorials/mac_win_client.md
index af2668e10..375f73102 100644
--- a/docs/tutorials/mac_win_client.md
+++ b/docs/tutorials/mac_win_client.md
@@ -55,7 +55,7 @@ host:
 
 In order for the client to communicate with the server you need to enable and start the SSH daemon on your Linux machine, if it is not currently enabled.
 ```
-sudo systemctl enable --now -s sshd
+sudo systemctl enable --now sshd
 ```
 
 #### Setting up SSH
diff --git a/go.mod b/go.mod
index c093319e8..2ed1c56d1 100644
--- a/go.mod
+++ b/go.mod
@@ -11,11 +11,11 @@ require (
 	github.com/containernetworking/cni v0.8.0
 	github.com/containernetworking/plugins v0.8.7
 	github.com/containers/buildah v1.18.0
-	github.com/containers/common v0.27.0
+	github.com/containers/common v0.29.0
 	github.com/containers/conmon v2.0.20+incompatible
-	github.com/containers/image/v5 v5.8.0
+	github.com/containers/image/v5 v5.8.1
 	github.com/containers/psgo v1.5.1
-	github.com/containers/storage v1.24.0
+	github.com/containers/storage v1.24.1
 	github.com/coreos/go-systemd/v22 v22.1.0
 	github.com/cri-o/ocicni v0.2.1-0.20201102180012-75c612fda1a2
 	github.com/cyphar/filepath-securejoin v0.2.2
diff --git a/go.sum b/go.sum
index baff472f6..761ba04de 100644
--- a/go.sum
+++ b/go.sum
@@ -96,13 +96,15 @@ github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CY
 github.com/containers/buildah v1.18.0 h1:mWEm013LVNGecF++sYo0T7fe/4pqMas/PQxQ/qviC68=
 github.com/containers/buildah v1.18.0/go.mod h1:qHLk7RUL7cHfA7ve1MKkZ6cyKUxHD0YxiLJcKY+mJe8=
 github.com/containers/common v0.26.3/go.mod h1:hJWZIlrl5MsE2ELNRa+MPp6I1kPbXHauuj0Ym4BsLG4=
-github.com/containers/common v0.27.0 h1:+QlYEOitVYtU9/x8xebRgxdGqt4sLaIqV6MBOns+zLk=
-github.com/containers/common v0.27.0/go.mod h1:ZTswJJfu4aGF6Anyi2yON8Getda9NDYcdIzurOEHHXI=
+github.com/containers/common v0.29.0 h1:hTMC+urdkk5bKfhL/OgCixIX5xjJgQ2l2jPG745ECFQ=
+github.com/containers/common v0.29.0/go.mod h1:yT4GTUHsKRmpaDb+mecXRnIMre7W3ZgwXqaYMywXlaA=
 github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
 github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
 github.com/containers/image/v5 v5.7.0/go.mod h1:8aOy+YaItukxghRORkvhq5ibWttHErzDLy6egrKfKos=
 github.com/containers/image/v5 v5.8.0 h1:B3FGHi0bdGXgg698kBIGOlHCXN5n+scJr6/5354GOPU=
 github.com/containers/image/v5 v5.8.0/go.mod h1:jKxdRtyIDumVa56hdsZvV+gwx4zB50hRou6pIuCWLkg=
+github.com/containers/image/v5 v5.8.1 h1:aHW8a/Kd0dTJ7PTL/fc6y12sJqHxWgqilu+XyHfjD8Q=
+github.com/containers/image/v5 v5.8.1/go.mod h1:blOEFd/iFdeyh891ByhCVUc+xAcaI3gBegXECwz9UbQ=
 github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
 github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
 github.com/containers/ocicrypt v1.0.3 h1:vYgl+RZ9Q3DPMuTfxmN+qp0X2Bj52uuY2vnt6GzVe1c=
@@ -111,10 +113,10 @@ github.com/containers/psgo v1.5.1 h1:MQNb7FLbXqBdqz6u4lI2QWizVz4RSTzs1+Nk9XT1iVA
 github.com/containers/psgo v1.5.1/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
 github.com/containers/storage v1.23.6/go.mod h1:haFs0HRowKwyzvWEx9EgI3WsL8XCSnBDb5f8P5CAxJY=
 github.com/containers/storage v1.23.7/go.mod h1:cUT2zHjtx+WlVri30obWmM2gpqpi8jfPsmIzP1TVpEI=
-github.com/containers/storage v1.23.9 h1:qbgnTp76pLSyW3vYwY5GH4vk5cHYVXFJ+CsUEBp9TMw=
-github.com/containers/storage v1.23.9/go.mod h1:3b2ktpB6pw53SEeIoFfO0sQfP9+IoJJKPq5iJk74gxE=
 github.com/containers/storage v1.24.0 h1:Fo2LkF7tkMLmo38sTZ/G8wHjcn8JfUFPfyTxM4WwMfk=
 github.com/containers/storage v1.24.0/go.mod h1:A4d3BzuZK9b3oLVEsiSRhZLPIx3z7utgiPyXLK/YMhY=
+github.com/containers/storage v1.24.1 h1:1+f8fy6ly35c8SLet5jzZ8t0WJJs5+xSpfMAYw0R3kc=
+github.com/containers/storage v1.24.1/go.mod h1:0xJL06Dmd+ZYXIUdnBUPN0JnhHGgwMkLvnnAonJfWJU=
 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/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
@@ -322,6 +324,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
 github.com/klauspost/compress v1.11.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ=
 github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.3 h1:dB4Bn0tN3wdCzQxnS8r06kV74qN/TAfaIS0bVE8h3jc=
+github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
 github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
diff --git a/libpod/container.go b/libpod/container.go
index 4b9e6a5ba..e954d84eb 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -13,10 +13,12 @@ import (
 	"github.com/containers/image/v5/manifest"
 	"github.com/containers/podman/v2/libpod/define"
 	"github.com/containers/podman/v2/libpod/lock"
+	"github.com/containers/podman/v2/pkg/rootless"
 	"github.com/containers/storage"
 	"github.com/cri-o/ocicni/pkg/ocicni"
 	spec "github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
 )
 
 // CgroupfsDefaultCgroupParent is the cgroup parent for CGroupFS in libpod
@@ -920,19 +922,39 @@ func (c *Container) CGroupPath() (string, error) {
 		return "", errors.Wrapf(define.ErrNoCgroups, "this container is not creating cgroups")
 	}
 
-	// Read /proc/[PID]/cgroup and look at the first line.  cgroups(7)
-	// nails it down to three fields with the 3rd pointing to the cgroup's
-	// path which works both on v1 and v2.
+	// Read /proc/[PID]/cgroup and find the *longest* cgroup entry.  That's
+	// needed to account for hacks in cgroups v1, where each line in the
+	// file could potentially point to a cgroup.  The longest one, however,
+	// is the libpod-specific one we're looking for.
+	//
+	// See #8397 on the need for the longest-path look up.
 	procPath := fmt.Sprintf("/proc/%d/cgroup", c.state.PID)
 	lines, err := ioutil.ReadFile(procPath)
 	if err != nil {
 		return "", err
 	}
-	fields := bytes.Split(bytes.Split(lines, []byte("\n"))[0], []byte(":"))
-	if len(fields) != 3 {
-		return "", errors.Errorf("expected 3 fields but got %d: %s", len(fields), procPath)
+
+	var cgroupPath string
+	for _, line := range bytes.Split(lines, []byte("\n")) {
+		// cgroups(7) nails it down to three fields with the 3rd
+		// pointing to the cgroup's path which works both on v1 and v2.
+		fields := bytes.Split(line, []byte(":"))
+		if len(fields) != 3 {
+			logrus.Debugf("Error parsing cgroup: expected 3 fields but got %d: %s", len(fields), procPath)
+			continue
+		}
+		path := string(fields[2])
+		if len(path) > len(cgroupPath) {
+			cgroupPath = path
+		}
+
 	}
-	return string(fields[2]), nil
+
+	if len(cgroupPath) == 0 {
+		return "", errors.Errorf("could not find any cgroup in %q", procPath)
+	}
+
+	return cgroupPath, nil
 }
 
 // RootFsSize returns the root FS size of the container
@@ -1074,13 +1096,17 @@ func (c *Container) Umask() string {
 // values at runtime via network connect and disconnect.
 // If the container is configured to use CNI and this function returns an empty
 // array, the container will still be connected to the default network.
-func (c *Container) Networks() ([]string, error) {
+// The second return parameter, a bool, indicates that the container container
+// is joining the default CNI network - the network name will be included in the
+// returned array of network names, but the container did not explicitly join
+// this network.
+func (c *Container) Networks() ([]string, bool, error) {
 	if !c.batched {
 		c.lock.Lock()
 		defer c.lock.Unlock()
 
 		if err := c.syncContainer(); err != nil {
-			return nil, err
+			return nil, false, err
 		}
 	}
 
@@ -1088,19 +1114,22 @@ func (c *Container) Networks() ([]string, error) {
 }
 
 // Unlocked accessor for networks
-func (c *Container) networks() ([]string, error) {
+func (c *Container) networks() ([]string, bool, error) {
 	networks, err := c.runtime.state.GetNetworks(c)
 	if err != nil && errors.Cause(err) == define.ErrNoSuchNetwork {
-		return c.config.Networks, nil
+		if len(c.config.Networks) == 0 && !rootless.IsRootless() {
+			return []string{c.runtime.netPlugin.GetDefaultNetworkName()}, true, nil
+		}
+		return c.config.Networks, false, nil
 	}
 
-	return networks, err
+	return networks, false, err
 }
 
 // networksByNameIndex provides us with a map of container networks where key
 // is network name and value is the index position
 func (c *Container) networksByNameIndex() (map[string]int, error) {
-	networks, err := c.networks()
+	networks, _, err := c.networks()
 	if err != nil {
 		return nil, err
 	}
diff --git a/libpod/container_api.go b/libpod/container_api.go
index a9808a30e..6a7ddc421 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -714,3 +714,17 @@ func (c *Container) Restore(ctx context.Context, options ContainerCheckpointOpti
 	defer c.newContainerEvent(events.Restore)
 	return c.restore(ctx, options)
 }
+
+// Indicate whether or not the container should restart
+func (c *Container) ShouldRestart(ctx context.Context) bool {
+	logrus.Debugf("Checking if container %s should restart", c.ID())
+	if !c.batched {
+		c.lock.Lock()
+		defer c.lock.Unlock()
+
+		if err := c.syncContainer(); err != nil {
+			return false
+		}
+	}
+	return c.shouldRestart()
+}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 108954bad..b6a3244ea 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -206,37 +206,39 @@ func (c *Container) handleExitFile(exitFile string, fi os.FileInfo) error {
 	return nil
 }
 
-// Handle container restart policy.
-// This is called when a container has exited, and was not explicitly stopped by
-// an API call to stop the container or pod it is in.
-func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr error) {
-	// If we did not get a restart policy match, exit immediately.
+func (c *Container) shouldRestart() bool {
+	// If we did not get a restart policy match, return false
 	// Do the same if we're not a policy that restarts.
 	if !c.state.RestartPolicyMatch ||
 		c.config.RestartPolicy == RestartPolicyNo ||
 		c.config.RestartPolicy == RestartPolicyNone {
-		return false, nil
+		return false
 	}
 
 	// If we're RestartPolicyOnFailure, we need to check retries and exit
 	// code.
 	if c.config.RestartPolicy == RestartPolicyOnFailure {
 		if c.state.ExitCode == 0 {
-			return false, nil
+			return false
 		}
 
 		// If we don't have a max retries set, continue
 		if c.config.RestartRetries > 0 {
-			if c.state.RestartCount < c.config.RestartRetries {
-				logrus.Debugf("Container %s restart policy trigger: on retry %d (of %d)",
-					c.ID(), c.state.RestartCount, c.config.RestartRetries)
-			} else {
-				logrus.Debugf("Container %s restart policy trigger: retries exhausted", c.ID())
-				return false, nil
+			if c.state.RestartCount >= c.config.RestartRetries {
+				return false
 			}
 		}
 	}
+	return true
+}
 
+// Handle container restart policy.
+// This is called when a container has exited, and was not explicitly stopped by
+// an API call to stop the container or pod it is in.
+func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr error) {
+	if !c.shouldRestart() {
+		return false, nil
+	}
 	logrus.Debugf("Restarting container %s due to restart policy %s", c.ID(), c.config.RestartPolicy)
 
 	// Need to check if dependencies are alive.
@@ -641,18 +643,13 @@ func (c *Container) removeIPv4Allocations() error {
 		cniDefaultNetwork = c.runtime.netPlugin.GetDefaultNetworkName()
 	}
 
-	networks, err := c.networks()
+	networks, _, err := c.networks()
 	if err != nil {
 		return err
 	}
 
-	switch {
-	case len(networks) > 0 && len(networks) != len(c.state.NetworkStatus):
+	if len(networks) != len(c.state.NetworkStatus) {
 		return errors.Wrapf(define.ErrInternal, "network mismatch: asked to join %d CNI networks but got %d CNI results", len(networks), len(c.state.NetworkStatus))
-	case len(networks) == 0 && len(c.state.NetworkStatus) != 1:
-		return errors.Wrapf(define.ErrInternal, "network mismatch: did not specify CNI networks but joined more than one (%d)", len(c.state.NetworkStatus))
-	case len(networks) == 0 && cniDefaultNetwork == "":
-		return errors.Wrapf(define.ErrInternal, "could not retrieve name of CNI default network")
 	}
 
 	for index, result := range c.state.NetworkStatus {
diff --git a/libpod/healthcheck_linux.go b/libpod/healthcheck_linux.go
index b0f1ff35d..0ad15da09 100644
--- a/libpod/healthcheck_linux.go
+++ b/libpod/healthcheck_linux.go
@@ -26,6 +26,10 @@ func (c *Container) createTimer() error {
 	if rootless.IsRootless() {
 		cmd = append(cmd, "--user")
 	}
+	path := os.Getenv("PATH")
+	if path != "" {
+		cmd = append(cmd, "--setenv=PATH="+path)
+	}
 	cmd = append(cmd, "--unit", c.ID(), fmt.Sprintf("--on-unit-inactive=%s", c.HealthCheckConfig().Interval.String()), "--timer-property=AccuracySec=1s", podman, "healthcheck", "run", c.ID())
 
 	conn, err := systemd.ConnectToDBUS()
diff --git a/libpod/image/manifests.go b/libpod/image/manifests.go
index 59678fdb2..14f7c2f83 100644
--- a/libpod/image/manifests.go
+++ b/libpod/image/manifests.go
@@ -2,13 +2,14 @@ package image
 
 import (
 	"context"
+	"fmt"
 
 	"github.com/containers/buildah/manifests"
+	"github.com/containers/image/v5/docker"
 	"github.com/containers/image/v5/manifest"
 	"github.com/containers/image/v5/transports/alltransports"
 	"github.com/containers/image/v5/types"
 	"github.com/opencontainers/go-digest"
-	"github.com/pkg/errors"
 )
 
 // Options for adding a manifest
@@ -69,19 +70,10 @@ func CreateManifestList(rt *Runtime, systemContext types.SystemContext, names []
 	list := manifests.Create()
 	opts := ManifestAddOpts{Images: names, All: all}
 	for _, img := range imgs {
-		var ref types.ImageReference
-		newImage, err := rt.NewFromLocal(img)
-		if err == nil {
-			ir, err := newImage.toImageRef(context.Background())
-			if err != nil {
-				return "", err
-			}
-			if ir == nil {
-				return "", errors.New("unable to convert image to ImageReference")
-			}
-			ref = ir.Reference()
-		} else {
-			ref, err = alltransports.ParseImageName(img)
+		ref, err := alltransports.ParseImageName(img)
+		if err != nil {
+			dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
+			ref, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, img))
 			if err != nil {
 				return "", err
 			}
@@ -134,18 +126,10 @@ func addManifestToList(ref types.ImageReference, list manifests.List, systemCont
 
 // AddManifest adds a manifest to a given manifest list.
 func (i *Image) AddManifest(systemContext types.SystemContext, opts ManifestAddOpts) (string, error) {
-	var (
-		ref types.ImageReference
-	)
-	newImage, err := i.imageruntime.NewFromLocal(opts.Images[0])
-	if err == nil {
-		ir, err := newImage.toImageRef(context.Background())
-		if err != nil {
-			return "", err
-		}
-		ref = ir.Reference()
-	} else {
-		ref, err = alltransports.ParseImageName(opts.Images[0])
+	ref, err := alltransports.ParseImageName(opts.Images[0])
+	if err != nil {
+		dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
+		ref, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, opts.Images[0]))
 		if err != nil {
 			return "", err
 		}
diff --git a/libpod/network/config.go b/libpod/network/config.go
index ce8a4446c..ce351129e 100644
--- a/libpod/network/config.go
+++ b/libpod/network/config.go
@@ -129,6 +129,16 @@ func (f FirewallConfig) Bytes() ([]byte, error) {
 	return json.MarshalIndent(f, "", "\t")
 }
 
+// TuningConfig describes the tuning plugin
+type TuningConfig struct {
+	PluginType string `json:"type"`
+}
+
+// Bytes outputs the configuration as []byte
+func (f TuningConfig) Bytes() ([]byte, error) {
+	return json.MarshalIndent(f, "", "\t")
+}
+
 // DNSNameConfig describes the dns container name resolution plugin config
 type DNSNameConfig struct {
 	PluginType   string          `json:"type"`
diff --git a/libpod/network/create.go b/libpod/network/create.go
index 387f4fcd3..7e4fc574a 100644
--- a/libpod/network/create.go
+++ b/libpod/network/create.go
@@ -176,6 +176,7 @@ func createBridge(name string, options entities.NetworkCreateOptions, runtimeCon
 	plugins = append(plugins, bridge)
 	plugins = append(plugins, NewPortMapPlugin())
 	plugins = append(plugins, NewFirewallPlugin())
+	plugins = append(plugins, NewTuningPlugin())
 	// if we find the dnsname plugin or are rootless, we add configuration for it
 	// the rootless-cni-infra container has the dnsname plugin always installed
 	if (HasDNSNamePlugin(runtimeConfig.Network.CNIPluginDirs) || rootless.IsRootless()) && !options.DisableDNS {
diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go
index 111f1715c..ee9adce14 100644
--- a/libpod/network/netconflist.go
+++ b/libpod/network/netconflist.go
@@ -119,6 +119,13 @@ func NewFirewallPlugin() FirewallConfig {
 	}
 }
 
+// NewTuningPlugin creates a generic tuning section
+func NewTuningPlugin() TuningConfig {
+	return TuningConfig{
+		PluginType: "tuning",
+	}
+}
+
 // NewDNSNamePlugin creates the dnsname config with a given
 // domainname
 func NewDNSNamePlugin(domainName string) DNSNameConfig {
diff --git a/libpod/network/subnet.go b/libpod/network/subnet.go
index 90f0cdfce..120038e57 100644
--- a/libpod/network/subnet.go
+++ b/libpod/network/subnet.go
@@ -54,14 +54,10 @@ func LastIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer
 
 	ones, bits := cidr.Mask.Size()
 	if ones == bits {
-		return FirstIPInSubnet(cidr)
+		return cidr.IP, nil
 	}
-	hostStart := ones / 8
-	// Handle the first host byte
-	cidr.IP[hostStart] |= 0xff & cidr.Mask[hostStart]
-	// Fill the rest with ones
-	for i := hostStart; i < len(cidr.IP); i++ {
-		cidr.IP[i] = 0xff
+	for i := range cidr.IP {
+		cidr.IP[i] = cidr.IP[i] | ^cidr.Mask[i]
 	}
 	return cidr.IP, nil
 }
@@ -73,6 +69,10 @@ func FirstIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer
 	if err != nil {
 		return nil, err
 	}
+	ones, bits := cidr.Mask.Size()
+	if ones == bits {
+		return cidr.IP, nil
+	}
 	cidr.IP[len(cidr.IP)-1]++
 	return cidr.IP, nil
 }
diff --git a/libpod/network/subnet_test.go b/libpod/network/subnet_test.go
index 917c3be88..55b2443bd 100644
--- a/libpod/network/subnet_test.go
+++ b/libpod/network/subnet_test.go
@@ -33,3 +33,65 @@ func TestNextSubnet(t *testing.T) {
 		})
 	}
 }
+
+func TestFirstIPInSubnet(t *testing.T) {
+	tests := []struct {
+		name    string
+		args    *net.IPNet
+		want    net.IP
+		wantErr bool
+	}{
+		{"class b", parseCIDR("192.168.0.0/16"), net.ParseIP("192.168.0.1"), false},
+		{"class c", parseCIDR("192.168.1.0/24"), net.ParseIP("192.168.1.1"), false},
+		{"cidr /23", parseCIDR("192.168.0.0/23"), net.ParseIP("192.168.0.1"), false},
+		{"cidr /25", parseCIDR("192.168.1.0/25"), net.ParseIP("192.168.1.1"), false},
+		{"cidr /26", parseCIDR("172.16.1.128/26"), net.ParseIP("172.16.1.129"), false},
+		{"class a", parseCIDR("10.0.0.0/8"), net.ParseIP("10.0.0.1"), false},
+		{"cidr /32", parseCIDR("192.168.255.4/32"), net.ParseIP("192.168.255.4"), false},
+		{"cidr /31", parseCIDR("192.168.255.4/31"), net.ParseIP("192.168.255.5"), false},
+	}
+	for _, tt := range tests {
+		test := tt
+		t.Run(test.name, func(t *testing.T) {
+			got, err := FirstIPInSubnet(test.args)
+			if (err != nil) != test.wantErr {
+				t.Errorf("FirstIPInSubnet() error = %v, wantErr %v", err, test.wantErr)
+				return
+			}
+			if !got.Equal(test.want) {
+				t.Errorf("FirstIPInSubnet() got = %v, want %v", got, test.want)
+			}
+		})
+	}
+}
+
+func TestLastIPInSubnet(t *testing.T) {
+	tests := []struct {
+		name    string
+		args    *net.IPNet
+		want    net.IP
+		wantErr bool
+	}{
+		{"class b", parseCIDR("192.168.0.0/16"), net.ParseIP("192.168.255.255"), false},
+		{"class c", parseCIDR("192.168.1.0/24"), net.ParseIP("192.168.1.255"), false},
+		{"cidr /23", parseCIDR("192.168.0.0/23"), net.ParseIP("192.168.1.255"), false},
+		{"cidr /25", parseCIDR("192.168.1.0/25"), net.ParseIP("192.168.1.127"), false},
+		{"cidr /26", parseCIDR("172.16.1.128/26"), net.ParseIP("172.16.1.191"), false},
+		{"class a", parseCIDR("10.0.0.0/8"), net.ParseIP("10.255.255.255"), false},
+		{"cidr /32", parseCIDR("192.168.255.4/32"), net.ParseIP("192.168.255.4"), false},
+		{"cidr /31", parseCIDR("192.168.255.4/31"), net.ParseIP("192.168.255.5"), false},
+	}
+	for _, tt := range tests {
+		test := tt
+		t.Run(test.name, func(t *testing.T) {
+			got, err := LastIPInSubnet(test.args)
+			if (err != nil) != test.wantErr {
+				t.Errorf("LastIPInSubnet() error = %v, wantErr %v", err, test.wantErr)
+				return
+			}
+			if !got.Equal(test.want) {
+				t.Errorf("LastIPInSubnet() got = %v, want %v", got, test.want)
+			}
+		})
+	}
+}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 8dce7c9fe..4e7ffaf81 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -110,10 +110,15 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re
 
 	podName := getCNIPodName(ctr)
 
-	networks, err := ctr.networks()
+	networks, _, err := ctr.networks()
 	if err != nil {
 		return nil, err
 	}
+	// All networks have been removed from the container.
+	// This is effectively forcing net=none.
+	if len(networks) == 0 {
+		return nil, nil
+	}
 
 	// Update container map of interface descriptions
 	if err := ctr.setupNetworkDescriptions(networks); err != nil {
@@ -224,7 +229,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
 	if ctr.config.NetMode.IsSlirp4netns() {
 		return r.setupSlirp4netns(ctr)
 	}
-	networks, err := ctr.networks()
+	networks, _, err := ctr.networks()
 	if err != nil {
 		return err
 	}
@@ -744,13 +749,13 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
 
 	logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID())
 
-	networks, err := ctr.networks()
+	networks, _, err := ctr.networks()
 	if err != nil {
 		return err
 	}
 
 	// rootless containers do not use the CNI plugin directly
-	if !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() {
+	if !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() && len(networks) > 0 {
 		var requestedIP net.IP
 		if ctr.requestedIP != nil {
 			requestedIP = ctr.requestedIP
@@ -863,7 +868,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
 	settings := new(define.InspectNetworkSettings)
 	settings.Ports = makeInspectPortBindings(c.config.PortMappings)
 
-	networks, err := c.networks()
+	networks, isDefault, err := c.networks()
 	if err != nil {
 		return nil, err
 	}
@@ -872,7 +877,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
 	if c.state.NetNS == nil {
 		// We still want to make dummy configurations for each CNI net
 		// the container joined.
-		if len(networks) > 0 {
+		if len(networks) > 0 && !isDefault {
 			settings.Networks = make(map[string]*define.InspectAdditionalNetwork, len(networks))
 			for _, net := range networks {
 				cniNet := new(define.InspectAdditionalNetwork)
@@ -893,9 +898,9 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
 	}
 
 	// If we have CNI networks - handle that here
-	if len(networks) > 0 {
+	if len(networks) > 0 && !isDefault {
 		if len(networks) != len(c.state.NetworkStatus) {
-			return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI networks but have information on %d networks", len(networks), len(c.state.NetworkStatus))
+			return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI network(s) %v, but have information on %d network(s)", len(networks), networks, len(c.state.NetworkStatus))
 		}
 
 		settings.Networks = make(map[string]*define.InspectAdditionalNetwork)
@@ -1101,7 +1106,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
 		return err
 	}
 
-	ctrNetworks, err := c.networks()
+	ctrNetworks, _, err := c.networks()
 	if err != nil {
 		return err
 	}
@@ -1139,8 +1144,8 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
 		// build a list of network names so we can sort and
 		// get the new name's index
 		var networkNames []string
-		for netName := range networks {
-			networkNames = append(networkNames, netName)
+		for name := range networks {
+			networkNames = append(networkNames, name)
 		}
 		networkNames = append(networkNames, netName)
 		// sort
@@ -1152,6 +1157,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
 		// populate network status
 		copy(networkStatus[index+1:], networkStatus[index:])
 		networkStatus[index] = networkResults[0]
+		c.state.NetworkStatus = networkStatus
 	}
 	c.newNetworkEvent(events.NetworkConnect, netName)
 	return c.save()
diff --git a/libpod/rootless_cni_linux.go b/libpod/rootless_cni_linux.go
index 1d6158cc2..2c2977f9f 100644
--- a/libpod/rootless_cni_linux.go
+++ b/libpod/rootless_cni_linux.go
@@ -40,7 +40,7 @@ const (
 //
 // AllocRootlessCNI does not lock c. c should be already locked.
 func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.Result, error) {
-	networks, err := c.networks()
+	networks, _, err := c.networks()
 	if err != nil {
 		return nil, nil, err
 	}
@@ -81,7 +81,7 @@ func AllocRootlessCNI(ctx context.Context, c *Container) (ns.NetNS, []*cnitypes.
 //
 // DeallocRootlessCNI does not lock c. c should be already locked.
 func DeallocRootlessCNI(ctx context.Context, c *Container) error {
-	networks, err := c.networks()
+	networks, _, err := c.networks()
 	if err != nil {
 		return err
 	}
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 00be8e845..5886455e7 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -298,6 +298,9 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
 		state.Running = true
 	}
 
+	formatCapabilities(inspect.HostConfig.CapDrop)
+	formatCapabilities(inspect.HostConfig.CapAdd)
+
 	h, err := json.Marshal(inspect.HostConfig)
 	if err != nil {
 		return nil, err
@@ -318,8 +321,8 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
 	cb := types.ContainerJSONBase{
 		ID:              l.ID(),
 		Created:         l.CreatedTime().Format(time.RFC3339Nano),
-		Path:            "",
-		Args:            nil,
+		Path:            inspect.Path,
+		Args:            inspect.Args,
 		State:           &state,
 		Image:           imageName,
 		ResolvConfPath:  inspect.ResolvConfPath,
@@ -328,7 +331,7 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
 		LogPath:         l.LogPath(),
 		Node:            nil,
 		Name:            fmt.Sprintf("/%s", l.Name()),
-		RestartCount:    0,
+		RestartCount:    int(inspect.RestartCount),
 		Driver:          inspect.Driver,
 		Platform:        "linux",
 		MountLabel:      inspect.MountLabel,
@@ -428,3 +431,9 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
 	}
 	return &c, nil
 }
+
+func formatCapabilities(slice []string) {
+	for i := range slice {
+		slice[i] = strings.TrimPrefix(slice[i], "CAP_")
+	}
+}
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 4efe770b3..729639928 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -19,7 +19,6 @@ import (
 func CreateContainer(w http.ResponseWriter, r *http.Request) {
 	runtime := r.Context().Value("runtime").(*libpod.Runtime)
 	decoder := r.Context().Value("decoder").(*schema.Decoder)
-	input := handlers.CreateContainerConfig{}
 	query := struct {
 		Name string `schema:"name"`
 	}{
@@ -30,11 +29,15 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
 			errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
 		return
 	}
-	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
+
+	// compatible configuration
+	body := handlers.CreateContainerConfig{}
+	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
 		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
 		return
 	}
-	if len(input.HostConfig.Links) > 0 {
+
+	if len(body.HostConfig.Links) > 0 {
 		utils.Error(w, utils.ErrLinkNotSupport.Error(), http.StatusBadRequest, errors.Wrapf(utils.ErrLinkNotSupport, "bad parameter"))
 		return
 	}
@@ -43,7 +46,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
 		utils.Error(w, "unable to obtain runtime config", http.StatusInternalServerError, errors.Wrap(err, "unable to get runtime config"))
 	}
 
-	newImage, err := runtime.ImageRuntime().NewFromLocal(input.Image)
+	newImage, err := runtime.ImageRuntime().NewFromLocal(body.Config.Image)
 	if err != nil {
 		if errors.Cause(err) == define.ErrNoSuchImage {
 			utils.Error(w, "No such image", http.StatusNotFound, err)
@@ -54,11 +57,8 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	// Add the container name to the input struct
-	input.Name = query.Name
-
-	// Take input structure and convert to cliopts
-	cliOpts, args, err := common.ContainerCreateToContainerCLIOpts(input, rtc.Engine.CgroupManager)
+	// Take body structure and convert to cliopts
+	cliOpts, args, err := common.ContainerCreateToContainerCLIOpts(body, rtc.Engine.CgroupManager)
 	if err != nil {
 		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "make cli opts()"))
 		return
@@ -69,6 +69,9 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	// Override the container name in the body struct
+	body.Name = query.Name
+
 	ic := abi.ContainerEngine{Libpod: runtime}
 	report, err := ic.ContainerCreate(r.Context(), sg)
 	if err != nil {
diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go
index 2bb165522..4b3a390f1 100644
--- a/pkg/api/handlers/compat/info.go
+++ b/pkg/api/handlers/compat/info.go
@@ -17,6 +17,7 @@ import (
 	"github.com/containers/podman/v2/pkg/api/handlers/utils"
 	"github.com/containers/podman/v2/pkg/rootless"
 	docker "github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/api/types/swarm"
 	"github.com/google/uuid"
 	"github.com/pkg/errors"
@@ -103,7 +104,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
 		PidsLimit:          sysInfo.PidsLimit,
 		Plugins:            docker.PluginsInfo{},
 		ProductLicense:     "Apache-2.0",
-		RegistryConfig:     nil,
+		RegistryConfig:     new(registry.ServiceConfig),
 		RuncCommit:         docker.Commit{},
 		Runtimes:           getRuntimes(configInfo),
 		SecurityOptions:    getSecOpts(sysInfo),
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index 7e6481321..14eb44831 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -344,3 +344,27 @@ func InitContainer(w http.ResponseWriter, r *http.Request) {
 	}
 	utils.WriteResponse(w, http.StatusNoContent, "")
 }
+
+func ShouldRestart(w http.ResponseWriter, r *http.Request) {
+	runtime := r.Context().Value("runtime").(*libpod.Runtime)
+	// Now use the ABI implementation to prevent us from having duplicate
+	// code.
+	containerEngine := abi.ContainerEngine{Libpod: runtime}
+
+	name := utils.GetName(r)
+	report, err := containerEngine.ShouldRestart(r.Context(), name)
+	if err != nil {
+		if errors.Cause(err) == define.ErrNoSuchCtr {
+			utils.ContainerNotFound(w, name, err)
+			return
+		}
+		utils.InternalServerError(w, err)
+		return
+
+	}
+	if report.Value {
+		utils.WriteResponse(w, http.StatusNoContent, "")
+	} else {
+		utils.ContainerNotFound(w, name, define.ErrNoSuchCtr)
+	}
+}
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index 6bb5f5101..40cf16807 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -110,11 +110,12 @@ type ContainerWaitOKBody struct {
 	}
 }
 
+// CreateContainerConfig used when compatible endpoint creates a container
 type CreateContainerConfig struct {
-	Name string
-	dockerContainer.Config
-	HostConfig       dockerContainer.HostConfig
-	NetworkingConfig dockerNetwork.NetworkingConfig
+	Name                   string                         // container name
+	dockerContainer.Config                                // desired container configuration
+	HostConfig             dockerContainer.HostConfig     // host dependent configuration for container
+	NetworkingConfig       dockerNetwork.NetworkingConfig // network configuration for container
 }
 
 // swagger:model IDResponse
@@ -253,7 +254,7 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
 		//	StdinOnce:       false,
 		Env: info.Config.Env,
 		Cmd: info.Config.Cmd,
-		//Healthcheck: l.ImageData.HealthCheck,
+		// Healthcheck: l.ImageData.HealthCheck,
 		//	ArgsEscaped:     false,
 		//	Image:           "",
 		Volumes:    info.Config.Volumes,
@@ -261,7 +262,7 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
 		Entrypoint: info.Config.Entrypoint,
 		//	NetworkDisabled: false,
 		//	MacAddress:      "",
-		//OnBuild:    info.Config.OnBuild,
+		// OnBuild:    info.Config.OnBuild,
 		Labels:     info.Labels,
 		StopSignal: info.Config.StopSignal,
 		//	StopTimeout:     nil,
diff --git a/pkg/api/server/handler_api.go b/pkg/api/server/handler_api.go
index 28f5a0b42..1d0ddb457 100644
--- a/pkg/api/server/handler_api.go
+++ b/pkg/api/server/handler_api.go
@@ -30,14 +30,14 @@ func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
 		// Wrapper to hide some boiler plate
 		fn := func(w http.ResponseWriter, r *http.Request) {
 			rid := uuid.New().String()
+			logrus.Infof("APIHandler(%s) -- %s %s BEGIN", rid, r.Method, r.URL.String())
 			if logrus.IsLevelEnabled(logrus.DebugLevel) {
-				logrus.Debugf("APIHandler(%s) -- Method: %s URL: %s", rid, r.Method, r.URL.String())
 				for k, v := range r.Header {
 					switch auth.HeaderAuthName(k) {
 					case auth.XRegistryConfigHeader, auth.XRegistryAuthHeader:
-						logrus.Debugf("APIHandler(%s) -- Header: %s: <hidden>", rid, k)
+						logrus.Debugf("APIHandler(%s) -- Header: %s=<hidden>", rid, k)
 					default:
-						logrus.Debugf("APIHandler(%s) -- Header: %s: %v", rid, k, v)
+						logrus.Debugf("APIHandler(%s) -- Header: %s=%v", rid, k, v)
 					}
 				}
 			}
@@ -63,6 +63,7 @@ func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
 			w.Header().Set("Server", "Libpod/"+lv+" ("+runtime.GOOS+")")
 
 			h(w, r)
+			logrus.Debugf("APIHandler(%s) -- %s %s END", rid, r.Method, r.URL.String())
 		}
 		fn(w, r)
 	}
diff --git a/pkg/api/server/listener_api.go b/pkg/api/server/listener_api.go
index 4984216b8..2d02df7dc 100644
--- a/pkg/api/server/listener_api.go
+++ b/pkg/api/server/listener_api.go
@@ -27,5 +27,6 @@ func ListenUnix(network string, path string) (net.Listener, error) {
 	if err != nil {
 		return nil, errors.Wrapf(err, "net.Listen(%s, %s) failed to report the failure to create socket", network, path)
 	}
+
 	return listener, nil
 }
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 64008767b..09b6079e4 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -51,10 +51,7 @@ func NewServer(runtime *libpod.Runtime) (*APIServer, error) {
 }
 
 // NewServerWithSettings will create and configure a new API server using provided settings
-func NewServerWithSettings(runtime *libpod.Runtime, duration time.Duration, listener *net.Listener) (
-	*APIServer,
-	error,
-) {
+func NewServerWithSettings(runtime *libpod.Runtime, duration time.Duration, listener *net.Listener) (*APIServer, error) {
 	return newServer(runtime, duration, listener)
 }
 
@@ -75,6 +72,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
 		listener = &listeners[0]
 	}
 
+	logrus.Infof("API server listening on %q", (*listener).Addr())
 	router := mux.NewRouter().UseEncodedPath()
 	idle := idle.NewTracker(duration)
 
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index b5cd2128b..4331ae6c2 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -390,3 +390,15 @@ func ContainerInit(ctx context.Context, nameOrID string) error {
 	}
 	return response.Process(nil)
 }
+
+func ShouldRestart(ctx context.Context, nameOrID string) (bool, error) {
+	conn, err := bindings.GetClient(ctx)
+	if err != nil {
+		return false, err
+	}
+	response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/shouldrestart", nil, nil, nameOrID)
+	if err != nil {
+		return false, err
+	}
+	return response.IsSuccess(), nil
+}
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 101542a98..ab545d882 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -51,10 +51,10 @@ func (i *Image) Id() string { // nolint
 }
 
 type ImageSummary struct {
-	ID          string            `json:"Id"`
-	ParentId    string            `json:",omitempty"` // nolint
-	RepoTags    []string          `json:",omitempty"`
-	Created     int64             `json:",omitempty"`
+	ID          string   `json:"Id"`
+	ParentId    string   // nolint
+	RepoTags    []string `json:",omitempty"`
+	Created     int64
 	Size        int64             `json:",omitempty"`
 	SharedSize  int               `json:",omitempty"`
 	VirtualSize int64             `json:",omitempty"`
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 4b69ac74e..ff4277a2e 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -911,7 +911,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
 	} else {
 		report.ExitCode = int(ecode)
 	}
-	if opts.Rm {
+	if opts.Rm && !ctr.ShouldRestart(ctx) {
 		if err := ic.Libpod.RemoveContainer(ctx, ctr, false, true); err != nil {
 			if errors.Cause(err) == define.ErrNoSuchCtr ||
 				errors.Cause(err) == define.ErrCtrRemoved {
@@ -992,7 +992,7 @@ func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []st
 			return []*entities.ContainerCleanupReport{}, nil
 		}
 
-		if options.Remove {
+		if options.Remove && !ctr.ShouldRestart(ctx) {
 			err = ic.Libpod.RemoveContainer(ctx, ctr, false, true)
 			if err != nil {
 				report.RmErr = errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID())
@@ -1015,6 +1015,7 @@ func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []st
 			_, err = ic.Libpod.RemoveImage(ctx, ctrImage, false)
 			report.RmiErr = err
 		}
+
 		reports = append(reports, &report)
 	}
 	return reports, nil
@@ -1314,3 +1315,13 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
 
 	return statsChan, nil
 }
+
+// ShouldRestart returns whether the container should be restarted
+func (ic *ContainerEngine) ShouldRestart(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
+	ctr, err := ic.Libpod.LookupContainer(nameOrID)
+	if err != nil {
+		return nil, err
+	}
+
+	return &entities.BoolReport{Value: ctr.ShouldRestart(ctx)}, nil
+}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 8066e1c00..1aa5afbe7 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -595,12 +595,20 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
 		// Defer the removal, so we can return early if needed and
 		// de-spaghetti the code.
 		defer func() {
-			if err := containers.Remove(ic.ClientCxt, con.ID, bindings.PFalse, bindings.PTrue); err != nil {
-				if errorhandling.Contains(err, define.ErrNoSuchCtr) ||
-					errorhandling.Contains(err, define.ErrCtrRemoved) {
-					logrus.Warnf("Container %s does not exist: %v", con.ID, err)
-				} else {
-					logrus.Errorf("Error removing container %s: %v", con.ID, err)
+			shouldRestart, err := containers.ShouldRestart(ic.ClientCxt, con.ID)
+			if err != nil {
+				logrus.Errorf("Failed to check if %s should restart: %v", con.ID, err)
+				return
+			}
+
+			if !shouldRestart {
+				if err := containers.Remove(ic.ClientCxt, con.ID, bindings.PFalse, bindings.PTrue); err != nil {
+					if errorhandling.Contains(err, define.ErrNoSuchCtr) ||
+						errorhandling.Contains(err, define.ErrCtrRemoved) {
+						logrus.Warnf("Container %s does not exist: %v", con.ID, err)
+					} else {
+						logrus.Errorf("Error removing container %s: %v", con.ID, err)
+					}
 				}
 			}
 		}()
@@ -737,3 +745,8 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
 	}
 	return containers.Stats(ic.ClientCxt, namesOrIds, &options.Stream)
 }
+
+// ShouldRestart reports back whether the containre will restart
+func (ic *ContainerEngine) ShouldRestart(_ context.Context, id string) (bool, error) {
+	return containers.ShouldRestart(ic.ClientCxt, id)
+}
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index c049e64cf..45a374216 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -111,7 +111,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
 		return nil, errors.Wrap(err, "invalid config provided")
 	}
 
-	finalMounts, finalVolumes, err := finalizeMounts(ctx, s, rt, rtc, newImage)
+	finalMounts, finalVolumes, finalOverlays, err := finalizeMounts(ctx, s, rt, rtc, newImage)
 	if err != nil {
 		return nil, err
 	}
@@ -121,7 +121,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
 		return nil, err
 	}
 
-	opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, newImage, command)
+	opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, finalOverlays, newImage, command)
 	if err != nil {
 		return nil, err
 	}
@@ -144,7 +144,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
 	return rt.NewContainer(ctx, runtimeSpec, options...)
 }
 
-func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, pod *libpod.Pod, volumes []*specgen.NamedVolume, img *image.Image, command []string) ([]libpod.CtrCreateOption, error) {
+func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, pod *libpod.Pod, volumes []*specgen.NamedVolume, overlays []*specgen.OverlayVolume, img *image.Image, command []string) ([]libpod.CtrCreateOption, error) {
 	var options []libpod.CtrCreateOption
 	var err error
 
@@ -224,7 +224,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
 	for _, volume := range volumes {
 		destinations = append(destinations, volume.Dest)
 	}
-	for _, overlayVolume := range s.OverlayVolumes {
+	for _, overlayVolume := range overlays {
 		destinations = append(destinations, overlayVolume.Destination)
 	}
 	for _, imageVolume := range s.ImageVolumes {
@@ -244,9 +244,9 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
 		options = append(options, libpod.WithNamedVolumes(vols))
 	}
 
-	if len(s.OverlayVolumes) != 0 {
+	if len(overlays) != 0 {
 		var vols []*libpod.ContainerOverlayVolume
-		for _, v := range s.OverlayVolumes {
+		for _, v := range overlays {
 			vols = append(vols, &libpod.ContainerOverlayVolume{
 				Dest:   v.Destination,
 				Source: v.Source,
diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go
index b225f79ee..331a5c5bf 100644
--- a/pkg/specgen/generate/storage.go
+++ b/pkg/specgen/generate/storage.go
@@ -33,17 +33,17 @@ var (
 )
 
 // Produce final mounts and named volumes for a container
-func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, img *image.Image) ([]spec.Mount, []*specgen.NamedVolume, error) {
+func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, img *image.Image) ([]spec.Mount, []*specgen.NamedVolume, []*specgen.OverlayVolume, error) {
 	// Get image volumes
 	baseMounts, baseVolumes, err := getImageVolumes(ctx, img, s)
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, nil, err
 	}
 
 	// Get volumes-from mounts
 	volFromMounts, volFromVolumes, err := getVolumesFrom(s.VolumesFrom, rt)
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, nil, err
 	}
 
 	// Supersede from --volumes-from.
@@ -57,19 +57,53 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
 	// Need to make map forms of specgen mounts/volumes.
 	unifiedMounts := map[string]spec.Mount{}
 	unifiedVolumes := map[string]*specgen.NamedVolume{}
+	unifiedOverlays := map[string]*specgen.OverlayVolume{}
+
+	// Need to make map forms of specgen mounts/volumes.
+	commonMounts, commonVolumes, commonOverlayVolumes, err := specgen.GenVolumeMounts(rtc.Volumes())
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
 	for _, m := range s.Mounts {
 		if _, ok := unifiedMounts[m.Destination]; ok {
-			return nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", m.Destination)
+			return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", m.Destination)
 		}
 		unifiedMounts[m.Destination] = m
 	}
+
+	for _, m := range commonMounts {
+		if _, ok := unifiedMounts[m.Destination]; !ok {
+			unifiedMounts[m.Destination] = m
+		}
+	}
+
 	for _, v := range s.Volumes {
 		if _, ok := unifiedVolumes[v.Dest]; ok {
-			return nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Dest)
+			return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Dest)
 		}
 		unifiedVolumes[v.Dest] = v
 	}
 
+	for _, v := range commonVolumes {
+		if _, ok := unifiedVolumes[v.Dest]; !ok {
+			unifiedVolumes[v.Dest] = v
+		}
+	}
+
+	for _, v := range s.OverlayVolumes {
+		if _, ok := unifiedOverlays[v.Destination]; ok {
+			return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Destination)
+		}
+		unifiedOverlays[v.Destination] = v
+	}
+
+	for _, v := range commonOverlayVolumes {
+		if _, ok := unifiedOverlays[v.Destination]; ok {
+			unifiedOverlays[v.Destination] = v
+		}
+	}
+
 	// If requested, add container init binary
 	if s.Init {
 		initPath := s.InitPath
@@ -78,10 +112,10 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
 		}
 		initMount, err := addContainerInitBinary(s, initPath)
 		if err != nil {
-			return nil, nil, err
+			return nil, nil, nil, err
 		}
 		if _, ok := unifiedMounts[initMount.Destination]; ok {
-			return nil, nil, errors.Wrapf(errDuplicateDest, "conflict with mount added by --init to %q", initMount.Destination)
+			return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict with mount added by --init to %q", initMount.Destination)
 		}
 		unifiedMounts[initMount.Destination] = initMount
 	}
@@ -115,12 +149,12 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
 	// Check for conflicts between named volumes and mounts
 	for dest := range baseMounts {
 		if _, ok := baseVolumes[dest]; ok {
-			return nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
+			return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
 		}
 	}
 	for dest := range baseVolumes {
 		if _, ok := baseMounts[dest]; ok {
-			return nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
+			return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
 		}
 	}
 	// Final step: maps to arrays
@@ -129,7 +163,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
 		if mount.Type == TypeBind {
 			absSrc, err := filepath.Abs(mount.Source)
 			if err != nil {
-				return nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source)
+				return nil, nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source)
 			}
 			mount.Source = absSrc
 		}
@@ -140,7 +174,12 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
 		finalVolumes = append(finalVolumes, volume)
 	}
 
-	return finalMounts, finalVolumes, nil
+	finalOverlays := make([]*specgen.OverlayVolume, 0, len(unifiedOverlays))
+	for _, volume := range unifiedOverlays {
+		finalOverlays = append(finalOverlays, volume)
+	}
+
+	return finalMounts, finalVolumes, finalOverlays, nil
 }
 
 // Get image volumes from the given image
diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go
index 90c56d366..11108a5c1 100644
--- a/pkg/specgen/namespaces.go
+++ b/pkg/specgen/namespaces.go
@@ -272,16 +272,10 @@ func ParseNetworkNamespace(ns string) (Namespace, []string, error) {
 		toReturn.NSMode = Private
 	case strings.HasPrefix(ns, "ns:"):
 		split := strings.SplitN(ns, ":", 2)
-		if len(split) != 2 {
-			return toReturn, nil, errors.Errorf("must provide a path to a namespace when specifying ns:")
-		}
 		toReturn.NSMode = Path
 		toReturn.Value = split[1]
 	case strings.HasPrefix(ns, "container:"):
 		split := strings.SplitN(ns, ":", 2)
-		if len(split) != 2 {
-			return toReturn, nil, errors.Errorf("must provide name or ID or a container when specifying container:")
-		}
 		toReturn.NSMode = FromContainer
 		toReturn.Value = split[1]
 	default:
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index 0a9a16ea7..fad2406e5 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -1,13 +1,13 @@
 package specgen
 
 import (
-	"errors"
 	"net"
 	"syscall"
 
 	"github.com/containers/image/v5/manifest"
 	"github.com/containers/storage"
 	spec "github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/pkg/errors"
 )
 
 //  LogConfig describes the logging characteristics for a container
@@ -459,42 +459,6 @@ type SpecGenerator struct {
 	ContainerHealthCheckConfig
 }
 
-// NamedVolume holds information about a named volume that will be mounted into
-// the container.
-type NamedVolume struct {
-	// Name is the name of the named volume to be mounted. May be empty.
-	// If empty, a new named volume with a pseudorandomly generated name
-	// will be mounted at the given destination.
-	Name string
-	// Destination to mount the named volume within the container. Must be
-	// an absolute path. Path will be created if it does not exist.
-	Dest string
-	// Options are options that the named volume will be mounted with.
-	Options []string
-}
-
-// OverlayVolume holds information about a overlay volume that will be mounted into
-// the container.
-type OverlayVolume struct {
-	// Destination is the absolute path where the mount will be placed in the container.
-	Destination string `json:"destination"`
-	// Source specifies the source path of the mount.
-	Source string `json:"source,omitempty"`
-}
-
-// ImageVolume is a volume based on a container image.  The container image is
-// first mounted on the host and is then bind-mounted into the container.  An
-// ImageVolume is always mounted read only.
-type ImageVolume struct {
-	// Source is the source of the image volume.  The image can be referred
-	// to by name and by ID.
-	Source string
-	// Destination is the absolute path of the mount in the container.
-	Destination string
-	// ReadWrite sets the volume writable.
-	ReadWrite bool
-}
-
 // PortMapping is one or more ports that will be mapped into the container.
 type PortMapping struct {
 	// HostIP is the IP that we will bind to on the host.
diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go
new file mode 100644
index 000000000..1178f9960
--- /dev/null
+++ b/pkg/specgen/volumes.go
@@ -0,0 +1,149 @@
+package specgen
+
+import (
+	"path/filepath"
+	"strings"
+
+	"github.com/containers/buildah/pkg/parse"
+	spec "github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+)
+
+// NamedVolume holds information about a named volume that will be mounted into
+// the container.
+type NamedVolume struct {
+	// Name is the name of the named volume to be mounted. May be empty.
+	// If empty, a new named volume with a pseudorandomly generated name
+	// will be mounted at the given destination.
+	Name string
+	// Destination to mount the named volume within the container. Must be
+	// an absolute path. Path will be created if it does not exist.
+	Dest string
+	// Options are options that the named volume will be mounted with.
+	Options []string
+}
+
+// OverlayVolume holds information about a overlay volume that will be mounted into
+// the container.
+type OverlayVolume struct {
+	// Destination is the absolute path where the mount will be placed in the container.
+	Destination string `json:"destination"`
+	// Source specifies the source path of the mount.
+	Source string `json:"source,omitempty"`
+}
+
+// ImageVolume is a volume based on a container image.  The container image is
+// first mounted on the host and is then bind-mounted into the container.  An
+// ImageVolume is always mounted read only.
+type ImageVolume struct {
+	// Source is the source of the image volume.  The image can be referred
+	// to by name and by ID.
+	Source string
+	// Destination is the absolute path of the mount in the container.
+	Destination string
+	// ReadWrite sets the volume writable.
+	ReadWrite bool
+}
+
+// GenVolumeMounts parses user input into mounts, volumes and overlay volumes
+func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*NamedVolume, map[string]*OverlayVolume, error) {
+	errDuplicateDest := errors.Errorf("duplicate mount destination")
+
+	mounts := make(map[string]spec.Mount)
+	volumes := make(map[string]*NamedVolume)
+	overlayVolumes := make(map[string]*OverlayVolume)
+
+	volumeFormatErr := errors.Errorf("incorrect volume format, should be [host-dir:]ctr-dir[:option]")
+
+	for _, vol := range volumeFlag {
+		var (
+			options []string
+			src     string
+			dest    string
+			err     error
+		)
+
+		splitVol := strings.Split(vol, ":")
+		if len(splitVol) > 3 {
+			return nil, nil, nil, errors.Wrapf(volumeFormatErr, vol)
+		}
+
+		src = splitVol[0]
+		if len(splitVol) == 1 {
+			// This is an anonymous named volume. Only thing given
+			// is destination.
+			// Name/source will be blank, and populated by libpod.
+			src = ""
+			dest = splitVol[0]
+		} else if len(splitVol) > 1 {
+			dest = splitVol[1]
+		}
+		if len(splitVol) > 2 {
+			if options, err = parse.ValidateVolumeOpts(strings.Split(splitVol[2], ",")); err != nil {
+				return nil, nil, nil, err
+			}
+		}
+
+		// Do not check source dir for anonymous volumes
+		if len(splitVol) > 1 {
+			if err := parse.ValidateVolumeHostDir(src); err != nil {
+				return nil, nil, nil, err
+			}
+		}
+		if err := parse.ValidateVolumeCtrDir(dest); err != nil {
+			return nil, nil, nil, err
+		}
+
+		cleanDest := filepath.Clean(dest)
+
+		if strings.HasPrefix(src, "/") || strings.HasPrefix(src, ".") {
+			// This is not a named volume
+			overlayFlag := false
+			for _, o := range options {
+				if o == "O" {
+					overlayFlag = true
+					if len(options) > 1 {
+						return nil, nil, nil, errors.New("can't use 'O' with other options")
+					}
+				}
+			}
+			if overlayFlag {
+				// This is a overlay volume
+				newOverlayVol := new(OverlayVolume)
+				newOverlayVol.Destination = cleanDest
+				newOverlayVol.Source = src
+				if _, ok := overlayVolumes[newOverlayVol.Destination]; ok {
+					return nil, nil, nil, errors.Wrapf(errDuplicateDest, newOverlayVol.Destination)
+				}
+				overlayVolumes[newOverlayVol.Destination] = newOverlayVol
+			} else {
+				newMount := spec.Mount{
+					Destination: cleanDest,
+					Type:        "bind",
+					Source:      src,
+					Options:     options,
+				}
+				if _, ok := mounts[newMount.Destination]; ok {
+					return nil, nil, nil, errors.Wrapf(errDuplicateDest, newMount.Destination)
+				}
+				mounts[newMount.Destination] = newMount
+			}
+		} else {
+			// This is a named volume
+			newNamedVol := new(NamedVolume)
+			newNamedVol.Name = src
+			newNamedVol.Dest = cleanDest
+			newNamedVol.Options = options
+
+			if _, ok := volumes[newNamedVol.Dest]; ok {
+				return nil, nil, nil, errors.Wrapf(errDuplicateDest, newNamedVol.Dest)
+			}
+			volumes[newNamedVol.Dest] = newNamedVol
+		}
+
+		logrus.Debugf("User mount %s:%s options %v", src, dest, options)
+	}
+
+	return mounts, volumes, overlayVolumes, nil
+}
diff --git a/test/apiv2/rest_api/__init__.py b/test/apiv2/rest_api/__init__.py
index 8100a4df5..db0257f03 100644
--- a/test/apiv2/rest_api/__init__.py
+++ b/test/apiv2/rest_api/__init__.py
@@ -16,19 +16,18 @@ class Podman(object):
         binary = os.getenv("PODMAN", "bin/podman")
         self.cmd = [binary, "--storage-driver=vfs"]
 
-        cgroupfs = os.getenv("CGROUP_MANAGER", "cgroupfs")
+        cgroupfs = os.getenv("CGROUP_MANAGER", "systemd")
         self.cmd.append(f"--cgroup-manager={cgroupfs}")
 
         if os.getenv("DEBUG"):
             self.cmd.append("--log-level=debug")
+            self.cmd.append("--syslog=true")
 
         self.anchor_directory = tempfile.mkdtemp(prefix="podman_restapi_")
         self.cmd.append("--root=" + os.path.join(self.anchor_directory, "crio"))
         self.cmd.append("--runroot=" + os.path.join(self.anchor_directory, "crio-run"))
 
-        os.environ["REGISTRIES_CONFIG_PATH"] = os.path.join(
-            self.anchor_directory, "registry.conf"
-        )
+        os.environ["REGISTRIES_CONFIG_PATH"] = os.path.join(self.anchor_directory, "registry.conf")
         p = configparser.ConfigParser()
         p.read_dict(
             {
@@ -40,14 +39,10 @@ class Podman(object):
         with open(os.environ["REGISTRIES_CONFIG_PATH"], "w") as w:
             p.write(w)
 
-        os.environ["CNI_CONFIG_PATH"] = os.path.join(
-            self.anchor_directory, "cni", "net.d"
-        )
+        os.environ["CNI_CONFIG_PATH"] = os.path.join(self.anchor_directory, "cni", "net.d")
         os.makedirs(os.environ["CNI_CONFIG_PATH"], exist_ok=True)
         self.cmd.append("--cni-config-dir=" + os.environ["CNI_CONFIG_PATH"])
-        cni_cfg = os.path.join(
-            os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist"
-        )
+        cni_cfg = os.path.join(os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist")
         # json decoded and encoded to ensure legal json
         buf = json.loads(
             """
diff --git a/test/apiv2/rest_api/test_rest_v2_0_0.py b/test/apiv2/rest_api/test_rest_v2_0_0.py
index 49e18f063..52348d4f4 100644
--- a/test/apiv2/rest_api/test_rest_v2_0_0.py
+++ b/test/apiv2/rest_api/test_rest_v2_0_0.py
@@ -61,9 +61,7 @@ class TestApi(unittest.TestCase):
         super().setUpClass()
 
         TestApi.podman = Podman()
-        TestApi.service = TestApi.podman.open(
-            "system", "service", "tcp:localhost:8080", "--time=0"
-        )
+        TestApi.service = TestApi.podman.open("system", "service", "tcp:localhost:8080", "--time=0")
         # give the service some time to be ready...
         time.sleep(2)
 
@@ -165,11 +163,71 @@ class TestApi(unittest.TestCase):
         r = requests.get(_url(ctnr("/containers/{}/logs?stdout=true")))
         self.assertEqual(r.status_code, 200, r.text)
 
-    def test_post_create_compat(self):
+    # TODO Need to support Docker-py order of network/container creates
+    def test_post_create_compat_connect(self):
         """Create network and container then connect to network"""
-        net = requests.post(
-            PODMAN_URL + "/v1.40/networks/create", json={"Name": "TestNetwork"}
+        net_default = requests.post(
+            PODMAN_URL + "/v1.40/networks/create", json={"Name": "TestDefaultNetwork"}
+        )
+        self.assertEqual(net_default.status_code, 201, net_default.text)
+
+        create = requests.post(
+            PODMAN_URL + "/v1.40/containers/create?name=postCreate",
+            json={
+                "Cmd": ["top"],
+                "Image": "alpine:latest",
+                "NetworkDisabled": False,
+                # FIXME adding these 2 lines cause: (This is sampled from docker-py)
+                #   "network already exists","message":"container
+                #  01306e499df5441560d70071a54342611e422a94de20865add50a9565fd79fb9 is already connected to CNI network \"TestDefaultNetwork\": network already exists"
+                # "HostConfig": {"NetworkMode": "TestDefaultNetwork"},
+                # "NetworkingConfig": {"EndpointsConfig": {"TestDefaultNetwork": None}},
+                # FIXME These two lines cause:
+                # CNI network \"TestNetwork\" not found","message":"error configuring network namespace for container 369ddfa7d3211ebf1fbd5ddbff91bd33fa948858cea2985c133d6b6507546dff: CNI network \"TestNetwork\" not found"
+                # "HostConfig": {"NetworkMode": "TestNetwork"},
+                # "NetworkingConfig": {"EndpointsConfig": {"TestNetwork": None}},
+                # FIXME no networking defined cause: (note this error is from the container inspect below)
+                # "internal libpod error","message":"network inspection mismatch: asked to join 2 CNI network(s) [TestDefaultNetwork podman], but have information on 1 network(s): internal libpod error"
+            },
+        )
+        self.assertEqual(create.status_code, 201, create.text)
+        payload = json.loads(create.text)
+        self.assertIsNotNone(payload["Id"])
+
+        start = requests.post(PODMAN_URL + f"/v1.40/containers/{payload['Id']}/start")
+        self.assertEqual(start.status_code, 204, start.text)
+
+        connect = requests.post(
+            PODMAN_URL + "/v1.40/networks/TestDefaultNetwork/connect",
+            json={"Container": payload["Id"]},
+        )
+        self.assertEqual(connect.status_code, 200, connect.text)
+        self.assertEqual(connect.text, "OK\n")
+
+        inspect = requests.get(f"{PODMAN_URL}/v1.40/containers/{payload['Id']}/json")
+        self.assertEqual(inspect.status_code, 200, inspect.text)
+
+        payload = json.loads(inspect.text)
+        self.assertFalse(payload["Config"].get("NetworkDisabled", False))
+
+        self.assertEqual(
+            "TestDefaultNetwork",
+            payload["NetworkSettings"]["Networks"]["TestDefaultNetwork"]["NetworkID"],
         )
+        # TODO restore this to test, when joining multiple networks possible
+        # self.assertEqual(
+        #     "TestNetwork",
+        #     payload["NetworkSettings"]["Networks"]["TestNetwork"]["NetworkID"],
+        # )
+        # TODO Need to support network aliases
+        # self.assertIn(
+        #     "test_post_create",
+        #     payload["NetworkSettings"]["Networks"]["TestNetwork"]["Aliases"],
+        # )
+
+    def test_post_create_compat(self):
+        """Create network and connect container during create"""
+        net = requests.post(PODMAN_URL + "/v1.40/networks/create", json={"Name": "TestNetwork"})
         self.assertEqual(net.status_code, 201, net.text)
 
         create = requests.post(
@@ -178,23 +236,21 @@ class TestApi(unittest.TestCase):
                 "Cmd": ["date"],
                 "Image": "alpine:latest",
                 "NetworkDisabled": False,
-                "NetworkConfig": {
-                    "EndpointConfig": {"TestNetwork": {"Aliases": ["test_post_create"]}}
-                },
+                "HostConfig": {"NetworkMode": "TestNetwork"},
             },
         )
         self.assertEqual(create.status_code, 201, create.text)
         payload = json.loads(create.text)
         self.assertIsNotNone(payload["Id"])
 
-        # This cannot be done until full completion of the network connect
-        # stack and network disconnect stack are complete
-        # connect = requests.post(
-        #     PODMAN_URL + "/v1.40/networks/TestNetwork/connect",
-        #     json={"Container": payload["Id"]},
-        # )
-        # self.assertEqual(connect.status_code, 200, connect.text)
-        # self.assertEqual(connect.text, "OK\n")
+        inspect = requests.get(f"{PODMAN_URL}/v1.40/containers/{payload['Id']}/json")
+        self.assertEqual(inspect.status_code, 200, inspect.text)
+        payload = json.loads(inspect.text)
+        self.assertFalse(payload["Config"].get("NetworkDisabled", False))
+        self.assertEqual(
+            "TestNetwork",
+            payload["NetworkSettings"]["Networks"]["TestNetwork"]["NetworkID"],
+        )
 
     def test_commit(self):
         r = requests.post(_url(ctnr("/commit?container={}")))
diff --git a/test/apiv2/rest_api/v1_test_rest_v1_0_0.py b/test/apiv2/rest_api/v1_test_rest_v1_0_0.py
index acd6273ef..23528a246 100644
--- a/test/apiv2/rest_api/v1_test_rest_v1_0_0.py
+++ b/test/apiv2/rest_api/v1_test_rest_v1_0_0.py
@@ -84,9 +84,7 @@ class TestApi(unittest.TestCase):
             print("\nService Stderr:\n" + stderr.decode("utf-8"))
 
         if TestApi.podman.returncode > 0:
-            sys.stderr.write(
-                "podman exited with error code {}\n".format(TestApi.podman.returncode)
-            )
+            sys.stderr.write("podman exited with error code {}\n".format(TestApi.podman.returncode))
             sys.exit(2)
 
         return super().tearDownClass()
diff --git a/test/e2e/config/containers-remote.conf b/test/e2e/config/containers-remote.conf
new file mode 100644
index 000000000..bc9eab951
--- /dev/null
+++ b/test/e2e/config/containers-remote.conf
@@ -0,0 +1,51 @@
+[containers]
+
+# A list of ulimits to be set in containers by default, specified as
+# "<ulimit name>=<soft limit>:<hard limit>", for example:
+# "nofile=1024:2048"
+# See setrlimit(2) for a list of resource names.
+# Any limit not specified here will be inherited from the process launching the
+# container engine.
+# Ulimits has limits for non privileged container engines.
+#
+default_ulimits = [
+  "nofile=100:100",
+]
+
+# Environment variable list for the conmon process; used for passing necessary
+# environment variables to conmon or the runtime.
+#
+env = [
+    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+    "foo=bar1",
+]
+
+# container engines use container separation using MAC(SELinux) labeling.
+# Flag is ignored on label disabled systems.
+#
+label = false
+
+# Size of /dev/shm. Specified as <number><unit>.
+# Unit is optional, values:
+# b (bytes), k (kilobytes), m (megabytes), or g (gigabytes).
+# If the unit is omitted, the system uses bytes.
+#
+shm_size = "202k"
+
+# List of devices. Specified as
+# "<device-on-host>:<device-on-container>:<permissions>", for example:
+# "/dev/sdc:/dev/xvdc:rwm".
+# If it is empty or commented out, only the default devices will be used
+#
+devices = []
+
+default_sysctls = [
+  "net.ipv4.ping_group_range=0 0",
+]
+
+dns_searches=[ "barfoo.com", ]
+dns_servers=[ "4.3.2.1", ]
+
+tz = "America/New_York"
+
+umask = "0022"
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index 1d5be218b..906153c0f 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -177,6 +177,9 @@ var _ = Describe("Podman run", func() {
 		}
 
 		os.Setenv("CONTAINERS_CONF", conffile)
+		if IsRemote() {
+			podmanTest.RestartRemoteService()
+		}
 		result := podmanTest.Podman([]string{"run", ALPINE, "ls", tempdir})
 		result.WaitWithDefaultTimeout()
 		Expect(result.ExitCode()).To(Equal(0))
@@ -224,6 +227,17 @@ var _ = Describe("Podman run", func() {
 		Expect(session.LineInOuputStartsWith("search")).To(BeFalse())
 	})
 
+	It("podman run use containers.conf search domain", func() {
+		session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		Expect(session.LineInOuputStartsWith("search")).To(BeTrue())
+		Expect(session.OutputToString()).To(ContainSubstring("foobar.com"))
+
+		Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4"))
+		Expect(session.OutputToString()).To(ContainSubstring("debug"))
+	})
+
 	It("podman run containers.conf timezone", func() {
 		//containers.conf timezone set to Pacific/Honolulu
 		session := podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"})
@@ -231,6 +245,7 @@ var _ = Describe("Podman run", func() {
 		Expect(session.ExitCode()).To(Equal(0))
 		Expect(session.OutputToString()).To(ContainSubstring("HST"))
 	})
+
 	It("podman run containers.conf umask", func() {
 		//containers.conf umask set to 0002
 		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
@@ -243,4 +258,57 @@ var _ = Describe("Podman run", func() {
 		Expect(session.OutputToString()).To(Equal("0002"))
 	})
 
+	It("podman-remote test localcontainers.conf versus remote containers.conf", func() {
+		if !IsRemote() {
+			Skip("this test is only for remote")
+		}
+
+		os.Setenv("CONTAINERS_CONF", "config/containers-remote.conf")
+		// Configuration that comes from remote server
+		// env
+		session := podmanTest.Podman([]string{"run", ALPINE, "printenv", "foo"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		Expect(session.OutputToString()).To(Equal("bar"))
+
+		// dns-search, server, options
+		session = podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		Expect(session.LineInOuputStartsWith("search")).To(BeTrue())
+		Expect(session.OutputToString()).To(ContainSubstring("foobar.com"))
+		Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4"))
+		Expect(session.OutputToString()).To(ContainSubstring("debug"))
+
+		// sysctls
+		session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/proc/sys/net/ipv4/ping_group_range"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		Expect(session.OutputToString()).To(ContainSubstring("1000"))
+
+		// shm-size
+		session = podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		Expect(session.OutputToString()).To(ContainSubstring("size=200k"))
+
+		// ulimits
+		session = podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		Expect(session.OutputToString()).To(ContainSubstring("500"))
+
+		// Configuration that comes from remote client
+		// Timezone
+		session = podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		Expect(session.OutputToString()).To(ContainSubstring("EST"))
+
+		// Umask
+		session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "umask"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		Expect(session.OutputToString()).To(Equal("0022"))
+	})
 })
diff --git a/test/e2e/create_staticmac_test.go b/test/e2e/create_staticmac_test.go
index adffdc1ca..1ac431da2 100644
--- a/test/e2e/create_staticmac_test.go
+++ b/test/e2e/create_staticmac_test.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/containers/podman/v2/pkg/rootless"
 	. "github.com/containers/podman/v2/test/utils"
+	"github.com/containers/storage/pkg/stringid"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 )
@@ -45,4 +46,21 @@ var _ = Describe("Podman run with --mac-address flag", func() {
 			Expect(result.OutputToString()).To(ContainSubstring("92:d0:c6:0a:29:34"))
 		}
 	})
+
+	It("Podman run --mac-address with custom network", func() {
+		net := "n1" + stringid.GenerateNonCryptoID()
+		session := podmanTest.Podman([]string{"network", "create", net})
+		session.WaitWithDefaultTimeout()
+		defer podmanTest.removeCNINetwork(net)
+		Expect(session.ExitCode()).To(BeZero())
+
+		result := podmanTest.Podman([]string{"run", "--network", net, "--mac-address", "92:d0:c6:00:29:34", ALPINE, "ip", "addr"})
+		result.WaitWithDefaultTimeout()
+		if rootless.IsRootless() {
+			Expect(result.ExitCode()).To(Equal(125))
+		} else {
+			Expect(result.ExitCode()).To(Equal(0))
+			Expect(result.OutputToString()).To(ContainSubstring("92:d0:c6:00:29:34"))
+		}
+	})
 })
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index c6593df34..139a90ac7 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -76,31 +76,36 @@ var _ = Describe("Podman network", func() {
 		Expect(session.LineInOutputContains(name)).To(BeFalse())
 	})
 
-	It("podman network rm no args", func() {
-		session := podmanTest.Podman([]string{"network", "rm"})
-		session.WaitWithDefaultTimeout()
-		Expect(session.ExitCode()).ToNot(BeZero())
-	})
-
-	It("podman network rm", func() {
-		SkipIfRootless("FIXME: This one is definitely broken in rootless mode")
-		name, path := generateNetworkConfig(podmanTest)
-		defer removeConf(path)
-
-		session := podmanTest.Podman([]string{"network", "ls", "--quiet"})
-		session.WaitWithDefaultTimeout()
-		Expect(session.ExitCode()).To(Equal(0))
-		Expect(session.LineInOutputContains(name)).To(BeTrue())
-
-		rm := podmanTest.Podman([]string{"network", "rm", name})
-		rm.WaitWithDefaultTimeout()
-		Expect(rm.ExitCode()).To(BeZero())
-
-		results := podmanTest.Podman([]string{"network", "ls", "--quiet"})
-		results.WaitWithDefaultTimeout()
-		Expect(results.ExitCode()).To(Equal(0))
-		Expect(results.LineInOutputContains(name)).To(BeFalse())
-	})
+	rm_func := func(rm string) {
+		It(fmt.Sprintf("podman network %s no args", rm), func() {
+			session := podmanTest.Podman([]string{"network", rm})
+			session.WaitWithDefaultTimeout()
+			Expect(session.ExitCode()).ToNot(BeZero())
+
+		})
+
+		It(fmt.Sprintf("podman network %s", rm), func() {
+			name, path := generateNetworkConfig(podmanTest)
+			defer removeConf(path)
+
+			session := podmanTest.Podman([]string{"network", "ls", "--quiet"})
+			session.WaitWithDefaultTimeout()
+			Expect(session.ExitCode()).To(Equal(0))
+			Expect(session.LineInOutputContains(name)).To(BeTrue())
+
+			rm := podmanTest.Podman([]string{"network", rm, name})
+			rm.WaitWithDefaultTimeout()
+			Expect(rm.ExitCode()).To(BeZero())
+
+			results := podmanTest.Podman([]string{"network", "ls", "--quiet"})
+			results.WaitWithDefaultTimeout()
+			Expect(results.ExitCode()).To(Equal(0))
+			Expect(results.LineInOutputContains(name)).To(BeFalse())
+		})
+	}
+
+	rm_func("rm")
+	rm_func("remove")
 
 	It("podman network inspect no args", func() {
 		session := podmanTest.Podman([]string{"network", "inspect"})
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index be0a2f6f0..ccfbcefae 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -9,6 +9,7 @@ import (
 
 	"github.com/containers/podman/v2/pkg/rootless"
 	. "github.com/containers/podman/v2/test/utils"
+	"github.com/containers/storage/pkg/stringid"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 )
@@ -476,4 +477,23 @@ entrypoint ["/fromimage"]
 		Expect(status3.ExitCode()).To(Equal(0))
 		Expect(strings.Contains(status3.OutputToString(), "Degraded")).To(BeTrue())
 	})
+
+	It("podman create pod invalid network config", func() {
+		net1 := "n1" + stringid.GenerateNonCryptoID()
+		session := podmanTest.Podman([]string{"network", "create", net1})
+		session.WaitWithDefaultTimeout()
+		defer podmanTest.removeCNINetwork(net1)
+		Expect(session.ExitCode()).To(BeZero())
+
+		session = podmanTest.Podman([]string{"pod", "create", "--network", "host", "--network", net1})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(125))
+		Expect(session.ErrorToString()).To(ContainSubstring("host"))
+		Expect(session.ErrorToString()).To(ContainSubstring("bridge"))
+
+		session = podmanTest.Podman([]string{"pod", "create", "--network", "container:abc"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(125))
+		Expect(session.ErrorToString()).To(ContainSubstring("pods presently do not support network mode container"))
+	})
 })
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index fd08d4308..05571157c 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -44,6 +44,12 @@ var _ = Describe("Podman ps", func() {
 		Expect(session.ExitCode()).To(Equal(0))
 	})
 
+	It("podman container ps no containers", func() {
+		session := podmanTest.Podman([]string{"container", "ps"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+	})
+
 	It("podman ps default", func() {
 		session := podmanTest.RunTopContainer("")
 		session.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 3e80e953e..1d416498c 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -665,4 +665,33 @@ var _ = Describe("Podman run networking", func() {
 		session.WaitWithDefaultTimeout()
 		Expect(session.ExitCode()).To(BeZero())
 	})
+
+	It("podman run with multiple networks", func() {
+		net1 := "n1" + stringid.GenerateNonCryptoID()
+		session := podmanTest.Podman([]string{"network", "create", net1})
+		session.WaitWithDefaultTimeout()
+		defer podmanTest.removeCNINetwork(net1)
+		Expect(session.ExitCode()).To(BeZero())
+
+		net2 := "n2" + stringid.GenerateNonCryptoID()
+		session = podmanTest.Podman([]string{"network", "create", net2})
+		session.WaitWithDefaultTimeout()
+		defer podmanTest.removeCNINetwork(net2)
+		Expect(session.ExitCode()).To(BeZero())
+
+		run := podmanTest.Podman([]string{"run", "--network", net1, "--network", net2, ALPINE, "ip", "-o", "-4", "addr"})
+		run.WaitWithDefaultTimeout()
+		Expect(run.ExitCode()).To(BeZero())
+		Expect(len(run.OutputToStringArray())).To(Equal(3))
+		Expect(run.OutputToString()).To(ContainSubstring("lo"))
+		Expect(run.OutputToString()).To(ContainSubstring("eth0"))
+		Expect(run.OutputToString()).To(ContainSubstring("eth1"))
+
+		//invalid config network host and cni should fail
+		run = podmanTest.Podman([]string{"run", "--network", "host", "--network", net2, ALPINE, "ip", "-o", "-4", "addr"})
+		run.WaitWithDefaultTimeout()
+		Expect(run.ExitCode()).To(Equal(125))
+		Expect(run.ErrorToString()).To(ContainSubstring("host"))
+		Expect(run.ErrorToString()).To(ContainSubstring("bridge"))
+	})
 })
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 5ee85efb9..0d65a3e59 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -75,11 +75,9 @@ var _ = Describe("Podman run", func() {
 		session.WaitWithDefaultTimeout()
 		Expect(session.ExitCode()).To(Equal(0))
 
-		// the --rm option conflicts with --restart, when the restartPolicy is not "" and "no"
-		// so the exitCode should not equal 0
 		session = podmanTest.Podman([]string{"run", "--rm", "--restart", "on-failure", ALPINE})
 		session.WaitWithDefaultTimeout()
-		Expect(session.ExitCode()).To(Not(Equal(0)))
+		Expect(session.ExitCode()).To(Equal(0))
 
 		session = podmanTest.Podman([]string{"run", "--rm", "--restart", "always", ALPINE})
 		session.WaitWithDefaultTimeout()
diff --git a/test/python/docker/__init__.py b/test/python/docker/__init__.py
index 316b102f4..351834316 100644
--- a/test/python/docker/__init__.py
+++ b/test/python/docker/__init__.py
@@ -39,9 +39,7 @@ class Podman(object):
         self.cmd.append("--root=" + os.path.join(self.anchor_directory, "crio"))
         self.cmd.append("--runroot=" + os.path.join(self.anchor_directory, "crio-run"))
 
-        os.environ["REGISTRIES_CONFIG_PATH"] = os.path.join(
-            self.anchor_directory, "registry.conf"
-        )
+        os.environ["REGISTRIES_CONFIG_PATH"] = os.path.join(self.anchor_directory, "registry.conf")
         p = configparser.ConfigParser()
         p.read_dict(
             {
@@ -53,20 +51,16 @@ class Podman(object):
         with open(os.environ["REGISTRIES_CONFIG_PATH"], "w") as w:
             p.write(w)
 
-        os.environ["CNI_CONFIG_PATH"] = os.path.join(
-            self.anchor_directory, "cni", "net.d"
-        )
+        os.environ["CNI_CONFIG_PATH"] = os.path.join(self.anchor_directory, "cni", "net.d")
         os.makedirs(os.environ["CNI_CONFIG_PATH"], exist_ok=True)
         self.cmd.append("--cni-config-dir=" + os.environ["CNI_CONFIG_PATH"])
-        cni_cfg = os.path.join(
-            os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist"
-        )
+        cni_cfg = os.path.join(os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist")
         # json decoded and encoded to ensure legal json
         buf = json.loads(
             """
             {
               "cniVersion": "0.3.0",
-              "name": "podman",
+              "name": "default",
               "plugins": [{
                   "type": "bridge",
                   "bridge": "cni0",
diff --git a/test/python/docker/common.py b/test/python/docker/common.py
index e79d64a9b..11f512495 100644
--- a/test/python/docker/common.py
+++ b/test/python/docker/common.py
@@ -4,9 +4,7 @@ from test.python.docker import constant
 
 
 def run_top_container(client: DockerClient):
-    c = client.containers.create(
-        constant.ALPINE, command="top", detach=True, tty=True, name="top"
-    )
+    c = client.containers.create(constant.ALPINE, command="top", detach=True, tty=True, name="top")
     c.start()
     return c.id
 
diff --git a/test/python/docker/test_containers.py b/test/python/docker/test_containers.py
index 0fd419d9d..20d8417c3 100644
--- a/test/python/docker/test_containers.py
+++ b/test/python/docker/test_containers.py
@@ -87,7 +87,7 @@ class TestContainers(unittest.TestCase):
         self.assertEqual(len(containers), 2)
 
     def test_stop_container(self):
-        top = self.client.containers.get("top")
+        top = self.client.containers.get(TestContainers.topContainerId)
         self.assertEqual(top.status, "running")
 
         # Stop a running container and validate the state
diff --git a/test/python/docker/test_images.py b/test/python/docker/test_images.py
index 7ef3d708b..1fa4aade9 100644
--- a/test/python/docker/test_images.py
+++ b/test/python/docker/test_images.py
@@ -78,9 +78,7 @@ class TestImages(unittest.TestCase):
         self.assertEqual(len(self.client.images.list()), 2)
 
         # List images with filter
-        self.assertEqual(
-            len(self.client.images.list(filters={"reference": "alpine"})), 1
-        )
+        self.assertEqual(len(self.client.images.list(filters={"reference": "alpine"})), 1)
 
     def test_search_image(self):
         """Search for image"""
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index c6a9a660e..2769781f2 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -113,6 +113,10 @@ type ContainersConfig struct {
 	// DNSSearches set default DNS search domains.
 	DNSSearches []string `toml:"dns_searches,omitempty"`
 
+	// EnableKeyring tells the container engines whether to create
+	// a kernel keyring for use within the container
+	EnableKeyring bool `toml:"keyring,omitempty"`
+
 	// EnableLabeling tells the container engines whether to use MAC
 	// Labeling to separate containers (SELinux)
 	EnableLabeling bool `toml:"label,omitempty"`
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index e8519b251..ed7c91931 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -146,9 +146,13 @@ default_sysctls = [
 #
 # ipcns = "private"
 
-# Flag tells container engine to whether to use container separation using
-# MAC(SELinux)labeling or not.
-# Flag is ignored on label disabled systems.
+# keyring tells the container engine whether to create
+# a kernel keyring for use within the container.
+# keyring = true
+
+# label tells the container engine whether to use container separation using
+# MAC(SELinux) labeling or not.
+# The label flag is ignored on label disabled systems.
 #
 # label = true
 
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 5f8f4999f..4f1460e3b 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -46,8 +46,6 @@ var (
 	DefaultInitPath = "/usr/libexec/podman/catatonit"
 	// DefaultInfraImage to use for infra container
 	DefaultInfraImage = "k8s.gcr.io/pause:3.2"
-	// DefaultInfraCommand to be run in an infra container
-	DefaultInfraCommand = "/pause"
 	// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
 	DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
 	// DefaultDetachKeys is the default keys sequence for detaching a
@@ -179,6 +177,7 @@ func DefaultConfig() (*Config, error) {
 			DNSServers:          []string{},
 			DNSOptions:          []string{},
 			DNSSearches:         []string{},
+			EnableKeyring:       true,
 			EnableLabeling:      selinuxEnabled(),
 			Env: []string{
 				"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
@@ -308,7 +307,6 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
 	c.InitPath = DefaultInitPath
 	c.NoPivotRoot = false
 
-	c.InfraCommand = DefaultInfraCommand
 	c.InfraImage = DefaultInfraImage
 	c.EnablePortReservation = true
 	c.NumLocks = 2048
diff --git a/vendor/github.com/containers/common/pkg/retry/retry.go b/vendor/github.com/containers/common/pkg/retry/retry.go
index d0ac19fb6..f6ecab0c0 100644
--- a/vendor/github.com/containers/common/pkg/retry/retry.go
+++ b/vendor/github.com/containers/common/pkg/retry/retry.go
@@ -30,7 +30,7 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions
 		if retryOptions.Delay != 0 {
 			delay = retryOptions.Delay
 		}
-		logrus.Infof("Warning: failed, retrying in %s ... (%d/%d)", delay, attempt+1, retryOptions.MaxRetry)
+		logrus.Infof("Warning: failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err)
 		select {
 		case <-time.After(delay):
 			break
diff --git a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go
index ddc25ac67..09629724d 100644
--- a/vendor/github.com/containers/common/pkg/seccomp/default_linux.go
+++ b/vendor/github.com/containers/common/pkg/seccomp/default_linux.go
@@ -174,6 +174,7 @@ func DefaultProfile() *Seccomp {
 				"ioprio_get",
 				"ioprio_set",
 				"ipc",
+				"keyctl",
 				"kill",
 				"lchown",
 				"lchown32",
@@ -327,6 +328,7 @@ func DefaultProfile() *Seccomp {
 				"signalfd",
 				"signalfd4",
 				"sigreturn",
+				"socket",
 				"socketcall",
 				"socketpair",
 				"splice",
diff --git a/vendor/github.com/containers/common/pkg/seccomp/supported.go b/vendor/github.com/containers/common/pkg/seccomp/supported.go
index ab2a94a73..1177ef630 100644
--- a/vendor/github.com/containers/common/pkg/seccomp/supported.go
+++ b/vendor/github.com/containers/common/pkg/seccomp/supported.go
@@ -1,3 +1,5 @@
+// +build !windows
+
 package seccomp
 
 import (
diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go
index ef7c612e2..72f4e00f7 100644
--- a/vendor/github.com/containers/common/version/version.go
+++ b/vendor/github.com/containers/common/version/version.go
@@ -1,4 +1,4 @@
 package version
 
 // Version is the version of the build.
-const Version = "0.27.0"
+const Version = "0.29.0"
diff --git a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/shortnames.go b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/shortnames.go
index fadfe1a35..4001b65b6 100644
--- a/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/shortnames.go
+++ b/vendor/github.com/containers/image/v5/pkg/sysregistriesv2/shortnames.go
@@ -8,8 +8,8 @@ import (
 	"github.com/BurntSushi/toml"
 	"github.com/containers/image/v5/docker/reference"
 	"github.com/containers/image/v5/types"
+	"github.com/containers/storage/pkg/homedir"
 	"github.com/containers/storage/pkg/lockfile"
-	"github.com/docker/docker/pkg/homedir"
 	"github.com/pkg/errors"
 )
 
diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go
index 3ef1c2410..14e553c9f 100644
--- a/vendor/github.com/containers/image/v5/version/version.go
+++ b/vendor/github.com/containers/image/v5/version/version.go
@@ -8,7 +8,7 @@ const (
 	// VersionMinor is for functionality in a backwards-compatible manner
 	VersionMinor = 8
 	// VersionPatch is for backwards-compatible bug fixes
-	VersionPatch = 0
+	VersionPatch = 1
 
 	// VersionDev indicates development branch. Releases will be empty string.
 	VersionDev = ""
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index 53cc1a6f9..f9e8384bb 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.24.0
+1.24.1
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index 34c1ea7ad..86a5d8644 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -8,7 +8,7 @@ require (
 	github.com/Microsoft/hcsshim v0.8.9
 	github.com/docker/go-units v0.4.0
 	github.com/hashicorp/go-multierror v1.1.0
-	github.com/klauspost/compress v1.11.2
+	github.com/klauspost/compress v1.11.3
 	github.com/klauspost/pgzip v1.2.5
 	github.com/mattn/go-shellwords v1.0.10
 	github.com/mistifyio/go-zfs v2.1.1+incompatible
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index bec6aa59a..a5d3f3b82 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -64,8 +64,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ=
-github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.3 h1:dB4Bn0tN3wdCzQxnS8r06kV74qN/TAfaIS0bVE8h3jc=
+github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
 github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
diff --git a/vendor/github.com/containers/storage/pkg/unshare/unshare.go b/vendor/github.com/containers/storage/pkg/unshare/unshare.go
index a08fb674d..a9210b0bf 100644
--- a/vendor/github.com/containers/storage/pkg/unshare/unshare.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare.go
@@ -26,6 +26,7 @@ func HomeDir() (string, error) {
 				return
 			}
 			homeDir, homeDirErr = usr.HomeDir, nil
+			return
 		}
 		homeDir, homeDirErr = home, nil
 	})
diff --git a/vendor/github.com/klauspost/compress/flate/gen_inflate.go b/vendor/github.com/klauspost/compress/flate/gen_inflate.go
index b26d19ec2..35fc072a3 100644
--- a/vendor/github.com/klauspost/compress/flate/gen_inflate.go
+++ b/vendor/github.com/klauspost/compress/flate/gen_inflate.go
@@ -42,16 +42,6 @@ func (f *decompressor) $FUNCNAME$() {
 		stateDict
 	)
 	fr := f.r.($TYPE$)
-	moreBits := func() error {
-		c, err := fr.ReadByte()
-		if err != nil {
-			return noEOF(err)
-		}
-		f.roffset++
-		f.b |= uint32(c) << f.nb
-		f.nb += 8
-		return nil
-	}
 
 	switch f.stepState {
 	case stateInit:
@@ -112,9 +102,7 @@ readLiteral:
 			}
 		}
 
-		var n uint // number of bits extra
 		var length int
-		var err error
 		switch {
 		case v < 256:
 			f.dict.writeByte(byte(v))
@@ -131,71 +119,97 @@ readLiteral:
 		// otherwise, reference to older data
 		case v < 265:
 			length = v - (257 - 3)
-			n = 0
-		case v < 269:
-			length = v*2 - (265*2 - 11)
-			n = 1
-		case v < 273:
-			length = v*4 - (269*4 - 19)
-			n = 2
-		case v < 277:
-			length = v*8 - (273*8 - 35)
-			n = 3
-		case v < 281:
-			length = v*16 - (277*16 - 67)
-			n = 4
-		case v < 285:
-			length = v*32 - (281*32 - 131)
-			n = 5
 		case v < maxNumLit:
-			length = 258
-			n = 0
-		default:
-			if debugDecode {
-				fmt.Println(v, ">= maxNumLit")
-			}
-			f.err = CorruptInputError(f.roffset)
-			return
-		}
-		if n > 0 {
+			val := decCodeToLen[(v - 257)]
+			length = int(val.length) + 3
+			n := uint(val.extra)
 			for f.nb < n {
-				if err = moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits n>0:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8	
 			}
 			length += int(f.b & uint32(1<<(n&regSizeMaskUint32)-1))
 			f.b >>= n & regSizeMaskUint32
 			f.nb -= n
+		default:
+			if debugDecode {
+				fmt.Println(v, ">= maxNumLit")
+			}
+			f.err = CorruptInputError(f.roffset)
+			return
 		}
 
 		var dist uint32
 		if f.hd == nil {
 			for f.nb < 5 {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<5:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3)))
 			f.b >>= 5
 			f.nb -= 5
 		} else {
-			sym, err := f.huffSym(f.hd)
-			if err != nil {
-				if debugDecode {
-					fmt.Println("huffsym:", err)
+			// Since a huffmanDecoder can be empty or be composed of a degenerate tree
+			// with single element, huffSym must error on these two edge cases. In both
+			// cases, the chunks slice will be 0 for the invalid sequence, leading it
+			// satisfy the n == 0 check below.
+			n := uint(f.hd.maxRead)
+			// Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers,
+			// but is smart enough to keep local variables in registers, so use nb and b,
+			// inline call to moreBits and reassign b,nb back to f on return.
+			nb, b := f.nb, f.b
+			for {
+				for nb < n {
+					c, err := fr.ReadByte()
+					if err != nil {
+						f.b = b
+						f.nb = nb
+						f.err = noEOF(err)
+						return
+					}
+					f.roffset++
+					b |= uint32(c) << (nb & regSizeMaskUint32)
+					nb += 8
+				}
+				chunk := f.hd.chunks[b&(huffmanNumChunks-1)]
+				n = uint(chunk & huffmanCountMask)
+				if n > huffmanChunkBits {
+					chunk = f.hd.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hd.linkMask]
+					n = uint(chunk & huffmanCountMask)
+				}
+				if n <= nb {
+					if n == 0 {
+						f.b = b
+						f.nb = nb
+						if debugDecode {
+							fmt.Println("huffsym: n==0")
+						}
+						f.err = CorruptInputError(f.roffset)
+						return
+					}
+					f.b = b >> (n & regSizeMaskUint32)
+					f.nb = nb - n
+					dist = uint32(chunk >> huffmanValueShift)
+					break
 				}
-				f.err = err
-				return
 			}
-			dist = uint32(sym)
 		}
 
 		switch {
@@ -206,13 +220,17 @@ readLiteral:
 			// have 1 bit in bottom of dist, need nb more.
 			extra := (dist & 1) << (nb & regSizeMaskUint32)
 			for f.nb < nb {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<nb:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			extra |= f.b & uint32(1<<(nb&regSizeMaskUint32)-1)
 			f.b >>= nb & regSizeMaskUint32
diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go
index 189e9fe0b..16bc51408 100644
--- a/vendor/github.com/klauspost/compress/flate/inflate.go
+++ b/vendor/github.com/klauspost/compress/flate/inflate.go
@@ -29,6 +29,13 @@ const (
 	debugDecode = false
 )
 
+// Value of length - 3 and extra bits.
+type lengthExtra struct {
+	length, extra uint8
+}
+
+var decCodeToLen = [32]lengthExtra{{length: 0x0, extra: 0x0}, {length: 0x1, extra: 0x0}, {length: 0x2, extra: 0x0}, {length: 0x3, extra: 0x0}, {length: 0x4, extra: 0x0}, {length: 0x5, extra: 0x0}, {length: 0x6, extra: 0x0}, {length: 0x7, extra: 0x0}, {length: 0x8, extra: 0x1}, {length: 0xa, extra: 0x1}, {length: 0xc, extra: 0x1}, {length: 0xe, extra: 0x1}, {length: 0x10, extra: 0x2}, {length: 0x14, extra: 0x2}, {length: 0x18, extra: 0x2}, {length: 0x1c, extra: 0x2}, {length: 0x20, extra: 0x3}, {length: 0x28, extra: 0x3}, {length: 0x30, extra: 0x3}, {length: 0x38, extra: 0x3}, {length: 0x40, extra: 0x4}, {length: 0x50, extra: 0x4}, {length: 0x60, extra: 0x4}, {length: 0x70, extra: 0x4}, {length: 0x80, extra: 0x5}, {length: 0xa0, extra: 0x5}, {length: 0xc0, extra: 0x5}, {length: 0xe0, extra: 0x5}, {length: 0xff, extra: 0x0}, {length: 0x0, extra: 0x0}, {length: 0x0, extra: 0x0}, {length: 0x0, extra: 0x0}}
+
 // Initialize the fixedHuffmanDecoder only once upon first use.
 var fixedOnce sync.Once
 var fixedHuffmanDecoder huffmanDecoder
diff --git a/vendor/github.com/klauspost/compress/flate/inflate_gen.go b/vendor/github.com/klauspost/compress/flate/inflate_gen.go
index 9a92a1b30..cc6db2792 100644
--- a/vendor/github.com/klauspost/compress/flate/inflate_gen.go
+++ b/vendor/github.com/klauspost/compress/flate/inflate_gen.go
@@ -20,16 +20,6 @@ func (f *decompressor) huffmanBytesBuffer() {
 		stateDict
 	)
 	fr := f.r.(*bytes.Buffer)
-	moreBits := func() error {
-		c, err := fr.ReadByte()
-		if err != nil {
-			return noEOF(err)
-		}
-		f.roffset++
-		f.b |= uint32(c) << f.nb
-		f.nb += 8
-		return nil
-	}
 
 	switch f.stepState {
 	case stateInit:
@@ -90,9 +80,7 @@ readLiteral:
 			}
 		}
 
-		var n uint // number of bits extra
 		var length int
-		var err error
 		switch {
 		case v < 256:
 			f.dict.writeByte(byte(v))
@@ -109,71 +97,97 @@ readLiteral:
 		// otherwise, reference to older data
 		case v < 265:
 			length = v - (257 - 3)
-			n = 0
-		case v < 269:
-			length = v*2 - (265*2 - 11)
-			n = 1
-		case v < 273:
-			length = v*4 - (269*4 - 19)
-			n = 2
-		case v < 277:
-			length = v*8 - (273*8 - 35)
-			n = 3
-		case v < 281:
-			length = v*16 - (277*16 - 67)
-			n = 4
-		case v < 285:
-			length = v*32 - (281*32 - 131)
-			n = 5
 		case v < maxNumLit:
-			length = 258
-			n = 0
-		default:
-			if debugDecode {
-				fmt.Println(v, ">= maxNumLit")
-			}
-			f.err = CorruptInputError(f.roffset)
-			return
-		}
-		if n > 0 {
+			val := decCodeToLen[(v - 257)]
+			length = int(val.length) + 3
+			n := uint(val.extra)
 			for f.nb < n {
-				if err = moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits n>0:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			length += int(f.b & uint32(1<<(n&regSizeMaskUint32)-1))
 			f.b >>= n & regSizeMaskUint32
 			f.nb -= n
+		default:
+			if debugDecode {
+				fmt.Println(v, ">= maxNumLit")
+			}
+			f.err = CorruptInputError(f.roffset)
+			return
 		}
 
 		var dist uint32
 		if f.hd == nil {
 			for f.nb < 5 {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<5:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3)))
 			f.b >>= 5
 			f.nb -= 5
 		} else {
-			sym, err := f.huffSym(f.hd)
-			if err != nil {
-				if debugDecode {
-					fmt.Println("huffsym:", err)
+			// Since a huffmanDecoder can be empty or be composed of a degenerate tree
+			// with single element, huffSym must error on these two edge cases. In both
+			// cases, the chunks slice will be 0 for the invalid sequence, leading it
+			// satisfy the n == 0 check below.
+			n := uint(f.hd.maxRead)
+			// Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers,
+			// but is smart enough to keep local variables in registers, so use nb and b,
+			// inline call to moreBits and reassign b,nb back to f on return.
+			nb, b := f.nb, f.b
+			for {
+				for nb < n {
+					c, err := fr.ReadByte()
+					if err != nil {
+						f.b = b
+						f.nb = nb
+						f.err = noEOF(err)
+						return
+					}
+					f.roffset++
+					b |= uint32(c) << (nb & regSizeMaskUint32)
+					nb += 8
+				}
+				chunk := f.hd.chunks[b&(huffmanNumChunks-1)]
+				n = uint(chunk & huffmanCountMask)
+				if n > huffmanChunkBits {
+					chunk = f.hd.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hd.linkMask]
+					n = uint(chunk & huffmanCountMask)
+				}
+				if n <= nb {
+					if n == 0 {
+						f.b = b
+						f.nb = nb
+						if debugDecode {
+							fmt.Println("huffsym: n==0")
+						}
+						f.err = CorruptInputError(f.roffset)
+						return
+					}
+					f.b = b >> (n & regSizeMaskUint32)
+					f.nb = nb - n
+					dist = uint32(chunk >> huffmanValueShift)
+					break
 				}
-				f.err = err
-				return
 			}
-			dist = uint32(sym)
 		}
 
 		switch {
@@ -184,13 +198,17 @@ readLiteral:
 			// have 1 bit in bottom of dist, need nb more.
 			extra := (dist & 1) << (nb & regSizeMaskUint32)
 			for f.nb < nb {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<nb:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			extra |= f.b & uint32(1<<(nb&regSizeMaskUint32)-1)
 			f.b >>= nb & regSizeMaskUint32
@@ -246,16 +264,6 @@ func (f *decompressor) huffmanBytesReader() {
 		stateDict
 	)
 	fr := f.r.(*bytes.Reader)
-	moreBits := func() error {
-		c, err := fr.ReadByte()
-		if err != nil {
-			return noEOF(err)
-		}
-		f.roffset++
-		f.b |= uint32(c) << f.nb
-		f.nb += 8
-		return nil
-	}
 
 	switch f.stepState {
 	case stateInit:
@@ -316,9 +324,7 @@ readLiteral:
 			}
 		}
 
-		var n uint // number of bits extra
 		var length int
-		var err error
 		switch {
 		case v < 256:
 			f.dict.writeByte(byte(v))
@@ -335,71 +341,97 @@ readLiteral:
 		// otherwise, reference to older data
 		case v < 265:
 			length = v - (257 - 3)
-			n = 0
-		case v < 269:
-			length = v*2 - (265*2 - 11)
-			n = 1
-		case v < 273:
-			length = v*4 - (269*4 - 19)
-			n = 2
-		case v < 277:
-			length = v*8 - (273*8 - 35)
-			n = 3
-		case v < 281:
-			length = v*16 - (277*16 - 67)
-			n = 4
-		case v < 285:
-			length = v*32 - (281*32 - 131)
-			n = 5
 		case v < maxNumLit:
-			length = 258
-			n = 0
-		default:
-			if debugDecode {
-				fmt.Println(v, ">= maxNumLit")
-			}
-			f.err = CorruptInputError(f.roffset)
-			return
-		}
-		if n > 0 {
+			val := decCodeToLen[(v - 257)]
+			length = int(val.length) + 3
+			n := uint(val.extra)
 			for f.nb < n {
-				if err = moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits n>0:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			length += int(f.b & uint32(1<<(n&regSizeMaskUint32)-1))
 			f.b >>= n & regSizeMaskUint32
 			f.nb -= n
+		default:
+			if debugDecode {
+				fmt.Println(v, ">= maxNumLit")
+			}
+			f.err = CorruptInputError(f.roffset)
+			return
 		}
 
 		var dist uint32
 		if f.hd == nil {
 			for f.nb < 5 {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<5:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3)))
 			f.b >>= 5
 			f.nb -= 5
 		} else {
-			sym, err := f.huffSym(f.hd)
-			if err != nil {
-				if debugDecode {
-					fmt.Println("huffsym:", err)
+			// Since a huffmanDecoder can be empty or be composed of a degenerate tree
+			// with single element, huffSym must error on these two edge cases. In both
+			// cases, the chunks slice will be 0 for the invalid sequence, leading it
+			// satisfy the n == 0 check below.
+			n := uint(f.hd.maxRead)
+			// Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers,
+			// but is smart enough to keep local variables in registers, so use nb and b,
+			// inline call to moreBits and reassign b,nb back to f on return.
+			nb, b := f.nb, f.b
+			for {
+				for nb < n {
+					c, err := fr.ReadByte()
+					if err != nil {
+						f.b = b
+						f.nb = nb
+						f.err = noEOF(err)
+						return
+					}
+					f.roffset++
+					b |= uint32(c) << (nb & regSizeMaskUint32)
+					nb += 8
+				}
+				chunk := f.hd.chunks[b&(huffmanNumChunks-1)]
+				n = uint(chunk & huffmanCountMask)
+				if n > huffmanChunkBits {
+					chunk = f.hd.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hd.linkMask]
+					n = uint(chunk & huffmanCountMask)
+				}
+				if n <= nb {
+					if n == 0 {
+						f.b = b
+						f.nb = nb
+						if debugDecode {
+							fmt.Println("huffsym: n==0")
+						}
+						f.err = CorruptInputError(f.roffset)
+						return
+					}
+					f.b = b >> (n & regSizeMaskUint32)
+					f.nb = nb - n
+					dist = uint32(chunk >> huffmanValueShift)
+					break
 				}
-				f.err = err
-				return
 			}
-			dist = uint32(sym)
 		}
 
 		switch {
@@ -410,13 +442,17 @@ readLiteral:
 			// have 1 bit in bottom of dist, need nb more.
 			extra := (dist & 1) << (nb & regSizeMaskUint32)
 			for f.nb < nb {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<nb:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			extra |= f.b & uint32(1<<(nb&regSizeMaskUint32)-1)
 			f.b >>= nb & regSizeMaskUint32
@@ -472,16 +508,6 @@ func (f *decompressor) huffmanBufioReader() {
 		stateDict
 	)
 	fr := f.r.(*bufio.Reader)
-	moreBits := func() error {
-		c, err := fr.ReadByte()
-		if err != nil {
-			return noEOF(err)
-		}
-		f.roffset++
-		f.b |= uint32(c) << f.nb
-		f.nb += 8
-		return nil
-	}
 
 	switch f.stepState {
 	case stateInit:
@@ -542,9 +568,7 @@ readLiteral:
 			}
 		}
 
-		var n uint // number of bits extra
 		var length int
-		var err error
 		switch {
 		case v < 256:
 			f.dict.writeByte(byte(v))
@@ -561,71 +585,97 @@ readLiteral:
 		// otherwise, reference to older data
 		case v < 265:
 			length = v - (257 - 3)
-			n = 0
-		case v < 269:
-			length = v*2 - (265*2 - 11)
-			n = 1
-		case v < 273:
-			length = v*4 - (269*4 - 19)
-			n = 2
-		case v < 277:
-			length = v*8 - (273*8 - 35)
-			n = 3
-		case v < 281:
-			length = v*16 - (277*16 - 67)
-			n = 4
-		case v < 285:
-			length = v*32 - (281*32 - 131)
-			n = 5
 		case v < maxNumLit:
-			length = 258
-			n = 0
-		default:
-			if debugDecode {
-				fmt.Println(v, ">= maxNumLit")
-			}
-			f.err = CorruptInputError(f.roffset)
-			return
-		}
-		if n > 0 {
+			val := decCodeToLen[(v - 257)]
+			length = int(val.length) + 3
+			n := uint(val.extra)
 			for f.nb < n {
-				if err = moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits n>0:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			length += int(f.b & uint32(1<<(n&regSizeMaskUint32)-1))
 			f.b >>= n & regSizeMaskUint32
 			f.nb -= n
+		default:
+			if debugDecode {
+				fmt.Println(v, ">= maxNumLit")
+			}
+			f.err = CorruptInputError(f.roffset)
+			return
 		}
 
 		var dist uint32
 		if f.hd == nil {
 			for f.nb < 5 {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<5:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3)))
 			f.b >>= 5
 			f.nb -= 5
 		} else {
-			sym, err := f.huffSym(f.hd)
-			if err != nil {
-				if debugDecode {
-					fmt.Println("huffsym:", err)
+			// Since a huffmanDecoder can be empty or be composed of a degenerate tree
+			// with single element, huffSym must error on these two edge cases. In both
+			// cases, the chunks slice will be 0 for the invalid sequence, leading it
+			// satisfy the n == 0 check below.
+			n := uint(f.hd.maxRead)
+			// Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers,
+			// but is smart enough to keep local variables in registers, so use nb and b,
+			// inline call to moreBits and reassign b,nb back to f on return.
+			nb, b := f.nb, f.b
+			for {
+				for nb < n {
+					c, err := fr.ReadByte()
+					if err != nil {
+						f.b = b
+						f.nb = nb
+						f.err = noEOF(err)
+						return
+					}
+					f.roffset++
+					b |= uint32(c) << (nb & regSizeMaskUint32)
+					nb += 8
+				}
+				chunk := f.hd.chunks[b&(huffmanNumChunks-1)]
+				n = uint(chunk & huffmanCountMask)
+				if n > huffmanChunkBits {
+					chunk = f.hd.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hd.linkMask]
+					n = uint(chunk & huffmanCountMask)
+				}
+				if n <= nb {
+					if n == 0 {
+						f.b = b
+						f.nb = nb
+						if debugDecode {
+							fmt.Println("huffsym: n==0")
+						}
+						f.err = CorruptInputError(f.roffset)
+						return
+					}
+					f.b = b >> (n & regSizeMaskUint32)
+					f.nb = nb - n
+					dist = uint32(chunk >> huffmanValueShift)
+					break
 				}
-				f.err = err
-				return
 			}
-			dist = uint32(sym)
 		}
 
 		switch {
@@ -636,13 +686,17 @@ readLiteral:
 			// have 1 bit in bottom of dist, need nb more.
 			extra := (dist & 1) << (nb & regSizeMaskUint32)
 			for f.nb < nb {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<nb:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			extra |= f.b & uint32(1<<(nb&regSizeMaskUint32)-1)
 			f.b >>= nb & regSizeMaskUint32
@@ -698,16 +752,6 @@ func (f *decompressor) huffmanStringsReader() {
 		stateDict
 	)
 	fr := f.r.(*strings.Reader)
-	moreBits := func() error {
-		c, err := fr.ReadByte()
-		if err != nil {
-			return noEOF(err)
-		}
-		f.roffset++
-		f.b |= uint32(c) << f.nb
-		f.nb += 8
-		return nil
-	}
 
 	switch f.stepState {
 	case stateInit:
@@ -768,9 +812,7 @@ readLiteral:
 			}
 		}
 
-		var n uint // number of bits extra
 		var length int
-		var err error
 		switch {
 		case v < 256:
 			f.dict.writeByte(byte(v))
@@ -787,71 +829,97 @@ readLiteral:
 		// otherwise, reference to older data
 		case v < 265:
 			length = v - (257 - 3)
-			n = 0
-		case v < 269:
-			length = v*2 - (265*2 - 11)
-			n = 1
-		case v < 273:
-			length = v*4 - (269*4 - 19)
-			n = 2
-		case v < 277:
-			length = v*8 - (273*8 - 35)
-			n = 3
-		case v < 281:
-			length = v*16 - (277*16 - 67)
-			n = 4
-		case v < 285:
-			length = v*32 - (281*32 - 131)
-			n = 5
 		case v < maxNumLit:
-			length = 258
-			n = 0
-		default:
-			if debugDecode {
-				fmt.Println(v, ">= maxNumLit")
-			}
-			f.err = CorruptInputError(f.roffset)
-			return
-		}
-		if n > 0 {
+			val := decCodeToLen[(v - 257)]
+			length = int(val.length) + 3
+			n := uint(val.extra)
 			for f.nb < n {
-				if err = moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits n>0:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			length += int(f.b & uint32(1<<(n&regSizeMaskUint32)-1))
 			f.b >>= n & regSizeMaskUint32
 			f.nb -= n
+		default:
+			if debugDecode {
+				fmt.Println(v, ">= maxNumLit")
+			}
+			f.err = CorruptInputError(f.roffset)
+			return
 		}
 
 		var dist uint32
 		if f.hd == nil {
 			for f.nb < 5 {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<5:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3)))
 			f.b >>= 5
 			f.nb -= 5
 		} else {
-			sym, err := f.huffSym(f.hd)
-			if err != nil {
-				if debugDecode {
-					fmt.Println("huffsym:", err)
+			// Since a huffmanDecoder can be empty or be composed of a degenerate tree
+			// with single element, huffSym must error on these two edge cases. In both
+			// cases, the chunks slice will be 0 for the invalid sequence, leading it
+			// satisfy the n == 0 check below.
+			n := uint(f.hd.maxRead)
+			// Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers,
+			// but is smart enough to keep local variables in registers, so use nb and b,
+			// inline call to moreBits and reassign b,nb back to f on return.
+			nb, b := f.nb, f.b
+			for {
+				for nb < n {
+					c, err := fr.ReadByte()
+					if err != nil {
+						f.b = b
+						f.nb = nb
+						f.err = noEOF(err)
+						return
+					}
+					f.roffset++
+					b |= uint32(c) << (nb & regSizeMaskUint32)
+					nb += 8
+				}
+				chunk := f.hd.chunks[b&(huffmanNumChunks-1)]
+				n = uint(chunk & huffmanCountMask)
+				if n > huffmanChunkBits {
+					chunk = f.hd.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hd.linkMask]
+					n = uint(chunk & huffmanCountMask)
+				}
+				if n <= nb {
+					if n == 0 {
+						f.b = b
+						f.nb = nb
+						if debugDecode {
+							fmt.Println("huffsym: n==0")
+						}
+						f.err = CorruptInputError(f.roffset)
+						return
+					}
+					f.b = b >> (n & regSizeMaskUint32)
+					f.nb = nb - n
+					dist = uint32(chunk >> huffmanValueShift)
+					break
 				}
-				f.err = err
-				return
 			}
-			dist = uint32(sym)
 		}
 
 		switch {
@@ -862,13 +930,17 @@ readLiteral:
 			// have 1 bit in bottom of dist, need nb more.
 			extra := (dist & 1) << (nb & regSizeMaskUint32)
 			for f.nb < nb {
-				if err = f.moreBits(); err != nil {
+				c, err := fr.ReadByte()
+				if err != nil {
 					if debugDecode {
 						fmt.Println("morebits f.nb<nb:", err)
 					}
 					f.err = err
 					return
 				}
+				f.roffset++
+				f.b |= uint32(c) << f.nb
+				f.nb += 8
 			}
 			extra |= f.b & uint32(1<<(nb&regSizeMaskUint32)-1)
 			f.b >>= nb & regSizeMaskUint32
diff --git a/vendor/github.com/klauspost/compress/zstd/README.md b/vendor/github.com/klauspost/compress/zstd/README.md
index 07f7285f0..08e553f75 100644
--- a/vendor/github.com/klauspost/compress/zstd/README.md
+++ b/vendor/github.com/klauspost/compress/zstd/README.md
@@ -54,11 +54,11 @@ To create a writer with default options, do like this:
 ```Go
 // Compress input to output.
 func Compress(in io.Reader, out io.Writer) error {
-    w, err := NewWriter(output)
+    enc, err := zstd.NewWriter(out)
     if err != nil {
         return err
     }
-    _, err := io.Copy(w, input)
+    _, err = io.Copy(enc, in)
     if err != nil {
         enc.Close()
         return err
diff --git a/vendor/github.com/klauspost/compress/zstd/decoder.go b/vendor/github.com/klauspost/compress/zstd/decoder.go
index d78be6d42..cdda0de58 100644
--- a/vendor/github.com/klauspost/compress/zstd/decoder.go
+++ b/vendor/github.com/klauspost/compress/zstd/decoder.go
@@ -323,19 +323,23 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) {
 		}
 		if frame.FrameContentSize > 0 && frame.FrameContentSize < 1<<30 {
 			// Never preallocate moe than 1 GB up front.
-			if uint64(cap(dst)) < frame.FrameContentSize {
+			if cap(dst)-len(dst) < int(frame.FrameContentSize) {
 				dst2 := make([]byte, len(dst), len(dst)+int(frame.FrameContentSize))
 				copy(dst2, dst)
 				dst = dst2
 			}
 		}
 		if cap(dst) == 0 {
-			// Allocate window size * 2 by default if nothing is provided and we didn't get frame content size.
-			size := frame.WindowSize * 2
+			// Allocate len(input) * 2 by default if nothing is provided
+			// and we didn't get frame content size.
+			size := len(input) * 2
 			// Cap to 1 MB.
 			if size > 1<<20 {
 				size = 1 << 20
 			}
+			if uint64(size) > d.o.maxDecodedSize {
+				size = int(d.o.maxDecodedSize)
+			}
 			dst = make([]byte, 0, size)
 		}
 
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 320d9851f..674b7a4e4 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -88,7 +88,7 @@ github.com/containers/buildah/pkg/secrets
 github.com/containers/buildah/pkg/supplemented
 github.com/containers/buildah/pkg/umask
 github.com/containers/buildah/util
-# github.com/containers/common v0.27.0
+# github.com/containers/common v0.29.0
 github.com/containers/common/pkg/apparmor
 github.com/containers/common/pkg/apparmor/internal/supported
 github.com/containers/common/pkg/auth
@@ -104,7 +104,7 @@ github.com/containers/common/pkg/sysinfo
 github.com/containers/common/version
 # github.com/containers/conmon v2.0.20+incompatible
 github.com/containers/conmon/runner/config
-# github.com/containers/image/v5 v5.8.0
+# github.com/containers/image/v5 v5.8.1
 github.com/containers/image/v5/copy
 github.com/containers/image/v5/directory
 github.com/containers/image/v5/directory/explicitfilepath
@@ -168,7 +168,7 @@ github.com/containers/psgo/internal/dev
 github.com/containers/psgo/internal/host
 github.com/containers/psgo/internal/proc
 github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.24.0
+# github.com/containers/storage v1.24.1
 github.com/containers/storage
 github.com/containers/storage/drivers
 github.com/containers/storage/drivers/aufs
@@ -339,7 +339,7 @@ github.com/json-iterator/go
 # github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a
 github.com/juju/ansiterm
 github.com/juju/ansiterm/tabwriter
-# github.com/klauspost/compress v1.11.2
+# github.com/klauspost/compress v1.11.3
 github.com/klauspost/compress/flate
 github.com/klauspost/compress/fse
 github.com/klauspost/compress/huff0
-- 
cgit v1.2.3-54-g00ecf