github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/daemon/delete.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "fmt" 5 "os" 6 "path" 7 "strings" 8 "time" 9 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/container" 12 "github.com/docker/docker/errdefs" 13 "github.com/docker/docker/pkg/system" 14 "github.com/pkg/errors" 15 "github.com/sirupsen/logrus" 16 ) 17 18 // ContainerRm removes the container id from the filesystem. An error 19 // is returned if the container is not found, or if the remove 20 // fails. If the remove succeeds, the container name is released, and 21 // network links are removed. 22 func (daemon *Daemon) ContainerRm(name string, config *types.ContainerRmConfig) error { 23 start := time.Now() 24 container, err := daemon.GetContainer(name) 25 if err != nil { 26 return err 27 } 28 29 // Container state RemovalInProgress should be used to avoid races. 30 if inProgress := container.SetRemovalInProgress(); inProgress { 31 err := fmt.Errorf("removal of container %s is already in progress", name) 32 return errdefs.Conflict(err) 33 } 34 defer container.ResetRemovalInProgress() 35 36 // check if container wasn't deregistered by previous rm since Get 37 if c := daemon.containers.Get(container.ID); c == nil { 38 return nil 39 } 40 41 if config.RemoveLink { 42 return daemon.rmLink(container, name) 43 } 44 45 err = daemon.cleanupContainer(container, config.ForceRemove, config.RemoveVolume) 46 containerActions.WithValues("delete").UpdateSince(start) 47 48 return err 49 } 50 51 func (daemon *Daemon) rmLink(container *container.Container, name string) error { 52 if name[0] != '/' { 53 name = "/" + name 54 } 55 parent, n := path.Split(name) 56 if parent == "/" { 57 return fmt.Errorf("Conflict, cannot remove the default link name of the container") 58 } 59 60 parent = strings.TrimSuffix(parent, "/") 61 pe, err := daemon.containersReplica.Snapshot().GetID(parent) 62 if err != nil { 63 return fmt.Errorf("Cannot get parent %s for link name %s", parent, name) 64 } 65 66 daemon.releaseName(name) 67 parentContainer, _ := daemon.GetContainer(pe) 68 if parentContainer != nil { 69 daemon.linkIndex.unlink(name, container, parentContainer) 70 if err := daemon.updateNetwork(parentContainer); err != nil { 71 logrus.Debugf("Could not update network to remove link %s: %v", n, err) 72 } 73 } 74 return nil 75 } 76 77 // cleanupContainer unregisters a container from the daemon, stops stats 78 // collection and cleanly removes contents and metadata from the filesystem. 79 func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemove, removeVolume bool) (err error) { 80 if container.IsRunning() { 81 if !forceRemove { 82 state := container.StateString() 83 procedure := "Stop the container before attempting removal or force remove" 84 if state == "paused" { 85 procedure = "Unpause and then " + strings.ToLower(procedure) 86 } 87 err := fmt.Errorf("You cannot remove a %s container %s. %s", state, container.ID, procedure) 88 return errdefs.Conflict(err) 89 } 90 if err := daemon.Kill(container); err != nil { 91 return fmt.Errorf("Could not kill running container %s, cannot remove - %v", container.ID, err) 92 } 93 } 94 if !system.IsOSSupported(container.OS) { 95 return fmt.Errorf("cannot remove %s: %s ", container.ID, system.ErrNotSupportedOperatingSystem) 96 } 97 98 // stop collection of stats for the container regardless 99 // if stats are currently getting collected. 100 daemon.statsCollector.StopCollection(container) 101 102 if err = daemon.containerStop(container, 3); err != nil { 103 return err 104 } 105 106 // Mark container dead. We don't want anybody to be restarting it. 107 container.Lock() 108 container.Dead = true 109 110 // Save container state to disk. So that if error happens before 111 // container meta file got removed from disk, then a restart of 112 // docker should not make a dead container alive. 113 if err := container.CheckpointTo(daemon.containersReplica); err != nil && !os.IsNotExist(err) { 114 logrus.Errorf("Error saving dying container to disk: %v", err) 115 } 116 container.Unlock() 117 118 // When container creation fails and `RWLayer` has not been created yet, we 119 // do not call `ReleaseRWLayer` 120 if container.RWLayer != nil { 121 err := daemon.imageService.ReleaseLayer(container.RWLayer, container.OS) 122 if err != nil { 123 err = errors.Wrapf(err, "container %s", container.ID) 124 container.SetRemovalError(err) 125 return err 126 } 127 container.RWLayer = nil 128 } 129 130 if err := system.EnsureRemoveAll(container.Root); err != nil { 131 e := errors.Wrapf(err, "unable to remove filesystem for %s", container.ID) 132 container.SetRemovalError(e) 133 return e 134 } 135 136 linkNames := daemon.linkIndex.delete(container) 137 selinuxFreeLxcContexts(container.ProcessLabel) 138 daemon.idIndex.Delete(container.ID) 139 daemon.containers.Delete(container.ID) 140 daemon.containersReplica.Delete(container) 141 if e := daemon.removeMountPoints(container, removeVolume); e != nil { 142 logrus.Error(e) 143 } 144 for _, name := range linkNames { 145 daemon.releaseName(name) 146 } 147 container.SetRemoved() 148 stateCtr.del(container.ID) 149 150 daemon.LogContainerEvent(container, "destroy") 151 return nil 152 }