-
Notifications
You must be signed in to change notification settings - Fork 18.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Docker pull "dry run" mode #16450
Docker pull "dry run" mode #16450
Conversation
Signed-off-by: Sylvain Révéreault <sylvain@revereault.fr>
Signed-off-by: Sylvain Révéreault <sylvain@revereault.fr>
Signed-off-by: Sylvain Révéreault <sylvain@revereault.fr>
Signed-off-by: Yann Gravrand <y.gravrand@gmail.com>
Signed-off-by: Yann Gravrand <y.gravrand@gmail.com>
Signed-off-by: Yann Gravrand <y.gravrand@gmail.com>
@@ -112,7 +113,7 @@ func (s *Server) postImagesCreate(ctx context.Context, w http.ResponseWriter, r | |||
OutStream: output, | |||
} | |||
|
|||
err = s.daemon.Repositories().Pull(image, tag, imagePullConfig) | |||
err = s.daemon.Repositories().Pull(image, tag, imagePullConfig, dryRun != "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would turn on the "dryRun" mode even if dryRun
was set to false in the request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aaronlehmann Seems that the CLI does not send the "dryRun=" parameter when set to false.
Do you see a possible improvement here though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CLI won't send it, but I could see someone using the API directly inserting dryRun=false
.
...which reminds me that this parameter should be documented in docs/reference/api/docker_remote_api.md.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Will change the test and update the docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a helper function for this, boolValue
Signed-off-by: Yann Gravrand <y.gravrand@gmail.com>
…n normal mode Signed-off-by: Yann Gravrand <y.gravrand@gmail.com>
@aaronlehmann Thanks for your review! Can you check it out again? |
@@ -76,6 +76,9 @@ func (p *v2Puller) pullV2Repository(tag string) (err error) { | |||
broadcaster.Add(p.config.OutStream) | |||
if found { | |||
// Another pull of the same repository is already taking place; just wait for it to finish | |||
if dryRun { | |||
broadcaster.Write(p.sf.FormatStatus(tag, "!!! Another pull of the same image is already running, dry-run is not possible unless you restart the Docker daemon !!!")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should write to p.config.OutStream
rather than broadcaster
; otherwise the message will go to all clients that are watching this pull.
I'd also suggest changing the message to remove the !!!
characters, and also remove "unless you restart the Docker daemon" (because the user only needs to wait for the pull to finish).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, consider what happens if someone tries to do docker pull myimage
and docker pull -dry-run myimage
at the same time. If the dry-run pull starts first, the normal pull may attach to that broadcaster, and the pull will never happen.
In dry-run mode, this function should probably avoid calling poolAdd
and poolRemoveWithError
at all, to avoid being mistaken for an actual pull. It could pass p.config.OutStream
to pullV2Tag
in this case, instead of broadcaster
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your comments.
Our client requesting a pull in "dry-mode" shouldn't affect other pulls.
Will make changes as soon as I can.
Thanks for making the changes so far. I added a few more comments. |
@@ -17,6 +17,7 @@ import ( | |||
func (cli *DockerCli) CmdPull(args ...string) error { | |||
cmd := Cli.Subcmd("pull", []string{"NAME[:TAG|@DIGEST]"}, "Pull an image or a repository from a registry", true) | |||
allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository") | |||
dryRun := cmd.Bool([]string{"d", "-dry-run"}, false, "Dry run mode - only displays the download size") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not use the -d
option here.
Generally I would associate -d
as detach for something like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-n
would the correct param for a "Dry run".
In general 👎 for a bool argument, and especially adding it to the arguments for pull, which are already massive. I think implementing this as a different puller implementation would be better than adding to the real one. I also feel like this is getting pretty close to hitting this: https://github.com/docker/docker/blob/611dbd8957581fa451a4103259100a5e2d115b8c/ROADMAP.md#23-remote-registry-operations ping @stevvooe |
Also, this is pretty cool, I know a lot of people would like to be able to get at this sort of information. |
Signed-off-by: Yann Gravrand <y.gravrand@gmail.com>
@ygravrand I mean a new implementation for the But still, see the link I shared wrt to the moratorium on code changes to code that deals with the registry. |
@@ -112,7 +112,7 @@ func (s *TagStore) Pull(image string, tag string, imagePullConfig *ImagePullConf | |||
lastErr = err | |||
continue | |||
} | |||
if fallback, err := puller.Pull(tag); err != nil { | |||
if fallback, err := puller.Pull(tag, dryRun); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make a lot of sense to have an interface with a dryRun
parameter. Just change the implementation of the interface to make it not take an action.
The main problem with this is that one must always consider how dryRun
is interpreted when making additions to the implementation. If an individual is fixing a bug in an implementation and is not aware of this interface, we risk having unprotected mutations.
The right approach is to have a separate implementation of puller
resolved at instantiation time that implements puller. If we have to parameterize on deeper methods of puller, we should provide interfaces that can be injected further down and do not provide a no-op.
First, I'll say this is a much needed and valuable feature. Being able to see what actions a system might take based on the input is immensely and contributes directly to better usability. Albeit, dry run does not really address the request of #1512, which would be better served by a As @cpuguy83 stated, this definitely runs afoul of https://github.com/docker/docker/blob/611dbd8957581fa451a4103259100a5e2d115b8c/ROADMAP.md#23-remote-registry-operations. However, that moratorium has been enacted to ensure that use cases such as dry run are trivially implementable. The main problem plaguing this PR is that there are if statements speckled throughout the code, demonstrating the need for the work that needs to occur before we lift the moratorium. The intent here is not to prevent this kind of feature but rather to enable safe implementation. Put more succinctly, this PR is so hard to implement because we have not addressed the issues driving the moratorium. I apologize that you may have lost time implementing something we have to say no to, but the hard problems need to be solved here before we continue to add features. |
@stevvooe @cpuguy83 Thanks for the review. I agree with you a 100% about the "scattered if statements" ugliness of the submitted code (Go and codebase newcomers :) ). A separate implementation of |
I totally agree with @ygravrand : this was our first try at adding features to Docker's codebase, and we almost discovered Go while doing it (during the Docker Global Hack Day), but as the feature seems to interest more people than the two of us, we'll be glad to implement it "the right way" (and we certainly will need guidance for that ;-) ). |
@ygravrand @srevereault If you're up for it that would be great but I don't want you to have a poor experience from the current state of the codebase (it is both moving and complex). Albeit, one may learn quite a bit. For this case, a Really, we need to have methods that encode higher-level operations like "pull layer" and "pull manifest". The key to this is having some reference types from distribution/distribution#963 that can address individual components of a pull. The addition of that type really makes this a lot easier, since you don't have to keep adjusting the level of arguments based on the resource. It makes the puller recursive. From that, there are other details that may come into play. One problem that commonly comes up is querying and managing download state. I know features are the glamorous part, but there is a lot of core work that could really help move us forward. If you're still game, feel free to contact me via the mailing list or IRC. |
@ygravrand @srevereault @stevvooe where we here? |
@LK4D4 This is a needed feature but I'm not sure this design is the right approach. The reference package is in place, so making refactoring the puller should be ongoing. @ygravrand @srevereault Are you planning to take this further? |
@stevvooe yes, still planning to work on this, but I couldn't find the time in the last month. I will probably need guidance on this... I suppose looking at distribution/distribution#963 would be a good start ? |
I would recommend holding off on this. The pull and push code has some major changes in the works for 1.10. It would be a lot easier to wait for these changes to land and then build on top of them. |
I agree with @aaronlehmann. As much as I appreciate this feature, I think it's not reasonable to merge right now. I'm closing this until we can figure it out, which doesn't mean we don't want this, but that we cannot currently merge it. Thank you again for the great contribution @ygravrand: I suggest you open an issue so we can keep track of this, and hopefully revive the subject as soon as the ongoing refactoring work lands. |
This is our contribution to Docker Global Hack Day 3.
It adds the ability to "dry run" a "docker pull" command, obtaining only the total size of image layers that have to be downloaded.
A new
-d
flag activates this mode:At the end of the Hackaton, we found this related Feature request: #1512. Although it's labelled "docker pull info", a comment by @unclejack states that a flag approach would be preferred.
So it seems we're in the right direction with this.
Some limitations: