mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Container memory limit can be specified in kilobytes, megabytes or gigabytes
-m 10 # 10 bytes -m 10b # 10 bytes -m 10k # 10240 bytes (10 * 1024) -m 10m # 10485760 bytes (10 * 1024 * 1024) -m 10g # 10737418240 bytes (10 * 1024 * 1024 * 1024) Units are case-insensitive, and 'kb', 'mb' and 'gb' are equivalent to 'k', 'm' and 'g'.
This commit is contained in:
parent
4dc156252b
commit
9ee9d2f995
4 changed files with 83 additions and 6 deletions
22
container.go
22
container.go
|
@ -162,7 +162,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
||||||
cmd.Var(flAttach, "a", "Attach to stdin, stdout or stderr.")
|
cmd.Var(flAttach, "a", "Attach to stdin, stdout or stderr.")
|
||||||
flStdin := cmd.Bool("i", false, "Keep stdin open even if not attached")
|
flStdin := cmd.Bool("i", false, "Keep stdin open even if not attached")
|
||||||
flTty := cmd.Bool("t", false, "Allocate a pseudo-tty")
|
flTty := cmd.Bool("t", false, "Allocate a pseudo-tty")
|
||||||
flMemory := cmd.Int64("m", 0, "Memory limit (in bytes)")
|
flMemoryString := cmd.String("m", "", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)")
|
||||||
flContainerIDFile := cmd.String("cidfile", "", "Write the container ID to the file")
|
flContainerIDFile := cmd.String("cidfile", "", "Write the container ID to the file")
|
||||||
flNetwork := cmd.Bool("n", true, "Enable networking for this container")
|
flNetwork := cmd.Bool("n", true, "Enable networking for this container")
|
||||||
flPrivileged := cmd.Bool("privileged", false, "Give extended privileges to this container")
|
flPrivileged := cmd.Bool("privileged", false, "Give extended privileges to this container")
|
||||||
|
@ -170,9 +170,9 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
||||||
cmd.Bool("sig-proxy", true, "Proxify all received signal to the process (even in non-tty mode)")
|
cmd.Bool("sig-proxy", true, "Proxify all received signal to the process (even in non-tty mode)")
|
||||||
cmd.String("name", "", "Assign a name to the container")
|
cmd.String("name", "", "Assign a name to the container")
|
||||||
|
|
||||||
if capabilities != nil && *flMemory > 0 && !capabilities.MemoryLimit {
|
if capabilities != nil && *flMemoryString != "" && !capabilities.MemoryLimit {
|
||||||
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
|
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
|
||||||
*flMemory = 0
|
*flMemoryString = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
flCpuShares := cmd.Int64("c", 0, "CPU shares (relative weight)")
|
flCpuShares := cmd.Int64("c", 0, "CPU shares (relative weight)")
|
||||||
|
@ -239,6 +239,18 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var flMemory int64
|
||||||
|
|
||||||
|
if *flMemoryString != "" {
|
||||||
|
parsedMemory, err := utils.RAMInBytes(*flMemoryString)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, cmd, err
|
||||||
|
}
|
||||||
|
|
||||||
|
flMemory = parsedMemory
|
||||||
|
}
|
||||||
|
|
||||||
var binds []string
|
var binds []string
|
||||||
|
|
||||||
// add any bind targets to the list of container volumes
|
// add any bind targets to the list of container volumes
|
||||||
|
@ -306,7 +318,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
||||||
Tty: *flTty,
|
Tty: *flTty,
|
||||||
NetworkDisabled: !*flNetwork,
|
NetworkDisabled: !*flNetwork,
|
||||||
OpenStdin: *flStdin,
|
OpenStdin: *flStdin,
|
||||||
Memory: *flMemory,
|
Memory: flMemory,
|
||||||
CpuShares: *flCpuShares,
|
CpuShares: *flCpuShares,
|
||||||
AttachStdin: flAttach.Get("stdin"),
|
AttachStdin: flAttach.Get("stdin"),
|
||||||
AttachStdout: flAttach.Get("stdout"),
|
AttachStdout: flAttach.Get("stdout"),
|
||||||
|
@ -330,7 +342,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
||||||
Links: flLinks,
|
Links: flLinks,
|
||||||
}
|
}
|
||||||
|
|
||||||
if capabilities != nil && *flMemory > 0 && !capabilities.SwapLimit {
|
if capabilities != nil && flMemory > 0 && !capabilities.SwapLimit {
|
||||||
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
||||||
config.MemorySwap = -1
|
config.MemorySwap = -1
|
||||||
}
|
}
|
||||||
|
|
|
@ -568,7 +568,7 @@ network communication.
|
||||||
-h="": Container host name
|
-h="": Container host name
|
||||||
-i=false: Keep stdin open even if not attached
|
-i=false: Keep stdin open even if not attached
|
||||||
-privileged=false: Give extended privileges to this container
|
-privileged=false: Give extended privileges to this container
|
||||||
-m=0: Memory limit (in bytes)
|
-m="": Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
|
||||||
-n=true: Enable networking for this container
|
-n=true: Enable networking for this container
|
||||||
-p=[]: Map a network port to the container
|
-p=[]: Map a network port to the container
|
||||||
-rm=false: Automatically remove the container when it exits (incompatible with -d)
|
-rm=false: Automatically remove the container when it exits (incompatible with -d)
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -176,6 +177,37 @@ func HumanSize(size int64) string {
|
||||||
return fmt.Sprintf("%.4g %s", sizef, units[i])
|
return fmt.Sprintf("%.4g %s", sizef, units[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parses a human-readable string representing an amount of RAM
|
||||||
|
// in bytes, kibibytes, mebibytes or gibibytes, and returns the
|
||||||
|
// number of bytes, or -1 if the string is unparseable.
|
||||||
|
// Units are case-insensitive, and the 'b' suffix is optional.
|
||||||
|
func RAMInBytes(size string) (bytes int64, err error) {
|
||||||
|
re, error := regexp.Compile("^(\\d+)([kKmMgG])?[bB]?$")
|
||||||
|
if error != nil { return -1, error }
|
||||||
|
|
||||||
|
matches := re.FindStringSubmatch(size)
|
||||||
|
|
||||||
|
if len(matches) != 3 {
|
||||||
|
return -1, fmt.Errorf("Invalid size: '%s'", size)
|
||||||
|
}
|
||||||
|
|
||||||
|
memLimit, error := strconv.ParseInt(matches[1], 10, 0)
|
||||||
|
if error != nil { return -1, error }
|
||||||
|
|
||||||
|
unit := strings.ToLower(matches[2])
|
||||||
|
|
||||||
|
if unit == "k" {
|
||||||
|
memLimit *= 1024
|
||||||
|
} else if unit == "m" {
|
||||||
|
memLimit *= 1024*1024
|
||||||
|
} else if unit == "g" {
|
||||||
|
memLimit *= 1024*1024*1024
|
||||||
|
}
|
||||||
|
|
||||||
|
return memLimit, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func Trunc(s string, maxlen int) string {
|
func Trunc(s string, maxlen int) string {
|
||||||
if len(s) <= maxlen {
|
if len(s) <= maxlen {
|
||||||
return s
|
return s
|
||||||
|
|
|
@ -265,6 +265,39 @@ func TestHumanSize(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRAMInBytes(t *testing.T) {
|
||||||
|
assertRAMInBytes(t, "32", false, 32)
|
||||||
|
assertRAMInBytes(t, "32b", false, 32)
|
||||||
|
assertRAMInBytes(t, "32B", false, 32)
|
||||||
|
assertRAMInBytes(t, "32k", false, 32*1024)
|
||||||
|
assertRAMInBytes(t, "32K", false, 32*1024)
|
||||||
|
assertRAMInBytes(t, "32kb", false, 32*1024)
|
||||||
|
assertRAMInBytes(t, "32Kb", false, 32*1024)
|
||||||
|
assertRAMInBytes(t, "32Mb", false, 32*1024*1024)
|
||||||
|
assertRAMInBytes(t, "32Gb", false, 32*1024*1024*1024)
|
||||||
|
|
||||||
|
assertRAMInBytes(t, "", true, -1)
|
||||||
|
assertRAMInBytes(t, "hello", true, -1)
|
||||||
|
assertRAMInBytes(t, "-32", true, -1)
|
||||||
|
assertRAMInBytes(t, " 32 ", true, -1)
|
||||||
|
assertRAMInBytes(t, "32 mb", true, -1)
|
||||||
|
assertRAMInBytes(t, "32m b", true, -1)
|
||||||
|
assertRAMInBytes(t, "32bm", true, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertRAMInBytes(t *testing.T, size string, expectError bool, expectedBytes int64) {
|
||||||
|
actualBytes, err := RAMInBytes(size)
|
||||||
|
if (err != nil) && !expectError {
|
||||||
|
t.Errorf("Unexpected error parsing '%s': %s", size, err)
|
||||||
|
}
|
||||||
|
if (err == nil) && expectError {
|
||||||
|
t.Errorf("Expected to get an error parsing '%s', but got none (bytes=%d)", size, actualBytes)
|
||||||
|
}
|
||||||
|
if actualBytes != expectedBytes {
|
||||||
|
t.Errorf("Expected '%s' to parse as %d bytes, got %d", size, expectedBytes, actualBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseHost(t *testing.T) {
|
func TestParseHost(t *testing.T) {
|
||||||
if addr, err := ParseHost("127.0.0.1", 4243, "0.0.0.0"); err != nil || addr != "tcp://0.0.0.0:4243" {
|
if addr, err := ParseHost("127.0.0.1", 4243, "0.0.0.0"); err != nil || addr != "tcp://0.0.0.0:4243" {
|
||||||
t.Errorf("0.0.0.0 -> expected tcp://0.0.0.0:4243, got %s", addr)
|
t.Errorf("0.0.0.0 -> expected tcp://0.0.0.0:4243, got %s", addr)
|
||||||
|
|
Loading…
Add table
Reference in a new issue