Merge pull request #18977 from anusha-ragunathan/builder

Use ImageBuildOptions in builder.
This commit is contained in:
David Calavera 2016-01-05 11:54:21 -08:00
commit acfd5eb947
14 changed files with 147 additions and 178 deletions

View File

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

View File

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

View File

@ -68,11 +68,72 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
return repoAndTags, nil 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 { func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
var ( var (
authConfigs = map[string]types.AuthConfig{} authConfigs = map[string]types.AuthConfig{}
authConfigsEncoded = r.Header.Get("X-Registry-Config") authConfigsEncoded = r.Header.Get("X-Registry-Config")
buildConfig = &dockerfile.Config{}
notVerboseBuffer = bytes.NewBuffer(nil) 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") w.Header().Set("Content-Type", "application/json")
version := httputils.VersionFromContext(ctx)
output := ioutils.NewWriteFlusher(w) output := ioutils.NewWriteFlusher(w)
defer output.Close() defer output.Close()
sf := streamformatter.NewJSONStreamFormatter() sf := streamformatter.NewJSONStreamFormatter()
errf := func(err error) error { errf := func(err error) error {
if !buildConfig.Verbose && notVerboseBuffer.Len() > 0 { if httputils.BoolValue(r, "q") && notVerboseBuffer.Len() > 0 {
output.Write(notVerboseBuffer.Bytes()) output.Write(notVerboseBuffer.Bytes())
} }
// Do not write the error in the http output if it's still empty. // 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 return nil
} }
if httputils.BoolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") { buildOptions, err := newImageBuildOptions(ctx, r)
buildConfig.Remove = true if err != nil {
} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") { return errf(err)
buildConfig.Remove = true
} else {
buildConfig.Remove = httputils.BoolValue(r, "rm")
}
if httputils.BoolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
buildConfig.Pull = true
} }
repoAndTags, err := sanitizeRepoAndTags(r.Form["t"]) repoAndTags, err := sanitizeRepoAndTags(r.Form["t"])
@ -123,59 +177,13 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
return errf(err) 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") remoteURL := r.FormValue("remote")
// Currently, only used if context is from a remote url. // Currently, only used if context is from a remote url.
// Look at code in DetectContextFromRemoteURL for more information. // Look at code in DetectContextFromRemoteURL for more information.
createProgressReader := func(in io.ReadCloser) io.ReadCloser { createProgressReader := func(in io.ReadCloser) io.ReadCloser {
progressOutput := sf.NewProgressOutput(output, true) progressOutput := sf.NewProgressOutput(output, true)
if !buildConfig.Verbose { if buildOptions.SuppressOutput {
progressOutput = sf.NewProgressOutput(notVerboseBuffer, true) progressOutput = sf.NewProgressOutput(notVerboseBuffer, true)
} }
return progress.NewProgressReader(in, progressOutput, r.ContentLength, "Downloading context", remoteURL) 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) logrus.Debugf("[BUILDER] failed to remove temporary context: %v", err)
} }
}() }()
if len(dockerfileName) > 0 {
buildOptions.Dockerfile = dockerfileName
}
uidMaps, gidMaps := br.backend.GetUIDGIDMaps() uidMaps, gidMaps := br.backend.GetUIDGIDMaps()
defaultArchiver := &archive.Archiver{ defaultArchiver := &archive.Archiver{
@ -201,23 +212,28 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
UIDMaps: uidMaps, UIDMaps: uidMaps,
GIDMaps: gidMaps, GIDMaps: gidMaps,
} }
docker := &daemonbuilder.Docker{ docker := &daemonbuilder.Docker{
Daemon: br.backend, Daemon: br.backend,
OutOld: output, OutOld: output,
AuthConfigs: authConfigs, AuthConfigs: authConfigs,
Archiver: defaultArchiver, Archiver: defaultArchiver,
} }
if !buildConfig.Verbose { if buildOptions.SuppressOutput {
docker.OutOld = notVerboseBuffer 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 { if err != nil {
return errf(err) return errf(err)
} }
b.Stdout = &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf} b.Stdout = &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
b.Stderr = &streamformatter.StderrFormatter{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.Stdout = &streamformatter.StdoutFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
b.Stderr = &streamformatter.StderrFormatter{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() imgID, err := b.Build()
if err != nil { if err != nil {
return errf(err) 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 // 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. // 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} stdout := &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
fmt.Fprintf(stdout, "%s\n", string(imgID)) fmt.Fprintf(stdout, "%s\n", string(imgID))
} }

View File

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

View File

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

View File

@ -10,11 +10,11 @@ import (
"sync" "sync"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder" "github.com/docker/docker/builder"
"github.com/docker/docker/builder/dockerfile/parser" "github.com/docker/docker/builder/dockerfile/parser"
"github.com/docker/docker/pkg/stringid" "github.com/docker/docker/pkg/stringid"
"github.com/docker/go-units"
) )
var validCommitCommands = map[string]bool{ var validCommitCommands = map[string]bool{
@ -41,38 +41,10 @@ var BuiltinAllowedBuildArgs = map[string]bool{
"no_proxy": true, "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 // Builder is a Dockerfile builder
// It implements the builder.Backend interface. // It implements the builder.Backend interface.
type Builder struct { type Builder struct {
*Config options *types.ImageBuildOptions
Stdout io.Writer Stdout io.Writer
Stderr 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. // NewBuilder creates a new Dockerfile builder from an optional dockerfile and a Config.
// If dockerfile is nil, the Dockerfile specified by Config.DockerfileName, // If dockerfile is nil, the Dockerfile specified by Config.DockerfileName,
// will be read from the Context passed to Build(). // 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 { if config == nil {
config = new(Config) config = new(types.ImageBuildOptions)
} }
if config.BuildArgs == nil { if config.BuildArgs == nil {
config.BuildArgs = make(map[string]string) config.BuildArgs = make(map[string]string)
} }
b = &Builder{ b = &Builder{
Config: config, options: config,
Stdout: os.Stdout, Stdout: os.Stdout,
Stderr: os.Stderr, Stderr: os.Stderr,
docker: docker, docker: backend,
context: context, context: context,
runConfig: new(container.Config), runConfig: new(container.Config),
tmpContainers: map[string]struct{}{}, tmpContainers: map[string]struct{}{},
@ -162,14 +134,14 @@ func (b *Builder) Build() (string, error) {
// Not cancelled yet, keep going... // Not cancelled yet, keep going...
} }
if err := b.dispatch(i, n); err != nil { if err := b.dispatch(i, n); err != nil {
if b.ForceRemove { if b.options.ForceRemove {
b.clearTmp() b.clearTmp()
} }
return "", err return "", err
} }
shortImgID = stringid.TruncateID(b.image) shortImgID = stringid.TruncateID(b.image)
fmt.Fprintf(b.Stdout, " ---> %s\n", shortImgID) fmt.Fprintf(b.Stdout, " ---> %s\n", shortImgID)
if b.Remove { if b.options.Remove {
b.clearTmp() 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 // check if there are any leftover build-args that were passed but not
// consumed during build. Return an error, if there are any. // consumed during build. Return an error, if there are any.
leftoverArgs := []string{} leftoverArgs := []string{}
for arg := range b.BuildArgs { for arg := range b.options.BuildArgs {
if !b.isBuildArgAllowed(arg) { if !b.isBuildArgAllowed(arg) {
leftoverArgs = append(leftoverArgs, arg) leftoverArgs = append(leftoverArgs, arg)
} }

View File

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

View File

@ -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 // a subsequent one. So, putting the buildArgs list after the Config.Env
// list, in 'envs', is safe. // list, in 'envs', is safe.
envs := b.runConfig.Env envs := b.runConfig.Env
for key, val := range b.BuildArgs { for key, val := range b.options.BuildArgs {
if !b.isBuildArgAllowed(key) { if !b.isBuildArgAllowed(key) {
// skip build-args that are not in allowed list, meaning they have // skip build-args that are not in allowed list, meaning they have
// not been defined by an "ARG" Dockerfile command yet. // not been defined by an "ARG" Dockerfile command yet.

View File

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

View File

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

View File

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

View File

@ -1403,18 +1403,6 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *check.C) {
c.Assert(string(body), checker.Contains, "SHM size must be greater then 0") 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) { func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *check.C) {
var defaultSHMSize int64 = 67108864 var defaultSHMSize int64 = 67108864
config := map[string]interface{}{ config := map[string]interface{}{
@ -1436,7 +1424,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *check.
var containerJSON types.ContainerJSON var containerJSON types.ContainerJSON
c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil) 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) out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`) 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 var containerJSON types.ContainerJSON
c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil) 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) out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`) 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 var containerJSON types.ContainerJSON
c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil) 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) out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=1048576k`) shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=1048576k`)

View File

@ -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) 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 != "" { if *flShmSize != "" {
shmSize, err := units.RAMInBytes(*flShmSize) shmSize, err = units.RAMInBytes(*flShmSize)
if err != nil { if err != nil {
return nil, nil, cmd, err return nil, nil, cmd, err
} }
parsedShm = &shmSize
} }
var binds []string 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}, LogConfig: container.LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
VolumeDriver: *flVolumeDriver, VolumeDriver: *flVolumeDriver,
Isolation: container.IsolationLevel(*flIsolation), Isolation: container.IsolationLevel(*flIsolation),
ShmSize: parsedShm, ShmSize: shmSize,
Resources: resources, Resources: resources,
Tmpfs: tmpfs, Tmpfs: tmpfs,
} }

View File

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