Explorar el Código

Merge pull request #18977 from anusha-ragunathan/builder

Use ImageBuildOptions in builder.
David Calavera hace 9 años
padre
commit
acfd5eb947

+ 12 - 3
api/client/build.go

@@ -16,6 +16,7 @@ import (
 
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/builder/dockerignore"
 	Cli "github.com/docker/docker/cli"
 	"github.com/docker/docker/opts"
@@ -207,6 +208,14 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
 		}
 	}
 
+	var shmSize int64
+	if *flShmSize != "" {
+		shmSize, err = units.RAMInBytes(*flShmSize)
+		if err != nil {
+			return err
+		}
+	}
+
 	var remoteContext string
 	if isRemote {
 		remoteContext = cmd.Arg(0)
@@ -223,17 +232,17 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
 		Remove:         *rm,
 		ForceRemove:    *forceRm,
 		PullParent:     *pull,
-		Isolation:      *isolation,
+		IsolationLevel: container.IsolationLevel(*isolation),
 		CPUSetCPUs:     *flCPUSetCpus,
 		CPUSetMems:     *flCPUSetMems,
 		CPUShares:      *flCPUShares,
 		CPUQuota:       *flCPUQuota,
 		CPUPeriod:      *flCPUPeriod,
 		CgroupParent:   *flCgroupParent,
-		ShmSize:        *flShmSize,
 		Dockerfile:     relDockerfile,
+		ShmSize:        shmSize,
 		Ulimits:        flUlimits.GetList(),
-		BuildArgs:      flBuildArg.GetAll(),
+		BuildArgs:      runconfigopts.ConvertKVStringsToMap(flBuildArg.GetAll()),
 		AuthConfigs:    cli.configFile.AuthConfigs,
 	}
 

+ 4 - 14
api/client/lib/image_build.go

@@ -11,7 +11,6 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/container"
-	"github.com/docker/go-units"
 )
 
 var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
@@ -73,8 +72,8 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro
 		query.Set("pull", "1")
 	}
 
-	if !container.IsolationLevel.IsDefault(container.IsolationLevel(options.Isolation)) {
-		query.Set("isolation", options.Isolation)
+	if !container.IsolationLevel.IsDefault(options.IsolationLevel) {
+		query.Set("isolation", string(options.IsolationLevel))
 	}
 
 	query.Set("cpusetcpus", options.CPUSetCPUs)
@@ -85,15 +84,7 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro
 	query.Set("memory", strconv.FormatInt(options.Memory, 10))
 	query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
 	query.Set("cgroupparent", options.CgroupParent)
-
-	if options.ShmSize != "" {
-		parsedShmSize, err := units.RAMInBytes(options.ShmSize)
-		if err != nil {
-			return query, err
-		}
-		query.Set("shmsize", strconv.FormatInt(parsedShmSize, 10))
-	}
-
+	query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
 	query.Set("dockerfile", options.Dockerfile)
 
 	ulimitsJSON, err := json.Marshal(options.Ulimits)
@@ -102,8 +93,7 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro
 	}
 	query.Set("ulimits", string(ulimitsJSON))
 
-	buildArgs := convertKVStringsToMap(options.BuildArgs)
-	buildArgsJSON, err := json.Marshal(buildArgs)
+	buildArgsJSON, err := json.Marshal(options.BuildArgs)
 	if err != nil {
 		return query, err
 	}

+ 79 - 67
api/server/router/build/build_routes.go

@@ -68,11 +68,72 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
 	return repoAndTags, nil
 }
 
+func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
+	version := httputils.VersionFromContext(ctx)
+	options := &types.ImageBuildOptions{}
+	if httputils.BoolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
+		options.Remove = true
+	} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
+		options.Remove = true
+	} else {
+		options.Remove = httputils.BoolValue(r, "rm")
+	}
+	if httputils.BoolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
+		options.PullParent = true
+	}
+
+	options.Dockerfile = r.FormValue("dockerfile")
+	options.SuppressOutput = httputils.BoolValue(r, "q")
+	options.NoCache = httputils.BoolValue(r, "nocache")
+	options.ForceRemove = httputils.BoolValue(r, "forcerm")
+	options.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
+	options.Memory = httputils.Int64ValueOrZero(r, "memory")
+	options.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
+	options.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
+	options.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
+	options.CPUSetCPUs = r.FormValue("cpusetcpus")
+	options.CPUSetMems = r.FormValue("cpusetmems")
+	options.CgroupParent = r.FormValue("cgroupparent")
+
+	if r.Form.Get("shmsize") != "" {
+		shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
+		if err != nil {
+			return nil, err
+		}
+		options.ShmSize = shmSize
+	}
+
+	if i := container.IsolationLevel(r.FormValue("isolation")); i != "" {
+		if !container.IsolationLevel.IsValid(i) {
+			return nil, fmt.Errorf("Unsupported isolation: %q", i)
+		}
+		options.IsolationLevel = i
+	}
+
+	var buildUlimits = []*units.Ulimit{}
+	ulimitsJSON := r.FormValue("ulimits")
+	if ulimitsJSON != "" {
+		if err := json.NewDecoder(strings.NewReader(ulimitsJSON)).Decode(&buildUlimits); err != nil {
+			return nil, err
+		}
+		options.Ulimits = buildUlimits
+	}
+
+	var buildArgs = map[string]string{}
+	buildArgsJSON := r.FormValue("buildargs")
+	if buildArgsJSON != "" {
+		if err := json.NewDecoder(strings.NewReader(buildArgsJSON)).Decode(&buildArgs); err != nil {
+			return nil, err
+		}
+		options.BuildArgs = buildArgs
+	}
+	return options, nil
+}
+
 func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	var (
 		authConfigs        = map[string]types.AuthConfig{}
 		authConfigsEncoded = r.Header.Get("X-Registry-Config")
-		buildConfig        = &dockerfile.Config{}
 		notVerboseBuffer   = bytes.NewBuffer(nil)
 	)
 
@@ -87,12 +148,11 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
 
 	w.Header().Set("Content-Type", "application/json")
 
-	version := httputils.VersionFromContext(ctx)
 	output := ioutils.NewWriteFlusher(w)
 	defer output.Close()
 	sf := streamformatter.NewJSONStreamFormatter()
 	errf := func(err error) error {
-		if !buildConfig.Verbose && notVerboseBuffer.Len() > 0 {
+		if httputils.BoolValue(r, "q") && notVerboseBuffer.Len() > 0 {
 			output.Write(notVerboseBuffer.Bytes())
 		}
 		// Do not write the error in the http output if it's still empty.
@@ -107,15 +167,9 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
 		return nil
 	}
 
-	if httputils.BoolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
-		buildConfig.Remove = true
-	} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
-		buildConfig.Remove = true
-	} else {
-		buildConfig.Remove = httputils.BoolValue(r, "rm")
-	}
-	if httputils.BoolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
-		buildConfig.Pull = true
+	buildOptions, err := newImageBuildOptions(ctx, r)
+	if err != nil {
+		return errf(err)
 	}
 
 	repoAndTags, err := sanitizeRepoAndTags(r.Form["t"])
@@ -123,59 +177,13 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
 		return errf(err)
 	}
 
-	buildConfig.DockerfileName = r.FormValue("dockerfile")
-	buildConfig.Verbose = !httputils.BoolValue(r, "q")
-	buildConfig.UseCache = !httputils.BoolValue(r, "nocache")
-	buildConfig.ForceRemove = httputils.BoolValue(r, "forcerm")
-	buildConfig.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
-	buildConfig.Memory = httputils.Int64ValueOrZero(r, "memory")
-	buildConfig.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
-	buildConfig.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
-	buildConfig.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
-	buildConfig.CPUSetCpus = r.FormValue("cpusetcpus")
-	buildConfig.CPUSetMems = r.FormValue("cpusetmems")
-	buildConfig.CgroupParent = r.FormValue("cgroupparent")
-
-	if r.Form.Get("shmsize") != "" {
-		shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
-		if err != nil {
-			return errf(err)
-		}
-		buildConfig.ShmSize = &shmSize
-	}
-
-	if i := container.IsolationLevel(r.FormValue("isolation")); i != "" {
-		if !container.IsolationLevel.IsValid(i) {
-			return errf(fmt.Errorf("Unsupported isolation: %q", i))
-		}
-		buildConfig.Isolation = i
-	}
-
-	var buildUlimits = []*units.Ulimit{}
-	ulimitsJSON := r.FormValue("ulimits")
-	if ulimitsJSON != "" {
-		if err := json.NewDecoder(strings.NewReader(ulimitsJSON)).Decode(&buildUlimits); err != nil {
-			return errf(err)
-		}
-		buildConfig.Ulimits = buildUlimits
-	}
-
-	var buildArgs = map[string]string{}
-	buildArgsJSON := r.FormValue("buildargs")
-	if buildArgsJSON != "" {
-		if err := json.NewDecoder(strings.NewReader(buildArgsJSON)).Decode(&buildArgs); err != nil {
-			return errf(err)
-		}
-		buildConfig.BuildArgs = buildArgs
-	}
-
 	remoteURL := r.FormValue("remote")
 
 	// Currently, only used if context is from a remote url.
 	// Look at code in DetectContextFromRemoteURL for more information.
 	createProgressReader := func(in io.ReadCloser) io.ReadCloser {
 		progressOutput := sf.NewProgressOutput(output, true)
-		if !buildConfig.Verbose {
+		if buildOptions.SuppressOutput {
 			progressOutput = sf.NewProgressOutput(notVerboseBuffer, true)
 		}
 		return progress.NewProgressReader(in, progressOutput, r.ContentLength, "Downloading context", remoteURL)
@@ -194,6 +202,9 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
 			logrus.Debugf("[BUILDER] failed to remove temporary context: %v", err)
 		}
 	}()
+	if len(dockerfileName) > 0 {
+		buildOptions.Dockerfile = dockerfileName
+	}
 
 	uidMaps, gidMaps := br.backend.GetUIDGIDMaps()
 	defaultArchiver := &archive.Archiver{
@@ -201,23 +212,28 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
 		UIDMaps: uidMaps,
 		GIDMaps: gidMaps,
 	}
+
 	docker := &daemonbuilder.Docker{
 		Daemon:      br.backend,
 		OutOld:      output,
 		AuthConfigs: authConfigs,
 		Archiver:    defaultArchiver,
 	}
-	if !buildConfig.Verbose {
+	if buildOptions.SuppressOutput {
 		docker.OutOld = notVerboseBuffer
 	}
 
-	b, err := dockerfile.NewBuilder(buildConfig, docker, builder.DockerIgnoreContext{ModifiableContext: context}, nil)
+	b, err := dockerfile.NewBuilder(
+		buildOptions, // result of newBuildConfig
+		docker,
+		builder.DockerIgnoreContext{ModifiableContext: context},
+		nil)
 	if err != nil {
 		return errf(err)
 	}
 	b.Stdout = &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
 	b.Stderr = &streamformatter.StderrFormatter{Writer: output, StreamFormatter: sf}
-	if !buildConfig.Verbose {
+	if buildOptions.SuppressOutput {
 		b.Stdout = &streamformatter.StdoutFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
 		b.Stderr = &streamformatter.StderrFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
 	}
@@ -235,10 +251,6 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
 		}()
 	}
 
-	if len(dockerfileName) > 0 {
-		b.DockerfileName = dockerfileName
-	}
-
 	imgID, err := b.Build()
 	if err != nil {
 		return errf(err)
@@ -252,7 +264,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
 
 	// Everything worked so if -q was provided the output from the daemon
 	// should be just the image ID and we'll print that to stdout.
-	if !buildConfig.Verbose {
+	if buildOptions.SuppressOutput {
 		stdout := &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
 		fmt.Fprintf(stdout, "%s\n", string(imgID))
 	}

+ 3 - 3
api/types/client.go

@@ -127,7 +127,7 @@ type ImageBuildOptions struct {
 	Remove         bool
 	ForceRemove    bool
 	PullParent     bool
-	Isolation      string
+	IsolationLevel container.IsolationLevel
 	CPUSetCPUs     string
 	CPUSetMems     string
 	CPUShares      int64
@@ -136,10 +136,10 @@ type ImageBuildOptions struct {
 	Memory         int64
 	MemorySwap     int64
 	CgroupParent   string
-	ShmSize        string
+	ShmSize        int64
 	Dockerfile     string
 	Ulimits        []*units.Ulimit
-	BuildArgs      []string
+	BuildArgs      map[string]string
 	AuthConfigs    map[string]AuthConfig
 	Context        io.Reader
 }

+ 1 - 1
api/types/container/host_config.go

@@ -216,7 +216,7 @@ type HostConfig struct {
 	SecurityOpt     []string           // List of string values to customize labels for MLS systems, such as SELinux.
 	Tmpfs           map[string]string  `json:",omitempty"` // List of tmpfs (mounts) used for the container
 	UTSMode         UTSMode            // UTS namespace to use for the container
-	ShmSize         *int64             // Total shm memory usage
+	ShmSize         int64              // Total shm memory usage
 
 	// Applicable to Windows
 	ConsoleSize [2]int         // Initial console size

+ 9 - 37
builder/dockerfile/builder.go

@@ -10,11 +10,11 @@ import (
 	"sync"
 
 	"github.com/Sirupsen/logrus"
+	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/builder"
 	"github.com/docker/docker/builder/dockerfile/parser"
 	"github.com/docker/docker/pkg/stringid"
-	"github.com/docker/go-units"
 )
 
 var validCommitCommands = map[string]bool{
@@ -41,38 +41,10 @@ var BuiltinAllowedBuildArgs = map[string]bool{
 	"no_proxy":    true,
 }
 
-// Config constitutes the configuration for a Dockerfile builder.
-type Config struct {
-	// only used if Dockerfile has to be extracted from Context
-	DockerfileName string
-
-	Verbose     bool
-	UseCache    bool
-	Remove      bool
-	ForceRemove bool
-	Pull        bool
-	BuildArgs   map[string]string // build-time args received in build context for expansion/substitution and commands in 'run'.
-	Isolation   container.IsolationLevel
-
-	// resource constraints
-	// TODO: factor out to be reused with Run ?
-
-	Memory       int64
-	MemorySwap   int64
-	ShmSize      *int64
-	CPUShares    int64
-	CPUPeriod    int64
-	CPUQuota     int64
-	CPUSetCpus   string
-	CPUSetMems   string
-	CgroupParent string
-	Ulimits      []*units.Ulimit
-}
-
 // Builder is a Dockerfile builder
 // It implements the builder.Backend interface.
 type Builder struct {
-	*Config
+	options *types.ImageBuildOptions
 
 	Stdout io.Writer
 	Stderr io.Writer
@@ -101,18 +73,18 @@ type Builder struct {
 // NewBuilder creates a new Dockerfile builder from an optional dockerfile and a Config.
 // If dockerfile is nil, the Dockerfile specified by Config.DockerfileName,
 // will be read from the Context passed to Build().
-func NewBuilder(config *Config, docker builder.Backend, context builder.Context, dockerfile io.ReadCloser) (b *Builder, err error) {
+func NewBuilder(config *types.ImageBuildOptions, backend builder.Backend, context builder.Context, dockerfile io.ReadCloser) (b *Builder, err error) {
 	if config == nil {
-		config = new(Config)
+		config = new(types.ImageBuildOptions)
 	}
 	if config.BuildArgs == nil {
 		config.BuildArgs = make(map[string]string)
 	}
 	b = &Builder{
-		Config:           config,
+		options:          config,
 		Stdout:           os.Stdout,
 		Stderr:           os.Stderr,
-		docker:           docker,
+		docker:           backend,
 		context:          context,
 		runConfig:        new(container.Config),
 		tmpContainers:    map[string]struct{}{},
@@ -162,14 +134,14 @@ func (b *Builder) Build() (string, error) {
 			// Not cancelled yet, keep going...
 		}
 		if err := b.dispatch(i, n); err != nil {
-			if b.ForceRemove {
+			if b.options.ForceRemove {
 				b.clearTmp()
 			}
 			return "", err
 		}
 		shortImgID = stringid.TruncateID(b.image)
 		fmt.Fprintf(b.Stdout, " ---> %s\n", shortImgID)
-		if b.Remove {
+		if b.options.Remove {
 			b.clearTmp()
 		}
 	}
@@ -177,7 +149,7 @@ func (b *Builder) Build() (string, error) {
 	// check if there are any leftover build-args that were passed but not
 	// consumed during build. Return an error, if there are any.
 	leftoverArgs := []string{}
-	for arg := range b.BuildArgs {
+	for arg := range b.options.BuildArgs {
 		if !b.isBuildArgAllowed(arg) {
 			leftoverArgs = append(leftoverArgs, arg)
 		}

+ 4 - 4
builder/dockerfile/dispatchers.go

@@ -209,7 +209,7 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
 		err   error
 	)
 	// TODO: don't use `name`, instead resolve it to a digest
-	if !b.Pull {
+	if !b.options.PullParent {
 		image, err = b.docker.GetImage(name)
 		// TODO: shouldn't we error out if error is different from "not found" ?
 	}
@@ -339,7 +339,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
 	// lookup for same image built with same build time environment.
 	cmdBuildEnv := []string{}
 	configEnv := runconfigopts.ConvertKVStringsToMap(b.runConfig.Env)
-	for key, val := range b.BuildArgs {
+	for key, val := range b.options.BuildArgs {
 		if !b.isBuildArgAllowed(key) {
 			// skip build-args that are not in allowed list, meaning they have
 			// not been defined by an "ARG" Dockerfile command yet.
@@ -622,8 +622,8 @@ func arg(b *Builder, args []string, attributes map[string]bool, original string)
 	// If there is a default value associated with this arg then add it to the
 	// b.buildArgs if one is not already passed to the builder. The args passed
 	// to builder override the default value of 'arg'.
-	if _, ok := b.BuildArgs[name]; !ok && hasDefault {
-		b.BuildArgs[name] = value
+	if _, ok := b.options.BuildArgs[name]; !ok && hasDefault {
+		b.options.BuildArgs[name] = value
 	}
 
 	return b.commit("", b.runConfig.Cmd, fmt.Sprintf("ARG %s", arg))

+ 1 - 1
builder/dockerfile/evaluator.go

@@ -148,7 +148,7 @@ func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
 	// a subsequent one. So, putting the buildArgs list after the Config.Env
 	// list, in 'envs', is safe.
 	envs := b.runConfig.Env
-	for key, val := range b.BuildArgs {
+	for key, val := range b.options.BuildArgs {
 		if !b.isBuildArgAllowed(key) {
 			// skip build-args that are not in allowed list, meaning they have
 			// not been defined by an "ARG" Dockerfile command yet.

+ 21 - 21
builder/dockerfile/internals.go

@@ -450,7 +450,7 @@ func (b *Builder) processImageFrom(img builder.Image) error {
 // If there is any error, it returns `(false, err)`.
 func (b *Builder) probeCache() (bool, error) {
 	c, ok := b.docker.(builder.ImageCache)
-	if !ok || !b.UseCache || b.cacheBusted {
+	if !ok || b.options.NoCache || b.cacheBusted {
 		return false, nil
 	}
 	cache, err := c.GetCachedImage(b.image, b.runConfig)
@@ -477,21 +477,21 @@ func (b *Builder) create() (string, error) {
 	b.runConfig.Image = b.image
 
 	resources := container.Resources{
-		CgroupParent: b.CgroupParent,
-		CPUShares:    b.CPUShares,
-		CPUPeriod:    b.CPUPeriod,
-		CPUQuota:     b.CPUQuota,
-		CpusetCpus:   b.CPUSetCpus,
-		CpusetMems:   b.CPUSetMems,
-		Memory:       b.Memory,
-		MemorySwap:   b.MemorySwap,
-		Ulimits:      b.Ulimits,
+		CgroupParent: b.options.CgroupParent,
+		CPUShares:    b.options.CPUShares,
+		CPUPeriod:    b.options.CPUPeriod,
+		CPUQuota:     b.options.CPUQuota,
+		CpusetCpus:   b.options.CPUSetCPUs,
+		CpusetMems:   b.options.CPUSetMems,
+		Memory:       b.options.Memory,
+		MemorySwap:   b.options.MemorySwap,
+		Ulimits:      b.options.Ulimits,
 	}
 
 	// TODO: why not embed a hostconfig in builder?
 	hostConfig := &container.HostConfig{
-		Isolation: b.Isolation,
-		ShmSize:   b.ShmSize,
+		Isolation: b.options.IsolationLevel,
+		ShmSize:   b.options.ShmSize,
 		Resources: resources,
 	}
 
@@ -587,20 +587,20 @@ func (b *Builder) readDockerfile() error {
 	// If no -f was specified then look for 'Dockerfile'. If we can't find
 	// that then look for 'dockerfile'.  If neither are found then default
 	// back to 'Dockerfile' and use that in the error message.
-	if b.DockerfileName == "" {
-		b.DockerfileName = api.DefaultDockerfileName
-		if _, _, err := b.context.Stat(b.DockerfileName); os.IsNotExist(err) {
-			lowercase := strings.ToLower(b.DockerfileName)
+	if b.options.Dockerfile == "" {
+		b.options.Dockerfile = api.DefaultDockerfileName
+		if _, _, err := b.context.Stat(b.options.Dockerfile); os.IsNotExist(err) {
+			lowercase := strings.ToLower(b.options.Dockerfile)
 			if _, _, err := b.context.Stat(lowercase); err == nil {
-				b.DockerfileName = lowercase
+				b.options.Dockerfile = lowercase
 			}
 		}
 	}
 
-	f, err := b.context.Open(b.DockerfileName)
+	f, err := b.context.Open(b.options.Dockerfile)
 	if err != nil {
 		if os.IsNotExist(err) {
-			return fmt.Errorf("Cannot locate specified Dockerfile: %s", b.DockerfileName)
+			return fmt.Errorf("Cannot locate specified Dockerfile: %s", b.options.Dockerfile)
 		}
 		return err
 	}
@@ -611,7 +611,7 @@ func (b *Builder) readDockerfile() error {
 			return fmt.Errorf("Unexpected error reading Dockerfile: %v", err)
 		}
 		if fi.Size() == 0 {
-			return fmt.Errorf("The Dockerfile (%s) cannot be empty", b.DockerfileName)
+			return fmt.Errorf("The Dockerfile (%s) cannot be empty", b.options.Dockerfile)
 		}
 	}
 	b.dockerfile, err = parser.Parse(f)
@@ -629,7 +629,7 @@ func (b *Builder) readDockerfile() error {
 	// Note that this assumes the Dockerfile has been read into memory and
 	// is now safe to be removed.
 	if dockerIgnore, ok := b.context.(builder.DockerIgnoreContext); ok {
-		dockerIgnore.Process([]string{b.DockerfileName})
+		dockerIgnore.Process([]string{b.options.Dockerfile})
 	}
 	return nil
 }

+ 2 - 2
daemon/container_operations_unix.go

@@ -899,8 +899,8 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
 		}
 
 		shmSize := container.DefaultSHMSize
-		if c.HostConfig.ShmSize != nil {
-			shmSize = *c.HostConfig.ShmSize
+		if c.HostConfig.ShmSize != 0 {
+			shmSize = c.HostConfig.ShmSize
 		}
 		shmproperty := "mode=1777,size=" + strconv.FormatInt(shmSize, 10)
 		if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, c.GetMountLabel())); err != nil {

+ 3 - 4
daemon/daemon_unix.go

@@ -191,9 +191,8 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
 		// By default, MemorySwap is set to twice the size of Memory.
 		hostConfig.MemorySwap = hostConfig.Memory * 2
 	}
-	if hostConfig.ShmSize == nil {
-		shmSize := container.DefaultSHMSize
-		hostConfig.ShmSize = &shmSize
+	if hostConfig.ShmSize == 0 {
+		hostConfig.ShmSize = container.DefaultSHMSize
 	}
 	var err error
 	if hostConfig.SecurityOpt == nil {
@@ -365,7 +364,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
 	}
 	warnings = append(warnings, w...)
 
-	if hostConfig.ShmSize != nil && *hostConfig.ShmSize <= 0 {
+	if hostConfig.ShmSize < 0 {
 		return warnings, fmt.Errorf("SHM size must be greater then 0")
 	}
 

+ 3 - 15
integration-cli/docker_api_containers_test.go

@@ -1403,18 +1403,6 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *check.C) {
 	c.Assert(string(body), checker.Contains, "SHM size must be greater then 0")
 }
 
-func (s *DockerSuite) TestPostContainersCreateShmSizeZero(c *check.C) {
-	config := map[string]interface{}{
-		"Image":      "busybox",
-		"HostConfig": map[string]interface{}{"ShmSize": 0},
-	}
-
-	status, body, err := sockRequest("POST", "/containers/create", config)
-	c.Assert(err, check.IsNil)
-	c.Assert(status, check.Equals, http.StatusInternalServerError)
-	c.Assert(string(body), checker.Contains, "SHM size must be greater then 0")
-}
-
 func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *check.C) {
 	var defaultSHMSize int64 = 67108864
 	config := map[string]interface{}{
@@ -1436,7 +1424,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *check.
 	var containerJSON types.ContainerJSON
 	c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil)
 
-	c.Assert(*containerJSON.HostConfig.ShmSize, check.Equals, defaultSHMSize)
+	c.Assert(containerJSON.HostConfig.ShmSize, check.Equals, defaultSHMSize)
 
 	out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
 	shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`)
@@ -1466,7 +1454,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeOmitted(c *check.C) {
 	var containerJSON types.ContainerJSON
 	c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil)
 
-	c.Assert(*containerJSON.HostConfig.ShmSize, check.Equals, int64(67108864))
+	c.Assert(containerJSON.HostConfig.ShmSize, check.Equals, int64(67108864))
 
 	out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
 	shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`)
@@ -1496,7 +1484,7 @@ func (s *DockerSuite) TestPostContainersCreateWithShmSize(c *check.C) {
 	var containerJSON types.ContainerJSON
 	c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil)
 
-	c.Assert(*containerJSON.HostConfig.ShmSize, check.Equals, int64(1073741824))
+	c.Assert(containerJSON.HostConfig.ShmSize, check.Equals, int64(1073741824))
 
 	out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
 	shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=1048576k`)

+ 3 - 4
runconfig/opts/parse.go

@@ -186,13 +186,12 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
 		return nil, nil, cmd, fmt.Errorf("Invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
 	}
 
-	var parsedShm *int64
+	var shmSize int64
 	if *flShmSize != "" {
-		shmSize, err := units.RAMInBytes(*flShmSize)
+		shmSize, err = units.RAMInBytes(*flShmSize)
 		if err != nil {
 			return nil, nil, cmd, err
 		}
-		parsedShm = &shmSize
 	}
 
 	var binds []string
@@ -397,7 +396,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
 		LogConfig:      container.LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
 		VolumeDriver:   *flVolumeDriver,
 		Isolation:      container.IsolationLevel(*flIsolation),
-		ShmSize:        parsedShm,
+		ShmSize:        shmSize,
 		Resources:      resources,
 		Tmpfs:          tmpfs,
 	}

+ 2 - 2
runconfig/opts/parse_test.go

@@ -535,8 +535,8 @@ func TestParseModes(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if *hostconfig.ShmSize != 134217728 {
-		t.Fatalf("Expected a valid ShmSize, got %d", *hostconfig.ShmSize)
+	if hostconfig.ShmSize != 134217728 {
+		t.Fatalf("Expected a valid ShmSize, got %d", hostconfig.ShmSize)
 	}
 }