LCOW: Support for docker cp, ADD/COPY on build#34252
Conversation
a8c0d2e to
010670b
Compare
|
Example of docker cp working: |
|
@stevvooe PTAL as well. Right now, everything is complete aside from the lcow/remotefs implementation, which mostly works, but has some reliability issues. This PR can be split into multiple PRs (one for interface changes, one for LCOW changse, one for remotefs implementation) so if that is easier to do, I can do that as well. You would need everything to have it work, but it would probably be easier to review. |
builder/dockerfile/internals.go
Outdated
| return false | ||
| } | ||
|
|
||
| func validateCopySourcePath(imageSource *imageMount, origPath, platform string) error { |
There was a problem hiding this comment.
Please move these two helpers to below the single function where they are called.
builder/dockerfile/internals.go
Outdated
|
|
||
| func validateCopySourcePath(imageSource *imageMount, origPath, platform string) error { | ||
| // validate windows paths from other images | ||
| if imageSource == nil || platform != "windows" { |
There was a problem hiding this comment.
A type and constant for platform and "windows" would be nice
There was a problem hiding this comment.
There's quite a few platform string that was already here. I think it's from @jhowardmsft's first LCOW PR. He's working on a platform API for the builder, so do you want the change now or in his PR? @jhowardmsft: Thoughts?
There was a problem hiding this comment.
I'm not sure this makes sense at this point*. There's dozens of places outside of LCOW where platform strings are used directly without a constant. It's been a long-standing pattern like this.
E:\go\src\github.com\docker\docker [jjh/buildplatformapi]> (git grep '\"windows\"' *.go | Measure-Object).Count
262
* Sure, no objection to doing this a little further down the road, across the entire code base (ideally at a point where the fast-arriving LCOW PRs aren't going to merge conflict).
builder/dockerfile/copy.go
Outdated
| // Work in daemon-specific filepath semantics | ||
| inst.dest = filepath.FromSlash(args[last]) | ||
| separator = string(os.PathSeparator) | ||
| } |
There was a problem hiding this comment.
For the most part the path details seem to be well abstracted, but they leak out in this function.
Instead of this maybe we could have a system.HasDirectorySuffix() and system.FromSlash() or something like that?
system is already a large package, so maybe that's not the right place for it.
There was a problem hiding this comment.
I added a platform tag to the copier struct. The platform was already in the dispathRequest.builder, so I just had to extract that into thecopierFromDistpatchRequest. I added a system.FromSlash() and system.Separator() to check the directory suffix.
If the copy instruction dest doesn't need the daemon/platform specific paths here, we could also just do a check like if len(infos) > 1 && !strings.HasSuffix(filepath.ToSlash(inst.dest), "/")
a9edf9a to
8340720
Compare
|
Couple of updates.
|
3654690 to
c4f3fef
Compare
|
Now that #34170 is merged. I rebased to just my commit and the vendor. |
c4f3fef to
39f436d
Compare
daemon/graphdriver/lcow/lcow_svm.go
Outdated
There was a problem hiding this comment.
This should switch over to github.com/Microsoft/opengcs/client now.
daemon/graphdriver/lcow/lcow.go
Outdated
There was a problem hiding this comment.
This is problematic. I hit a nil pointer de-reference panic due to this change at L411. Previously, the code had an explicit nil check here. Repro was docker cp IDOfStoppedContainer:/bin/sh .
There was a problem hiding this comment.
I can't repro it, but the logic in startServiceVMIfNotRunning needs some tweaking. See here:
defer func() {
// Signal that start has finished, passing in the error if any.
svm.signalStartFinished(err)
if err == nil {
return
}
// We added a ref to the VM, since we failed, we should delete the ref.
d.terminateServiceVM(id, "error path on startServiceVMIfNotRunning", false)
}()
/* Some functions that can fail. */
// Start it.
logrus.Debugf("lcowdriver: startServiceVmIfNotRunning: (%s) starting %s", context, svm.config.Name)
if err := svm.config.StartUtilityVM(); err != nil {
return nil, fmt.Errorf("failed to start service utility VM (%s): %s", context, err)
}Bascially, if any function fails before the svm.config.StartUtilityVM() part, then svm.config.Uvm will be nil, triggering a panic, so I need to guard L411 with some check.
daemon/graphdriver/lcow/lcow.go
Outdated
|
@stevvooe PTAL + add whoever else should take a look |
daemon/graphdriver/lcow/lcow_svm.go
Outdated
There was a problem hiding this comment.
Has this comment been moved to the correct place? It used to be in the driver struct for the cache.
001deb3 to
b4b4a8a
Compare
johnstep
left a comment
There was a problem hiding this comment.
I only skimmed the rest of the PR, but the LCOW graph driver changes look good!
daemon/graphdriver/lcow/lcow.go
Outdated
There was a problem hiding this comment.
Nit: Why is syscall separate from the previous set of imports?
There was a problem hiding this comment.
just seems like a typo
daemon/graphdriver/lcow/remotefs.go
Outdated
daemon/graphdriver/lcow/remotefs.go
Outdated
There was a problem hiding this comment.
You could move this after locking on line 103, and remove the Unlock on 105.
daemon/graphdriver/lcow/lcow.go
Outdated
There was a problem hiding this comment.
Note: Seems a little odd to recurse here, but it's not a problem.
daemon/graphdriver/lcow/lcow_svm.go
Outdated
There was a problem hiding this comment.
Shouldn't this function remove the mount if this is the last reference?
There was a problem hiding this comment.
good catch! should be > 1
daemon/graphdriver/lcow/lcow_svm.go
Outdated
There was a problem hiding this comment.
Nit: Why is io separate from the previous set of imports?
|
I just got aware of this, and it's too big for me to have a proper look in a decent timeframe, but it does look like overkill. I think something is wrong if we have to re-implement the POSIX interface within moby. This would be better served by an actual filesystem driver. Any reason not to go that way? It would also allow Microsoft to change its behavior in sync with their shim without requiring changes within Docker. |
a488760 to
4e9acdf
Compare
|
rebased + updated with @johnstep 's feedback |
Signed-off-by: Akash Gupta <akagup@microsoft.com>
This enables docker cp and ADD/COPY docker build support for LCOW. Originally, the graphdriver.Get() interface returned a local path to the container root filesystem. This does not work for LCOW, so the Get() method now returns an interface that LCOW implements to support copying to and from the container. Signed-off-by: Akash Gupta <akagup@microsoft.com>
4e9acdf to
7a7357d
Compare
might not be the cleanest way, but it's definitly the way with the minimum code change. Signed-off-by: Victor Vieux <victorvieux@gmail.com>
119cbf3 to
ff68674
Compare
johnstep
left a comment
There was a problem hiding this comment.
LGTM (based on code, will test soon)
|
Graphdriver changes LGTM |
|
from #34252 (comment)
@dmcgowan @mlaventure is this one ready to go? |
|
LGTM |
- What I did
Added support for LCOW container file operations like
docker cpandADD/COPYfordocker build- How I did it
Get()returned a(string, error). I changed it to return a new interfaceRootFSdefined inpkg/rootfs/rootfs.go. It has theDriverandPathDriverinterface fromcontinuity, which abstracts the file operations from theospackage behind the interface. TheRootFSinterface also has container specific methods, such as resolving scoped paths.RootFSinterface for non-LCOW and LCOW cases. In the non-LCOW cases, it's just a wrapper around theospackage, but for LCOW, docker sends the file operations to a Linux Service VM that handles it.- How to verify it
For regressions due to the interface break, I'm hoping the CI will catch them. For LCOW, I'm running @jhowardmsft 's LCOW testing script and also manually verifying that
docker cpanddocker buildworks.- Description for the changelog
Support for docker cp and ADD/COPY in docker build
- A picture of a cute animal (not mandatory but encouraged)