mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	CLI flag for docker create(run) to change block device size.
Signed-off-by: Shishir Mahajan <shishir.mahajan@redhat.com>
This commit is contained in:
		
							parent
							
								
									35986d4824
								
							
						
					
					
						commit
						b16decfccf
					
				
					 30 changed files with 228 additions and 72 deletions
				
			
		| 
						 | 
					@ -137,7 +137,7 @@ func main() {
 | 
				
			||||||
			usage()
 | 
								usage()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err := devices.AddDevice(args[1], args[2])
 | 
							err := devices.AddDevice(args[1], args[2], nil)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			fmt.Println("Can't create snap device: ", err)
 | 
								fmt.Println("Can't create snap device: ", err)
 | 
				
			||||||
			os.Exit(1)
 | 
								os.Exit(1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,6 +84,8 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig) (retC *containe
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						container.HostConfig.StorageOpt = params.HostConfig.StorageOpt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set RWLayer for container after mount labels have been set
 | 
						// Set RWLayer for container after mount labels have been set
 | 
				
			||||||
	if err := daemon.setRWLayer(container); err != nil {
 | 
						if err := daemon.setRWLayer(container); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -156,7 +158,7 @@ func (daemon *Daemon) setRWLayer(container *container.Container) error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		layerID = img.RootFS.ChainID()
 | 
							layerID = img.RootFS.ChainID()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rwLayer, err := daemon.layerStore.CreateRWLayer(container.ID, layerID, container.MountLabel, daemon.setupInitLayer)
 | 
						rwLayer, err := daemon.layerStore.CreateRWLayer(container.ID, layerID, container.MountLabel, daemon.setupInitLayer, container.HostConfig.StorageOpt)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -195,7 +195,12 @@ func (a *Driver) Exists(id string) bool {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create three folders for each id
 | 
					// Create three folders for each id
 | 
				
			||||||
// mnt, layers, and diff
 | 
					// mnt, layers, and diff
 | 
				
			||||||
func (a *Driver) Create(id, parent, mountLabel string) error {
 | 
					func (a *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(storageOpt) != 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("--storage-opt is not supported for aufs")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := a.createDirsFor(id); err != nil {
 | 
						if err := a.createDirsFor(id); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,7 +101,7 @@ func TestCreateNewDir(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ func TestCreateNewDirStructure(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,7 +131,7 @@ func TestRemoveImage(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,7 +156,7 @@ func TestGetWithoutParent(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -183,7 +183,7 @@ func TestCleanupWithDir(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,7 +196,7 @@ func TestMountedFalseResponse(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,10 +215,10 @@ func TestMountedTrueReponse(t *testing.T) {
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
	defer d.Cleanup()
 | 
						defer d.Cleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := d.Create("2", "1", ""); err != nil {
 | 
						if err := d.Create("2", "1", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,10 +241,10 @@ func TestMountWithParent(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := d.Create("2", "1", ""); err != nil {
 | 
						if err := d.Create("2", "1", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -272,10 +272,10 @@ func TestRemoveMountedDir(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := d.Create("2", "1", ""); err != nil {
 | 
						if err := d.Create("2", "1", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -311,7 +311,7 @@ func TestCreateWithInvalidParent(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "docker", ""); err == nil {
 | 
						if err := d.Create("1", "docker", "", nil); err == nil {
 | 
				
			||||||
		t.Fatalf("Error should not be nil with parent does not exist")
 | 
							t.Fatalf("Error should not be nil with parent does not exist")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -320,7 +320,7 @@ func TestGetDiff(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -354,10 +354,10 @@ func TestChanges(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := d.Create("2", "1", ""); err != nil {
 | 
						if err := d.Create("2", "1", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -403,7 +403,7 @@ func TestChanges(t *testing.T) {
 | 
				
			||||||
		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
 | 
							t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("3", "2", ""); err != nil {
 | 
						if err := d.Create("3", "2", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mntPoint, err = d.Get("3", "")
 | 
						mntPoint, err = d.Get("3", "")
 | 
				
			||||||
| 
						 | 
					@ -448,7 +448,7 @@ func TestDiffSize(t *testing.T) {
 | 
				
			||||||
	d := newDriver(t)
 | 
						d := newDriver(t)
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -490,7 +490,7 @@ func TestChildDiffSize(t *testing.T) {
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
	defer d.Cleanup()
 | 
						defer d.Cleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -526,7 +526,7 @@ func TestChildDiffSize(t *testing.T) {
 | 
				
			||||||
		t.Fatalf("Expected size to be %d got %d", size, diffSize)
 | 
							t.Fatalf("Expected size to be %d got %d", size, diffSize)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("2", "1", ""); err != nil {
 | 
						if err := d.Create("2", "1", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -545,7 +545,7 @@ func TestExists(t *testing.T) {
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
	defer d.Cleanup()
 | 
						defer d.Cleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -563,7 +563,7 @@ func TestStatus(t *testing.T) {
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
	defer d.Cleanup()
 | 
						defer d.Cleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -592,7 +592,7 @@ func TestApplyDiff(t *testing.T) {
 | 
				
			||||||
	defer os.RemoveAll(tmp)
 | 
						defer os.RemoveAll(tmp)
 | 
				
			||||||
	defer d.Cleanup()
 | 
						defer d.Cleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("1", "", ""); err != nil {
 | 
						if err := d.Create("1", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -618,10 +618,10 @@ func TestApplyDiff(t *testing.T) {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create("2", "", ""); err != nil {
 | 
						if err := d.Create("2", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := d.Create("3", "2", ""); err != nil {
 | 
						if err := d.Create("3", "2", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -671,7 +671,7 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		current = hash(current)
 | 
							current = hash(current)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := d.Create(current, parent, ""); err != nil {
 | 
							if err := d.Create(current, parent, "", nil); err != nil {
 | 
				
			||||||
			t.Logf("Current layer %d", i)
 | 
								t.Logf("Current layer %d", i)
 | 
				
			||||||
			t.Error(err)
 | 
								t.Error(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -750,11 +750,11 @@ func BenchmarkConcurrentAccess(b *testing.B) {
 | 
				
			||||||
		ids = append(ids, stringid.GenerateNonCryptoID())
 | 
							ids = append(ids, stringid.GenerateNonCryptoID())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create(ids[0], "", ""); err != nil {
 | 
						if err := d.Create(ids[0], "", "", nil); err != nil {
 | 
				
			||||||
		b.Fatal(err)
 | 
							b.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := d.Create(ids[1], ids[0], ""); err != nil {
 | 
						if err := d.Create(ids[1], ids[0], "", nil); err != nil {
 | 
				
			||||||
		b.Fatal(err)
 | 
							b.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -770,7 +770,7 @@ func BenchmarkConcurrentAccess(b *testing.B) {
 | 
				
			||||||
	for _, id := range ids {
 | 
						for _, id := range ids {
 | 
				
			||||||
		go func(id string) {
 | 
							go func(id string) {
 | 
				
			||||||
			defer outerGroup.Done()
 | 
								defer outerGroup.Done()
 | 
				
			||||||
			if err := d.Create(id, parent, ""); err != nil {
 | 
								if err := d.Create(id, parent, "", nil); err != nil {
 | 
				
			||||||
				b.Logf("Create %s failed", id)
 | 
									b.Logf("Create %s failed", id)
 | 
				
			||||||
				chErr <- err
 | 
									chErr <- err
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,7 +242,12 @@ func (d *Driver) subvolumesDirID(id string) string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create the filesystem with given id.
 | 
					// Create the filesystem with given id.
 | 
				
			||||||
func (d *Driver) Create(id, parent, mountLabel string) error {
 | 
					func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(storageOpt) != 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("--storage-opt is not supported for btrfs")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	subvolumes := path.Join(d.home, "subvolumes")
 | 
						subvolumes := path.Join(d.home, "subvolumes")
 | 
				
			||||||
	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 | 
						rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ func TestBtrfsCreateSnap(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestBtrfsSubvolDelete(t *testing.T) {
 | 
					func TestBtrfsSubvolDelete(t *testing.T) {
 | 
				
			||||||
	d := graphtest.GetDriver(t, "btrfs")
 | 
						d := graphtest.GetDriver(t, "btrfs")
 | 
				
			||||||
	if err := d.Create("test", "", ""); err != nil {
 | 
						if err := d.Create("test", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer graphtest.PutDriver(t)
 | 
						defer graphtest.PutDriver(t)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -839,7 +839,7 @@ func (devices *DeviceSet) createRegisterDevice(hash string) (*devInfo, error) {
 | 
				
			||||||
	return info, nil
 | 
						return info, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (devices *DeviceSet) createRegisterSnapDevice(hash string, baseInfo *devInfo) error {
 | 
					func (devices *DeviceSet) createRegisterSnapDevice(hash string, baseInfo *devInfo, size uint64) error {
 | 
				
			||||||
	if err := devices.poolHasFreeSpace(); err != nil {
 | 
						if err := devices.poolHasFreeSpace(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -878,7 +878,7 @@ func (devices *DeviceSet) createRegisterSnapDevice(hash string, baseInfo *devInf
 | 
				
			||||||
		break
 | 
							break
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err := devices.registerDevice(deviceID, hash, baseInfo.Size, devices.OpenTransactionID); err != nil {
 | 
						if _, err := devices.registerDevice(deviceID, hash, size, devices.OpenTransactionID); err != nil {
 | 
				
			||||||
		devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID)
 | 
							devicemapper.DeleteDevice(devices.getPoolDevName(), deviceID)
 | 
				
			||||||
		devices.markDeviceIDFree(deviceID)
 | 
							devices.markDeviceIDFree(deviceID)
 | 
				
			||||||
		logrus.Debugf("devmapper: Error registering device: %s", err)
 | 
							logrus.Debugf("devmapper: Error registering device: %s", err)
 | 
				
			||||||
| 
						 | 
					@ -1830,7 +1830,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AddDevice adds a device and registers in the hash.
 | 
					// AddDevice adds a device and registers in the hash.
 | 
				
			||||||
func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
 | 
					func (devices *DeviceSet) AddDevice(hash, baseHash string, storageOpt map[string]string) error {
 | 
				
			||||||
	logrus.Debugf("devmapper: AddDevice(hash=%s basehash=%s)", hash, baseHash)
 | 
						logrus.Debugf("devmapper: AddDevice(hash=%s basehash=%s)", hash, baseHash)
 | 
				
			||||||
	defer logrus.Debugf("devmapper: AddDevice(hash=%s basehash=%s) END", hash, baseHash)
 | 
						defer logrus.Debugf("devmapper: AddDevice(hash=%s basehash=%s) END", hash, baseHash)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1856,10 +1856,56 @@ func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
 | 
				
			||||||
		return fmt.Errorf("devmapper: device %s already exists. Deleted=%v", hash, info.Deleted)
 | 
							return fmt.Errorf("devmapper: device %s already exists. Deleted=%v", hash, info.Deleted)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := devices.createRegisterSnapDevice(hash, baseInfo); err != nil {
 | 
						devinfo := &devInfo{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := devices.parseStorageOpt(storageOpt, devinfo); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if devinfo.Size == 0 {
 | 
				
			||||||
 | 
							devinfo.Size = baseInfo.Size
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if devinfo.Size < baseInfo.Size {
 | 
				
			||||||
 | 
							return fmt.Errorf("devmapper: Container size cannot be smaller than %s", units.HumanSize(float64(baseInfo.Size)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := devices.createRegisterSnapDevice(hash, baseInfo, devinfo.Size); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Grow the container rootfs.
 | 
				
			||||||
 | 
						if devinfo.Size > 0 {
 | 
				
			||||||
 | 
							info, err := devices.lookupDevice(hash)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err := devices.growFS(info); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (devices *DeviceSet) parseStorageOpt(storageOpt map[string]string, devinfo *devInfo) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read size to change the block device size per container.
 | 
				
			||||||
 | 
						for key, val := range storageOpt {
 | 
				
			||||||
 | 
							key := strings.ToLower(key)
 | 
				
			||||||
 | 
							switch key {
 | 
				
			||||||
 | 
							case "size":
 | 
				
			||||||
 | 
								size, err := units.RAMInBytes(val)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								devinfo.Size = uint64(size)
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return fmt.Errorf("Unknown option %s", key)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,8 +118,8 @@ func (d *Driver) Cleanup() error {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create adds a device with a given id and the parent.
 | 
					// Create adds a device with a given id and the parent.
 | 
				
			||||||
func (d *Driver) Create(id, parent, mountLabel string) error {
 | 
					func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 | 
				
			||||||
	if err := d.DeviceSet.AddDevice(id, parent); err != nil {
 | 
						if err := d.DeviceSet.AddDevice(id, parent, storageOpt); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ type ProtoDriver interface {
 | 
				
			||||||
	String() string
 | 
						String() string
 | 
				
			||||||
	// Create creates a new, empty, filesystem layer with the
 | 
						// Create creates a new, empty, filesystem layer with the
 | 
				
			||||||
	// specified id and parent and mountLabel. Parent and mountLabel may be "".
 | 
						// specified id and parent and mountLabel. Parent and mountLabel may be "".
 | 
				
			||||||
	Create(id, parent, mountLabel string) error
 | 
						Create(id, parent, mountLabel string, storageOpt map[string]string) error
 | 
				
			||||||
	// Remove attempts to remove the filesystem layer with this id.
 | 
						// Remove attempts to remove the filesystem layer with this id.
 | 
				
			||||||
	Remove(id string) error
 | 
						Remove(id string) error
 | 
				
			||||||
	// Get returns the mountpoint for the layered filesystem referred
 | 
						// Get returns the mountpoint for the layered filesystem referred
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,7 +177,7 @@ func DriverTestCreateEmpty(t *testing.T, drivername string) {
 | 
				
			||||||
	driver := GetDriver(t, drivername)
 | 
						driver := GetDriver(t, drivername)
 | 
				
			||||||
	defer PutDriver(t)
 | 
						defer PutDriver(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := driver.Create("empty", "", ""); err != nil {
 | 
						if err := driver.Create("empty", "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,7 +215,7 @@ func createBase(t *testing.T, driver graphdriver.Driver, name string) {
 | 
				
			||||||
	oldmask := syscall.Umask(0)
 | 
						oldmask := syscall.Umask(0)
 | 
				
			||||||
	defer syscall.Umask(oldmask)
 | 
						defer syscall.Umask(oldmask)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := driver.Create(name, "", ""); err != nil {
 | 
						if err := driver.Create(name, "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,7 +283,7 @@ func DriverTestCreateSnap(t *testing.T, drivername string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	createBase(t, driver, "Base")
 | 
						createBase(t, driver, "Base")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := driver.Create("Snap", "Base", ""); err != nil {
 | 
						if err := driver.Create("Snap", "Base", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -222,7 +222,12 @@ func (d *Driver) Cleanup() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create is used to create the upper, lower, and merge directories required for overlay fs for a given id.
 | 
					// Create is used to create the upper, lower, and merge directories required for overlay fs for a given id.
 | 
				
			||||||
// The parent filesystem is used to configure these directories for the overlay.
 | 
					// The parent filesystem is used to configure these directories for the overlay.
 | 
				
			||||||
func (d *Driver) Create(id, parent, mountLabel string) (retErr error) {
 | 
					func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) (retErr error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(storageOpt) != 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("--storage-opt is not supported for overlay")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dir := d.dir(id)
 | 
						dir := d.dir(id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 | 
						rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,7 @@ func (d *graphDriverProxy) String() string {
 | 
				
			||||||
	return d.name
 | 
						return d.name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *graphDriverProxy) Create(id, parent, mountLabel string) error {
 | 
					func (d *graphDriverProxy) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 | 
				
			||||||
	args := &graphDriverRequest{
 | 
						args := &graphDriverRequest{
 | 
				
			||||||
		ID:         id,
 | 
							ID:         id,
 | 
				
			||||||
		Parent:     parent,
 | 
							Parent:     parent,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,7 +69,11 @@ func (d *Driver) Cleanup() error {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create prepares the filesystem for the VFS driver and copies the directory for the given id under the parent.
 | 
					// Create prepares the filesystem for the VFS driver and copies the directory for the given id under the parent.
 | 
				
			||||||
func (d *Driver) Create(id, parent, mountLabel string) error {
 | 
					func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 | 
				
			||||||
 | 
						if len(storageOpt) != 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("--storage-opt is not supported for vfs")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dir := d.dir(id)
 | 
						dir := d.dir(id)
 | 
				
			||||||
	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 | 
						rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,7 +107,11 @@ func (d *Driver) Exists(id string) bool {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create creates a new layer with the given id.
 | 
					// Create creates a new layer with the given id.
 | 
				
			||||||
func (d *Driver) Create(id, parent, mountLabel string) error {
 | 
					func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 | 
				
			||||||
 | 
						if len(storageOpt) != 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("--storage-opt is not supported for windows")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rPId, err := d.resolveID(parent)
 | 
						rPId, err := d.resolveID(parent)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					@ -432,7 +436,7 @@ func (d *Driver) GetCustomImageInfos() ([]CustomImageInfo, error) {
 | 
				
			||||||
		h := sha512.Sum384([]byte(folderName))
 | 
							h := sha512.Sum384([]byte(folderName))
 | 
				
			||||||
		id := fmt.Sprintf("%x", h[:32])
 | 
							id := fmt.Sprintf("%x", h[:32])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := d.Create(id, "", ""); err != nil {
 | 
							if err := d.Create(id, "", "", nil); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Create the alternate ID file.
 | 
							// Create the alternate ID file.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,7 +241,11 @@ func (d *Driver) mountPath(id string) string {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create prepares the dataset and filesystem for the ZFS driver for the given id under the parent.
 | 
					// Create prepares the dataset and filesystem for the ZFS driver for the given id under the parent.
 | 
				
			||||||
func (d *Driver) Create(id string, parent string, mountLabel string) error {
 | 
					func (d *Driver) Create(id string, parent string, mountLabel string, storageOpt map[string]string) error {
 | 
				
			||||||
 | 
						if len(storageOpt) != 0 {
 | 
				
			||||||
 | 
							return fmt.Errorf("--storage-opt is not supported for zfs")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := d.create(id, parent)
 | 
						err := d.create(id, parent)
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ func (ls *mockLayerStore) Get(chainID layer.ChainID) (layer.Layer, error) {
 | 
				
			||||||
func (ls *mockLayerStore) Release(l layer.Layer) ([]layer.Metadata, error) {
 | 
					func (ls *mockLayerStore) Release(l layer.Layer) ([]layer.Metadata, error) {
 | 
				
			||||||
	return []layer.Metadata{}, nil
 | 
						return []layer.Metadata{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (ls *mockLayerStore) CreateRWLayer(string, layer.ChainID, string, layer.MountInit) (layer.RWLayer, error) {
 | 
					func (ls *mockLayerStore) CreateRWLayer(string, layer.ChainID, string, layer.MountInit, map[string]string) (layer.RWLayer, error) {
 | 
				
			||||||
	return nil, errors.New("not implemented")
 | 
						return nil, errors.New("not implemented")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,6 +116,8 @@ This section lists each version from latest to oldest.  Each listing includes a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[Docker Remote API v1.24](docker_remote_api_v1.24.md) documentation
 | 
					[Docker Remote API v1.24](docker_remote_api_v1.24.md) documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `POST /containers/create` now takes `StorageOpt` field.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### v1.23 API changes
 | 
					### v1.23 API changes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[Docker Remote API v1.23](docker_remote_api_v1.23.md) documentation
 | 
					[Docker Remote API v1.23](docker_remote_api_v1.23.md) documentation
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -325,6 +325,7 @@ Create a container
 | 
				
			||||||
             "Ulimits": [{}],
 | 
					             "Ulimits": [{}],
 | 
				
			||||||
             "LogConfig": { "Type": "json-file", "Config": {} },
 | 
					             "LogConfig": { "Type": "json-file", "Config": {} },
 | 
				
			||||||
             "SecurityOpt": [""],
 | 
					             "SecurityOpt": [""],
 | 
				
			||||||
 | 
					             "StorageOpt": {},
 | 
				
			||||||
             "CgroupParent": "",
 | 
					             "CgroupParent": "",
 | 
				
			||||||
             "VolumeDriver": "",
 | 
					             "VolumeDriver": "",
 | 
				
			||||||
             "ShmSize": 67108864
 | 
					             "ShmSize": 67108864
 | 
				
			||||||
| 
						 | 
					@ -444,6 +445,8 @@ Json Parameters:
 | 
				
			||||||
          `Ulimits: { "Name": "nofile", "Soft": 1024, "Hard": 2048 }`
 | 
					          `Ulimits: { "Name": "nofile", "Soft": 1024, "Hard": 2048 }`
 | 
				
			||||||
    -   **SecurityOpt**: A list of string values to customize labels for MLS
 | 
					    -   **SecurityOpt**: A list of string values to customize labels for MLS
 | 
				
			||||||
        systems, such as SELinux.
 | 
					        systems, such as SELinux.
 | 
				
			||||||
 | 
					    -   **StorageOpt**: Storage driver options per container. Options can be passed in the form
 | 
				
			||||||
 | 
					        `{"size":"120G"}`
 | 
				
			||||||
    -   **LogConfig** - Log configuration for the container, specified as a JSON object in the form
 | 
					    -   **LogConfig** - Log configuration for the container, specified as a JSON object in the form
 | 
				
			||||||
          `{ "Type": "<driver_name>", "Config": {"key1": "val1"}}`.
 | 
					          `{ "Type": "<driver_name>", "Config": {"key1": "val1"}}`.
 | 
				
			||||||
          Available types: `json-file`, `syslog`, `journald`, `gelf`, `fluentd`, `awslogs`, `splunk`, `etwlogs`, `none`.
 | 
					          Available types: `json-file`, `syslog`, `journald`, `gelf`, `fluentd`, `awslogs`, `splunk`, `etwlogs`, `none`.
 | 
				
			||||||
| 
						 | 
					@ -568,6 +571,7 @@ Return low-level information on the container `id`
 | 
				
			||||||
				"Type": "json-file"
 | 
									"Type": "json-file"
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			"SecurityOpt": null,
 | 
								"SecurityOpt": null,
 | 
				
			||||||
 | 
								"StorageOpt": null,
 | 
				
			||||||
			"VolumesFrom": null,
 | 
								"VolumesFrom": null,
 | 
				
			||||||
			"Ulimits": [{}],
 | 
								"Ulimits": [{}],
 | 
				
			||||||
			"VolumeDriver": "",
 | 
								"VolumeDriver": "",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,7 @@ Creates a new container.
 | 
				
			||||||
      --security-opt=[]             Security options
 | 
					      --security-opt=[]             Security options
 | 
				
			||||||
      --stop-signal="SIGTERM"       Signal to stop a container
 | 
					      --stop-signal="SIGTERM"       Signal to stop a container
 | 
				
			||||||
      --shm-size=[]                 Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.  Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`.
 | 
					      --shm-size=[]                 Size of `/dev/shm`. The format is `<number><unit>`. `number` must be greater than `0`.  Unit is optional and can be `b` (bytes), `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses `64m`.
 | 
				
			||||||
 | 
					      --storage-opt=[]              Set storage driver options per container
 | 
				
			||||||
      -t, --tty                     Allocate a pseudo-TTY
 | 
					      -t, --tty                     Allocate a pseudo-TTY
 | 
				
			||||||
      -u, --user=""                 Username or UID
 | 
					      -u, --user=""                 Username or UID
 | 
				
			||||||
      --userns=""                   Container user namespace
 | 
					      --userns=""                   Container user namespace
 | 
				
			||||||
| 
						 | 
					@ -145,6 +146,13 @@ then be used from the subsequent container:
 | 
				
			||||||
    drwx--S---  2 1000 staff  460 Dec  5 00:51 .ssh
 | 
					    drwx--S---  2 1000 staff  460 Dec  5 00:51 .ssh
 | 
				
			||||||
    drwxr-xr-x 32 1000 staff 1140 Dec  5 04:01 docker
 | 
					    drwxr-xr-x 32 1000 staff 1140 Dec  5 04:01 docker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Set storage driver options per container. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $ docker create -it --storage-opt size=120G fedora /bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This (size) will allow to set the container rootfs size to 120G at creation time. 
 | 
				
			||||||
 | 
					User cannot pass a size less than the Default BaseFS Size. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Specify isolation technology for container (--isolation)
 | 
					### Specify isolation technology for container (--isolation)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This option is useful in situations where you are running Docker containers on
 | 
					This option is useful in situations where you are running Docker containers on
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,6 +83,7 @@ parent = "smn_cli"
 | 
				
			||||||
      --security-opt=[]             Security Options
 | 
					      --security-opt=[]             Security Options
 | 
				
			||||||
      --sig-proxy=true              Proxy received signals to the process
 | 
					      --sig-proxy=true              Proxy received signals to the process
 | 
				
			||||||
      --stop-signal="SIGTERM"       Signal to stop a container
 | 
					      --stop-signal="SIGTERM"       Signal to stop a container
 | 
				
			||||||
 | 
					      --storage-opt=[]              Set storage driver options per container
 | 
				
			||||||
      -t, --tty                     Allocate a pseudo-TTY
 | 
					      -t, --tty                     Allocate a pseudo-TTY
 | 
				
			||||||
      -u, --user=""                 Username or UID (format: <name|uid>[:<group|gid>])
 | 
					      -u, --user=""                 Username or UID (format: <name|uid>[:<group|gid>])
 | 
				
			||||||
      --userns=""                   Container user namespace
 | 
					      --userns=""                   Container user namespace
 | 
				
			||||||
| 
						 | 
					@ -167,6 +168,13 @@ flag exists to allow special use-cases, like running Docker within Docker.
 | 
				
			||||||
The `-w` lets the command being executed inside directory given, here
 | 
					The `-w` lets the command being executed inside directory given, here
 | 
				
			||||||
`/path/to/dir/`. If the path does not exists it is created inside the container.
 | 
					`/path/to/dir/`. If the path does not exists it is created inside the container.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Set storage driver options per container
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $ docker create -it --storage-opt size=120G fedora /bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This (size) will allow to set the container rootfs size to 120G at creation time. 
 | 
				
			||||||
 | 
					User cannot pass a size less than the Default BaseFS Size.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Mount tmpfs (--tmpfs)
 | 
					### Mount tmpfs (--tmpfs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $ docker run -d --tmpfs /run:rw,noexec,nosuid,size=65536k my_image
 | 
					    $ docker run -d --tmpfs /run:rw,noexec,nosuid,size=65536k my_image
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,6 +60,27 @@ func (s *DockerSuite) TestCreateArgs(c *check.C) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Make sure we can grow the container's rootfs at creation time.
 | 
				
			||||||
 | 
					func (s *DockerSuite) TestCreateGrowRootfs(c *check.C) {
 | 
				
			||||||
 | 
						testRequires(c, Devicemapper)
 | 
				
			||||||
 | 
						out, _ := dockerCmd(c, "create", "--storage-opt", "size=120G", "busybox")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cleanedContainerID := strings.TrimSpace(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						inspectOut := inspectField(c, cleanedContainerID, "HostConfig.StorageOpt")
 | 
				
			||||||
 | 
						c.Assert(inspectOut, checker.Equals, "[size=120G]")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Make sure we cannot shrink the container's rootfs at creation time.
 | 
				
			||||||
 | 
					func (s *DockerSuite) TestCreateShrinkRootfs(c *check.C) {
 | 
				
			||||||
 | 
						testRequires(c, Devicemapper)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ensure this fails
 | 
				
			||||||
 | 
						out, _, err := dockerCmdWithError("create", "--storage-opt", "size=80G", "busybox")
 | 
				
			||||||
 | 
						c.Assert(err, check.NotNil, check.Commentf(out))
 | 
				
			||||||
 | 
						c.Assert(out, checker.Contains, "Container size cannot be smaller than")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Make sure we can set hostconfig options too
 | 
					// Make sure we can set hostconfig options too
 | 
				
			||||||
func (s *DockerSuite) TestCreateHostConfig(c *check.C) {
 | 
					func (s *DockerSuite) TestCreateHostConfig(c *check.C) {
 | 
				
			||||||
	out, _ := dockerCmd(c, "create", "-P", "busybox", "echo")
 | 
						out, _ := dockerCmd(c, "create", "-P", "busybox", "echo")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,7 +122,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
 | 
				
			||||||
		if err := decReq(r.Body, &req, w); err != nil {
 | 
							if err := decReq(r.Body, &req, w); err != nil {
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := driver.Create(req.ID, req.Parent, ""); err != nil {
 | 
							if err := driver.Create(req.ID, req.Parent, "", nil); err != nil {
 | 
				
			||||||
			respond(w, err)
 | 
								respond(w, err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,7 +171,7 @@ type Store interface {
 | 
				
			||||||
	Get(ChainID) (Layer, error)
 | 
						Get(ChainID) (Layer, error)
 | 
				
			||||||
	Release(Layer) ([]Metadata, error)
 | 
						Release(Layer) ([]Metadata, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CreateRWLayer(id string, parent ChainID, mountLabel string, initFunc MountInit) (RWLayer, error)
 | 
						CreateRWLayer(id string, parent ChainID, mountLabel string, initFunc MountInit, storageOpt map[string]string) (RWLayer, error)
 | 
				
			||||||
	GetRWLayer(id string) (RWLayer, error)
 | 
						GetRWLayer(id string) (RWLayer, error)
 | 
				
			||||||
	GetMountID(id string) (string, error)
 | 
						GetMountID(id string) (string, error)
 | 
				
			||||||
	ReleaseRWLayer(RWLayer) ([]Metadata, error)
 | 
						ReleaseRWLayer(RWLayer) ([]Metadata, error)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -263,7 +263,7 @@ func (ls *layerStore) Register(ts io.Reader, parent ChainID) (Layer, error) {
 | 
				
			||||||
		references:     map[Layer]struct{}{},
 | 
							references:     map[Layer]struct{}{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = ls.driver.Create(layer.cacheID, pid, ""); err != nil {
 | 
						if err = ls.driver.Create(layer.cacheID, pid, "", nil); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -414,7 +414,7 @@ func (ls *layerStore) Release(l Layer) ([]Metadata, error) {
 | 
				
			||||||
	return ls.releaseLayer(layer)
 | 
						return ls.releaseLayer(layer)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (ls *layerStore) CreateRWLayer(name string, parent ChainID, mountLabel string, initFunc MountInit) (RWLayer, error) {
 | 
					func (ls *layerStore) CreateRWLayer(name string, parent ChainID, mountLabel string, initFunc MountInit, storageOpt map[string]string) (RWLayer, error) {
 | 
				
			||||||
	ls.mountL.Lock()
 | 
						ls.mountL.Lock()
 | 
				
			||||||
	defer ls.mountL.Unlock()
 | 
						defer ls.mountL.Unlock()
 | 
				
			||||||
	m, ok := ls.mounts[name]
 | 
						m, ok := ls.mounts[name]
 | 
				
			||||||
| 
						 | 
					@ -451,14 +451,14 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, mountLabel stri
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if initFunc != nil {
 | 
						if initFunc != nil {
 | 
				
			||||||
		pid, err = ls.initMount(m.mountID, pid, mountLabel, initFunc)
 | 
							pid, err = ls.initMount(m.mountID, pid, mountLabel, initFunc, storageOpt)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		m.initID = pid
 | 
							m.initID = pid
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = ls.driver.Create(m.mountID, pid, ""); err != nil {
 | 
						if err = ls.driver.Create(m.mountID, pid, "", storageOpt); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -561,14 +561,14 @@ func (ls *layerStore) saveMount(mount *mountedLayer) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit) (string, error) {
 | 
					func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit, storageOpt map[string]string) (string, error) {
 | 
				
			||||||
	// Use "<graph-id>-init" to maintain compatibility with graph drivers
 | 
						// Use "<graph-id>-init" to maintain compatibility with graph drivers
 | 
				
			||||||
	// which are expecting this layer with this special name. If all
 | 
						// which are expecting this layer with this special name. If all
 | 
				
			||||||
	// graph drivers can be updated to not rely on knowing about this layer
 | 
						// graph drivers can be updated to not rely on knowing about this layer
 | 
				
			||||||
	// then the initID should be randomly generated.
 | 
						// then the initID should be randomly generated.
 | 
				
			||||||
	initID := fmt.Sprintf("%s-init", graphID)
 | 
						initID := fmt.Sprintf("%s-init", graphID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := ls.driver.Create(initID, parent, mountLabel); err != nil {
 | 
						if err := ls.driver.Create(initID, parent, mountLabel, storageOpt); err != nil {
 | 
				
			||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p, err := ls.driver.Get(initID, "")
 | 
						p, err := ls.driver.Get(initID, "")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ type layerInit func(root string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) {
 | 
					func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) {
 | 
				
			||||||
	containerID := stringid.GenerateRandomID()
 | 
						containerID := stringid.GenerateRandomID()
 | 
				
			||||||
	mount, err := ls.CreateRWLayer(containerID, parent, "", nil)
 | 
						mount, err := ls.CreateRWLayer(containerID, parent, "", nil, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -279,7 +279,7 @@ func TestMountAndRegister(t *testing.T) {
 | 
				
			||||||
	size, _ := layer.Size()
 | 
						size, _ := layer.Size()
 | 
				
			||||||
	t.Logf("Layer size: %d", size)
 | 
						t.Logf("Layer size: %d", size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mount2, err := ls.CreateRWLayer("new-test-mount", layer.ChainID(), "", nil)
 | 
						mount2, err := ls.CreateRWLayer("new-test-mount", layer.ChainID(), "", nil, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -387,7 +387,7 @@ func TestStoreRestore(t *testing.T) {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m, err := ls.CreateRWLayer("some-mount_name", layer3.ChainID(), "", nil)
 | 
						m, err := ls.CreateRWLayer("some-mount_name", layer3.ChainID(), "", nil, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -421,7 +421,7 @@ func TestStoreRestore(t *testing.T) {
 | 
				
			||||||
	assertLayerEqual(t, layer3b, layer3)
 | 
						assertLayerEqual(t, layer3b, layer3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create again with same name, should return error
 | 
						// Create again with same name, should return error
 | 
				
			||||||
	if _, err := ls2.CreateRWLayer("some-mount_name", layer3b.ChainID(), "", nil); err == nil {
 | 
						if _, err := ls2.CreateRWLayer("some-mount_name", layer3b.ChainID(), "", nil, nil); err == nil {
 | 
				
			||||||
		t.Fatal("Expected error creating mount with same name")
 | 
							t.Fatal("Expected error creating mount with same name")
 | 
				
			||||||
	} else if err != ErrMountNameConflict {
 | 
						} else if err != ErrMountNameConflict {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,7 +78,7 @@ func TestLayerMigration(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	graphID1 := stringid.GenerateRandomID()
 | 
						graphID1 := stringid.GenerateRandomID()
 | 
				
			||||||
	if err := graph.Create(graphID1, "", ""); err != nil {
 | 
						if err := graph.Create(graphID1, "", "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, err := graph.ApplyDiff(graphID1, "", archive.Reader(bytes.NewReader(tar1))); err != nil {
 | 
						if _, err := graph.ApplyDiff(graphID1, "", archive.Reader(bytes.NewReader(tar1))); err != nil {
 | 
				
			||||||
| 
						 | 
					@ -123,7 +123,7 @@ func TestLayerMigration(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	graphID2 := stringid.GenerateRandomID()
 | 
						graphID2 := stringid.GenerateRandomID()
 | 
				
			||||||
	if err := graph.Create(graphID2, graphID1, ""); err != nil {
 | 
						if err := graph.Create(graphID2, graphID1, "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, err := graph.ApplyDiff(graphID2, graphID1, archive.Reader(bytes.NewReader(tar2))); err != nil {
 | 
						if _, err := graph.ApplyDiff(graphID2, graphID1, archive.Reader(bytes.NewReader(tar2))); err != nil {
 | 
				
			||||||
| 
						 | 
					@ -165,7 +165,7 @@ func tarFromFilesInGraph(graph graphdriver.Driver, graphID, parentID string, fil
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := graph.Create(graphID, parentID, ""); err != nil {
 | 
						if err := graph.Create(graphID, parentID, "", nil); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, err := graph.ApplyDiff(graphID, parentID, archive.Reader(bytes.NewReader(t))); err != nil {
 | 
						if _, err := graph.ApplyDiff(graphID, parentID, archive.Reader(bytes.NewReader(t))); err != nil {
 | 
				
			||||||
| 
						 | 
					@ -320,14 +320,14 @@ func TestMountMigration(t *testing.T) {
 | 
				
			||||||
	containerID := stringid.GenerateRandomID()
 | 
						containerID := stringid.GenerateRandomID()
 | 
				
			||||||
	containerInit := fmt.Sprintf("%s-init", containerID)
 | 
						containerInit := fmt.Sprintf("%s-init", containerID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := graph.Create(containerInit, graphID1, ""); err != nil {
 | 
						if err := graph.Create(containerInit, graphID1, "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, err := graph.ApplyDiff(containerInit, graphID1, archive.Reader(bytes.NewReader(initTar))); err != nil {
 | 
						if _, err := graph.ApplyDiff(containerInit, graphID1, archive.Reader(bytes.NewReader(initTar))); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := graph.Create(containerID, containerInit, ""); err != nil {
 | 
						if err := graph.Create(containerID, containerInit, "", nil); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, err := graph.ApplyDiff(containerID, containerInit, archive.Reader(bytes.NewReader(mountTar))); err != nil {
 | 
						if _, err := graph.ApplyDiff(containerID, containerInit, archive.Reader(bytes.NewReader(mountTar))); err != nil {
 | 
				
			||||||
| 
						 | 
					@ -382,7 +382,7 @@ func TestMountMigration(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	assertActivityCount(t, rwLayer1, 1)
 | 
						assertActivityCount(t, rwLayer1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err := ls.CreateRWLayer("migration-mount", layer1.ChainID(), "", nil); err == nil {
 | 
						if _, err := ls.CreateRWLayer("migration-mount", layer1.ChainID(), "", nil, nil); err == nil {
 | 
				
			||||||
		t.Fatal("Expected error creating mount with same name")
 | 
							t.Fatal("Expected error creating mount with same name")
 | 
				
			||||||
	} else if err != ErrMountNameConflict {
 | 
						} else if err != ErrMountNameConflict {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ func TestMountInit(t *testing.T) {
 | 
				
			||||||
		return initfile.ApplyFile(root)
 | 
							return initfile.ApplyFile(root)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), "", mountInit)
 | 
						m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), "", mountInit, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -89,7 +89,7 @@ func TestMountSize(t *testing.T) {
 | 
				
			||||||
		return newTestFile("file-init", contentInit, 0777).ApplyFile(root)
 | 
							return newTestFile("file-init", contentInit, 0777).ApplyFile(root)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), "", mountInit)
 | 
						m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), "", mountInit, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -138,7 +138,7 @@ func TestMountChanges(t *testing.T) {
 | 
				
			||||||
		return initfile.ApplyFile(root)
 | 
							return initfile.ApplyFile(root)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), "", mountInit)
 | 
						m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), "", mountInit, nil)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,6 +64,7 @@ docker-create - Create a new container
 | 
				
			||||||
[**--read-only**]
 | 
					[**--read-only**]
 | 
				
			||||||
[**--restart**[=*RESTART*]]
 | 
					[**--restart**[=*RESTART*]]
 | 
				
			||||||
[**--security-opt**[=*[]*]]
 | 
					[**--security-opt**[=*[]*]]
 | 
				
			||||||
 | 
					[**--storage-opt**[=*[]*]]
 | 
				
			||||||
[**--stop-signal**[=*SIGNAL*]]
 | 
					[**--stop-signal**[=*SIGNAL*]]
 | 
				
			||||||
[**--shm-size**[=*[]*]]
 | 
					[**--shm-size**[=*[]*]]
 | 
				
			||||||
[**-t**|**--tty**]
 | 
					[**-t**|**--tty**]
 | 
				
			||||||
| 
						 | 
					@ -325,6 +326,13 @@ unit, `b` is used. Set LIMIT to `-1` to enable unlimited swap.
 | 
				
			||||||
    "seccomp:unconfined" : Turn off seccomp confinement for the container
 | 
					    "seccomp:unconfined" : Turn off seccomp confinement for the container
 | 
				
			||||||
    "seccomp:profile.json :  White listed syscalls seccomp Json file to be used as a seccomp filter
 | 
					    "seccomp:profile.json :  White listed syscalls seccomp Json file to be used as a seccomp filter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**--storage-opt**=[]
 | 
				
			||||||
 | 
					   Storage driver options per container
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   $ docker create -it --storage-opt size=120G fedora /bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   This (size) will allow to set the container rootfs size to 120G at creation time. User cannot pass a size less than the Default BaseFS Size.
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
**--stop-signal**=*SIGTERM*
 | 
					**--stop-signal**=*SIGTERM*
 | 
				
			||||||
  Signal to stop a container. Default is SIGTERM.
 | 
					  Signal to stop a container. Default is SIGTERM.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,6 +67,7 @@ docker-run - Run a command in a new container
 | 
				
			||||||
[**--restart**[=*RESTART*]]
 | 
					[**--restart**[=*RESTART*]]
 | 
				
			||||||
[**--rm**]
 | 
					[**--rm**]
 | 
				
			||||||
[**--security-opt**[=*[]*]]
 | 
					[**--security-opt**[=*[]*]]
 | 
				
			||||||
 | 
					[**--storage-opt**[=*[]*]]
 | 
				
			||||||
[**--stop-signal**[=*SIGNAL*]]
 | 
					[**--stop-signal**[=*SIGNAL*]]
 | 
				
			||||||
[**--shm-size**[=*[]*]]
 | 
					[**--shm-size**[=*[]*]]
 | 
				
			||||||
[**--sig-proxy**[=*true*]]
 | 
					[**--sig-proxy**[=*true*]]
 | 
				
			||||||
| 
						 | 
					@ -476,6 +477,13 @@ its root filesystem mounted as read only prohibiting any writes.
 | 
				
			||||||
    "apparmor=unconfined" : Turn off apparmor confinement for the container
 | 
					    "apparmor=unconfined" : Turn off apparmor confinement for the container
 | 
				
			||||||
    "apparmor=your-profile" : Set the apparmor confinement profile for the container
 | 
					    "apparmor=your-profile" : Set the apparmor confinement profile for the container
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**--storage-opt**=[]
 | 
				
			||||||
 | 
					   Storage driver options per container
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   $ docker run -it --storage-opt size=120G fedora /bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   This (size) will allow to set the container rootfs size to 120G at creation time. User cannot pass a size less than the Default BaseFS Size.
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
**--stop-signal**=*SIGTERM*
 | 
					**--stop-signal**=*SIGTERM*
 | 
				
			||||||
  Signal to stop a container. Default is SIGTERM.
 | 
					  Signal to stop a container. Default is SIGTERM.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
 | 
				
			||||||
		flCapDrop           = opts.NewListOpts(nil)
 | 
							flCapDrop           = opts.NewListOpts(nil)
 | 
				
			||||||
		flGroupAdd          = opts.NewListOpts(nil)
 | 
							flGroupAdd          = opts.NewListOpts(nil)
 | 
				
			||||||
		flSecurityOpt       = opts.NewListOpts(nil)
 | 
							flSecurityOpt       = opts.NewListOpts(nil)
 | 
				
			||||||
 | 
							flStorageOpt        = opts.NewListOpts(nil)
 | 
				
			||||||
		flLabelsFile        = opts.NewListOpts(nil)
 | 
							flLabelsFile        = opts.NewListOpts(nil)
 | 
				
			||||||
		flLoggingOpts       = opts.NewListOpts(nil)
 | 
							flLoggingOpts       = opts.NewListOpts(nil)
 | 
				
			||||||
		flPrivileged        = cmd.Bool([]string{"-privileged"}, false, "Give extended privileges to this container")
 | 
							flPrivileged        = cmd.Bool([]string{"-privileged"}, false, "Give extended privileges to this container")
 | 
				
			||||||
| 
						 | 
					@ -124,6 +125,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
 | 
				
			||||||
	cmd.Var(&flCapDrop, []string{"-cap-drop"}, "Drop Linux capabilities")
 | 
						cmd.Var(&flCapDrop, []string{"-cap-drop"}, "Drop Linux capabilities")
 | 
				
			||||||
	cmd.Var(&flGroupAdd, []string{"-group-add"}, "Add additional groups to join")
 | 
						cmd.Var(&flGroupAdd, []string{"-group-add"}, "Add additional groups to join")
 | 
				
			||||||
	cmd.Var(&flSecurityOpt, []string{"-security-opt"}, "Security Options")
 | 
						cmd.Var(&flSecurityOpt, []string{"-security-opt"}, "Security Options")
 | 
				
			||||||
 | 
						cmd.Var(&flStorageOpt, []string{"-storage-opt"}, "Set storage driver options per container")
 | 
				
			||||||
	cmd.Var(flUlimits, []string{"-ulimit"}, "Ulimit options")
 | 
						cmd.Var(flUlimits, []string{"-ulimit"}, "Ulimit options")
 | 
				
			||||||
	cmd.Var(&flLoggingOpts, []string{"-log-opt"}, "Log driver options")
 | 
						cmd.Var(&flLoggingOpts, []string{"-log-opt"}, "Log driver options")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -337,6 +339,11 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
 | 
				
			||||||
		return nil, nil, nil, cmd, err
 | 
							return nil, nil, nil, cmd, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						storageOpts, err := parseStorageOpts(flStorageOpt.GetAll())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, nil, cmd, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resources := container.Resources{
 | 
						resources := container.Resources{
 | 
				
			||||||
		CgroupParent:         *flCgroupParent,
 | 
							CgroupParent:         *flCgroupParent,
 | 
				
			||||||
		Memory:               flMemory,
 | 
							Memory:               flMemory,
 | 
				
			||||||
| 
						 | 
					@ -415,6 +422,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
 | 
				
			||||||
		GroupAdd:       flGroupAdd.GetAll(),
 | 
							GroupAdd:       flGroupAdd.GetAll(),
 | 
				
			||||||
		RestartPolicy:  restartPolicy,
 | 
							RestartPolicy:  restartPolicy,
 | 
				
			||||||
		SecurityOpt:    securityOpts,
 | 
							SecurityOpt:    securityOpts,
 | 
				
			||||||
 | 
							StorageOpt:     storageOpts,
 | 
				
			||||||
		ReadonlyRootfs: *flReadonlyRootfs,
 | 
							ReadonlyRootfs: *flReadonlyRootfs,
 | 
				
			||||||
		LogConfig:      container.LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
 | 
							LogConfig:      container.LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
 | 
				
			||||||
		VolumeDriver:   *flVolumeDriver,
 | 
							VolumeDriver:   *flVolumeDriver,
 | 
				
			||||||
| 
						 | 
					@ -531,6 +539,20 @@ func parseSecurityOpts(securityOpts []string) ([]string, error) {
 | 
				
			||||||
	return securityOpts, nil
 | 
						return securityOpts, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// parse storage options per container into a map
 | 
				
			||||||
 | 
					func parseStorageOpts(storageOpts []string) (map[string]string, error) {
 | 
				
			||||||
 | 
						m := make(map[string]string)
 | 
				
			||||||
 | 
						for _, option := range storageOpts {
 | 
				
			||||||
 | 
							if strings.Contains(option, "=") {
 | 
				
			||||||
 | 
								opt := strings.SplitN(option, "=", 2)
 | 
				
			||||||
 | 
								m[opt[0]] = opt[1]
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("Invalid storage option.")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return m, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ParseRestartPolicy returns the parsed policy or an error indicating what is incorrect
 | 
					// ParseRestartPolicy returns the parsed policy or an error indicating what is incorrect
 | 
				
			||||||
func ParseRestartPolicy(policy string) (container.RestartPolicy, error) {
 | 
					func ParseRestartPolicy(policy string) (container.RestartPolicy, error) {
 | 
				
			||||||
	p := container.RestartPolicy{}
 | 
						p := container.RestartPolicy{}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue