Moving docker service digest pinning to client side#32388
Moving docker service digest pinning to client side#32388tiborvass merged 2 commits intomoby:masterfrom
Conversation
client/service_create.go
Outdated
There was a problem hiding this comment.
What happens if the Image is already a manifest? It looks like we're going to throw a warning
There was a problem hiding this comment.
You mean the image already contains a digest? Then the digest will be used to retrieve the manifest, and platform information added (this is not part of this PR, and will come later in a separate PR). Without the platform information stuff, we could just skip this call altogether.
|
I'm okay with this approach but I think we should add a flag in |
|
@aaronlehmann I agree, I'll add that. Are there any cons to this approach, apart from having to move digest pinning away from content-trust? |
|
I think it's problematic for the "service update" case. We should only be messing with the image field or the platform info if the user actually specified What if we moved |
|
@aaronlehmann I'll update When you say moving |
I'm not sure. It sounds like a good idea if it's possible. But I seem to remember that content trust involves a lot of code that lives in |
|
@aaronlehmann let me take a look. If it's easy to refactor, I'll include it in this PR. |
|
Update: Trust code is definitely entrenched in the CLI, and while it seems "refactorable", I don't think it should be a part of this PR because it is associated with content trust for running containers as well. |
f0467f7 to
0726fea
Compare
|
@aaronlehmann: updated this PR. Added a field called I also updated |
0726fea to
1160815
Compare
api/types/client.go
Outdated
There was a problem hiding this comment.
Let's name this something like QueryRegistry, since I guess it will be extended to things other than pinning by digest in the future (platform info...).
I think we should support the same flag for ServiceCreate, so that digest pinning is not mandatory for all client users.
Let's not mention the --image flag (except possibly as an example), because the client is independent of the Docker CLI.
client/service_create.go
Outdated
There was a problem hiding this comment.
We must not overwrite the Image field here if it already contains a digest (for example, if digest pinning was already done through content trust).
client/service_update.go
Outdated
There was a problem hiding this comment.
We must not overwrite the Image field here if it already contains a digest (for example, if digest pinning was already done through content trust).
286eb0e to
514baad
Compare
|
@aaronlehmann: addressed your comments. |
client/service_create.go
Outdated
There was a problem hiding this comment.
This doesn't seem right. We should be replacing the Image field if the image reference doesn't have a digest, not if it doesn't parse.
There was a problem hiding this comment.
The reasoning for this was to not update the image if it parses to a legitimate canonical reference AND a manifest is retrieved. Is that not what this is doing? I wanted to reuse something from the distribution/reference package. Do you recommend something else?
There was a problem hiding this comment.
Where does it check that the reference is canonical?
There was a problem hiding this comment.
func ParseNamed(s string) (Named, error) {
named, err := ParseNormalizedNamed(s)
if err != nil {
return nil, err
}
if named.String() != s {
return nil, ErrNameNotCanonical
}
return named, nil
}
This check I believed was doing that, but perhaps I'm getting it wrong.
f named.String() != s {
return nil, ErrNameNotCanonical
}
Adding a type check for reference.Canonical should fix that?
There was a problem hiding this comment.
That "canonical" is something else :(
Adding a type check for
reference.Canonicalshould fix that?
Yes
There was a problem hiding this comment.
Ah okay, let me add that. I wasn't going by the word "canonical" as much as the string check, but it's embarrassing now because that doesn't make any sense. Fixing it now.
514baad to
39a9b94
Compare
|
Since @dnephin mentioned that this my conflict with my PR (/pull/27455), @nishanttotla can you clarify whether the imageManifest func you're adding pulls from the registry or expects the image to be pre-pulled? |
client/service_create.go
Outdated
There was a problem hiding this comment.
Can be var distErr error (but it doesn't matter).
daemon/cluster/services.go
Outdated
There was a problem hiding this comment.
Is there a good reason to continue supporting DOCKER_SERVICE_PREFER_OFFLINE_IMAGE? This was for the integration tests, but if the integration tests use the latest API version, they shouldn't hit this code path anyway.
That said, it may take some work to get things right with the integration tests after removing this. It may be best to remove it in a followup. Speaking of which, how will we prevent CLI-oriented integration tests from trying to resolve digests for local images on Docker Hub? Should we add a CLI option to prevent digest pinning?
There was a problem hiding this comment.
This seems correct, we shouldn't have to keep DOCKER_SERVICE_PREFER_OFFLINE_IMAGE, but it does absolutely no harm right now, and isn't user facing, so we should just wait on removing it. I'll add a comment indicating this.
If the CLI-oriented tests will purely run CLI commands, then we will have to add a flag, there is no other way. Given that we know of scenarios where disabling is required, we should add the flag.
|
Mostly LGTM, but a little concerned that moving digest pinning to the client side will break the |
b2368aa to
6a43422
Compare
|
@aluzzardi what do you think about adding a flag? It shouldn't be hard to do, given that this PR already has an API-level option to disable the registry lookup. |
|
@nishanttotla @aaronlehmann A flag sounds great, I think it was one of the goals of moving resolution client side. May I suggest |
|
@aluzzardi @aaronlehmann I'll open a follow-up PR for that, since most changes will be in |
|
That sounds okay. Hopefully the circular dependency between |
|
I'll add the flag to the same PR (docker/cli#30) that enables the |
Signed-off-by: Nishant Totla <[email protected]>
Signed-off-by: Nishant Totla <[email protected]>
6a43422 to
c0afd9c
Compare
|
LGTM |
| // image name that could not be pinned by digest. The formatting | ||
| // is hardcoded, but could me made smarter in the future | ||
| func digestWarning(image string) string { | ||
| return fmt.Sprintf("image %s could not be accessed on a registry to record\nits digest. Each node will access %s independently,\npossibly leading to different nodes running different\nversions of the image.\n", image, image) |
There was a problem hiding this comment.
the \n in the middle like that is kinda unusual
There was a problem hiding this comment.
@tiborvass this is to add line breaks, since the text is big. This is how it is also in the daemon right now.
| // contacting a registry. A registry may be contacted to retrieve | ||
| // the image digest and manifest, which in turn can be used to update | ||
| // platform or other information about the service. | ||
| QueryRegistry bool |
There was a problem hiding this comment.
@nishanttotla I'm wondering if the default shouldn't be the current behavior. SkipRegistryQuery ?
There was a problem hiding this comment.
@tiborvass the corresponding CLI PR is docker/cli#30.
The idea is that QueryRegistry should be set on all service create commands unless the user explicitly provides a flag to prevent it, and for all service update commands that update the image, using the --image flag (also unless the user explicitly asks to not do it with the flag).
There was a problem hiding this comment.
@tiborvass: The current behavior is that the client does not perform this query.
There was a problem hiding this comment.
@aaronlehmann my bad i thought this was server side.
|
LGTM |
|
Adding link back to #31348 |
This PR is an alternative proposal to #32384, based on discussions with @aluzzardi @dhiltgen @alexmavr.
The heavy lifting in this case happens in the
clientpackage, which is easier to use for third-party clients, and they get the benefit of client-side digest pinning without having to do it themselves.cc @aaronlehmann
- What I did
Digest pinning was introduced for Docker services in #28173, and it was performed on the daemon. After #32061, I moved digest pinning to the client, simplifying it.
- How I did it
The client makes a call to
/images/image_name/manifestto retrieve manifest information, which contains the image digest.- How to verify it
docker service create --name test alpine sleep 1000thendocker service inspect testshould contain an image with the digest.- Description for the changelog
Docker service image pin by digest moved to client side.
- WIP
- A picture of a cute animal (not mandatory but encouraged)

This is Gosha, the friendliest cat in Berkeley.