Skip to content

Commit

Permalink
Merge pull request #10093 from crosbymichael/readonly-containers
Browse files Browse the repository at this point in the history
Add --read-only for read only container rootfs
  • Loading branch information
LK4D4 committed Jan 14, 2015
2 parents 3118ccc + 4094070 commit 95c0f07
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 1 deletion.
1 change: 1 addition & 0 deletions daemon/container.go
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion daemon/execdriver/driver.go
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions daemon/execdriver/native/create.go
Expand Up @@ -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") != ""
Expand Down
4 changes: 4 additions & 0 deletions docs/man/docker-create.1.md
Expand Up @@ -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*]]
Expand Down Expand Up @@ -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)

Expand Down
8 changes: 8 additions & 0 deletions docs/man/docker-run.1.md
Expand Up @@ -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**[=*[]*]]
Expand Down Expand Up @@ -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)

Expand Down
7 changes: 7 additions & 0 deletions docs/sources/reference/api/docker_remote_api.md
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions docs/sources/reference/api/docker_remote_api_v1.17.md
Expand Up @@ -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"],
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -323,6 +326,7 @@ Return low-level information on the container `id`
"NetworkMode": "bridge",
"PortBindings": {},
"Privileged": false,
"ReadonlyRootfs": false,
"PublishAllPorts": false,
"RestartPolicy": {
"MaximumRetryCount": 2,
Expand Down
9 changes: 9 additions & 0 deletions docs/sources/reference/commandline/cli.md
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions integration-cli/docker_cli_run_test.go
Expand Up @@ -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 changes: 2 additions & 0 deletions runconfig/hostconfig.go
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions runconfig/parse.go
Expand Up @@ -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.")
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 95c0f07

Please sign in to comment.