From 185ec6de43ffc5cba4a51e80bfb627a5ba187020 Mon Sep 17 00:00:00 2001 From: TomSweeneyRedHat Date: Wed, 7 Nov 2018 14:23:01 -0500 Subject: Touch up --log* options and daemons in man pages Signed-off-by: TomSweeneyRedHat --- docs/podman-run.1.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'docs/podman-run.1.md') diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index b708e3407..912026a55 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -78,7 +78,7 @@ Write the container ID to the file **--conmon-pidfile**="" -Write the pid of the `conmon` process to a file. `conmon` daemonizes separate from Podman, so this is necessary when using systemd to restart Podman containers. +Write the pid of the `conmon` process to a file. `conmon` runs in a separate process than Podman, so this is necessary when using systemd to restart Podman containers. **--cpu-period**=*0* @@ -333,16 +333,13 @@ Not implemented **--log-driver**="*json-file*" -Logging driver for the container. Default is defined by daemon `--log-driver` flag. - -**Warning**: the `podman logs` command works only for the `json-file` and -`journald` logging drivers. +Logging driver for the container. Currently not supported. This flag is a NOOP provided soley for scripting compatibility. **--log-opt**=[] -Logging driver specific options. +Logging driver specific options. Used to set the path to the container log file. For example: -`path=/var/log/container/mycontainer.json`: Set the path to the container log file. +`--log-opt path=/var/log/container/mycontainer.json` **--mac-address**="" @@ -399,7 +396,7 @@ The operator can identify a container in three ways: - Name (“jonah”) podman generates a UUID for each container, and if a name is not assigned -to the container with **--name** then the daemon will also generate a random +to the container with **--name** then it will generate a random string name. The name is useful any place you need to identify a container. This works for both background and foreground containers. -- cgit v1.2.3-54-g00ecf From 95f22a2ca055d6dec0281cee109375dc4fd9b78b Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 26 Nov 2018 21:31:06 +0100 Subject: network: allow slirp4netns mode also for root containers Signed-off-by: Giuseppe Scrivano --- docs/podman-create.1.md | 3 ++- docs/podman-run.1.md | 3 ++- libpod/container.go | 3 +++ libpod/container_easyjson.go | 13 +++++++++++++ libpod/container_internal.go | 2 +- libpod/oci.go | 2 +- libpod/options.go | 4 +++- libpod/runtime_pod_infra_linux.go | 6 +++++- pkg/spec/createconfig.go | 4 ++-- 9 files changed, 32 insertions(+), 8 deletions(-) (limited to 'docs/podman-run.1.md') diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index 68c00685b..474796a35 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -426,7 +426,8 @@ Set the Network mode for the container 'container:': 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. '|': connect to a user-defined network - 'ns:' path to a network namespace to join + 'ns:': path to a network namespace to join + 'slirp4netns': use slirp4netns to create a user network stack. This is the default for rootless containers **--network-alias**=[] diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index 912026a55..202091b07 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -408,7 +408,8 @@ Set the Network mode for the container: - `container:`: 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. - `|`: connect to a user-defined network -- `ns:` path to a network namespace to join +- `ns:`: path to a network namespace to join +- `slirp4netns`: use slirp4netns to create a user network stack. This is the default for rootless containers **--network-alias**=[] diff --git a/libpod/container.go b/libpod/container.go index 16f61d021..a8a58f4d8 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -9,6 +9,7 @@ import ( "github.com/containernetworking/cni/pkg/types" cnitypes "github.com/containernetworking/cni/pkg/types/current" + "github.com/containers/libpod/pkg/namespaces" "github.com/containers/storage" "github.com/cri-o/ocicni/pkg/ocicni" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -296,6 +297,8 @@ type ContainerConfig struct { HostAdd []string `json:"hostsAdd,omitempty"` // Network names (CNI) to add container to. Empty to use default network. Networks []string `json:"networks,omitempty"` + // Network mode specified for the default network. + NetMode namespaces.NetworkMode `json:"networkMode,omitempty"` // Image Config diff --git a/libpod/container_easyjson.go b/libpod/container_easyjson.go index 041cc08ac..8bf5cb64f 100644 --- a/libpod/container_easyjson.go +++ b/libpod/container_easyjson.go @@ -8,6 +8,7 @@ import ( json "encoding/json" types "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/current" + namespaces "github.com/containers/libpod/pkg/namespaces" storage "github.com/containers/storage" idtools "github.com/containers/storage/pkg/idtools" ocicni "github.com/cri-o/ocicni/pkg/ocicni" @@ -1550,6 +1551,8 @@ func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(in *jlexer.Lexer, ou } in.Delim(']') } + case "networkMode": + out.NetMode = namespaces.NetworkMode(in.String()) case "userVolumes": if in.IsNull() { in.Skip() @@ -2177,6 +2180,16 @@ func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(out *jwriter.Writer, out.RawByte(']') } } + if in.NetMode != "" { + const prefix string = ",\"networkMode\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.NetMode)) + } if len(in.UserVolumes) != 0 { const prefix string = ",\"userVolumes\":" if first { diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 051e0aeb7..e44ec76ec 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -586,7 +586,7 @@ func (c *Container) completeNetworkSetup() error { if err := c.syncContainer(); err != nil { return err } - if rootless.IsRootless() { + if c.config.NetMode == "slirp4netns" { return c.runtime.setupRootlessNetNS(c) } return c.runtime.setupNetNS(c) diff --git a/libpod/oci.go b/libpod/oci.go index a7aec06e5..e9cceda82 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -329,7 +329,7 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res cmd.ExtraFiles = append(cmd.ExtraFiles, ports...) } - if rootless.IsRootless() { + if ctr.config.NetMode.IsSlirp4netns() { ctr.rootlessSlirpSyncR, ctr.rootlessSlirpSyncW, err = os.Pipe() if err != nil { return errors.Wrapf(err, "failed to create rootless network sync pipe") diff --git a/libpod/options.go b/libpod/options.go index 507847d65..7f4e3ac6b 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -7,6 +7,7 @@ import ( "regexp" "syscall" + "github.com/containers/libpod/pkg/namespaces" "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" "github.com/cri-o/ocicni/pkg/ocicni" @@ -817,7 +818,7 @@ func WithDependencyCtrs(ctrs []*Container) CtrCreateOption { // namespace with a minimal configuration. // An optional array of port mappings can be provided. // Conflicts with WithNetNSFrom(). -func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, networks []string) CtrCreateOption { +func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmode string, networks []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { return ErrCtrFinalized @@ -831,6 +832,7 @@ func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netwo ctr.config.CreateNetNS = true ctr.config.PortMappings = portMappings ctr.config.Networks = networks + ctr.config.NetMode = namespaces.NetworkMode(netmode) return nil } diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index 450a2fb32..8a5dbef56 100644 --- a/libpod/runtime_pod_infra_linux.go +++ b/libpod/runtime_pod_infra_linux.go @@ -50,7 +50,11 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID // Since user namespace sharing is not implemented, we only need to check if it's rootless networks := make([]string, 0) - options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, isRootless, networks)) + netmode := "bridge" + if isRootless { + netmode = "slirp4netns" + } + options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, isRootless, netmode, networks)) return r.newContainer(ctx, g.Config, options...) } diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 6a0642ee7..a0fd40318 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -391,11 +391,11 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib options = append(options, libpod.WithNetNSFrom(connectedCtr)) } else if !c.NetMode.IsHost() && !c.NetMode.IsNone() { isRootless := rootless.IsRootless() - postConfigureNetNS := isRootless || (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost() + postConfigureNetNS := c.NetMode.IsSlirp4netns() || (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost() if isRootless && len(portBindings) > 0 { return nil, errors.New("port bindings are not yet supported by rootless containers") } - options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, networks)) + options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(c.NetMode), networks)) } if c.PidMode.IsContainer() { -- cgit v1.2.3-54-g00ecf From 3beacb73bced227b211bf3b8710382b94358614b Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Fri, 16 Nov 2018 06:51:26 -0500 Subject: Disable mount options when running --privileged We now default to setting storage options to "nodev", when running privileged containers, we need to turn this off so the processes can manipulate the image. Signed-off-by: Daniel J Walsh --- docs/podman-create.1.md | 7 ++++--- docs/podman-run.1.md | 5 +++-- libpod/container_internal.go | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) (limited to 'docs/podman-run.1.md') diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index 68c00685b..ab2cb8c60 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -465,9 +465,10 @@ By default, podman containers are This is because by default a container is not allowed to access any devices. A “privileged” container is given access to all devices. -When the operator executes **podman run --privileged**, podman enables access -to all devices on the host as well as set turn off most of the security measures -protecting the host from the container. +When the operator executes a privileged container, podman enables access +to all devices on the host, turns off graphdriver mount options, as well as +turning off most of the security measures protecting the host from the +container. **-p**, **--publish**=[] diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index 912026a55..f99d2f863 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -450,8 +450,9 @@ container is not allowed to access any devices. A “privileged” container is given access to all devices. When the operator executes **podman run --privileged**, podman enables access -to all devices on the host as well as set turn off most of the security measures -protecting the host from the container. +to all devices on the host, turns off graphdriver mount options, as well as +turning off most of the security measures protecting the host from the +container. **-p**, **--publish**=[] diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 051e0aeb7..a426191a4 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -273,6 +273,27 @@ func (c *Container) setupStorage(ctx context.Context) error { }, LabelOpts: c.config.LabelOpts, } + if c.config.Privileged { + privOpt := func(opt string) bool { + for _, privopt := range []string{"nodev", "nosuid", "noexec"} { + if opt == privopt { + return true + } + } + return false + } + defOptions, err := storage.GetDefaultMountOptions() + if err != nil { + return errors.Wrapf(err, "error getting default mount options") + } + var newOptions []string + for _, opt := range defOptions { + if !privOpt(opt) { + newOptions = append(newOptions, opt) + } + } + options.MountOpts = newOptions + } if c.config.Rootfs == "" { options.IDMappingOptions = c.config.IDMappings -- cgit v1.2.3-54-g00ecf From 9c359a31d542074ff686a2f9ad29deee73e92d79 Mon Sep 17 00:00:00 2001 From: baude Date: Fri, 30 Nov 2018 10:23:28 -0600 Subject: create pod on the fly when a user specifies --pod to podman create|run, we should create that pod automatically. the port bindings from the container are then inherited by the infra container. this signicantly improves the workflow of running containers inside pods with podman. the user is still encouraged to use podman pod create to have more granular control of the pod create options. Signed-off-by: baude --- cmd/podman/create.go | 65 +++++++++++++++++++++++++++++++++++++----------- docs/podman-create.1.md | 3 ++- docs/podman-run.1.md | 3 ++- pkg/spec/createconfig.go | 7 +++++- test/e2e/create_test.go | 11 ++++++++ test/e2e/run_test.go | 11 ++++++++ 6 files changed, 82 insertions(+), 18 deletions(-) (limited to 'docs/podman-run.1.md') diff --git a/cmd/podman/create.go b/cmd/podman/create.go index bcf830c7c..c40650f83 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -11,6 +11,7 @@ import ( "syscall" "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" ann "github.com/containers/libpod/pkg/annotations" @@ -375,8 +376,8 @@ func configureEntrypoint(c *cli.Context, data *inspect.ImageData) []string { return entrypoint } -func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string]string) (map[string]string, error) { - pod, err := runtime.LookupPod(c.String("pod")) +func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, error) { + pod, err := runtime.LookupPod(podName) if err != nil { return namespaces, err } @@ -409,6 +410,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim inputCommand, command []string memoryLimit, memoryReservation, memorySwap, memoryKernel int64 blkioWeight uint16 + namespaces map[string]string ) idmappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidname"), c.String("subgidname")) if err != nil { @@ -492,12 +494,21 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together") } + // EXPOSED PORTS + var portBindings map[nat.Port][]nat.PortBinding + if data != nil { + portBindings, err = cc.ExposedPorts(c.StringSlice("expose"), c.StringSlice("publish"), c.Bool("publish-all"), data.ContainerConfig.ExposedPorts) + if err != nil { + return nil, err + } + } + // Kernel Namespaces // TODO Fix handling of namespace from pod // Instead of integrating here, should be done in libpod // However, that also involves setting up security opts // when the pod's namespace is integrated - namespaces := map[string]string{ + namespaces = map[string]string{ "pid": c.String("pid"), "net": c.String("net"), "ipc": c.String("ipc"), @@ -505,8 +516,41 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim "uts": c.String("uts"), } + originalPodName := c.String("pod") + podName := strings.Replace(originalPodName, "new:", "", 1) + // after we strip out :new, make sure there is something left for a pod name + if len(podName) < 1 && c.IsSet("pod") { + return nil, errors.Errorf("new pod name must be at least one character") + } if c.IsSet("pod") { - namespaces, err = configurePod(c, runtime, namespaces) + if strings.HasPrefix(originalPodName, "new:") { + // pod does not exist; lets make it + var podOptions []libpod.PodCreateOption + podOptions = append(podOptions, libpod.WithPodName(podName), libpod.WithInfraContainer(), libpod.WithPodCgroups()) + if len(portBindings) > 0 { + ociPortBindings, err := cc.NatToOCIPortBindings(portBindings) + if err != nil { + return nil, err + } + podOptions = append(podOptions, libpod.WithInfraContainerPorts(ociPortBindings)) + } + + podNsOptions, err := shared.GetNamespaceOptions(strings.Split(DefaultKernelNamespaces, ",")) + if err != nil { + return nil, err + } + podOptions = append(podOptions, podNsOptions...) + // make pod + pod, err := runtime.NewPod(ctx, podOptions...) + if err != nil { + return nil, err + } + logrus.Debugf("pod %s created by new container request", pod.ID()) + + // The container now cannot have port bindings; so we reset the map + portBindings = make(map[nat.Port][]nat.PortBinding) + } + namespaces, err = configurePod(c, runtime, namespaces, podName) if err != nil { return nil, err } @@ -535,7 +579,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim // Make sure if network is set to container namespace, port binding is not also being asked for netMode := ns.NetworkMode(namespaces["net"]) if netMode.IsContainer() { - if len(c.StringSlice("publish")) > 0 || c.Bool("publish-all") { + if len(portBindings) > 0 { return nil, errors.Errorf("cannot set port bindings on an existing container network namespace") } } @@ -644,15 +688,6 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim return nil, errors.Errorf("No command specified on command line or as CMD or ENTRYPOINT in this image") } - // EXPOSED PORTS - var portBindings map[nat.Port][]nat.PortBinding - if data != nil { - portBindings, err = cc.ExposedPorts(c.StringSlice("expose"), c.StringSlice("publish"), c.Bool("publish-all"), data.ContainerConfig.ExposedPorts) - if err != nil { - return nil, err - } - } - // SHM Size shmSize, err := units.FromHumanSize(c.String("shm-size")) if err != nil { @@ -746,7 +781,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim NetMode: netMode, UtsMode: utsMode, PidMode: pidMode, - Pod: c.String("pod"), + Pod: podName, Privileged: c.Bool("privileged"), Publish: c.StringSlice("publish"), PublishAll: c.Bool("publish-all"), diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index 6fbdd0d03..f1409a554 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -455,7 +455,8 @@ Tune the container's pids limit. Set `-1` to have unlimited pids for the contain **--pod**="" -Run container in an existing pod +Run container in an existing pod. If you want podman to make the pod for you, preference the pod name with `new:`. +To make a pod with more granular options, use the `podman pod create` command before creating a container. **--privileged**=*true*|*false* diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index a6761a393..5917f6f7a 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -439,7 +439,8 @@ Tune the container's pids limit. Set `-1` to have unlimited pids for the contain **--pod**="" -Run container in an existing pod +Run container in an existing pod. If you want podman to make the pod for you, preference the pod name with `new:`. +To make a pod with more granular options, use the `podman pod create` command before creating a container. **--privileged**=*true*|*false* diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index a0fd40318..25f8cd7a1 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -496,8 +496,13 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib // CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands func (c *CreateConfig) CreatePortBindings() ([]ocicni.PortMapping, error) { + return NatToOCIPortBindings(c.PortBindings) +} + +// NatToOCIPortBindings iterates a nat.portmap slice and creates []ocicni portmapping slice +func NatToOCIPortBindings(ports nat.PortMap) ([]ocicni.PortMapping, error) { var portBindings []ocicni.PortMapping - for containerPb, hostPb := range c.PortBindings { + for containerPb, hostPb := range ports { var pm ocicni.PortMapping pm.ContainerPort = int32(containerPb.Int()) for _, i := range hostPb { diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 366a58f02..684a7cd88 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -189,4 +189,15 @@ var _ = Describe("Podman create", func() { Expect(session.ExitCode()).To(Equal(0)) Expect(session.OutputToString()).To(ContainSubstring("/create/test rw,nosuid,nodev,noexec,relatime - tmpfs")) }) + + It("podman create --pod automatically", func() { + session := podmanTest.Podman([]string{"create", "--pod", "new:foobar", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"}) + check.WaitWithDefaultTimeout() + match, _ := check.GrepString("foobar") + Expect(match).To(BeTrue()) + }) }) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 38504828b..aaee7fa53 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -628,4 +628,15 @@ USER mail` isSharedOnly := !strings.Contains(shared[0], "shared,") Expect(isSharedOnly).Should(BeTrue()) }) + + It("podman run --pod automatically", func() { + session := podmanTest.Podman([]string{"run", "--pod", "new:foobar", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"}) + check.WaitWithDefaultTimeout() + match, _ := check.GrepString("foobar") + Expect(match).To(BeTrue()) + }) }) -- cgit v1.2.3-54-g00ecf