github.com/clcy1243/docker@v1.6.0-rc3/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 21 container, err := daemon.Get(name) 22 if err != nil { 23 return job.Error(err) 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 65 if forceRemove { 66 if err := daemon.ForceRm(container); err != nil { 67 log.Errorf("Cannot destroy container %s: %v", name, err) 68 } 69 } else { 70 if err := daemon.Rm(container); err != nil { 71 return job.Errorf("Cannot destroy container %s: %v", name, err) 72 } 73 } 74 container.LogEvent("destroy") 75 if removeVolume { 76 daemon.DeleteVolumes(container.VolumePaths()) 77 } 78 } 79 return engine.StatusOK 80 } 81 82 func (daemon *Daemon) DeleteVolumes(volumeIDs map[string]struct{}) { 83 for id := range volumeIDs { 84 if err := daemon.volumes.Delete(id); err != nil { 85 log.Infof("%s", err) 86 continue 87 } 88 } 89 } 90 91 func (daemon *Daemon) Rm(container *Container) (err error) { 92 return daemon.commonRm(container, false) 93 } 94 95 func (daemon *Daemon) ForceRm(container *Container) (err error) { 96 return daemon.commonRm(container, true) 97 } 98 99 // Destroy unregisters a container from the daemon and cleanly removes its contents from the filesystem. 100 func (daemon *Daemon) commonRm(container *Container, forceRemove bool) (err error) { 101 if container == nil { 102 return fmt.Errorf("The given container is <nil>") 103 } 104 105 element := daemon.containers.Get(container.ID) 106 if element == nil { 107 return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.ID) 108 } 109 110 // Container state RemovalInProgress should be used to avoid races. 111 if err = container.SetRemovalInProgress(); err != nil { 112 return fmt.Errorf("Failed to set container state to RemovalInProgress: %s", err) 113 } 114 115 defer container.ResetRemovalInProgress() 116 117 if err = container.Stop(3); err != nil { 118 return err 119 } 120 121 // Mark container dead. We don't want anybody to be restarting it. 122 container.SetDead() 123 124 // Save container state to disk. So that if error happens before 125 // container meta file got removed from disk, then a restart of 126 // docker should not make a dead container alive. 127 container.ToDisk() 128 129 // If force removal is required, delete container from various 130 // indexes even if removal failed. 131 defer func() { 132 if err != nil && forceRemove { 133 daemon.idIndex.Delete(container.ID) 134 daemon.containers.Delete(container.ID) 135 } 136 }() 137 138 container.derefVolumes() 139 if _, err := daemon.containerGraph.Purge(container.ID); err != nil { 140 log.Debugf("Unable to remove container from link graph: %s", err) 141 } 142 143 if err = daemon.driver.Remove(container.ID); err != nil { 144 return fmt.Errorf("Driver %s failed to remove root filesystem %s: %s", daemon.driver, container.ID, err) 145 } 146 147 initID := fmt.Sprintf("%s-init", container.ID) 148 if err := daemon.driver.Remove(initID); err != nil { 149 return fmt.Errorf("Driver %s failed to remove init filesystem %s: %s", daemon.driver, initID, err) 150 } 151 152 if err = os.RemoveAll(container.root); err != nil { 153 return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err) 154 } 155 156 if err = daemon.execDriver.Clean(container.ID); err != nil { 157 return fmt.Errorf("Unable to remove execdriver data for %s: %s", container.ID, err) 158 } 159 160 selinuxFreeLxcContexts(container.ProcessLabel) 161 daemon.idIndex.Delete(container.ID) 162 daemon.containers.Delete(container.ID) 163 164 return nil 165 }