github.com/moby/docker@v26.1.3+incompatible/libcontainerd/replace.go (about) 1 package libcontainerd // import "github.com/docker/docker/libcontainerd" 2 3 import ( 4 "context" 5 6 "github.com/containerd/containerd" 7 "github.com/containerd/log" 8 "github.com/opencontainers/runtime-spec/specs-go" 9 "github.com/pkg/errors" 10 11 "github.com/docker/docker/errdefs" 12 "github.com/docker/docker/libcontainerd/types" 13 ) 14 15 // ReplaceContainer creates a new container, replacing any existing container 16 // with the same id if necessary. 17 func ReplaceContainer(ctx context.Context, client types.Client, id string, spec *specs.Spec, shim string, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) (types.Container, error) { 18 newContainer := func() (types.Container, error) { 19 return client.NewContainer(ctx, id, spec, shim, runtimeOptions, opts...) 20 } 21 ctr, err := newContainer() 22 if err == nil || !errdefs.IsConflict(err) { 23 return ctr, err 24 } 25 26 log := log.G(ctx).WithContext(ctx).WithField("container", id) 27 log.Debug("A container already exists with the same ID. Attempting to clean up the old container.") 28 ctr, err = client.LoadContainer(ctx, id) 29 if err != nil { 30 if errdefs.IsNotFound(err) { 31 // Task failed successfully: the container no longer exists, 32 // despite us not doing anything. May as well try to create 33 // the container again. It might succeed. 34 return newContainer() 35 } 36 return nil, errors.Wrap(err, "could not load stale containerd container object") 37 } 38 tsk, err := ctr.Task(ctx) 39 if err != nil { 40 if errdefs.IsNotFound(err) { 41 goto deleteContainer 42 } 43 // There is no point in trying to delete the container if we 44 // cannot determine whether or not it has a task. The containerd 45 // client would just try to load the task itself, get the same 46 // error, and give up. 47 return nil, errors.Wrap(err, "could not load stale containerd task object") 48 } 49 if err := tsk.ForceDelete(ctx); err != nil { 50 if !errdefs.IsNotFound(err) { 51 return nil, errors.Wrap(err, "could not delete stale containerd task object") 52 } 53 // The task might have exited on its own. Proceed with 54 // attempting to delete the container. 55 } 56 deleteContainer: 57 if err := ctr.Delete(ctx); err != nil && !errdefs.IsNotFound(err) { 58 return nil, errors.Wrap(err, "could not delete stale containerd container object") 59 } 60 61 return newContainer() 62 }