daemon/daemon.go Daemon: containerd libcontainerdtypes.Client
是和containerd交互的client

daemon/start.go
func (daemon *Daemon) containerStart

  1. err = daemon.containerd.Create(ctx, container.ID, spec, createOptions, withImageName(imageRef.String()))
  2. if err != nil {
  3. if errdefs.IsConflict(err) {
  4. logrus.WithError(err).WithField("container", container.ID).Error("Container not cleaned up from containerd from previous run")
  5. // best effort to clean up old container object
  6. daemon.containerd.DeleteTask(ctx, container.ID)
  7. if err := daemon.containerd.Delete(ctx, container.ID); err != nil && !errdefs.IsNotFound(err) {
  8. logrus.WithError(err).WithField("container", container.ID).Error("Error cleaning up stale containerd container object")
  9. }
  10. err = daemon.containerd.Create(ctx, container.ID, spec, createOptions, withImageName(imageRef.String()))
  11. }
  12. if err != nil {
  13. return translateContainerdStartErr(container.Path, container.SetExitCode, err)
  14. }
  15. }
  16. // TODO(mlaventure): we need to specify checkpoint options here
  17. pid, err := daemon.containerd.Start(context.Background(), container.ID, checkpointDir,
  18. container.StreamConfig.Stdin() != nil || container.Config.Tty,
  19. container.InitializeStdio)
  20. if err != nil {
  21. if err := daemon.containerd.Delete(context.Background(), container.ID); err != nil {
  22. logrus.WithError(err).WithField("container", container.ID).
  23. Error("failed to delete failed start container")
  24. }
  25. return translateContainerdStartErr(container.Path, container.SetExitCode, err)
  26. }

对于docker run这个命令:

实际执行的是 create + start