mirror of https://github.com/docker/docs.git
Merge pull request #18977 from anusha-ragunathan/builder
Use ImageBuildOptions in builder.
This commit is contained in:
commit
acfd5eb947
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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`)
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue