... | ... |
@@ -665,9 +665,11 @@ func (container *Container) Start(hostConfig *HostConfig) error { |
665 | 665 |
continue |
666 | 666 |
} |
667 | 667 |
var srcPath string |
668 |
+ var isBindMount bool |
|
668 | 669 |
srcRW := false |
669 | 670 |
// If an external bind is defined for this volume, use that as a source |
670 | 671 |
if bindMap, exists := binds[volPath]; exists { |
672 |
+ isBindMount = true |
|
671 | 673 |
srcPath = bindMap.SrcPath |
672 | 674 |
if strings.ToLower(bindMap.Mode) == "rw" { |
673 | 675 |
srcRW = true |
... | ... |
@@ -691,7 +693,9 @@ func (container *Container) Start(hostConfig *HostConfig) error { |
691 | 691 |
if err := os.MkdirAll(rootVolPath, 0755); err != nil { |
692 | 692 |
return nil |
693 | 693 |
} |
694 |
- if srcRW { |
|
694 |
+ |
|
695 |
+ // Do not copy or change permissions if we are mounting from the host |
|
696 |
+ if srcRW && !isBindMount { |
|
695 | 697 |
volList, err := ioutil.ReadDir(rootVolPath) |
696 | 698 |
if err != nil { |
697 | 699 |
return err |
... | ... |
@@ -702,22 +706,26 @@ func (container *Container) Start(hostConfig *HostConfig) error { |
702 | 702 |
return err |
703 | 703 |
} |
704 | 704 |
if len(srcList) == 0 { |
705 |
+ // If the source volume is empty copy files from the root into the volume |
|
705 | 706 |
if err := CopyWithTar(rootVolPath, srcPath); err != nil { |
706 | 707 |
return err |
707 | 708 |
} |
708 |
- } |
|
709 |
- } |
|
710 |
- var stat syscall.Stat_t |
|
711 |
- if err := syscall.Stat(rootVolPath, &stat); err != nil { |
|
712 |
- return err |
|
713 |
- } |
|
714 |
- var srcStat syscall.Stat_t |
|
715 |
- if err := syscall.Stat(srcPath, &srcStat); err != nil { |
|
716 |
- return err |
|
717 |
- } |
|
718 |
- if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid { |
|
719 |
- if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil { |
|
720 |
- return err |
|
709 |
+ |
|
710 |
+ var stat syscall.Stat_t |
|
711 |
+ if err := syscall.Stat(rootVolPath, &stat); err != nil { |
|
712 |
+ return err |
|
713 |
+ } |
|
714 |
+ var srcStat syscall.Stat_t |
|
715 |
+ if err := syscall.Stat(srcPath, &srcStat); err != nil { |
|
716 |
+ return err |
|
717 |
+ } |
|
718 |
+ // Change the source volume's ownership if it differs from the root |
|
719 |
+ // files that where just copied |
|
720 |
+ if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid { |
|
721 |
+ if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil { |
|
722 |
+ return err |
|
723 |
+ } |
|
724 |
+ } |
|
721 | 725 |
} |
722 | 726 |
} |
723 | 727 |
} |
... | ... |
@@ -1202,7 +1202,7 @@ func TestCopyVolumeUidGid(t *testing.T) { |
1202 | 1202 |
defer nuke(r) |
1203 | 1203 |
|
1204 | 1204 |
// Add directory not owned by root |
1205 |
- container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello && chown daemon.daemon /hello"}, t) |
|
1205 |
+ container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello && touch /hello/test.txt && chown daemon.daemon /hello"}, t) |
|
1206 | 1206 |
defer r.Destroy(container1) |
1207 | 1207 |
|
1208 | 1208 |
if container1.State.Running { |
... | ... |
@@ -1227,18 +1227,10 @@ func TestCopyVolumeUidGid(t *testing.T) { |
1227 | 1227 |
// Test that the uid and gid is copied from the image to the volume |
1228 | 1228 |
tmpDir1 := tempDir(t) |
1229 | 1229 |
defer os.RemoveAll(tmpDir1) |
1230 |
- stdout1, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello", tmpDir1), img.ID, "stat", "-c", "%U %G", "/hello"}, t) |
|
1230 |
+ stdout1, _ := runContainer(r, []string{"-v", "/hello", img.ID, "stat", "-c", "%U %G", "/hello"}, t) |
|
1231 | 1231 |
if !strings.Contains(stdout1, "daemon daemon") { |
1232 | 1232 |
t.Fatal("Container failed to transfer uid and gid to volume") |
1233 | 1233 |
} |
1234 |
- |
|
1235 |
- // Test that the uid and gid is not copied from the image when the volume is read only |
|
1236 |
- tmpDir2 := tempDir(t) |
|
1237 |
- defer os.RemoveAll(tmpDir1) |
|
1238 |
- stdout2, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:ro", tmpDir2), img.ID, "stat", "-c", "%U %G", "/hello"}, t) |
|
1239 |
- if strings.Contains(stdout2, "daemon daemon") { |
|
1240 |
- t.Fatal("Container transfered uid and gid to volume") |
|
1241 |
- } |
|
1242 | 1234 |
} |
1243 | 1235 |
|
1244 | 1236 |
// Test for #1582 |
... | ... |
@@ -1272,27 +1264,10 @@ func TestCopyVolumeContent(t *testing.T) { |
1272 | 1272 |
// Test that the content is copied from the image to the volume |
1273 | 1273 |
tmpDir1 := tempDir(t) |
1274 | 1274 |
defer os.RemoveAll(tmpDir1) |
1275 |
- stdout1, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello", tmpDir1), img.ID, "find", "/hello"}, t) |
|
1275 |
+ stdout1, _ := runContainer(r, []string{"-v", "/hello", img.ID, "find", "/hello"}, t) |
|
1276 | 1276 |
if !(strings.Contains(stdout1, "/hello/local/world") && strings.Contains(stdout1, "/hello/local")) { |
1277 | 1277 |
t.Fatal("Container failed to transfer content to volume") |
1278 | 1278 |
} |
1279 |
- |
|
1280 |
- // Test that the content is not copied when the volume is readonly |
|
1281 |
- tmpDir2 := tempDir(t) |
|
1282 |
- defer os.RemoveAll(tmpDir2) |
|
1283 |
- stdout2, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:ro", tmpDir2), img.ID, "find", "/hello"}, t) |
|
1284 |
- if strings.Contains(stdout2, "/hello/local/world") || strings.Contains(stdout2, "/hello/local") { |
|
1285 |
- t.Fatal("Container transfered content to readonly volume") |
|
1286 |
- } |
|
1287 |
- |
|
1288 |
- // Test that the content is not copied when the volume is non-empty |
|
1289 |
- tmpDir3 := tempDir(t) |
|
1290 |
- defer os.RemoveAll(tmpDir3) |
|
1291 |
- writeFile(path.Join(tmpDir3, "touch-me"), "", t) |
|
1292 |
- stdout3, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:rw", tmpDir3), img.ID, "find", "/hello"}, t) |
|
1293 |
- if strings.Contains(stdout3, "/hello/local/world") || strings.Contains(stdout3, "/hello/local") || !strings.Contains(stdout3, "/hello/touch-me") { |
|
1294 |
- t.Fatal("Container transfered content to non-empty volume") |
|
1295 |
- } |
|
1296 | 1279 |
} |
1297 | 1280 |
|
1298 | 1281 |
func TestBindMounts(t *testing.T) { |