diff --git a/g3doc/user_guide/tutorials/docker-in-gke-sandbox.md b/g3doc/user_guide/tutorials/docker-in-gke-sandbox.md index 256c84c4d..992e64df0 100644 --- a/g3doc/user_guide/tutorials/docker-in-gke-sandbox.md +++ b/g3doc/user_guide/tutorials/docker-in-gke-sandbox.md @@ -9,13 +9,13 @@ network driver and the bridge network driver are tested and supported. ## How to run Docker in a GKE Sandbox First, install a GKE cluster (1.29.0 or higher) and deploy a node pool with -gVisor enabled. You can view the full documentation [here][gke-sandbox-docs]. +gVisor enabled. You can view the full documentation +[here](https://cloud.google.com/kubernetes-engine/docs/how-to/sandbox-pods#enabling). Prepare a container image with pre-installed Docker: ```shell -$ cd g3doc/user_guide/tutorials/docker-in-gke-sandbox/ -$ docker build -t {registry_url}/docker-in-gvisor:latest . +$ docker build -t docker-in-gvisor images/basic/docker $ docker push {registry_url}/docker-in-gvisor:latest ``` diff --git a/g3doc/user_guide/tutorials/docker-in-gke-sandbox/Dockerfile b/g3doc/user_guide/tutorials/docker-in-gke-sandbox/Dockerfile deleted file mode 100644 index 5a7124578..000000000 --- a/g3doc/user_guide/tutorials/docker-in-gke-sandbox/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM ubuntu:22.04 - -ENV DEBIAN_FRONTEND="noninteractive" -RUN apt-get update && apt-get install -y docker.io - -COPY docker-run.sh /usr/local/bin/docker-run.sh - -CMD /usr/local/bin/docker-run.sh diff --git a/g3doc/user_guide/tutorials/docker-in-gke-sandbox/docker-run.sh b/g3doc/user_guide/tutorials/docker-in-gke-sandbox/docker-run.sh deleted file mode 100755 index 19271f95d..000000000 --- a/g3doc/user_guide/tutorials/docker-in-gke-sandbox/docker-run.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Copyright 2024 The gVisor Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -xe - -test -f /sys/fs/cgroup/devices/tasks || { - mount -t tmpfs cgroups /sys/fs/cgroup - mkdir /sys/fs/cgroup/devices - mount -t cgroup -o devices devices /sys/fs/cgroup/devices -} - -exec /usr/bin/dockerd --bridge=none --iptables=false --ip6tables=false "$@" diff --git a/g3doc/user_guide/tutorials/docker-in-gke-sandbox/docker.yaml b/g3doc/user_guide/tutorials/docker-in-gke-sandbox/docker.yaml index fd0cc11a6..1d0fe29ef 100644 --- a/g3doc/user_guide/tutorials/docker-in-gke-sandbox/docker.yaml +++ b/g3doc/user_guide/tutorials/docker-in-gke-sandbox/docker.yaml @@ -6,7 +6,7 @@ spec: runtimeClassName: gvisor containers: - name: docker-in-gvisor - image: avagin/docker-in-gvisor:0.1 + image: us-central1-docker.pkg.dev/gvisor-presubmit/gvisor-presubmit-images/basic/docker_x86_64:latest securityContext: capabilities: add: ["all"] diff --git a/g3doc/user_guide/tutorials/docker-in-gvisor.md b/g3doc/user_guide/tutorials/docker-in-gvisor.md index 85464ab4b..3f88a4fa4 100644 --- a/g3doc/user_guide/tutorials/docker-in-gvisor.md +++ b/g3doc/user_guide/tutorials/docker-in-gvisor.md @@ -31,15 +31,17 @@ entry. First, prepare a container image with pre-installed Docker: ```shell -$ cd images/basic/docker/ -$ docker build -t docker-in-gvisor . +$ docker build -t docker-in-gvisor images/basic/docker ``` -Since Docker requires root privileges and a full set of capabilities, a gVisor -sandbox needs to be started in privileged mode: +In a gVisor sandbox, Docker containers can be started with a set of capabilities +as `audit_write`, `chown`, `dac_override`, `fowner`, `fsetid`, `kill`, `mknod`, +`net_bind_service`, `net_admin`, `net_raw`, `setfcap`, `setgid`, `setpcap`, +`setuid`, `sys_admin`, `sys_chroot`, `sys_ptrace`. For the simplicity, let's +start the sandbox with all capabilities: ```shell -$ docker run --runtime runsc -d --rm --privileged --name docker-in-gvisor docker-in-gvisor +$ docker run --runtime runsc -d --rm --cap-add all --name docker-in-gvisor docker-in-gvisor ``` Now, we can build and run Docker containers. @@ -78,3 +80,6 @@ $ docker run -it --rm whalesay "Containers do not contain, but gVisor-s do!" \____\______/ ``` + +> In the sandbox, we can also run privileged containers by `docker run -it +> --privileged --rm whalesay "Containers do not contain, but gVisor-s do!"` diff --git a/test/image/image_test.go b/test/image/image_test.go index a7a3cf127..3d0ad71c7 100644 --- a/test/image/image_test.go +++ b/test/image/image_test.go @@ -339,25 +339,65 @@ func TestStdio(t *testing.T) { } } +func dockerInGvisorCapabilities() []string { + return []string{ + "audit_write", + "chown", + "dac_override", + "fowner", + "fsetid", + "kill", + "mknod", + "net_admin", + "net_bind_service", + "net_raw", + "setfcap", + "setgid", + "setpcap", + "setuid", + "sys_admin", + "sys_chroot", + "sys_ptrace", + } +} + func TestDockerOverlayWithHostNetwork(t *testing.T) { - testDocker(t, true, true) + testDocker(t, true, true, false) +} + +func TestPrivilegedDockerOverlayWithHostNetwork(t *testing.T) { + testDocker(t, true, true, true) } func TestDockerOverlay(t *testing.T) { - testDocker(t, true, false) + testDocker(t, true, false, false) +} + +func TestPrivilegedDockerOverlay(t *testing.T) { + testDocker(t, true, false, true) } func TestDockerWithHostNetwork(t *testing.T) { - testDocker(t, false, true) + testDocker(t, false, true, false) +} + +func TestPrivilegedDockerWithHostNetwork(t *testing.T) { + testDocker(t, false, true, true) } func TestDocker(t *testing.T) { // Overlayfs can't be built on top of another overlayfs, so docket has // to fall back to the vfs driver. - testDocker(t, false, false) + testDocker(t, false, false, false) } -func testDocker(t *testing.T, overlay, hostNetwork bool) { +func TestPrivilegedDocker(t *testing.T) { + // Overlayfs can't be built on top of another overlayfs, so docket has + // to fall back to the vfs driver. + testDocker(t, false, false, true) +} + +func testDocker(t *testing.T, overlay, hostNetwork, startPrivilegedContainer bool) { if testutil.IsRunningWithHostNet() { t.Skip("docker doesn't work with hostinet") } @@ -367,8 +407,8 @@ func testDocker(t *testing.T, overlay, hostNetwork bool) { // Start the container. opts := dockerutil.RunOpts{ - Image: "basic/docker", - Privileged: true, + Image: "basic/docker", + CapAdd: dockerInGvisorCapabilities(), } if overlay { opts.Mounts = []mount.Mount{ @@ -403,10 +443,14 @@ func testDocker(t *testing.T, overlay, hostNetwork bool) { } break } - cmd := []string{"docker", "run", "--rm", "alpine", "sh", "-c", "apk add curl && curl -h"} + cmd := []string{"docker", "run", "--rm"} if hostNetwork { - cmd = []string{"docker", "run", "--network", "host", "--rm", "alpine", "sh", "-c", "apk add curl && curl -h"} + cmd = append(cmd, "--network", "host") } + if startPrivilegedContainer { + cmd = append(cmd, "--privileged") + } + cmd = append(cmd, "alpine", "sh", "-c", "apk add curl && curl -h") _, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, cmd...) if err != nil { t.Fatalf("docker exec failed: %v", err)