github.com/chenchun/docker@v1.3.2-0.20150629222414-20467faf132b/daemon/delete.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 "os" 6 "path" 7 "runtime" 8 9 "github.com/Sirupsen/logrus" 10 ) 11 12 type ContainerRmConfig struct { 13 ForceRemove, RemoveVolume, RemoveLink bool 14 } 15 16 func (daemon *Daemon) ContainerRm(name string, config *ContainerRmConfig) error { 17 container, err := daemon.Get(name) 18 if err != nil { 19 return err 20 } 21 22 if config.RemoveLink { 23 name, err := GetFullContainerName(name) 24 if err != nil { 25 return err 26 } 27 parent, n := path.Split(name) 28 if parent == "/" { 29 return fmt.Errorf("Conflict, cannot remove the default name of the container") 30 } 31 pe := daemon.ContainerGraph().Get(parent) 32 if pe == nil { 33 return fmt.Errorf("Cannot get parent %s for name %s", parent, name) 34 } 35 parentContainer, _ := daemon.Get(pe.ID()) 36 37 if err := daemon.ContainerGraph().Delete(name); err != nil { 38 return err 39 } 40 41 if parentContainer != nil { 42 parentContainer.DisableLink(n) 43 } 44 45 return nil 46 } 47 48 if err := daemon.rm(container, config.ForceRemove); err != nil { 49 return fmt.Errorf("Cannot destroy container %s: %v", name, err) 50 } 51 52 if config.RemoveVolume { 53 container.removeMountPoints() 54 } 55 return nil 56 } 57 58 // Destroy unregisters a container from the daemon and cleanly removes its contents from the filesystem. 59 func (daemon *Daemon) rm(container *Container, forceRemove bool) (err error) { 60 if container.IsRunning() { 61 if !forceRemove { 62 return fmt.Errorf("Conflict, You cannot remove a running container. Stop the container before attempting removal or use -f") 63 } 64 if err := container.Kill(); err != nil { 65 return fmt.Errorf("Could not kill running container, cannot remove - %v", err) 66 } 67 } 68 69 // stop collection of stats for the container regardless 70 // if stats are currently getting collected. 71 daemon.statsCollector.stopCollection(container) 72 73 element := daemon.containers.Get(container.ID) 74 if element == nil { 75 return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.ID) 76 } 77 78 // Container state RemovalInProgress should be used to avoid races. 79 if err = container.SetRemovalInProgress(); err != nil { 80 return fmt.Errorf("Failed to set container state to RemovalInProgress: %s", err) 81 } 82 83 defer container.ResetRemovalInProgress() 84 85 if err = container.Stop(3); err != nil { 86 return err 87 } 88 89 // Mark container dead. We don't want anybody to be restarting it. 90 container.SetDead() 91 92 // Save container state to disk. So that if error happens before 93 // container meta file got removed from disk, then a restart of 94 // docker should not make a dead container alive. 95 container.ToDisk() 96 97 // If force removal is required, delete container from various 98 // indexes even if removal failed. 99 defer func() { 100 if err != nil && forceRemove { 101 daemon.idIndex.Delete(container.ID) 102 daemon.containers.Delete(container.ID) 103 os.RemoveAll(container.root) 104 container.LogEvent("destroy") 105 } 106 }() 107 108 if _, err := daemon.containerGraph.Purge(container.ID); err != nil { 109 logrus.Debugf("Unable to remove container from link graph: %s", err) 110 } 111 112 if err = daemon.driver.Remove(container.ID); err != nil { 113 return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.driver, container.ID, err) 114 } 115 116 // There will not be an -init on Windows, so don't fail by not attempting to delete it 117 if runtime.GOOS != "windows" { 118 initID := fmt.Sprintf("%s-init", container.ID) 119 if err := daemon.driver.Remove(initID); err != nil { 120 return fmt.Errorf("Driver %s failed to remove init filesystem %s: %s", daemon.driver, initID, err) 121 } 122 } 123 124 if err = os.RemoveAll(container.root); err != nil { 125 return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err) 126 } 127 128 if err = daemon.execDriver.Clean(container.ID); err != nil { 129 return fmt.Errorf("Unable to remove execdriver data for %s: %s", container.ID, err) 130 } 131 132 selinuxFreeLxcContexts(container.ProcessLabel) 133 daemon.idIndex.Delete(container.ID) 134 daemon.containers.Delete(container.ID) 135 136 container.LogEvent("destroy") 137 return nil 138 } 139 140 func (daemon *Daemon) DeleteVolumes(c *Container) error { 141 return c.removeMountPoints() 142 }