1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

automatically remove container via -rm

add AutoRemove to HostConfig
add -rm flag to docker run
add TestRunAutoRemove to test -rm
docs: add -rm to commandline/command/run
add hostConfig to container monitor
make monitor destroy the container via -rm

This adds support for automatically removing a container after it
exits. The removal of the container is handled on the server side.
This commit is contained in:
unclejack 2013-08-15 21:48:05 +03:00
parent 7447867edd
commit 22e7e107ad
4 changed files with 54 additions and 3 deletions

View file

@ -542,3 +542,40 @@ func TestAttachDisconnect(t *testing.T) {
cStdin.Close() cStdin.Close()
container.Wait() container.Wait()
} }
// Expected behaviour: container gets deleted automatically after exit
func TestRunAutoRemove(t *testing.T) {
stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime)
c := make(chan struct{})
go func() {
defer close(c)
if err := cli.CmdRun("-rm", unitTestImageID, "hostname"); err != nil {
t.Fatal(err)
}
}()
var temporaryContainerID string
setTimeout(t, "Reading command output time out", 2*time.Second, func() {
cmdOutput, err := bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
}
temporaryContainerID = cmdOutput
if err := closeWrap(stdout, stdoutPipe); err != nil {
t.Fatal(err)
}
})
setTimeout(t, "CmdRun timed out", 5*time.Second, func() {
<-c
})
time.Sleep(500 * time.Millisecond)
if len(globalRuntime.List()) > 0 {
t.Fatalf("failed to remove container automatically: container %s still exists", temporaryContainerID)
}
}

View file

@ -90,6 +90,7 @@ type HostConfig struct {
Binds []string Binds []string
ContainerIDFile string ContainerIDFile string
LxcConf []KeyValuePair LxcConf []KeyValuePair
AutoRemove bool
} }
type BindMap struct { type BindMap struct {
@ -126,6 +127,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
flContainerIDFile := cmd.String("cidfile", "", "Write the container ID to the file") flContainerIDFile := cmd.String("cidfile", "", "Write the container ID to the file")
flNetwork := cmd.Bool("n", true, "Enable networking for this container") flNetwork := cmd.Bool("n", true, "Enable networking for this container")
flPrivileged := cmd.Bool("privileged", false, "Give extended privileges to this container") flPrivileged := cmd.Bool("privileged", false, "Give extended privileges to this container")
flAutoRemove := cmd.Bool("rm", false, "Automatically remove the container when it exits (incompatible with -d)")
if capabilities != nil && *flMemory > 0 && !capabilities.MemoryLimit { if capabilities != nil && *flMemory > 0 && !capabilities.MemoryLimit {
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n") //fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
@ -174,6 +176,10 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
} }
} }
if *flDetach && *flAutoRemove {
return nil, nil, cmd, fmt.Errorf("Conflicting options: -rm and -d")
}
var binds []string var binds []string
// add any bind targets to the list of container volumes // add any bind targets to the list of container volumes
@ -242,6 +248,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
Binds: binds, Binds: binds,
ContainerIDFile: *flContainerIDFile, ContainerIDFile: *flContainerIDFile,
LxcConf: lxcConf, LxcConf: lxcConf,
AutoRemove: *flAutoRemove,
} }
if capabilities != nil && *flMemory > 0 && !capabilities.SwapLimit { if capabilities != nil && *flMemory > 0 && !capabilities.SwapLimit {
@ -818,7 +825,7 @@ func (container *Container) Start(hostConfig *HostConfig) error {
container.ToDisk() container.ToDisk()
container.SaveHostConfig(hostConfig) container.SaveHostConfig(hostConfig)
go container.monitor() go container.monitor(hostConfig)
return nil return nil
} }
@ -948,7 +955,7 @@ func (container *Container) waitLxc() error {
} }
} }
func (container *Container) monitor() { func (container *Container) monitor(hostConfig *HostConfig) {
// Wait for the program to exit // Wait for the program to exit
utils.Debugf("Waiting for process") utils.Debugf("Waiting for process")
@ -1018,6 +1025,11 @@ func (container *Container) monitor() {
// FIXME: why are we serializing running state to disk in the first place? // FIXME: why are we serializing running state to disk in the first place?
//log.Printf("%s: Failed to dump configuration to the disk: %s", container.ID, err) //log.Printf("%s: Failed to dump configuration to the disk: %s", container.ID, err)
} }
if hostConfig != nil {
if hostConfig.AutoRemove {
container.runtime.Destroy(container)
}
}
} }
func (container *Container) kill() error { func (container *Container) kill() error {

View file

@ -23,6 +23,7 @@
-m=0: Memory limit (in bytes) -m=0: Memory limit (in bytes)
-n=true: Enable networking for this container -n=true: Enable networking for this container
-p=[]: Map a network port to the container -p=[]: Map a network port to the container
-rm=false: Automatically remove the container when it exits (incompatible with -d)
-t=false: Allocate a pseudo-tty -t=false: Allocate a pseudo-tty
-u="": Username or UID -u="": Username or UID
-dns=[]: Set custom dns servers for the container -dns=[]: Set custom dns servers for the container

View file

@ -174,7 +174,8 @@ func (runtime *Runtime) Register(container *Container) error {
close(container.waitLock) close(container.waitLock)
} else if !nomonitor { } else if !nomonitor {
container.allocateNetwork() container.allocateNetwork()
go container.monitor() // hostConfig isn't needed here and can be nil
go container.monitor(nil)
} }
return nil return nil
} }