We remap the snapshot when we create a container, we have to to the
inverse when we commit the container into an image
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
| ... | ... |
@@ -16,6 +16,7 @@ import ( |
| 16 | 16 |
cerrdefs "github.com/containerd/containerd/errdefs" |
| 17 | 17 |
"github.com/containerd/containerd/images" |
| 18 | 18 |
"github.com/containerd/containerd/leases" |
| 19 |
+ "github.com/containerd/containerd/mount" |
|
| 19 | 20 |
"github.com/containerd/containerd/rootfs" |
| 20 | 21 |
"github.com/containerd/containerd/snapshots" |
| 21 | 22 |
"github.com/containerd/log" |
| ... | ... |
@@ -90,7 +91,7 @@ func (i *ImageService) CommitImage(ctx context.Context, cc backend.CommitConfig) |
| 90 | 90 |
if diffLayerDesc != nil {
|
| 91 | 91 |
rootfsID := identity.ChainID(imageConfig.RootFS.DiffIDs).String() |
| 92 | 92 |
|
| 93 |
- if err := applyDiffLayer(ctx, rootfsID, parentImage, sn, differ, *diffLayerDesc); err != nil {
|
|
| 93 |
+ if err := i.applyDiffLayer(ctx, rootfsID, cc.ContainerID, sn, differ, *diffLayerDesc); err != nil {
|
|
| 94 | 94 |
return "", fmt.Errorf("failed to apply diff: %w", err)
|
| 95 | 95 |
} |
| 96 | 96 |
|
| ... | ... |
@@ -291,13 +292,19 @@ func createDiff(ctx context.Context, name string, sn snapshots.Snapshotter, cs c |
| 291 | 291 |
} |
| 292 | 292 |
|
| 293 | 293 |
// applyDiffLayer will apply diff layer content created by createDiff into the snapshotter. |
| 294 |
-func applyDiffLayer(ctx context.Context, name string, baseImg imagespec.DockerOCIImage, sn snapshots.Snapshotter, differ diff.Applier, diffDesc ocispec.Descriptor) (retErr error) {
|
|
| 294 |
+func (i *ImageService) applyDiffLayer(ctx context.Context, name string, containerID string, sn snapshots.Snapshotter, differ diff.Applier, diffDesc ocispec.Descriptor) (retErr error) {
|
|
| 295 | 295 |
var ( |
| 296 | 296 |
key = uniquePart() + "-" + name |
| 297 |
- parent = identity.ChainID(baseImg.RootFS.DiffIDs).String() |
|
| 297 |
+ mounts []mount.Mount |
|
| 298 |
+ err error |
|
| 298 | 299 |
) |
| 299 | 300 |
|
| 300 |
- mount, err := sn.Prepare(ctx, key, parent) |
|
| 301 |
+ info, err := sn.Stat(ctx, containerID) |
|
| 302 |
+ if err != nil {
|
|
| 303 |
+ return err |
|
| 304 |
+ } |
|
| 305 |
+ |
|
| 306 |
+ mounts, err = sn.Prepare(ctx, key, info.Parent) |
|
| 301 | 307 |
if err != nil {
|
| 302 | 308 |
return fmt.Errorf("failed to prepare snapshot: %w", err)
|
| 303 | 309 |
} |
| ... | ... |
@@ -312,16 +319,46 @@ func applyDiffLayer(ctx context.Context, name string, baseImg imagespec.DockerOC |
| 312 | 312 |
} |
| 313 | 313 |
}() |
| 314 | 314 |
|
| 315 |
- if _, err = differ.Apply(ctx, diffDesc, mount); err != nil {
|
|
| 315 |
+ if _, err = differ.Apply(ctx, diffDesc, mounts); err != nil {
|
|
| 316 | 316 |
return err |
| 317 | 317 |
} |
| 318 | 318 |
|
| 319 |
+ if !i.idMapping.Empty() {
|
|
| 320 |
+ // The rootfs of the container is remapped if an id mapping exists, we |
|
| 321 |
+ // need to "unremap" it before committing the snapshot |
|
| 322 |
+ rootPair := i.idMapping.RootPair() |
|
| 323 |
+ usernsID := fmt.Sprintf("%s-%d-%d", key, rootPair.UID, rootPair.GID)
|
|
| 324 |
+ remappedID := usernsID + remapSuffix |
|
| 325 |
+ |
|
| 326 |
+ if err = sn.Commit(ctx, name+"-pre", key); err != nil {
|
|
| 327 |
+ if cerrdefs.IsAlreadyExists(err) {
|
|
| 328 |
+ return nil |
|
| 329 |
+ } |
|
| 330 |
+ return err |
|
| 331 |
+ } |
|
| 332 |
+ |
|
| 333 |
+ mounts, err = sn.Prepare(ctx, remappedID, name+"-pre") |
|
| 334 |
+ if err != nil {
|
|
| 335 |
+ return err |
|
| 336 |
+ } |
|
| 337 |
+ |
|
| 338 |
+ if err := i.unremapRootFS(ctx, mounts); err != nil {
|
|
| 339 |
+ return err |
|
| 340 |
+ } |
|
| 341 |
+ |
|
| 342 |
+ if err := sn.Commit(ctx, name, remappedID); err != nil {
|
|
| 343 |
+ return err |
|
| 344 |
+ } |
|
| 345 |
+ key = remappedID |
|
| 346 |
+ } |
|
| 347 |
+ |
|
| 319 | 348 |
if err = sn.Commit(ctx, name, key); err != nil {
|
| 320 | 349 |
if cerrdefs.IsAlreadyExists(err) {
|
| 321 | 350 |
return nil |
| 322 | 351 |
} |
| 323 | 352 |
return err |
| 324 | 353 |
} |
| 354 |
+ |
|
| 325 | 355 |
return nil |
| 326 | 356 |
} |
| 327 | 357 |
|
| ... | ... |
@@ -67,3 +67,25 @@ func (i *ImageService) remapRootFS(ctx context.Context, mounts []mount.Mount) er |
| 67 | 67 |
}) |
| 68 | 68 |
}) |
| 69 | 69 |
} |
| 70 |
+ |
|
| 71 |
+func (i *ImageService) unremapRootFS(ctx context.Context, mounts []mount.Mount) error {
|
|
| 72 |
+ return mount.WithTempMount(ctx, mounts, func(root string) error {
|
|
| 73 |
+ return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
|
| 74 |
+ if err != nil {
|
|
| 75 |
+ return err |
|
| 76 |
+ } |
|
| 77 |
+ |
|
| 78 |
+ stat := info.Sys().(*syscall.Stat_t) |
|
| 79 |
+ if stat == nil {
|
|
| 80 |
+ return fmt.Errorf("cannot get underlying data for %s", path)
|
|
| 81 |
+ } |
|
| 82 |
+ |
|
| 83 |
+ uid, gid, err := i.idMapping.ToContainer(idtools.Identity{UID: int(stat.Uid), GID: int(stat.Gid)})
|
|
| 84 |
+ if err != nil {
|
|
| 85 |
+ return err |
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ return os.Lchown(path, uid, gid) |
|
| 89 |
+ }) |
|
| 90 |
+ }) |
|
| 91 |
+} |
| ... | ... |
@@ -3,9 +3,14 @@ package containerd |
| 3 | 3 |
import ( |
| 4 | 4 |
"context" |
| 5 | 5 |
|
| 6 |
+ "github.com/containerd/containerd/mount" |
|
| 6 | 7 |
"github.com/containerd/containerd/snapshots" |
| 7 | 8 |
) |
| 8 | 9 |
|
| 9 | 10 |
func (i *ImageService) remapSnapshot(ctx context.Context, snapshotter snapshots.Snapshotter, id string, parentSnapshot string) error {
|
| 10 | 11 |
return nil |
| 11 | 12 |
} |
| 13 |
+ |
|
| 14 |
+func (i *ImageService) unremapRootFS(ctx context.Context, mounts []mount.Mount) error {
|
|
| 15 |
+ return nil |
|
| 16 |
+} |