diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index ab3a984f08..599b430ea0 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 4b52663c34..f34666fffa 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"
@@ -440,3 +441,66 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
 	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/volumes.go b/cmd/podman/common/volumes.go
index b3c160ddfb..0468f15e02 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/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 749af8a666..8251ba3b60 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*
 
@@ -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-run.1.md b/docs/source/markdown/podman-run.1.md
index 5b2cdd6a53..bc3d5a8bb0 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_
 
@@ -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.1.md b/docs/source/markdown/podman.1.md
index 1954ca2aa4..68a17d26b3 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*
 
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index c049e64cfa..45a374216e 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 b225f79ee1..331a5c5bfd 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/specgen.go b/pkg/specgen/specgen.go
index 0a9a16ea75..fad2406e53 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 0000000000..1178f9960e
--- /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/e2e/config/containers-remote.conf b/test/e2e/config/containers-remote.conf
new file mode 100644
index 0000000000..bc9eab9512
--- /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 1d5be218b8..906153c0fa 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"))
+	})
 })