Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/rootless.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Rootless mode (Experimental)

Requirements:
- runc `ecd55a4135e0a26de884ce436442914f945b1e76` (May 30, 2018) or later
- runc `a00bf0190895aa465a5fbed0268888e2c8ddfe85` (Oct 15, 2018) or later
- Some distros such as Debian (excluding Ubuntu) and Arch Linux require `echo 1 > /proc/sys/kernel/unprivileged_userns_clone`
- `newuidmap` and `newgidmap` need to be installed on the host. These commands are provided by the `uidmap` package.
- `/etc/subuid` and `/etc/subgid` should contain >= 65536 sub-IDs. e.g. `penguin:231072:65536`.
Expand Down Expand Up @@ -45,6 +45,7 @@ unshared# buildkitd
* `overlayfs` snapshotter is not supported except Ubuntu-flavored kernel: http://kernel.ubuntu.com/git/ubuntu/ubuntu-artful.git/commit/fs/overlayfs?h=Ubuntu-4.13.0-25.29&id=0a414bdc3d01f3b61ed86cfe3ce8b63a9240eba7
* containerd worker is not supported ( pending PR: https://github.com/containerd/containerd/pull/2006 )
* Network namespace is not used at the moment.
* Cgroups is disabled.

### Terminal 2:

Expand All @@ -61,7 +62,7 @@ $ docker run --name buildkitd -d --privileged -p 1234:1234 buildkit-rootless --
```

`docker run` requires `--privileged` but the BuildKit daemon is executed as a normal user.
See [`moby/moby#36597`](https://github.com/moby/moby/issues/36597, [`kubernetes/community#1934`](https://github.com/kubernetes/community/pull/1934) and [Jess's blog](https://blog.jessfraz.com/post/building-container-images-securely-on-kubernetes/) for the ongoing work to remove this requirement
See [`docker/cli#1347`](https://github.com/docker/cli/pull/1347) for the ongoing work to remove this requirement

```
$ docker exec buildkitd id
Expand Down
2 changes: 1 addition & 1 deletion examples/buildkit0/buildkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func main() {
var opt buildOpt
flag.BoolVar(&opt.withContainerd, "with-containerd", true, "enable containerd worker")
flag.StringVar(&opt.containerd, "containerd", "v1.2.0-rc.1", "containerd version")
flag.StringVar(&opt.runc, "runc", "dd56ece8236d6d9e5bed4ea0c31fe53c7b873ff4", "runc version")
flag.StringVar(&opt.runc, "runc", "a00bf0190895aa465a5fbed0268888e2c8ddfe85", "runc version")
flag.Parse()

bk := buildkit(opt)
Expand Down
2 changes: 1 addition & 1 deletion examples/buildkit1/buildkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func main() {
var opt buildOpt
flag.BoolVar(&opt.withContainerd, "with-containerd", true, "enable containerd worker")
flag.StringVar(&opt.containerd, "containerd", "v1.2.0-rc.1", "containerd version")
flag.StringVar(&opt.runc, "runc", "dd56ece8236d6d9e5bed4ea0c31fe53c7b873ff4", "runc version")
flag.StringVar(&opt.runc, "runc", "a00bf0190895aa465a5fbed0268888e2c8ddfe85", "runc version")
flag.Parse()

bk := buildkit(opt)
Expand Down
2 changes: 1 addition & 1 deletion examples/buildkit2/buildkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func main() {
var opt buildOpt
flag.BoolVar(&opt.withContainerd, "with-containerd", true, "enable containerd worker")
flag.StringVar(&opt.containerd, "containerd", "v1.2.0-rc.1", "containerd version")
flag.StringVar(&opt.runc, "runc", "dd56ece8236d6d9e5bed4ea0c31fe53c7b873ff4", "runc version")
flag.StringVar(&opt.runc, "runc", "a00bf0190895aa465a5fbed0268888e2c8ddfe85", "runc version")
flag.Parse()

bk := buildkit(opt)
Expand Down
2 changes: 1 addition & 1 deletion examples/buildkit3/buildkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func main() {
var opt buildOpt
flag.BoolVar(&opt.withContainerd, "with-containerd", true, "enable containerd worker")
flag.StringVar(&opt.containerd, "containerd", "v1.2.0-rc.1", "containerd version")
flag.StringVar(&opt.runc, "runc", "dd56ece8236d6d9e5bed4ea0c31fe53c7b873ff4", "runc version")
flag.StringVar(&opt.runc, "runc", "a00bf0190895aa465a5fbed0268888e2c8ddfe85", "runc version")
flag.StringVar(&opt.buildkit, "buildkit", "master", "buildkit version")
flag.Parse()

Expand Down
4 changes: 0 additions & 4 deletions frontend/dockerfile/dockerfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1604,10 +1604,6 @@ RUN ["ls"]
}

func testUser(t *testing.T, sb integration.Sandbox) {
if sb.Rootless() {
t.Skip("only for rootful worker, due to lack of support for additional gids (https://github.com/opencontainers/runc/issues/1835)")
}

f := getFrontend(t, sb)

dockerfile := []byte(`
Expand Down
2 changes: 1 addition & 1 deletion hack/dockerfiles/test.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG RUNC_VERSION=00dc70017d222b178a002ed30e9321b12647af2d
ARG RUNC_VERSION=a00bf0190895aa465a5fbed0268888e2c8ddfe85
ARG CONTAINERD_VERSION=v1.2.0-rc.1
# containerd v1.0 for integration tests
ARG CONTAINERD10_VERSION=v1.0.3
Expand Down
2 changes: 1 addition & 1 deletion hack/dockerfiles/test.buildkit.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax = tonistiigi/dockerfile:runmount20180925

ARG RUNC_VERSION=00dc70017d222b178a002ed30e9321b12647af2d
ARG RUNC_VERSION=a00bf0190895aa465a5fbed0268888e2c8ddfe85
ARG CONTAINERD_VERSION=v1.2.0-rc.1
# containerd v1.0 for integration tests
ARG CONTAINERD10_VERSION=v1.0.3
Expand Down
113 changes: 20 additions & 93 deletions util/rootless/specconv/specconv_linux.go
Original file line number Diff line number Diff line change
@@ -1,113 +1,40 @@
package specconv

import (
"os"
"sort"
"strings"

"github.com/opencontainers/runc/libcontainer/system"
"github.com/opencontainers/runc/libcontainer/user"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)

// ToRootless converts spec to be compatible with "rootless" runc.
// * Adds userns (Note: since we are already in userns, ideally we should not need to do this. runc-side issue is tracked at https://github.com/opencontainers/runc/issues/1837)
// * Fix up mount flags (same as above)
// * Replace /sys with bind-mount (FIXME: we don't need to do this if netns is unshared)
// * Remove /sys mount
// * Remove cgroups
//
// See docs/rootless.md for the supported runc revision.
func ToRootless(spec *specs.Spec) error {
if !system.RunningInUserNS() {
return errors.New("needs to be in user namespace")
}
uidMap, err := user.CurrentProcessUIDMap()
if err != nil && !os.IsNotExist(err) {
return err
}
gidMap, err := user.CurrentProcessUIDMap()
if err != nil && !os.IsNotExist(err) {
return err
}
return toRootless(spec, uidMap, gidMap)
}

// toRootless was forked from github.com/opencontainers/runc/libcontainer/specconv
func toRootless(spec *specs.Spec, uidMap, gidMap []user.IDMap) error {
if err := configureUserNS(spec, uidMap, gidMap); err != nil {
return err
}
if err := configureMounts(spec); err != nil {
return err
}

// Remove cgroup settings.
spec.Linux.Resources = nil
spec.Linux.CgroupsPath = ""
return nil
}

// configureUserNS add suserns and the current ID map to the spec.
// Since we are already in userns, ideally we should not need to add userns.
// However, currently rootless runc always requires userns to be added.
// https://github.com/opencontainers/runc/issues/1837
func configureUserNS(spec *specs.Spec, uidMap, gidMap []user.IDMap) error {
spec.Linux.Namespaces = append(spec.Linux.Namespaces, specs.LinuxNamespace{
Type: specs.UserNamespace,
})

sort.Slice(uidMap, func(i, j int) bool { return uidMap[i].ID < uidMap[j].ID })
uNextContainerID := int64(0)
for _, u := range uidMap {
spec.Linux.UIDMappings = append(spec.Linux.UIDMappings,
specs.LinuxIDMapping{
HostID: uint32(u.ID),
ContainerID: uint32(uNextContainerID),
Size: uint32(u.Count),
})
uNextContainerID += int64(u.Count)
}
sort.Slice(gidMap, func(i, j int) bool { return gidMap[i].ID < gidMap[j].ID })
gNextContainerID := int64(0)
for _, g := range gidMap {
spec.Linux.GIDMappings = append(spec.Linux.GIDMappings,
specs.LinuxIDMapping{
HostID: uint32(g.ID),
ContainerID: uint32(gNextContainerID),
Size: uint32(g.Count),
})
gNextContainerID += int64(g.Count)
}
return nil
}

func configureMounts(spec *specs.Spec) error {
// Remove /sys mount because we can't mount /sys when the daemon netns
// is not unshared from the host.
//
// Instead, we could bind-mount /sys from the host, however, `rbind, ro`
// does not make /sys/fs/cgroup read-only (and we can't bind-mount /sys
// without rbind)
//
// PR for making /sys/fs/cgroup read-only is proposed, but it is very
// complicated: https://github.com/opencontainers/runc/pull/1869
//
// For buildkit usecase, we suppose we don't need to provide /sys to
// containers and remove /sys mount as a workaround.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RFC

cc @giuseppe I suppose buildah should remove /sys as well?

var mounts []specs.Mount
for _, mount := range spec.Mounts {
// Ignore all mounts that are under /sys, because we add /sys later.
if strings.HasPrefix(mount.Destination, "/sys") {
continue
}

// Remove all gid= and uid= mappings.
// Since we are already in userns, ideally we should not need to do this.
// https://github.com/opencontainers/runc/issues/1837
var options []string
for _, option := range mount.Options {
if !strings.HasPrefix(option, "gid=") && !strings.HasPrefix(option, "uid=") {
options = append(options, option)
}
}
mount.Options = options
mounts = append(mounts, mount)
}

// Add the sysfs mount as an rbind, because we can't mount /sys unless we have netns.
// TODO: keep original /sys mount when we have netns.
mounts = append(mounts, specs.Mount{
Source: "/sys",
Destination: "/sys",
Type: "none",
Options: []string{"rbind", "nosuid", "noexec", "nodev", "ro"},
})
spec.Mounts = mounts

// Remove cgroups so as to avoid `container_linux.go:337: starting container process caused "process_linux.go:280: applying cgroup configuration for process caused \"mkdir /sys/fs/cgroup/cpuset/buildkit: permission denied\""`
spec.Linux.Resources = nil
spec.Linux.CgroupsPath = ""
return nil
}
42 changes: 0 additions & 42 deletions util/rootless/specconv/specconv_linux_test.go

This file was deleted.

5 changes: 1 addition & 4 deletions vendor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ github.com/gogo/googleapis b23578765ee54ff6bceff57f397d833bf4ca6869
github.com/golang/protobuf v1.1.0
github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
github.com/opencontainers/image-spec v1.0.1
github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
github.com/opencontainers/runc a00bf0190895aa465a5fbed0268888e2c8ddfe85
github.com/Microsoft/go-winio v0.4.11
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
Expand Down Expand Up @@ -67,6 +67,3 @@ github.com/opentracing-contrib/go-stdlib b1a47cfbdd7543e70e9ef3e73d0802ad306cc1c
# used by dockerfile tests
gotest.tools v2.1.0
github.com/google/go-cmp v0.2.0

# used by rootless spec conv test
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0

This file was deleted.

Loading