Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow running dockerd as a non-root user (Rootless mode) #38050

Merged
merged 1 commit into from
Feb 3, 2019

Conversation

AkihiroSuda
Copy link
Member

@AkihiroSuda AkihiroSuda commented Oct 16, 2018

- What I did

Allow running dockerd in an unprivileged user namespace (rootless mode).
Close #37375

No SETUID/SETCAP binary is required, except newuidmap and newgidmap.

For Kubernetes integration, please refer to https://github.com/rootless-containers/usernetes .

This PR contains two commits, but the first one is same as #38038 (overlayfs in userns for Ubuntu).
I'll rebase this PR when #38038 gets merged.
(Updated: #38083 is merged now)

- How I did it

By using user_namespaces(7), mount_namespaces(7), network_namespaces(7), and slirp4netns.

Please refer to docs/rootless.md for the details.

- How to verify it

  • Make sure /etc/subuid and /etc/subgid contain the entry for you
$ id -u
1001
$ whoami
penguin
$ grep ^$(whoami): /etc/subuid
penguin:231072:65536
$ grep ^$(whoami): /etc/subgid
penguin:231072:65536
  • Start daemon: dockerd-rootless.sh --experimental
  • Start client: docker -H unix://$XDG_RUNTIME_DIR/docker.sock run ...

Remarks:

  • Some distros such as Debian (excluding Ubuntu) and Arch Linux require sudo sh -c "echo 1 > /proc/sys/kernel/unprivileged_userns_clone".
  • Some distros require sudo modprobe ip_tables iptable_mangle iptable_nat iptable_filter.

Restrictions:

  • Only vfs graphdriver is supported. However, on Ubuntu and a few distros, overlay2 and overlay are also supported. Starting with Linux 4.18, we will be also able to implement FUSE snapshotters.
  • Cgroups (including docker top) and AppArmor are disabled at the moment. In future, Cgroups will be optionally available when delegation permission is confi
    gured on the host.
  • Checkpoint is not supported at the moment.
  • Running rootless dockerd in rootless/rootful dockerd is also possible, but not fully tested.

- Description for the changelog

Allow running dockerd in an unprivileged user namespace (rootless mode)

- A picture of a cute animal (not mandatory but encouraged)

penguin

https://en.wikipedia.org/wiki/Little_penguin#/media/File:Eudyptula_minor_Bruny_1.jpg

Screenshot:

penguin0@suda-ws01:~$ id
uid=1002(penguin0) gid=1006(penguin0) groups=1006(penguin0)
penguin0@suda-ws01:~$ ps u
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
penguin0 122952  0.0  0.0  21484  5156 pts/3    Ss   16:58   0:00 /bin/bash -l
penguin0 123093  0.0  0.0  21484  5200 pts/4    Ss   16:58   0:00 /bin/bash -l
penguin0 123094  0.0  0.0 134792  2860 pts/4    S    16:58   0:00 (sd-pam)
penguin0 123252  0.0  0.0   4628   784 pts/4    S+   16:58   0:00 /bin/sh /usr/local/bin/dockerd-rootless.sh --experimental
penguin0 123253  0.0  0.0 105772  3696 pts/4    Sl+  16:58   0:00 rootlesskit --net=slirp4netns --mtu=65520 --copy-up=/etc --copy-up=/run /usr/local/bin/dockerd-rootless.sh --experimental
penguin0 123257  0.0  0.0 105516  4024 pts/4    Sl+  16:58   0:00 /proc/self/exe --net=slirp4netns --mtu=65520 --copy-up=/etc --copy-up=/run /usr/local/bin/dockerd-rootless.sh --experimental
penguin0 123265  0.0  0.0   2980  1072 pts/4    S+   16:58   0:00 slirp4netns --mtu 65520 123257 tap0
penguin0 123281  0.0  0.0   4628   828 pts/4    S+   16:58   0:00 /bin/sh /usr/local/bin/dockerd-rootless.sh --experimental
penguin0 123283  0.6  0.8 583536 65728 pts/4    Sl+  16:58   0:00 dockerd --experimental
penguin0 125126  0.0  0.0  38372  3688 pts/3    R+   17:00   0:00 ps u
penguin0@suda-ws01:~$ docker -H unix:///run/user/1002/docker.sock run --rm hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

@AkihiroSuda
Copy link
Member Author

cc @tonistiigi @tiborvass

@codecov
Copy link

codecov bot commented Oct 16, 2018

Codecov Report

❗ No coverage uploaded for pull request base (master@50e63ad). Click here to learn what that means.
The diff coverage is 19.23%.

@@            Coverage Diff            @@
##             master   #38050   +/-   ##
=========================================
  Coverage          ?   36.54%           
=========================================
  Files             ?      610           
  Lines             ?    45368           
  Branches          ?        0           
=========================================
  Hits              ?    16581           
  Misses            ?    26497           
  Partials          ?     2290

@sargun
Copy link
Contributor

sargun commented Oct 17, 2018

How can you delegate cgroups? A piece of work prior to this might be supporting cgroup namespace?

@AkihiroSuda
Copy link
Member Author

AkihiroSuda commented Oct 17, 2018

How can you delegate cgroups? A piece of work prior to this might be supporting cgroup namespace?

Cgroups delegation is disabled on this PR and it is likely to be a separate PR in future.

Until we can get full cgroups v2 support in runc (blocked due to lack of freezer and device subsystems, see opencontainers/runc#654), we would need to use pam_cgfs, although it is unlikely to be available on Red Hat distros: containers/podman#1429

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

Not too familiar with all the requirements to make this work, but had a quick glance over, and left some comments/suggestions 🤗

Dockerfile Outdated Show resolved Hide resolved
cmd/dockerd/config_common_unix.go Outdated Show resolved Hide resolved
cmd/dockerd/daemon_unix.go Outdated Show resolved Hide resolved
cmd/dockerd/daemon_unix.go Outdated Show resolved Hide resolved
contrib/dockerd-rootless.sh Outdated Show resolved Hide resolved
pkg/archive/archive_linux.go Outdated Show resolved Hide resolved
pkg/archive/archive_linux.go Outdated Show resolved Hide resolved
pkg/archive/archive_linux.go Outdated Show resolved Hide resolved
pkg/archive/archive_linux.go Outdated Show resolved Hide resolved
pkg/archive/archive_linux.go Outdated Show resolved Hide resolved
@AkihiroSuda
Copy link
Member Author

addressed comments

@AkihiroSuda
Copy link
Member Author

Updated PR. Now user needs to be install either slirp4netns or vpnkit separately.

We should still include vpnkit in make install bundle, but let's discuss it separately. (And also slirp4netns in some "contrib" binary tgz maybe)

Copy link
Member

@cpuguy83 cpuguy83 left a comment

Choose a reason for hiding this comment

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

LGTM

@cpuguy83
Copy link
Member

cpuguy83 commented Feb 1, 2019

@thaJeztah You good?

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

Reviewing from my phone, so just from looking over the changes; left some comments/questions

I'm good to move this forward if those were errors on my side (and this is really cool to see arrive 👌😍🥳)

daemon/config/config_unix.go Outdated Show resolved Hide resolved
cmd/dockerd/daemon.go Show resolved Hide resolved
daemon/daemon_unix.go Show resolved Hide resolved
@thaJeztah
Copy link
Member

@AkihiroSuda are any packaging changes needed for this?

/cc @seemethere

…ode)

Please refer to `docs/rootless.md`.

TLDR:
 * Make sure `/etc/subuid` and `/etc/subgid` contain the entry for you
 * `dockerd-rootless.sh --experimental`
 * `docker -H unix://$XDG_RUNTIME_DIR/docker.sock run ...`

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
@AkihiroSuda
Copy link
Member Author

Updated PR

cc @estesp @icecrime 😃

@AkihiroSuda are any packaging changes needed for this?

I suggest adding dockerd-rootless.sh, rootlesskit and vpnkit to official RPM/DEB and binary tar archive, but not sure how to build VPNKit for non-amd64.
Also, I suggest providing slirp4netns binary as "contrib" pkg.

@thaJeztah
Copy link
Member

I suggest adding dockerd-rootless.sh, rootlesskit and vpnkit to official RPM/DEB and binary tar archive, but not sure how to build VPNKit for non-amd64.
Also, I suggest providing slirp4netns binary as "contrib" pkg.

Makes sense; if you have time; could you try opening a pull request in the https://github.com/docker/docker-ce-packaging repository? Perhaps the packaging team can work on it, but if you can prepare a PR, that may help speeding it up 🤗 (feel free to ping me if you need help/input on that one; I'll be on PTO for the next few days, but will try to catch up on notifications)

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks; this is really cool stuff 🥳

@cyphar
Copy link
Contributor

cyphar commented Feb 4, 2019

@AkihiroSuda Great work. 🎉

I suggest adding dockerd-rootless.sh, rootlesskit and vpnkit to official RPM/DEB and binary tar archive, but not sure how to build VPNKit for non-amd64.

Can we use slirp4netns instead of VPNKit (asking for openSUSE when we package this).

@thaJeztah
Copy link
Member

@cyphar I think the license for slirp4netns was the blocker for bundling it, but you can use it

@cyphar
Copy link
Contributor

cyphar commented Feb 4, 2019

Right, because we use rootlesskit anyway. Thanks.

@@ -46,5 +49,7 @@ func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
flags.BoolVar(&conf.NoNewPrivileges, "no-new-privileges", false, "Set no-new-privileges by default for new containers")
flags.StringVar(&conf.IpcMode, "default-ipc-mode", config.DefaultIpcMode, `Default mode for containers ipc ("shareable" | "private")`)
flags.Var(&conf.NetworkConfig.DefaultAddressPools, "default-address-pool", "Default address pools for node specific local networks")

// Mostly users don't need to set this flag explicitly.
flags.BoolVar(&conf.Rootless, "rootless", rootless.RunningWithNonRootUsername(), "Enable rootless mode (experimental)")
Copy link
Member

Choose a reason for hiding this comment

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

For anyone looking to thread the needle, this line appears to be the cause of #39009. 👍 ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.