Skip to content

Commit 2d64ab8

Browse files
committed
cri: Don't use rel path for image volumes
Runc 1.1 throws a warning when using rel destination paths, and runc 1.2 is planning to thow an error (i.e. won't start the container). Let's just make this an abs path in the only place it might not be: the mounts created due to `VOLUME` directives in the Dockerfile. Signed-off-by: Rodrigo Campos <[email protected]>
1 parent 81895d2 commit 2d64ab8

4 files changed

Lines changed: 43 additions & 9 deletions

File tree

integration/volume_copy_up_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func TestVolumeCopyUp(t *testing.T) {
9393
},
9494
},
9595
{
96-
containerPath: "C:/weird_test_dir",
96+
containerPath: "/C:/weird_test_dir",
9797
files: []volumeFile{
9898
{
9999
fileName: "weird_test_file",

pkg/cri/sbserver/container_create.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"path/filepath"
2424
"strconv"
25+
"strings"
2526
"time"
2627

2728
"github.com/containerd/typeurl/v2"
@@ -148,10 +149,15 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
148149
}
149150
}()
150151

152+
platform, err := controller.Platform(ctx, sandboxID)
153+
if err != nil {
154+
return nil, fmt.Errorf("failed to query sandbox platform: %w", err)
155+
}
156+
151157
var volumeMounts []*runtime.Mount
152158
if !c.config.IgnoreImageDefinedVolumes {
153159
// Create container image volumes mounts.
154-
volumeMounts = c.volumeMounts(containerRootDir, config.GetMounts(), &image.ImageSpec.Config)
160+
volumeMounts = c.volumeMounts(platform, containerRootDir, config.GetMounts(), &image.ImageSpec.Config)
155161
} else if len(image.ImageSpec.Config.Volumes) != 0 {
156162
log.G(ctx).Debugf("Ignoring volumes defined in image %v because IgnoreImageDefinedVolumes is set", image.ID)
157163
}
@@ -162,11 +168,6 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
162168
}
163169
log.G(ctx).Debugf("Use OCI runtime %+v for sandbox %q and container %q", ociRuntime, sandboxID, id)
164170

165-
platform, err := controller.Platform(ctx, sandboxID)
166-
if err != nil {
167-
return nil, fmt.Errorf("failed to query sandbox platform: %w", err)
168-
}
169-
170171
spec, err := c.buildContainerSpec(
171172
platform,
172173
id,
@@ -340,7 +341,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
340341
// volumeMounts sets up image volumes for container. Rely on the removal of container
341342
// root directory to do cleanup. Note that image volume will be skipped, if there is criMounts
342343
// specified with the same destination.
343-
func (c *criService) volumeMounts(containerRootDir string, criMounts []*runtime.Mount, config *imagespec.ImageConfig) []*runtime.Mount {
344+
func (c *criService) volumeMounts(platform platforms.Platform, containerRootDir string, criMounts []*runtime.Mount, config *imagespec.ImageConfig) []*runtime.Mount {
344345
if len(config.Volumes) == 0 {
345346
return nil
346347
}
@@ -355,6 +356,16 @@ func (c *criService) volumeMounts(containerRootDir string, criMounts []*runtime.
355356
}
356357
volumeID := util.GenerateID()
357358
src := filepath.Join(containerRootDir, "volumes", volumeID)
359+
// When the platform OS is Linux, ensure dst is a _Linux_ abs path.
360+
// We can't use filepath.IsAbs() because, when executing on Windows, it checks for
361+
// Windows abs paths.
362+
if platform.OS == "linux" && !strings.HasPrefix(dst, "/") {
363+
// On Windows, ToSlash() is needed to ensure the path is a valid Linux path.
364+
// On Linux, ToSlash() is a no-op.
365+
oldDst := dst
366+
dst = filepath.ToSlash(filepath.Join("/", dst))
367+
log.L.Debugf("Volume destination %q is not absolute, converted to %q", oldDst, dst)
368+
}
358369
// addOCIBindMounts will create these volumes.
359370
mounts = append(mounts, &runtime.Mount{
360371
ContainerPath: dst,

pkg/cri/sbserver/container_create_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ func TestVolumeMounts(t *testing.T) {
233233
testContainerRootDir := "test-container-root"
234234
for _, test := range []struct {
235235
desc string
236+
platform platforms.Platform
236237
criMounts []*runtime.Mount
237238
imageVolumes map[string]struct{}
238239
expectedMountDest []string
@@ -280,14 +281,30 @@ func TestVolumeMounts(t *testing.T) {
280281
"/test-volume-2/",
281282
},
282283
},
284+
{
285+
desc: "should make relative paths absolute on Linux",
286+
platform: platforms.Platform{OS: "linux"},
287+
imageVolumes: map[string]struct{}{
288+
"./test-volume-1": {},
289+
"C:/test-volume-2": {},
290+
"../../test-volume-3": {},
291+
"/abs/test-volume-4": {},
292+
},
293+
expectedMountDest: []string{
294+
"/test-volume-1",
295+
"/C:/test-volume-2",
296+
"/test-volume-3",
297+
"/abs/test-volume-4",
298+
},
299+
},
283300
} {
284301
test := test
285302
t.Run(test.desc, func(t *testing.T) {
286303
config := &imagespec.ImageConfig{
287304
Volumes: test.imageVolumes,
288305
}
289306
c := newTestCRIService()
290-
got := c.volumeMounts(testContainerRootDir, test.criMounts, config)
307+
got := c.volumeMounts(test.platform, testContainerRootDir, test.criMounts, config)
291308
assert.Len(t, got, len(test.expectedMountDest))
292309
for _, dest := range test.expectedMountDest {
293310
found := false

pkg/cri/server/container_create.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"errors"
2222
"fmt"
2323
"path/filepath"
24+
goruntime "runtime"
2425
"time"
2526

2627
"github.com/containerd/typeurl/v2"
@@ -332,6 +333,11 @@ func (c *criService) volumeMounts(containerRootDir string, criMounts []*runtime.
332333
}
333334
volumeID := util.GenerateID()
334335
src := filepath.Join(containerRootDir, "volumes", volumeID)
336+
if !filepath.IsAbs(dst) && goruntime.GOOS != "windows" {
337+
oldDst := dst
338+
dst = filepath.Join("/", dst)
339+
log.L.Debugf("Volume destination %q is not absolute, converted to %q", oldDst, dst)
340+
}
335341
// addOCIBindMounts will create these volumes.
336342
mounts = append(mounts, &runtime.Mount{
337343
ContainerPath: dst,

0 commit comments

Comments
 (0)