image_pull.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package daemon
  2. import (
  3. "io"
  4. "strings"
  5. "github.com/docker/distribution/digest"
  6. "github.com/docker/docker/builder"
  7. "github.com/docker/docker/distribution"
  8. "github.com/docker/docker/pkg/progress"
  9. "github.com/docker/docker/reference"
  10. "github.com/docker/docker/registry"
  11. "github.com/docker/engine-api/types"
  12. "golang.org/x/net/context"
  13. )
  14. // PullImage initiates a pull operation. image is the repository name to pull, and
  15. // tag may be either empty, or indicate a specific tag to pull.
  16. func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
  17. // Special case: "pull -a" may send an image name with a
  18. // trailing :. This is ugly, but let's not break API
  19. // compatibility.
  20. image = strings.TrimSuffix(image, ":")
  21. ref, err := reference.ParseNamed(image)
  22. if err != nil {
  23. return err
  24. }
  25. if tag != "" {
  26. // The "tag" could actually be a digest.
  27. var dgst digest.Digest
  28. dgst, err = digest.ParseDigest(tag)
  29. if err == nil {
  30. ref, err = reference.WithDigest(ref, dgst)
  31. } else {
  32. ref, err = reference.WithTag(ref, tag)
  33. }
  34. if err != nil {
  35. return err
  36. }
  37. }
  38. return daemon.pullImageWithReference(ctx, ref, metaHeaders, authConfig, outStream)
  39. }
  40. // PullOnBuild tells Docker to pull image referenced by `name`.
  41. func (daemon *Daemon) PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (builder.Image, error) {
  42. ref, err := reference.ParseNamed(name)
  43. if err != nil {
  44. return nil, err
  45. }
  46. ref = reference.WithDefaultTag(ref)
  47. pullRegistryAuth := &types.AuthConfig{}
  48. if len(authConfigs) > 0 {
  49. // The request came with a full auth config file, we prefer to use that
  50. repoInfo, err := daemon.RegistryService.ResolveRepository(ref)
  51. if err != nil {
  52. return nil, err
  53. }
  54. resolvedConfig := registry.ResolveAuthConfig(
  55. authConfigs,
  56. repoInfo.Index,
  57. )
  58. pullRegistryAuth = &resolvedConfig
  59. }
  60. if err := daemon.pullImageWithReference(ctx, ref, nil, pullRegistryAuth, output); err != nil {
  61. return nil, err
  62. }
  63. return daemon.GetImage(name)
  64. }
  65. func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
  66. // Include a buffer so that slow client connections don't affect
  67. // transfer performance.
  68. progressChan := make(chan progress.Progress, 100)
  69. writesDone := make(chan struct{})
  70. ctx, cancelFunc := context.WithCancel(ctx)
  71. go func() {
  72. writeDistributionProgress(cancelFunc, outStream, progressChan)
  73. close(writesDone)
  74. }()
  75. imagePullConfig := &distribution.ImagePullConfig{
  76. MetaHeaders: metaHeaders,
  77. AuthConfig: authConfig,
  78. ProgressOutput: progress.ChanOutput(progressChan),
  79. RegistryService: daemon.RegistryService,
  80. ImageEventLogger: daemon.LogImageEvent,
  81. MetadataStore: daemon.distributionMetadataStore,
  82. ImageStore: daemon.imageStore,
  83. ReferenceStore: daemon.referenceStore,
  84. DownloadManager: daemon.downloadManager,
  85. }
  86. err := distribution.Pull(ctx, ref, imagePullConfig)
  87. close(progressChan)
  88. <-writesDone
  89. return err
  90. }