Преглед изворни кода

Merge pull request #10093 from crosbymichael/readonly-containers

Add --read-only for read only container rootfs
Alexander Morozov пре 10 година
родитељ
комит
95c0f07966

+ 1 - 0
daemon/container.go

@@ -294,6 +294,7 @@ func populateCommand(c *Container, env []string) error {
 	c.command = &execdriver.Command{
 		ID:                 c.ID,
 		Rootfs:             c.RootfsPath(),
+		ReadonlyRootfs:     c.hostConfig.ReadonlyRootfs,
 		InitPath:           "/.dockerinit",
 		WorkingDir:         c.Config.WorkingDir,
 		Network:            en,

+ 2 - 1
daemon/execdriver/driver.go

@@ -125,7 +125,8 @@ type ProcessConfig struct {
 // Process wrapps an os/exec.Cmd to add more metadata
 type Command struct {
 	ID                 string            `json:"id"`
-	Rootfs             string            `json:"rootfs"`   // root fs of the container
+	Rootfs             string            `json:"rootfs"` // root fs of the container
+	ReadonlyRootfs     bool              `json:"readonly_rootfs"`
 	InitPath           string            `json:"initpath"` // dockerinit
 	WorkingDir         string            `json:"working_dir"`
 	ConfigPath         string            `json:"config_path"` // this should be able to be removed when the lxc template is moved into the driver

+ 1 - 0
daemon/execdriver/native/create.go

@@ -31,6 +31,7 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, e
 	container.Cgroups.AllowedDevices = c.AllowedDevices
 	container.MountConfig.DeviceNodes = c.AutoCreatedDevices
 	container.RootFs = c.Rootfs
+	container.MountConfig.ReadonlyFs = c.ReadonlyRootfs
 
 	// check to see if we are running in ramdisk to disable pivot root
 	container.MountConfig.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""

+ 4 - 0
docs/man/docker-create.1.md

@@ -34,6 +34,7 @@ docker-create - Create a new container
 [**-p**|**--publish**[=*[]*]]
 [**--pid**[=*[]*]]
 [**--privileged**[=*false*]]
+[**--read-only**[=*false*]]
 [**--restart**[=*RESTART*]]
 [**--security-opt**[=*[]*]]
 [**-t**|**--tty**[=*false*]]
@@ -140,6 +141,9 @@ IMAGE [COMMAND] [ARG...]
 **--privileged**=*true*|*false*
    Give extended privileges to this container. The default is *false*.
 
+**--read-only**=*true*|*false*
+    Mount the container's root filesystem as read only.
+
 **--restart**=""
    Restart policy to apply when a container exits (no, on-failure[:max-retry], always)
 

+ 8 - 0
docs/man/docker-run.1.md

@@ -35,6 +35,7 @@ docker-run - Run a command in a new container
 [**-p**|**--publish**[=*[]*]]
 [**--pid**[=*[]*]]
 [**--privileged**[=*false*]]
+[**--read-only**[=*false*]]
 [**--restart**[=*RESTART*]]
 [**--rm**[=*false*]]
 [**--security-opt**[=*[]*]]
@@ -253,6 +254,13 @@ to all devices on the host as well as set some configuration in AppArmor to
 allow the container nearly all the same access to the host as processes running
 outside of a container on the host.
 
+**--read-only**=*true*|*false*
+    Mount the container's root filesystem as read only.
+
+    By default a container will have its root filesystem writable allowing processes
+to write files anywhere.  By specifying the `--read-only` flag the container will have
+its root filesystem mounted as read only prohibiting any writes.
+
 **--restart**=""
    Restart policy to apply when a container exits (no, on-failure[:max-retry], always)
 

+ 7 - 0
docs/sources/reference/api/docker_remote_api.md

@@ -61,6 +61,13 @@ This endpoint now returns the list current execs associated with the container (
 **New!**
 New endpoint to rename a container `id` to a new name.
 
+`POST /containers/create`
+`POST /containers/(id)/start`
+
+**New!**
+(`ReadonlyRootfs`) can be passed in the host config to mount the container's
+root filesystem as read only.
+
 ## v1.16
 
 ### Full Documentation

+ 4 - 0
docs/sources/reference/api/docker_remote_api_v1.17.md

@@ -146,6 +146,7 @@ Create a container
                "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
                "PublishAllPorts": false,
                "Privileged": false,
+               "ReadonlyRootfs": false,
                "Dns": ["8.8.8.8"],
                "DnsSearch": [""],
                "VolumesFrom": ["parent", "other:ro"],
@@ -218,6 +219,8 @@ Json Parameters:
         exposed ports. Specified as a boolean value.
   -   **Privileged** - Gives the container full access to the host.  Specified as
         a boolean value.
+  -   **ReadonlyRootfs** - Mount the container's root filesystem as read only.
+        Specified as a boolean value.
   -   **Dns** - A list of dns servers for the container to use.
   -   **DnsSearch** - A list of DNS search domains
   -   **VolumesFrom** - A list of volumes to inherit from another container.
@@ -323,6 +326,7 @@ Return low-level information on the container `id`
 			"NetworkMode": "bridge",
 			"PortBindings": {},
 			"Privileged": false,
+			"ReadonlyRootfs": false,
 			"PublishAllPorts": false,
 			"RestartPolicy": {
 				"MaximumRetryCount": 2,

+ 9 - 0
docs/sources/reference/commandline/cli.md

@@ -755,6 +755,7 @@ Creates a new container.
                                    When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range. (e.g., `-p 1234-1236:1234-1236/tcp`)
                                    (use 'docker port' to see the actual mapping)
       --privileged=false         Give extended privileges to this container
+      --read-only=false           Mount the container's root filesystem as read only
       --restart=""               Restart policy to apply when a container exits (no, on-failure[:max-retry], always)
       --security-opt=[]          Security Options
       -t, --tty=false            Allocate a pseudo-TTY
@@ -1608,6 +1609,7 @@ removed before the image is removed.
                                    (use 'docker port' to see the actual mapping)
       --pid=host		 'host': use the host PID namespace inside the container.  Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
       --privileged=false         Give extended privileges to this container
+      --read-only=false           Mount the container's root filesystem as read only
       --restart=""               Restart policy to apply when a container exits (no, on-failure[:max-retry], always)
       --rm=false                 Automatically remove the container when it exits (incompatible with -d)
       --security-opt=[]          Security Options
@@ -1683,6 +1685,13 @@ will automatically create this directory on the host for you. In the
 example above, Docker will create the `/doesnt/exist`
 folder before starting your container.
 
+    $ sudo docker run --read-only -v /icanwrite busybox touch /icanwrite here
+
+Volumes can be used in combination with `--read-only` to control where 
+a container writes files.  The `--read only` flag mounts the container's root
+filesystem as read only prohibiting writes to locations other than the
+specified volumes for the container.
+
     $ sudo docker run -t -i -v /var/run/docker.sock:/var/run/docker.sock -v ./static-docker:/usr/bin/docker busybox sh
 
 By bind-mounting the docker unix socket and statically linked docker

+ 22 - 0
integration-cli/docker_cli_run_test.go

@@ -3036,3 +3036,25 @@ func TestRunRestartMaxRetries(t *testing.T) {
 	}
 	logDone("run - test max-retries for --restart")
 }
+
+func TestRunContainerWithWritableRootfs(t *testing.T) {
+	defer deleteAllContainers()
+	out, err := exec.Command(dockerBinary, "run", "--rm", "busybox", "touch", "/file").CombinedOutput()
+	if err != nil {
+		t.Fatal(string(out), err)
+	}
+	logDone("run - writable rootfs")
+}
+
+func TestRunContainerWithReadonlyRootfs(t *testing.T) {
+	defer deleteAllContainers()
+	out, err := exec.Command(dockerBinary, "run", "--read-only", "--rm", "busybox", "touch", "/file").CombinedOutput()
+	if err == nil {
+		t.Fatal("expected container to error on run with read only error")
+	}
+	expected := "Read-only file system"
+	if !strings.Contains(string(out), expected) {
+		t.Fatalf("expected output from failure to contain %s but contains %s", expected, out)
+	}
+	logDone("run - read only rootfs")
+}

+ 2 - 0
runconfig/hostconfig.go

@@ -118,6 +118,7 @@ type HostConfig struct {
 	CapDrop         []string
 	RestartPolicy   RestartPolicy
 	SecurityOpt     []string
+	ReadonlyRootfs  bool
 }
 
 // This is used by the create command when you want to set both the
@@ -148,6 +149,7 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
 		NetworkMode:     NetworkMode(job.Getenv("NetworkMode")),
 		IpcMode:         IpcMode(job.Getenv("IpcMode")),
 		PidMode:         PidMode(job.Getenv("PidMode")),
+		ReadonlyRootfs:  job.GetenvBool("ReadonlyRootfs"),
 	}
 
 	job.GetenvJson("LxcConf", &hostConfig.LxcConf)

+ 2 - 0
runconfig/parse.go

@@ -63,6 +63,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		flMacAddress      = cmd.String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)")
 		flIpcMode         = cmd.String([]string{"-ipc"}, "", "Default is to create a private IPC namespace (POSIX SysV IPC) for the container\n'container:<name|id>': reuses another container shared memory, semaphores and message queues\n'host': use the host shared memory,semaphores and message queues inside the container.  Note: the host mode gives the container full access to local shared memory and is therefore considered insecure.")
 		flRestartPolicy   = cmd.String([]string{"-restart"}, "", "Restart policy to apply when a container exits (no, on-failure[:max-retry], always)")
+		flReadonlyRootfs  = cmd.Bool([]string{"-read-only"}, false, "Mount the container's root filesystem as read only")
 	)
 
 	cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR.")
@@ -312,6 +313,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		CapDrop:         flCapDrop.GetAll(),
 		RestartPolicy:   restartPolicy,
 		SecurityOpt:     flSecurityOpt.GetAll(),
+		ReadonlyRootfs:  *flReadonlyRootfs,
 	}
 
 	// When allocating stdin in attached mode, close stdin at client disconnect