From f688b73835ce67f8a175b09b8a39859ae6b9ec06 Mon Sep 17 00:00:00 2001 From: Anusha Ragunathan Date: Tue, 29 Dec 2015 12:49:17 -0800 Subject: [PATCH] Use ImageBuildOptions in builder. dockerfile.Config is almost redundant with ImageBuildOptions. Unify the two so that the latter can be removed. This also helps build's API endpoint code to be less dependent on package dockerfile. Signed-off-by: Anusha Ragunathan Upstream-commit: 5190794f1d85d5406611eb69c270df62ac1cdc7f Component: engine --- components/engine/api/client/build.go | 15 +- .../engine/api/client/lib/image_build.go | 18 +-- .../api/server/router/build/build_routes.go | 146 ++++++++++-------- components/engine/api/types/client.go | 6 +- .../engine/api/types/container/host_config.go | 2 +- .../engine/builder/dockerfile/builder.go | 46 ++---- .../engine/builder/dockerfile/dispatchers.go | 8 +- .../engine/builder/dockerfile/evaluator.go | 2 +- .../engine/builder/dockerfile/internals.go | 42 ++--- .../daemon/container_operations_unix.go | 4 +- components/engine/daemon/daemon_unix.go | 7 +- .../docker_api_containers_test.go | 18 +-- components/engine/runconfig/opts/parse.go | 7 +- .../engine/runconfig/opts/parse_test.go | 4 +- 14 files changed, 147 insertions(+), 178 deletions(-) diff --git a/components/engine/api/client/build.go b/components/engine/api/client/build.go index 38ade49ef7..0e12b4de41 100644 --- a/components/engine/api/client/build.go +++ b/components/engine/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, } diff --git a/components/engine/api/client/lib/image_build.go b/components/engine/api/client/lib/image_build.go index 0ed5da8dc1..da4d6efc68 100644 --- a/components/engine/api/client/lib/image_build.go +++ b/components/engine/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 } diff --git a/components/engine/api/server/router/build/build_routes.go b/components/engine/api/server/router/build/build_routes.go index 4222004c07..0fec49586b 100644 --- a/components/engine/api/server/router/build/build_routes.go +++ b/components/engine/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)) } diff --git a/components/engine/api/types/client.go b/components/engine/api/types/client.go index 30f3b6fb8d..c936235173 100644 --- a/components/engine/api/types/client.go +++ b/components/engine/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 } diff --git a/components/engine/api/types/container/host_config.go b/components/engine/api/types/container/host_config.go index 96f73e1170..623e5d108f 100644 --- a/components/engine/api/types/container/host_config.go +++ b/components/engine/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 diff --git a/components/engine/builder/dockerfile/builder.go b/components/engine/builder/dockerfile/builder.go index 102918da9a..8951793bff 100644 --- a/components/engine/builder/dockerfile/builder.go +++ b/components/engine/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) } diff --git a/components/engine/builder/dockerfile/dispatchers.go b/components/engine/builder/dockerfile/dispatchers.go index 02d4413f1f..5f5f7f222e 100644 --- a/components/engine/builder/dockerfile/dispatchers.go +++ b/components/engine/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)) diff --git a/components/engine/builder/dockerfile/evaluator.go b/components/engine/builder/dockerfile/evaluator.go index 2b3d2c8297..270e3a4ffe 100644 --- a/components/engine/builder/dockerfile/evaluator.go +++ b/components/engine/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. diff --git a/components/engine/builder/dockerfile/internals.go b/components/engine/builder/dockerfile/internals.go index ce5f457a5e..70a9f44a59 100644 --- a/components/engine/builder/dockerfile/internals.go +++ b/components/engine/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 } diff --git a/components/engine/daemon/container_operations_unix.go b/components/engine/daemon/container_operations_unix.go index fb1f96677f..fceb2da42c 100644 --- a/components/engine/daemon/container_operations_unix.go +++ b/components/engine/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 { diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go index 68e04ea882..5186b29107 100644 --- a/components/engine/daemon/daemon_unix.go +++ b/components/engine/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") } diff --git a/components/engine/integration-cli/docker_api_containers_test.go b/components/engine/integration-cli/docker_api_containers_test.go index 5c33520170..6e1d288e61 100644 --- a/components/engine/integration-cli/docker_api_containers_test.go +++ b/components/engine/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`) diff --git a/components/engine/runconfig/opts/parse.go b/components/engine/runconfig/opts/parse.go index bef65c8779..ad3c0eeaab 100644 --- a/components/engine/runconfig/opts/parse.go +++ b/components/engine/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, } diff --git a/components/engine/runconfig/opts/parse_test.go b/components/engine/runconfig/opts/parse_test.go index 90703ea878..2c7e100ef9 100644 --- a/components/engine/runconfig/opts/parse_test.go +++ b/components/engine/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) } }