fixes #2671, add support for bind mounting individual files in to contai...
| ... | ... |
@@ -624,6 +624,7 @@ func (container *Container) Start() (err error) {
|
| 624 | 624 |
// Create the requested volumes if they don't exist |
| 625 | 625 |
for volPath := range container.Config.Volumes {
|
| 626 | 626 |
volPath = path.Clean(volPath) |
| 627 |
+ volIsDir := true |
|
| 627 | 628 |
// Skip existing volumes |
| 628 | 629 |
if _, exists := container.Volumes[volPath]; exists {
|
| 629 | 630 |
continue |
| ... | ... |
@@ -638,6 +639,16 @@ func (container *Container) Start() (err error) {
|
| 638 | 638 |
if strings.ToLower(bindMap.Mode) == "rw" {
|
| 639 | 639 |
srcRW = true |
| 640 | 640 |
} |
| 641 |
+ if file, err := os.Open(bindMap.SrcPath); err != nil {
|
|
| 642 |
+ return err |
|
| 643 |
+ } else {
|
|
| 644 |
+ defer file.Close() |
|
| 645 |
+ if stat, err := file.Stat(); err != nil {
|
|
| 646 |
+ return err |
|
| 647 |
+ } else {
|
|
| 648 |
+ volIsDir = stat.IsDir() |
|
| 649 |
+ } |
|
| 650 |
+ } |
|
| 641 | 651 |
// Otherwise create an directory in $ROOT/volumes/ and use that |
| 642 | 652 |
} else {
|
| 643 | 653 |
|
| ... | ... |
@@ -658,8 +669,30 @@ func (container *Container) Start() (err error) {
|
| 658 | 658 |
container.VolumesRW[volPath] = srcRW |
| 659 | 659 |
// Create the mountpoint |
| 660 | 660 |
rootVolPath := path.Join(container.RootfsPath(), volPath) |
| 661 |
- if err := os.MkdirAll(rootVolPath, 0755); err != nil {
|
|
| 662 |
- return err |
|
| 661 |
+ if volIsDir {
|
|
| 662 |
+ if err := os.MkdirAll(rootVolPath, 0755); err != nil {
|
|
| 663 |
+ return err |
|
| 664 |
+ } |
|
| 665 |
+ } |
|
| 666 |
+ |
|
| 667 |
+ volPath = path.Join(container.RootfsPath(), volPath) |
|
| 668 |
+ if _, err := os.Stat(volPath); err != nil {
|
|
| 669 |
+ if os.IsNotExist(err) {
|
|
| 670 |
+ if volIsDir {
|
|
| 671 |
+ if err := os.MkdirAll(volPath, 0755); err != nil {
|
|
| 672 |
+ return err |
|
| 673 |
+ } |
|
| 674 |
+ } else {
|
|
| 675 |
+ if err := os.MkdirAll(path.Dir(volPath), 0755); err != nil {
|
|
| 676 |
+ return err |
|
| 677 |
+ } |
|
| 678 |
+ if f, err := os.OpenFile(volPath, os.O_CREATE, 0755); err != nil {
|
|
| 679 |
+ return err |
|
| 680 |
+ } else {
|
|
| 681 |
+ f.Close() |
|
| 682 |
+ } |
|
| 683 |
+ } |
|
| 684 |
+ } |
|
| 663 | 685 |
} |
| 664 | 686 |
|
| 665 | 687 |
// Do not copy or change permissions if we are mounting from the host |
| ... | ... |
@@ -1257,6 +1257,13 @@ func TestBindMounts(t *testing.T) {
|
| 1257 | 1257 |
if _, err := runContainer(eng, r, []string{"-v", fmt.Sprintf("%s:.", tmpDir), "_", "ls", "."}, nil); err == nil {
|
| 1258 | 1258 |
t.Fatal("Container bind mounted illegal directory")
|
| 1259 | 1259 |
} |
| 1260 |
+ |
|
| 1261 |
+ // test mount a file |
|
| 1262 |
+ runContainer(eng, r, []string{"-v", fmt.Sprintf("%s/holla:/tmp/holla:rw", tmpDir), "_", "sh", "-c", "echo -n 'yotta' > /tmp/holla"}, t)
|
|
| 1263 |
+ content := readFile(path.Join(tmpDir, "holla"), t) // Will fail if the file doesn't exist |
|
| 1264 |
+ if content != "yotta" {
|
|
| 1265 |
+ t.Fatal("Container failed to write to bind mount file")
|
|
| 1266 |
+ } |
|
| 1260 | 1267 |
} |
| 1261 | 1268 |
|
| 1262 | 1269 |
// Test that -volumes-from supports both read-only mounts |