github.com/lxpollitt/docker@v1.5.0/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 // stop collection of stats for the container regardless 53 // if stats are currently getting collected. 54 daemon.statsCollector.stopCollection(container) 55 if container.IsRunning() { 56 if forceRemove { 57 if err := container.Kill(); err != nil { 58 return job.Errorf("Could not kill running container, cannot remove - %v", err) 59 } 60 } else { 61 return job.Errorf("Conflict, You cannot remove a running container. Stop the container before attempting removal or use -f") 62 } 63 } 64 if err := daemon.Destroy(container); err != nil { 65 return job.Errorf("Cannot destroy container %s: %s", name, err) 66 } 67 container.LogEvent("destroy") 68 if removeVolume { 69 daemon.DeleteVolumes(container.VolumePaths()) 70 } 71 } 72 return engine.StatusOK 73 } 74 75 func (daemon *Daemon) DeleteVolumes(volumeIDs map[string]struct{}) { 76 for id := range volumeIDs { 77 if err := daemon.volumes.Delete(id); err != nil { 78 log.Infof("%s", err) 79 continue 80 } 81 } 82 } 83 84 // Destroy unregisters a container from the daemon and cleanly removes its contents from the filesystem. 85 // FIXME: rename to Rm for consistency with the CLI command 86 func (daemon *Daemon) Destroy(container *Container) error { 87 if container == nil { 88 return fmt.Errorf("The given container is <nil>") 89 } 90 91 element := daemon.containers.Get(container.ID) 92 if element == nil { 93 return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.ID) 94 } 95 96 if err := container.Stop(3); err != nil { 97 return err 98 } 99 100 // Deregister the container before removing its directory, to avoid race conditions 101 daemon.idIndex.Delete(container.ID) 102 daemon.containers.Delete(container.ID) 103 container.derefVolumes() 104 if _, err := daemon.containerGraph.Purge(container.ID); err != nil { 105 log.Debugf("Unable to remove container from link graph: %s", err) 106 } 107 108 if err := daemon.driver.Remove(container.ID); err != nil { 109 return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.driver, container.ID, err) 110 } 111 112 initID := fmt.Sprintf("%s-init", container.ID) 113 if err := daemon.driver.Remove(initID); err != nil { 114 return fmt.Errorf("Driver %s failed to remove init filesystem %s: %s", daemon.driver, initID, err) 115 } 116 117 if err := os.RemoveAll(container.root); err != nil { 118 return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err) 119 } 120 121 if err := daemon.execDriver.Clean(container.ID); err != nil { 122 return fmt.Errorf("Unable to remove execdriver data for %s: %s", container.ID, err) 123 } 124 125 selinuxFreeLxcContexts(container.ProcessLabel) 126 127 return nil 128 }