зеркало из https://github.com/microsoft/docker.git
Print a status message when pull command is executed
Using repo tag in the status message for better usability, as per review comments Added documentation and Changed code to print Status after downloads are complete Addresses #2404 Signed-off-by: Srini Brahmaroutu <srbrahma@us.ibm.com>
This commit is contained in:
Родитель
4c8b8861ec
Коммит
ecff6303a3
|
@ -23,6 +23,8 @@ It is also possible to specify a non-default registry to pull from.
|
|||
# EXAMPLES
|
||||
|
||||
# Pull a repository with multiple images
|
||||
# Note that if the image is previously downloaded then the status would be
|
||||
# 'Status: Image is up to date for fedora'
|
||||
|
||||
$ sudo docker pull fedora
|
||||
Pulling repository fedora
|
||||
|
@ -31,6 +33,8 @@ It is also possible to specify a non-default registry to pull from.
|
|||
511136ea3c5a: Download complete
|
||||
73bd853d2ea5: Download complete
|
||||
|
||||
Status: Downloaded newer image for fedora
|
||||
|
||||
$ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
fedora rawhide ad57ef8d78d7 5 days ago 359.3 MB
|
||||
|
@ -39,6 +43,8 @@ It is also possible to specify a non-default registry to pull from.
|
|||
fedora latest 105182bb5e8b 5 days ago 372.7 MB
|
||||
|
||||
# Pull an image, manually specifying path to the registry and tag
|
||||
# Note that if the image is previously downloaded then the status would be
|
||||
# 'Status: Image is up to date for registry.hub.docker.com/fedora:20'
|
||||
|
||||
$ sudo docker pull registry.hub.docker.com/fedora:20
|
||||
Pulling repository fedora
|
||||
|
@ -46,6 +52,8 @@ It is also possible to specify a non-default registry to pull from.
|
|||
511136ea3c5a: Download complete
|
||||
fd241224e9cf: Download complete
|
||||
|
||||
Status: Downloaded newer image for registry.hub.docker.com/fedora:20
|
||||
|
||||
$ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
fedora 20 3f2fed40e4b0 4 days ago 372.7 MB
|
||||
|
|
|
@ -93,6 +93,8 @@ download the `centos` image.
|
|||
ef52fb1fe610: Download complete
|
||||
. . .
|
||||
|
||||
Status: Downloaded newer image for centos
|
||||
|
||||
We can see that each layer of the image has been pulled down and now we
|
||||
can run a container from this image and we won't have to wait to
|
||||
download the image.
|
||||
|
|
|
@ -67,6 +67,8 @@ Once you've found the image you want, you can download it with `docker pull <ima
|
|||
511136ea3c5a: Download complete
|
||||
7064731afe90: Download complete
|
||||
|
||||
Status: Downloaded newer image for centos
|
||||
|
||||
You now have an image from which you can run containers.
|
||||
|
||||
## Contributing to Docker Hub
|
||||
|
|
|
@ -122,6 +122,8 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
|||
}
|
||||
|
||||
errors := make(chan error)
|
||||
|
||||
layers_downloaded := false
|
||||
for _, image := range repoData.ImgList {
|
||||
downloadImage := func(img *registry.ImgData) {
|
||||
if askedTag != "" && img.Tag != askedTag {
|
||||
|
@ -158,15 +160,17 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
|||
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s", img.Tag, localName), nil))
|
||||
success := false
|
||||
var lastErr error
|
||||
var lastErr, err error
|
||||
var is_downloaded bool
|
||||
if mirrors != nil {
|
||||
for _, ep := range mirrors {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, mirror: %s", img.Tag, localName, ep), nil))
|
||||
if err := s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||
if is_downloaded, err = s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||
// Don't report errors when pulling from mirrors.
|
||||
log.Debugf("Error pulling image (%s) from %s, mirror: %s, %s", img.Tag, localName, ep, err)
|
||||
continue
|
||||
}
|
||||
layers_downloaded = layers_downloaded || is_downloaded
|
||||
success = true
|
||||
break
|
||||
}
|
||||
|
@ -174,13 +178,14 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
|||
if !success {
|
||||
for _, ep := range repoData.Endpoints {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, endpoint: %s", img.Tag, localName, ep), nil))
|
||||
if err := s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||
if is_downloaded, err = s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||
// It's not ideal that only the last error is returned, it would be better to concatenate the errors.
|
||||
// As the error is also given to the output stream the user will see the error.
|
||||
lastErr = err
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Error pulling image (%s) from %s, endpoint: %s, %s", img.Tag, localName, ep, err), nil))
|
||||
continue
|
||||
}
|
||||
layers_downloaded = layers_downloaded || is_downloaded
|
||||
success = true
|
||||
break
|
||||
}
|
||||
|
@ -227,18 +232,24 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
|||
}
|
||||
}
|
||||
|
||||
requestedTag := localName
|
||||
if len(askedTag) > 0 {
|
||||
requestedTag = localName + ":" + askedTag
|
||||
}
|
||||
WriteStatus(requestedTag, out, sf, layers_downloaded)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint string, token []string, sf *utils.StreamFormatter) error {
|
||||
func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint string, token []string, sf *utils.StreamFormatter) (bool, error) {
|
||||
history, err := r.GetRemoteHistory(imgID, endpoint, token)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pulling dependent layers", nil))
|
||||
// FIXME: Try to stream the images?
|
||||
// FIXME: Launch the getRemoteImage() in goroutines
|
||||
|
||||
layers_downloaded := false
|
||||
for i := len(history) - 1; i >= 0; i-- {
|
||||
id := history[i]
|
||||
|
||||
|
@ -262,15 +273,16 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
|
|||
imgJSON, imgSize, err = r.GetRemoteImageJSON(id, endpoint, token)
|
||||
if err != nil && j == retries {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
||||
return err
|
||||
return layers_downloaded, err
|
||||
} else if err != nil {
|
||||
time.Sleep(time.Duration(j) * 500 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
img, err = image.NewImgJSON(imgJSON)
|
||||
layers_downloaded = true
|
||||
if err != nil && j == retries {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
||||
return fmt.Errorf("Failed to parse json: %s", err)
|
||||
return layers_downloaded, fmt.Errorf("Failed to parse json: %s", err)
|
||||
} else if err != nil {
|
||||
time.Sleep(time.Duration(j) * 500 * time.Millisecond)
|
||||
continue
|
||||
|
@ -295,8 +307,9 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
|
|||
continue
|
||||
} else if err != nil {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
||||
return err
|
||||
return layers_downloaded, err
|
||||
}
|
||||
layers_downloaded = true
|
||||
defer layer.Close()
|
||||
|
||||
err = s.graph.Register(img, imgJSON,
|
||||
|
@ -306,14 +319,21 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
|
|||
continue
|
||||
} else if err != nil {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error downloading dependent layers", nil))
|
||||
return err
|
||||
return layers_downloaded, err
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Download complete", nil))
|
||||
|
||||
}
|
||||
return nil
|
||||
return layers_downloaded, nil
|
||||
}
|
||||
|
||||
func WriteStatus(requestedTag string, out io.Writer, sf *utils.StreamFormatter, layers_downloaded bool) {
|
||||
if layers_downloaded {
|
||||
out.Write(sf.FormatStatus("", "Status: Downloaded newer image for %s", requestedTag))
|
||||
} else {
|
||||
out.Write(sf.FormatStatus("", "Status: Image is up to date for %s", requestedTag))
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче