Merge pull request #10093 from crosbymichael/readonly-containers

Add --read-only for read only container rootfs
This commit is contained in:
Alexander Morozov 2015-01-14 15:56:51 -08:00
commit 95c0f07966
11 changed files with 62 additions and 1 deletions

View File

@ -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,

View File

@ -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

View File

@ -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") != ""

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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")
}

View File

@ -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)

View File

@ -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