diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index 20d976c0ba..7a3b26c853 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -16,11 +16,11 @@ import (
 	ann "github.com/containers/libpod/pkg/annotations"
 	"github.com/containers/libpod/pkg/apparmor"
 	"github.com/containers/libpod/pkg/inspect"
+	"github.com/containers/libpod/pkg/namespaces"
 	"github.com/containers/libpod/pkg/rootless"
 	cc "github.com/containers/libpod/pkg/spec"
 	"github.com/containers/libpod/pkg/util"
 	libpodVersion "github.com/containers/libpod/version"
-	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/pkg/signal"
 	"github.com/docker/go-connections/nat"
 	"github.com/docker/go-units"
@@ -456,7 +456,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
 	if !c.IsSet("pid") && pod != nil && pod.SharesPID() {
 		pidModeStr = cc.POD
 	}
-	pidMode := container.PidMode(pidModeStr)
+	pidMode := namespaces.PidMode(pidModeStr)
 	if !cc.Valid(string(pidMode), pidMode) {
 		return nil, errors.Errorf("--pid %q is not valid", c.String("pid"))
 	}
@@ -465,7 +465,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
 	if !c.IsSet("userns") && pod != nil && pod.SharesUser() {
 		usernsModeStr = cc.POD
 	}
-	usernsMode := container.UsernsMode(usernsModeStr)
+	usernsMode := namespaces.UsernsMode(usernsModeStr)
 	if !cc.Valid(string(usernsMode), usernsMode) {
 		return nil, errors.Errorf("--userns %q is not valid", c.String("userns"))
 	}
@@ -474,7 +474,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
 	if !c.IsSet("uts") && pod != nil && pod.SharesUTS() {
 		utsModeStr = cc.POD
 	}
-	utsMode := container.UTSMode(utsModeStr)
+	utsMode := namespaces.UTSMode(utsModeStr)
 	if !cc.Valid(string(utsMode), utsMode) {
 		return nil, errors.Errorf("--uts %q is not valid", c.String("uts"))
 	}
@@ -483,7 +483,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
 	if !c.IsSet("ipc") && pod != nil && pod.SharesIPC() {
 		ipcModeStr = cc.POD
 	}
-	ipcMode := container.IpcMode(ipcModeStr)
+	ipcMode := namespaces.IpcMode(ipcModeStr)
 	if !cc.Valid(string(ipcMode), ipcMode) {
 		return nil, errors.Errorf("--ipc %q is not valid", ipcMode)
 	}
@@ -492,7 +492,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
 		netModeStr = cc.POD
 	}
 	// Make sure if network is set to container namespace, port binding is not also being asked for
-	netMode := container.NetworkMode(netModeStr)
+	netMode := namespaces.NetworkMode(netModeStr)
 	if netMode.IsContainer() || cc.IsPod(netModeStr) {
 		if len(c.StringSlice("publish")) > 0 || c.Bool("publish-all") {
 			return nil, errors.Errorf("cannot set port bindings on an existing container network namespace")
diff --git a/cmd/podman/parse.go b/cmd/podman/parse.go
index 158a006fb7..ade592ddfa 100644
--- a/cmd/podman/parse.go
+++ b/cmd/podman/parse.go
@@ -239,50 +239,6 @@ func parseEnvFile(env map[string]string, filename string) error {
 	return scanner.Err()
 }
 
-// NsIpc represents the container ipc stack.
-// for ipc flag
-type NsIpc string
-
-// IsPrivate indicates whether the container uses its private ipc stack.
-func (n NsIpc) IsPrivate() bool {
-	return !(n.IsHost() || n.IsContainer())
-}
-
-// IsHost indicates whether the container uses the host's ipc stack.
-func (n NsIpc) IsHost() bool {
-	return n == "host"
-}
-
-// IsContainer indicates whether the container uses a container's ipc stack.
-func (n NsIpc) IsContainer() bool {
-	parts := strings.SplitN(string(n), ":", 2)
-	return len(parts) > 1 && parts[0] == "container"
-}
-
-// Valid indicates whether the ipc stack is valid.
-func (n NsIpc) Valid() bool {
-	parts := strings.Split(string(n), ":")
-	switch mode := parts[0]; mode {
-	case "", "host":
-	case "container":
-		if len(parts) != 2 || parts[1] == "" {
-			return false
-		}
-	default:
-		return false
-	}
-	return true
-}
-
-// Container returns the name of the container ipc stack is going to be used.
-func (n NsIpc) Container() string {
-	parts := strings.SplitN(string(n), ":", 2)
-	if len(parts) > 1 {
-		return parts[1]
-	}
-	return ""
-}
-
 // validateLabel validates that the specified string is a valid label, and returns it.
 // Labels are in the form on key=value.
 // for label flag
@@ -313,50 +269,6 @@ func parseLoggingOpts(logDriver string, logDriverOpt []string) (map[string]strin
 	return logOptsMap, nil
 }
 
-// NsPid represents the pid namespace of the container.
-//for pid flag
-type NsPid string
-
-// IsPrivate indicates whether the container uses its own new pid namespace.
-func (n NsPid) IsPrivate() bool {
-	return !(n.IsHost() || n.IsContainer())
-}
-
-// IsHost indicates whether the container uses the host's pid namespace.
-func (n NsPid) IsHost() bool {
-	return n == "host"
-}
-
-// IsContainer indicates whether the container uses a container's pid namespace.
-func (n NsPid) IsContainer() bool {
-	parts := strings.SplitN(string(n), ":", 2)
-	return len(parts) > 1 && parts[0] == "container"
-}
-
-// Valid indicates whether the pid namespace is valid.
-func (n NsPid) Valid() bool {
-	parts := strings.Split(string(n), ":")
-	switch mode := parts[0]; mode {
-	case "", "host":
-	case "container":
-		if len(parts) != 2 || parts[1] == "" {
-			return false
-		}
-	default:
-		return false
-	}
-	return true
-}
-
-// Container returns the name of the container whose pid namespace is going to be used.
-func (n NsPid) Container() string {
-	parts := strings.SplitN(string(n), ":", 2)
-	if len(parts) > 1 {
-		return parts[1]
-	}
-	return ""
-}
-
 // parsePortSpecs receives port specs in the format of ip:public:private/proto and parses
 // these in to the internal types
 // for publish, publish-all, and expose flags
@@ -567,56 +479,6 @@ func convertKVStringsToMap(values []string) map[string]string {
 	return result
 }
 
-// NsUser represents userns mode in the container.
-// for userns flag
-type NsUser string
-
-// IsHost indicates whether the container uses the host's userns.
-func (n NsUser) IsHost() bool {
-	return n == "host"
-}
-
-// IsPrivate indicates whether the container uses the a private userns.
-func (n NsUser) IsPrivate() bool {
-	return !(n.IsHost())
-}
-
-// Valid indicates whether the userns is valid.
-func (n NsUser) Valid() bool {
-	parts := strings.Split(string(n), ":")
-	switch mode := parts[0]; mode {
-	case "", "host":
-	default:
-		return false
-	}
-	return true
-}
-
-// NsUts represents the UTS namespace of the container.
-// for uts flag
-type NsUts string
-
-// IsPrivate indicates whether the container uses its private UTS namespace.
-func (n NsUts) IsPrivate() bool {
-	return !(n.IsHost())
-}
-
-// IsHost indicates whether the container uses the host's UTS namespace.
-func (n NsUts) IsHost() bool {
-	return n == "host"
-}
-
-// Valid indicates whether the UTS namespace is valid.
-func (n NsUts) Valid() bool {
-	parts := strings.Split(string(n), ":")
-	switch mode := parts[0]; mode {
-	case "", "host":
-	default:
-		return false
-	}
-	return true
-}
-
 // Takes a stringslice and converts to a uint32slice
 func stringSlicetoUint32Slice(inputSlice []string) ([]uint32, error) {
 	var outputSlice []uint32
diff --git a/cmd/podman/pod_create.go b/cmd/podman/pod_create.go
index 488fef869a..61086f890b 100644
--- a/cmd/podman/pod_create.go
+++ b/cmd/podman/pod_create.go
@@ -15,7 +15,7 @@ import (
 
 var (
 	// Kernel namespaces shared by default within a pod
-	DefaultKernelNamespaces = "ipc,net,uts"
+	DefaultKernelNamespaces = "cgroup,ipc,net,uts"
 )
 
 var podCreateDescription = "Creates a new empty pod. The pod ID is then" +
diff --git a/cmd/podman/shared/pod.go b/cmd/podman/shared/pod.go
index 1a14b3777c..badc7a8370 100644
--- a/cmd/podman/shared/pod.go
+++ b/cmd/podman/shared/pod.go
@@ -70,6 +70,8 @@ func GetNamespaceOptions(ns []string) ([]libpod.PodCreateOption, error) {
 	var erroredOptions []libpod.PodCreateOption
 	for _, toShare := range ns {
 		switch toShare {
+		case "cgroup":
+			options = append(options, libpod.WithPodCgroups())
 		case "net":
 			options = append(options, libpod.WithPodNet())
 		case "mnt":
diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go
new file mode 100644
index 0000000000..1bdb2b00db
--- /dev/null
+++ b/pkg/namespaces/namespaces.go
@@ -0,0 +1,219 @@
+package namespaces
+
+import (
+	"strings"
+)
+
+// UsernsMode represents userns mode in the container.
+type UsernsMode string
+
+// IsHost indicates whether the container uses the host's userns.
+func (n UsernsMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsPrivate indicates whether the container uses the a private userns.
+func (n UsernsMode) IsPrivate() bool {
+	return !(n.IsHost())
+}
+
+// Valid indicates whether the userns is valid.
+func (n UsernsMode) Valid() bool {
+	parts := strings.Split(string(n), ":")
+	switch mode := parts[0]; mode {
+	case "", "host":
+	default:
+		return false
+	}
+	return true
+}
+
+// UTSMode represents the UTS namespace of the container.
+type UTSMode string
+
+// IsPrivate indicates whether the container uses its private UTS namespace.
+func (n UTSMode) IsPrivate() bool {
+	return !(n.IsHost())
+}
+
+// IsHost indicates whether the container uses the host's UTS namespace.
+func (n UTSMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsContainer indicates whether the container uses a container's UTS namespace.
+func (n UTSMode) IsContainer() bool {
+	parts := strings.SplitN(string(n), ":", 2)
+	return len(parts) > 1 && parts[0] == "container"
+}
+
+// Container returns the name of the container whose uts namespace is going to be used.
+func (n UTSMode) Container() string {
+	parts := strings.SplitN(string(n), ":", 2)
+	if len(parts) > 1 {
+		return parts[1]
+	}
+	return ""
+}
+
+// Valid indicates whether the UTS namespace is valid.
+func (n UTSMode) Valid() bool {
+	parts := strings.Split(string(n), ":")
+	switch mode := parts[0]; mode {
+	case "", "host":
+	case "container":
+		if len(parts) != 2 || parts[1] == "" {
+			return false
+		}
+	default:
+		return false
+	}
+	return true
+}
+
+// IpcMode represents the container ipc stack.
+type IpcMode string
+
+// IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared.
+func (n IpcMode) IsPrivate() bool {
+	return n == "private"
+}
+
+// IsHost indicates whether the container shares the host's ipc namespace.
+func (n IpcMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsShareable indicates whether the container's ipc namespace can be shared with another container.
+func (n IpcMode) IsShareable() bool {
+	return n == "shareable"
+}
+
+// IsContainer indicates whether the container uses another container's ipc namespace.
+func (n IpcMode) IsContainer() bool {
+	parts := strings.SplitN(string(n), ":", 2)
+	return len(parts) > 1 && parts[0] == "container"
+}
+
+// IsNone indicates whether container IpcMode is set to "none".
+func (n IpcMode) IsNone() bool {
+	return n == "none"
+}
+
+// IsEmpty indicates whether container IpcMode is empty
+func (n IpcMode) IsEmpty() bool {
+	return n == ""
+}
+
+// Valid indicates whether the ipc mode is valid.
+func (n IpcMode) Valid() bool {
+	return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer()
+}
+
+// Container returns the name of the container ipc stack is going to be used.
+func (n IpcMode) Container() string {
+	parts := strings.SplitN(string(n), ":", 2)
+	if len(parts) > 1 && parts[0] == "container" {
+		return parts[1]
+	}
+	return ""
+}
+
+// PidMode represents the pid namespace of the container.
+type PidMode string
+
+// IsPrivate indicates whether the container uses its own new pid namespace.
+func (n PidMode) IsPrivate() bool {
+	return !(n.IsHost() || n.IsContainer())
+}
+
+// IsHost indicates whether the container uses the host's pid namespace.
+func (n PidMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsContainer indicates whether the container uses a container's pid namespace.
+func (n PidMode) IsContainer() bool {
+	parts := strings.SplitN(string(n), ":", 2)
+	return len(parts) > 1 && parts[0] == "container"
+}
+
+// Valid indicates whether the pid namespace is valid.
+func (n PidMode) Valid() bool {
+	parts := strings.Split(string(n), ":")
+	switch mode := parts[0]; mode {
+	case "", "host":
+	case "container":
+		if len(parts) != 2 || parts[1] == "" {
+			return false
+		}
+	default:
+		return false
+	}
+	return true
+}
+
+// Container returns the name of the container whose pid namespace is going to be used.
+func (n PidMode) Container() string {
+	parts := strings.SplitN(string(n), ":", 2)
+	if len(parts) > 1 {
+		return parts[1]
+	}
+	return ""
+}
+
+// NetworkMode represents the container network stack.
+type NetworkMode string
+
+// IsNone indicates whether container isn't using a network stack.
+func (n NetworkMode) IsNone() bool {
+	return n == "none"
+}
+
+// IsHost indicates whether the container uses the host's network stack.
+func (n NetworkMode) IsHost() bool {
+	return n == "host"
+}
+
+// IsDefault indicates whether container uses the default network stack.
+func (n NetworkMode) IsDefault() bool {
+	return n == "default"
+}
+
+// IsPrivate indicates whether container uses its private network stack.
+func (n NetworkMode) IsPrivate() bool {
+	return !(n.IsHost() || n.IsContainer())
+}
+
+// IsContainer indicates whether container uses a container network stack.
+func (n NetworkMode) IsContainer() bool {
+	parts := strings.SplitN(string(n), ":", 2)
+	return len(parts) > 1 && parts[0] == "container"
+}
+
+// ConnectedContainer is the id of the container which network this container is connected to.
+func (n NetworkMode) ConnectedContainer() string {
+	parts := strings.SplitN(string(n), ":", 2)
+	if len(parts) > 1 {
+		return parts[1]
+	}
+	return ""
+}
+
+//UserDefined indicates user-created network
+func (n NetworkMode) UserDefined() string {
+	if n.IsUserDefined() {
+		return string(n)
+	}
+	return ""
+}
+
+// IsBridge indicates whether container uses the bridge network stack
+func (n NetworkMode) IsBridge() bool {
+	return n == "bridge"
+}
+
+// IsUserDefined indicates user-created network
+func (n NetworkMode) IsUserDefined() bool {
+	return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer()
+}
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 0ab0bb9ff0..0b7ee993dc 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -8,10 +8,10 @@ import (
 	"syscall"
 
 	"github.com/containers/libpod/libpod"
+	"github.com/containers/libpod/pkg/namespaces"
 	"github.com/containers/libpod/pkg/rootless"
 	"github.com/containers/storage"
 	"github.com/cri-o/ocicni/pkg/ocicni"
-	"github.com/docker/docker/api/types/container"
 	"github.com/docker/go-connections/nat"
 	spec "github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/opencontainers/runtime-tools/generate"
@@ -90,22 +90,22 @@ type CreateConfig struct {
 	ImageID            string
 	BuiltinImgVolumes  map[string]struct{} // volumes defined in the image config
 	IDMappings         *storage.IDMappingOptions
-	ImageVolumeType    string                // how to handle the image volume, either bind, tmpfs, or ignore
-	Interactive        bool                  //interactive
-	IpcMode            container.IpcMode     //ipc
-	IP6Address         string                //ipv6
-	IPAddress          string                //ip
-	Labels             map[string]string     //label
-	LinkLocalIP        []string              // link-local-ip
-	LogDriver          string                // log-driver
-	LogDriverOpt       []string              // log-opt
-	MacAddress         string                //mac-address
-	Name               string                //name
-	NetMode            container.NetworkMode //net
-	Network            string                //network
-	NetworkAlias       []string              //network-alias
-	PidMode            container.PidMode     //pid
-	Pod                string                //pod
+	ImageVolumeType    string                 // how to handle the image volume, either bind, tmpfs, or ignore
+	Interactive        bool                   //interactive
+	IpcMode            namespaces.IpcMode     //ipc
+	IP6Address         string                 //ipv6
+	IPAddress          string                 //ip
+	Labels             map[string]string      //label
+	LinkLocalIP        []string               // link-local-ip
+	LogDriver          string                 // log-driver
+	LogDriverOpt       []string               // log-opt
+	MacAddress         string                 //mac-address
+	Name               string                 //name
+	NetMode            namespaces.NetworkMode //net
+	Network            string                 //network
+	NetworkAlias       []string               //network-alias
+	PidMode            namespaces.PidMode     //pid
+	Pod                string                 //pod
 	PortBindings       nat.PortMap
 	Privileged         bool     //privileged
 	Publish            []string //publish
@@ -119,12 +119,12 @@ type CreateConfig struct {
 	StopTimeout        uint              // stop-timeout
 	Sysctl             map[string]string //sysctl
 	Systemd            bool
-	Tmpfs              []string             // tmpfs
-	Tty                bool                 //tty
-	UsernsMode         container.UsernsMode //userns
-	User               string               //user
-	UtsMode            container.UTSMode    //uts
-	Volumes            []string             //volume
+	Tmpfs              []string              // tmpfs
+	Tty                bool                  //tty
+	UsernsMode         namespaces.UsernsMode //userns
+	User               string                //user
+	UtsMode            namespaces.UTSMode    //uts
+	Volumes            []string              //volume
 	VolumesFrom        []string
 	WorkDir            string //workdir
 	MountLabel         string //SecurityOpts
@@ -222,7 +222,7 @@ func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, e
 }
 
 // GetVolumesFrom reads the create-config artifact of the container to get volumes from
-// and adds it to c.Volumes of the curent container.
+// and adds it to c.Volumes of the current container.
 func (c *CreateConfig) GetVolumesFrom() error {
 	var options string
 	for _, vol := range c.VolumesFrom {
@@ -423,6 +423,14 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib
 	if IsPod(string(c.UtsMode)) {
 		options = append(options, libpod.WithUTSNSFromPod(pod))
 	}
+	if c.UtsMode.IsContainer() {
+		connectedCtr, err := c.Runtime.LookupContainer(c.UtsMode.Container())
+		if err != nil {
+			return nil, errors.Wrapf(err, "container %q not found", c.UtsMode.Container())
+		}
+
+		options = append(options, libpod.WithUTSNSFrom(connectedCtr))
+	}
 
 	// TODO: MNT, USER, CGROUP
 	options = append(options, libpod.WithStopSignal(c.StopSignal))
diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go
index e57f51cc15..843d7a5ba6 100644
--- a/pkg/varlinkapi/containers_create.go
+++ b/pkg/varlinkapi/containers_create.go
@@ -12,9 +12,9 @@ import (
 	"github.com/containers/libpod/libpod"
 	"github.com/containers/libpod/libpod/image"
 	"github.com/containers/libpod/pkg/inspect"
+	"github.com/containers/libpod/pkg/namespaces"
 	cc "github.com/containers/libpod/pkg/spec"
 	"github.com/containers/libpod/pkg/util"
-	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/pkg/signal"
 	"github.com/sirupsen/logrus"
 )
@@ -164,10 +164,10 @@ func varlinkCreateToCreateConfig(ctx context.Context, create iopodman.Create, ru
 		LogDriverOpt:      create.Log_driver_opt,
 		Name:              create.Name,
 		Network:           networkMode,
-		IpcMode:           container.IpcMode(create.Ipc_mode),
-		NetMode:           container.NetworkMode(networkMode),
-		UtsMode:           container.UTSMode(create.Uts_mode),
-		PidMode:           container.PidMode(create.Pid_mode),
+		IpcMode:           namespaces.IpcMode(create.Ipc_mode),
+		NetMode:           namespaces.NetworkMode(networkMode),
+		UtsMode:           namespaces.UTSMode(create.Uts_mode),
+		PidMode:           namespaces.PidMode(create.Pid_mode),
 		Pod:               create.Pod,
 		Privileged:        create.Privileged,
 		Publish:           create.Publish,
@@ -209,7 +209,7 @@ func varlinkCreateToCreateConfig(ctx context.Context, create iopodman.Create, ru
 		Tmpfs:       create.Tmpfs,
 		Tty:         create.Tty,
 		User:        user,
-		UsernsMode:  container.UsernsMode(create.Userns_mode),
+		UsernsMode:  namespaces.UsernsMode(create.Userns_mode),
 		Volumes:     create.Volumes,
 		WorkDir:     workDir,
 	}
diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go
index 84d5cd6f16..72ca37d6e8 100644
--- a/test/e2e/rootless_test.go
+++ b/test/e2e/rootless_test.go
@@ -6,6 +6,7 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"runtime"
 	"syscall"
 
 	. "github.com/onsi/ginkgo"
@@ -153,6 +154,8 @@ var _ = Describe("Podman rootless", func() {
 
 	runRootlessHelper := func(args []string) {
 		f := func(rootlessTest PodmanTest, xdgRuntimeDir string, home string, mountPath string) {
+			runtime.LockOSThread()
+			defer runtime.UnlockOSThread()
 			env := os.Environ()
 			env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
 			env = append(env, fmt.Sprintf("HOME=%s", home))