github.com/stchris/docker@v1.4.2-0.20150106053530-1510a324dbd5/daemon/delete.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 "os" 6 "path" 7 8 log "github.com/Sirupsen/logrus" 9 "github.com/docker/docker/engine" 10 ) 11 12 func (daemon *Daemon) ContainerRm(job *engine.Job) engine.Status { 13 if len(job.Args) != 1 { 14 return job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name) 15 } 16 name := job.Args[0] 17 removeVolume := job.GetenvBool("removeVolume") 18 removeLink := job.GetenvBool("removeLink") 19 forceRemove := job.GetenvBool("forceRemove") 20 container := daemon.Get(name) 21 22 if container == nil { 23 return job.Errorf("No such container: %s", name) 24 } 25 26 if removeLink { 27 name, err := GetFullContainerName(name) 28 if err != nil { 29 job.Error(err) 30 } 31 parent, n := path.Split(name) 32 if parent == "/" { 33 return job.Errorf("Conflict, cannot remove the default name of the container") 34 } 35 pe := daemon.ContainerGraph().Get(parent) 36 if pe == nil { 37 return job.Errorf("Cannot get parent %s for name %s", parent, name) 38 } 39 parentContainer := daemon.Get(pe.ID()) 40 41 if parentContainer != nil { 42 parentContainer.DisableLink(n) 43 } 44 45 if err := daemon.ContainerGraph().Delete(name); err != nil { 46 return job.Error(err) 47 } 48 return engine.StatusOK 49 } 50 51 if container != nil { 52 if container.IsRunning() { 53 if forceRemove { 54 if err := container.Kill(); err != nil { 55 return job.Errorf("Could not kill running container, cannot remove - %v", err) 56 } 57 } else { 58 return job.Errorf("Conflict, You cannot remove a running container. Stop the container before attempting removal or use -f") 59 } 60 } 61 if err := daemon.Destroy(container); err != nil { 62 return job.Errorf("Cannot destroy container %s: %s", name, err) 63 } 64 container.LogEvent("destroy") 65 if removeVolume { 66 daemon.DeleteVolumes(container.VolumePaths()) 67 } 68 } 69 return engine.StatusOK 70 } 71 72 func (daemon *Daemon) DeleteVolumes(volumeIDs map[string]struct{}) { 73 for id := range volumeIDs { 74 if err := daemon.volumes.Delete(id); err != nil { 75 log.Infof("%s", err) 76 continue 77 } 78 } 79 } 80 81 // Destroy unregisters a container from the daemon and cleanly removes its contents from the filesystem. 82 // FIXME: rename to Rm for consistency with the CLI command 83 func (daemon *Daemon) Destroy(container *Container) error { 84 if container == nil { 85 return fmt.Errorf("The given container is <nil>") 86 } 87 88 element := daemon.containers.Get(container.ID) 89 if element == nil { 90 return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.ID) 91 } 92 93 if err := container.Stop(3); err != nil { 94 return err 95 } 96 97 // Deregister the container before removing its directory, to avoid race conditions 98 daemon.idIndex.Delete(container.ID) 99 daemon.containers.Delete(container.ID) 100 container.derefVolumes() 101 if _, err := daemon.containerGraph.Purge(container.ID); err != nil { 102 log.Debugf("Unable to remove container from link graph: %s", err) 103 } 104 105 if err := daemon.driver.Remove(container.ID); err != nil { 106 return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.driver, container.ID, err) 107 } 108 109 initID := fmt.Sprintf("%s-init", container.ID) 110 if err := daemon.driver.Remove(initID); err != nil { 111 return fmt.Errorf("Driver %s failed to remove init filesystem %s: %s", daemon.driver, initID, err) 112 } 113 114 if err := os.RemoveAll(container.root); err != nil { 115 return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err) 116 } 117 118 if err := daemon.execDriver.Clean(container.ID); err != nil { 119 return fmt.Errorf("Unable to remove execdriver data for %s: %s", container.ID, err) 120 } 121 122 selinuxFreeLxcContexts(container.ProcessLabel) 123 124 return nil 125 }