... | ... |
@@ -7,11 +7,11 @@ Vagrant::Config.run do |config| |
7 | 7 |
# please see the online documentation at vagrantup.com. |
8 | 8 |
|
9 | 9 |
# Every Vagrant virtual environment requires a box to build off of. |
10 |
- config.vm.box = "quantal64" |
|
10 |
+ config.vm.box = "quantal64_3.5.0-25" |
|
11 | 11 |
|
12 | 12 |
# The url from where the 'config.vm.box' box will be fetched if it |
13 | 13 |
# doesn't already exist on the user's system. |
14 |
- config.vm.box_url = "http://unworkable.org/~niallo/quantal64.box" |
|
14 |
+ config.vm.box_url = "http://get.docker.io/vbox/ubuntu/12.10/quantal64_3.5.0-25.box" |
|
15 | 15 |
|
16 | 16 |
# Boot with a GUI so you can see the screen. (Default is headless) |
17 | 17 |
# config.vm.boot_mode = :gui |
... | ... |
@@ -111,6 +111,7 @@ func InteractiveMode(scripts ...string) error { |
111 | 111 |
if err != nil { |
112 | 112 |
return err |
113 | 113 |
} |
114 |
+ defer os.Remove(rcfile.Name()) |
|
114 | 115 |
io.WriteString(rcfile, "enable -n help\n") |
115 | 116 |
os.Setenv("PATH", tmp+":"+os.Getenv("PATH")) |
116 | 117 |
os.Setenv("PS1", "\\h docker> ") |
... | ... |
@@ -53,12 +53,13 @@ type Container struct { |
53 | 53 |
} |
54 | 54 |
|
55 | 55 |
type Config struct { |
56 |
- Hostname string |
|
57 |
- User string |
|
58 |
- Ram int64 |
|
59 |
- Ports []int |
|
60 |
- Tty bool // Attach standard streams to a tty, including stdin if it is not closed. |
|
61 |
- OpenStdin bool // Open stdin |
|
56 |
+ Hostname string |
|
57 |
+ User string |
|
58 |
+ Memory int64 // Memory limit (in bytes) |
|
59 |
+ MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap |
|
60 |
+ Ports []int |
|
61 |
+ Tty bool // Attach standard streams to a tty, including stdin if it is not closed. |
|
62 |
+ OpenStdin bool // Open stdin |
|
62 | 63 |
} |
63 | 64 |
|
64 | 65 |
type NetworkSettings struct { |
... | ... |
@@ -2,9 +2,12 @@ package docker |
2 | 2 |
|
3 | 3 |
import ( |
4 | 4 |
"./fs" |
5 |
+ "bufio" |
|
5 | 6 |
"fmt" |
6 | 7 |
"io" |
7 | 8 |
"io/ioutil" |
9 |
+ "math/rand" |
|
10 |
+ "os" |
|
8 | 11 |
"sort" |
9 | 12 |
"strings" |
10 | 13 |
"testing" |
... | ... |
@@ -23,7 +26,7 @@ func TestCommitRun(t *testing.T) { |
23 | 23 |
[]string{"-c", "echo hello > /world"}, |
24 | 24 |
GetTestImage(docker), |
25 | 25 |
&Config{ |
26 |
- Ram: 33554432, |
|
26 |
+ Memory: 33554432, |
|
27 | 27 |
}, |
28 | 28 |
) |
29 | 29 |
if err != nil { |
... | ... |
@@ -65,7 +68,7 @@ func TestCommitRun(t *testing.T) { |
65 | 65 |
[]string{"/world"}, |
66 | 66 |
img, |
67 | 67 |
&Config{ |
68 |
- Ram: 33554432, |
|
68 |
+ Memory: 33554432, |
|
69 | 69 |
}, |
70 | 70 |
) |
71 | 71 |
if err != nil { |
... | ... |
@@ -100,7 +103,7 @@ func TestRun(t *testing.T) { |
100 | 100 |
[]string{"-al"}, |
101 | 101 |
GetTestImage(docker), |
102 | 102 |
&Config{ |
103 |
- Ram: 33554432, |
|
103 |
+ Memory: 33554432, |
|
104 | 104 |
}, |
105 | 105 |
) |
106 | 106 |
if err != nil { |
... | ... |
@@ -349,7 +352,7 @@ func TestUser(t *testing.T) { |
349 | 349 |
// Set a username |
350 | 350 |
container, err = docker.Create( |
351 | 351 |
"user_root", |
352 |
- "/bin/id", |
|
352 |
+ "id", |
|
353 | 353 |
[]string{}, |
354 | 354 |
GetTestImage(docker), |
355 | 355 |
&Config{ |
... | ... |
@@ -393,7 +396,7 @@ func TestUser(t *testing.T) { |
393 | 393 |
// Set a different user by uid |
394 | 394 |
container, err = docker.Create( |
395 | 395 |
"user_uid1", |
396 |
- "/usr/bin/id", |
|
396 |
+ "id", |
|
397 | 397 |
[]string{}, |
398 | 398 |
GetTestImage(docker), |
399 | 399 |
&Config{ |
... | ... |
@@ -417,7 +420,7 @@ func TestUser(t *testing.T) { |
417 | 417 |
// Set a different user by username |
418 | 418 |
container, err = docker.Create( |
419 | 419 |
"user_daemon", |
420 |
- "/usr/bin/id", |
|
420 |
+ "id", |
|
421 | 421 |
[]string{}, |
422 | 422 |
GetTestImage(docker), |
423 | 423 |
&Config{ |
... | ... |
@@ -616,6 +619,59 @@ func TestEnv(t *testing.T) { |
616 | 616 |
} |
617 | 617 |
} |
618 | 618 |
|
619 |
+func grepFile(t *testing.T, path string, pattern string) { |
|
620 |
+ f, err := os.Open(path) |
|
621 |
+ if err != nil { |
|
622 |
+ t.Fatal(err) |
|
623 |
+ } |
|
624 |
+ defer f.Close() |
|
625 |
+ r := bufio.NewReader(f) |
|
626 |
+ var ( |
|
627 |
+ line string |
|
628 |
+ ) |
|
629 |
+ err = nil |
|
630 |
+ for err == nil { |
|
631 |
+ line, err = r.ReadString('\n') |
|
632 |
+ if strings.Contains(line, pattern) == true { |
|
633 |
+ return |
|
634 |
+ } |
|
635 |
+ } |
|
636 |
+ t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path) |
|
637 |
+} |
|
638 |
+ |
|
639 |
+func TestLXCConfig(t *testing.T) { |
|
640 |
+ docker, err := newTestDocker() |
|
641 |
+ if err != nil { |
|
642 |
+ t.Fatal(err) |
|
643 |
+ } |
|
644 |
+ defer nuke(docker) |
|
645 |
+ // Memory is allocated randomly for testing |
|
646 |
+ rand.Seed(time.Now().UTC().UnixNano()) |
|
647 |
+ memMin := 33554432 |
|
648 |
+ memMax := 536870912 |
|
649 |
+ mem := memMin + rand.Intn(memMax-memMin) |
|
650 |
+ container, err := docker.Create( |
|
651 |
+ "config_test", |
|
652 |
+ "/bin/true", |
|
653 |
+ []string{}, |
|
654 |
+ GetTestImage(docker), |
|
655 |
+ &Config{ |
|
656 |
+ Hostname: "foobar", |
|
657 |
+ Memory: int64(mem), |
|
658 |
+ }, |
|
659 |
+ ) |
|
660 |
+ if err != nil { |
|
661 |
+ t.Fatal(err) |
|
662 |
+ } |
|
663 |
+ defer docker.Destroy(container) |
|
664 |
+ container.generateLXCConfig() |
|
665 |
+ grepFile(t, container.lxcConfigPath, "lxc.utsname = foobar") |
|
666 |
+ grepFile(t, container.lxcConfigPath, |
|
667 |
+ fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem)) |
|
668 |
+ grepFile(t, container.lxcConfigPath, |
|
669 |
+ fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2)) |
|
670 |
+} |
|
671 |
+ |
|
619 | 672 |
func BenchmarkRunSequencial(b *testing.B) { |
620 | 673 |
docker, err := newTestDocker() |
621 | 674 |
if err != nil { |
... | ... |
@@ -1,20 +1,46 @@ |
1 |
-# This script is meant for quick & easy install via 'curl URL-OF-SCRIPPT | bash' |
|
2 |
-# Courtesy of Jeff Lindsay <progrium@gmail.com> |
|
3 |
- |
|
4 |
-cd /tmp |
|
5 |
- |
|
6 |
-echo "Ensuring dependencies are installed..." |
|
7 |
-apt-get --yes install lxc wget bsdtar 2>&1 > /dev/null |
|
8 |
- |
|
9 |
-echo "Downloading docker binary..." |
|
10 |
-wget -q https://dl.dropbox.com/u/20637798/docker.tar.gz 2>&1 > /dev/null |
|
11 |
-tar -xf docker.tar.gz 2>&1 > /dev/null |
|
1 |
+#!/bin/sh |
|
2 |
+# This script is meant for quick & easy install via 'curl URL-OF-SCRIPT | sh' |
|
3 |
+# Original version by Jeff Lindsay <progrium@gmail.com> |
|
4 |
+# Revamped by Jerome Petazzoni <jerome@dotcloud.com> |
|
5 |
+# |
|
6 |
+# This script canonical location is http://get.docker.io/; to update it, run: |
|
7 |
+# s3cmd put -m text/x-shellscript -P install.sh s3://get.docker.io/index |
|
8 |
+ |
|
9 |
+echo "Ensuring basic dependencies are installed..." |
|
10 |
+apt-get -qq update |
|
11 |
+apt-get -qq install lxc wget bsdtar |
|
12 |
+ |
|
13 |
+echo "Looking in /proc/filesystems to see if we have AUFS support..." |
|
14 |
+if grep -q aufs /proc/filesystems |
|
15 |
+then |
|
16 |
+ echo "Found." |
|
17 |
+else |
|
18 |
+ echo "Ahem, it looks like the current kernel does not support AUFS." |
|
19 |
+ echo "Let's see if we can load the AUFS module with modprobe..." |
|
20 |
+ if modprobe aufs |
|
21 |
+ then |
|
22 |
+ echo "Module loaded." |
|
23 |
+ else |
|
24 |
+ echo "Ahem, things didn't turn out as expected." |
|
25 |
+ KPKG=linux-image-extra-$(uname -r) |
|
26 |
+ echo "Trying to install $KPKG..." |
|
27 |
+ if apt-get -qq install $KPKG |
|
28 |
+ then |
|
29 |
+ echo "Installed." |
|
30 |
+ else |
|
31 |
+ echo "Oops, we couldn't install the -extra kernel." |
|
32 |
+ echo "Are you sure you are running a supported version of Ubuntu?" |
|
33 |
+ echo "Proceeding anyway, but Docker will probably NOT WORK!" |
|
34 |
+ fi |
|
35 |
+ fi |
|
36 |
+fi |
|
12 | 37 |
|
13 |
-echo "Installing into /usr/local/bin..." |
|
14 |
-mv docker/docker /usr/local/bin |
|
15 |
-mv dockerd/dockerd /usr/local/bin |
|
38 |
+echo "Downloading docker binary and uncompressing into /usr/local/bin..." |
|
39 |
+curl -s http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz | |
|
40 |
+tar -C /usr/local/bin --strip-components=1 -zxf- \ |
|
41 |
+docker-master/docker docker-master/dockerd |
|
16 | 42 |
|
17 |
-if [[ -f /etc/init/dockerd.conf ]] |
|
43 |
+if [ -f /etc/init/dockerd.conf ] |
|
18 | 44 |
then |
19 | 45 |
echo "Upstart script already exists." |
20 | 46 |
else |
... | ... |
@@ -22,13 +48,8 @@ else |
22 | 22 |
echo "exec /usr/local/bin/dockerd" > /etc/init/dockerd.conf |
23 | 23 |
fi |
24 | 24 |
|
25 |
-echo "Restarting dockerd..." |
|
26 |
-restart dockerd > /dev/null |
|
27 |
- |
|
28 |
-echo "Cleaning up..." |
|
29 |
-rmdir docker |
|
30 |
-rmdir dockerd |
|
31 |
-rm docker.tar.gz |
|
25 |
+echo "Starting dockerd..." |
|
26 |
+start dockerd > /dev/null |
|
32 | 27 |
|
33 |
-echo "Finished!" |
|
28 |
+echo "Done." |
|
34 | 29 |
echo |
... | ... |
@@ -85,16 +85,32 @@ lxc.mount.entry = /etc/resolv.conf {{$ROOTFS}}/etc/resolv.conf none bind,ro 0 0 |
85 | 85 |
lxc.cap.drop = audit_control audit_write mac_admin mac_override mknod net_raw setfcap setpcap sys_admin sys_boot sys_module sys_nice sys_pacct sys_rawio sys_resource sys_time sys_tty_config |
86 | 86 |
|
87 | 87 |
# limits |
88 |
-{{if .Config.Ram}} |
|
89 |
-lxc.cgroup.memory.limit_in_bytes = {{.Config.Ram}} |
|
88 |
+{{if .Config.Memory}} |
|
89 |
+lxc.cgroup.memory.limit_in_bytes = {{.Config.Memory}} |
|
90 |
+lxc.cgroup.memory.soft_limit_in_bytes = {{.Config.Memory}} |
|
91 |
+{{with $memSwap := getMemorySwap .Config}} |
|
92 |
+lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}} |
|
93 |
+{{end}} |
|
90 | 94 |
{{end}} |
91 | 95 |
` |
92 | 96 |
|
93 | 97 |
var LxcTemplateCompiled *template.Template |
94 | 98 |
|
99 |
+func getMemorySwap(config *Config) int64 { |
|
100 |
+ // By default, MemorySwap is set to twice the size of RAM. |
|
101 |
+ // If you want to omit MemorySwap, set it to `-1'. |
|
102 |
+ if config.MemorySwap < 0 { |
|
103 |
+ return 0 |
|
104 |
+ } |
|
105 |
+ return config.Memory * 2 |
|
106 |
+} |
|
107 |
+ |
|
95 | 108 |
func init() { |
96 | 109 |
var err error |
97 |
- LxcTemplateCompiled, err = template.New("lxc").Parse(LxcTemplate) |
|
110 |
+ funcMap := template.FuncMap{ |
|
111 |
+ "getMemorySwap": getMemorySwap, |
|
112 |
+ } |
|
113 |
+ LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate) |
|
98 | 114 |
if err != nil { |
99 | 115 |
panic(err) |
100 | 116 |
} |
... | ... |
@@ -1,14 +1,19 @@ |
1 | 1 |
class docker { |
2 | 2 |
|
3 | 3 |
# update this with latest docker binary distro |
4 |
- $docker_url = "https://dl.dropbox.com/u/20637798/docker.tar.gz" |
|
4 |
+ $docker_url = "http://docker.io.s3.amazonaws.com/builds/$kernel/$hardwaremodel/docker-master.tgz" |
|
5 | 5 |
# update this with latest go binary distry |
6 | 6 |
$go_url = "http://go.googlecode.com/files/go1.0.3.linux-amd64.tar.gz" |
7 | 7 |
|
8 |
- |
|
9 | 8 |
Package { ensure => "installed" } |
10 | 9 |
|
11 |
- package { ["lxc", "debootstrap", "wget", "bsdtar"]: } |
|
10 |
+ package { ["lxc", "debootstrap", "wget", "bsdtar", "git", |
|
11 |
+ "linux-image-3.5.0-25-generic", |
|
12 |
+ "linux-image-extra-3.5.0-25-generic", |
|
13 |
+ "virtualbox-guest-utils", |
|
14 |
+ "linux-headers-3.5.0-25-generic"]: } |
|
15 |
+ |
|
16 |
+ notify { "docker_url = $docker_url": withpath => true } |
|
12 | 17 |
|
13 | 18 |
exec { "debootstrap" : |
14 | 19 |
require => Package["debootstrap"], |
... | ... |
@@ -26,7 +31,7 @@ class docker { |
26 | 26 |
exec { "fetch-docker" : |
27 | 27 |
require => Package["wget"], |
28 | 28 |
command => "/usr/bin/wget -O - $docker_url | /bin/tar xz -C /home/vagrant", |
29 |
- creates => "/home/vagrant/docker/dockerd" |
|
29 |
+ creates => "/home/vagrant/docker-master" |
|
30 | 30 |
} |
31 | 31 |
|
32 | 32 |
file { "/etc/init/dockerd.conf": |
... | ... |
@@ -39,10 +44,21 @@ class docker { |
39 | 39 |
|
40 | 40 |
exec { "copy-docker-bin" : |
41 | 41 |
require => Exec["fetch-docker"], |
42 |
- command => "/bin/cp /home/vagrant/docker/docker /usr/local/bin", |
|
42 |
+ command => "/bin/cp /home/vagrant/docker-master/docker /usr/local/bin", |
|
43 | 43 |
creates => "/usr/local/bin/docker" |
44 | 44 |
} |
45 | 45 |
|
46 |
+ exec { "copy-dockerd-bin" : |
|
47 |
+ require => Exec["fetch-docker"], |
|
48 |
+ command => "/bin/cp /home/vagrant/docker-master/dockerd /usr/local/bin", |
|
49 |
+ creates => "/usr/local/bin/dockerd" |
|
50 |
+ } |
|
51 |
+ |
|
52 |
+ exec { "vbox-add" : |
|
53 |
+ require => Package["linux-headers-3.5.0-25-generic"], |
|
54 |
+ command => "/etc/init.d/vboxadd setup", |
|
55 |
+ } |
|
56 |
+ |
|
46 | 57 |
service { "dockerd" : |
47 | 58 |
ensure => "running", |
48 | 59 |
start => "/sbin/initctl start dockerd", |
... | ... |
@@ -37,28 +37,43 @@ func (srv *Server) Name() string { |
37 | 37 |
return "docker" |
38 | 38 |
} |
39 | 39 |
|
40 |
+// FIXME: Stop violating DRY by repeating usage here and in Subcmd declarations |
|
40 | 41 |
func (srv *Server) Help() string { |
41 | 42 |
help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n" |
42 | 43 |
for _, cmd := range [][]interface{}{ |
43 | 44 |
{"run", "Run a command in a container"}, |
44 | 45 |
{"ps", "Display a list of containers"}, |
45 | 46 |
{"import", "Create a new filesystem image from the contents of a tarball"}, |
46 |
- {"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"}, |
|
47 |
- {"rm", "Remove containers"}, |
|
48 |
- {"kill", "Kill a running container"}, |
|
49 |
- {"wait", "Wait for the state of a container to change"}, |
|
50 |
- {"stop", "Stop a running container"}, |
|
51 |
- {"start", "Start a stopped container"}, |
|
52 |
- {"restart", "Restart a running container"}, |
|
53 |
- {"logs", "Fetch the logs of a container"}, |
|
47 |
+ {"attach", "Attach to a running container"}, |
|
48 |
+ {"cat", "Write the contents of a container's file to standard output"}, |
|
49 |
+ {"commit", "Create a new image from a container's changes"}, |
|
50 |
+ {"cp", "Create a copy of IMAGE and call it NAME"}, |
|
51 |
+ {"debug", "(debug only) (No documentation available)"}, |
|
54 | 52 |
{"diff", "Inspect changes on a container's filesystem"}, |
55 |
- {"commit", "Save the state of a container"}, |
|
56 |
- {"attach", "Attach to the standard inputs and outputs of a running container"}, |
|
57 |
- {"wait", "Block until a container exits, then print its exit code"}, |
|
53 |
+ {"images", "List images"}, |
|
58 | 54 |
{"info", "Display system-wide information"}, |
55 |
+ {"inspect", "Return low-level information on a container"}, |
|
56 |
+ {"kill", "Kill a running container"}, |
|
57 |
+ {"layers", "(debug only) List filesystem layers"}, |
|
58 |
+ {"logs", "Fetch the logs of a container"}, |
|
59 |
+ {"ls", "List the contents of a container's directory"}, |
|
60 |
+ {"mirror", "(debug only) (No documentation available)"}, |
|
61 |
+ {"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"}, |
|
62 |
+ {"ps", "List containers"}, |
|
63 |
+ {"pull", "Download a new image from a remote location"}, |
|
64 |
+ {"put", "Import a new image from a local archive"}, |
|
65 |
+ {"reset", "Reset changes to a container's filesystem"}, |
|
66 |
+ {"restart", "Restart a running container"}, |
|
67 |
+ {"rm", "Remove a container"}, |
|
68 |
+ {"rmimage", "Remove an image"}, |
|
69 |
+ {"run", "Run a command in a new container"}, |
|
70 |
+ {"start", "Start a stopped container"}, |
|
71 |
+ {"stop", "Stop a running container"}, |
|
59 | 72 |
{"tar", "Stream the contents of a container as a tar archive"}, |
60 |
- {"web", "Generate a web UI"}, |
|
61 |
- {"images", "List images"}, |
|
73 |
+ {"umount", "(debug only) Mount a container's filesystem"}, |
|
74 |
+ {"wait", "Block until a container stops, then print its exit code"}, |
|
75 |
+ {"web", "A web UI for docker"}, |
|
76 |
+ {"write", "Write the contents of standard input to a container's file"}, |
|
62 | 77 |
} { |
63 | 78 |
help += fmt.Sprintf(" %-10.10s%s\n", cmd...) |
64 | 79 |
} |
... | ... |
@@ -69,7 +84,6 @@ func (srv *Server) Help() string { |
69 | 69 |
func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
70 | 70 |
cmd := rcli.Subcmd(stdout, "wait", "[OPTIONS] NAME", "Block until a container stops, then print its exit code.") |
71 | 71 |
if err := cmd.Parse(args); err != nil { |
72 |
- cmd.Usage() |
|
73 | 72 |
return nil |
74 | 73 |
} |
75 | 74 |
if cmd.NArg() < 1 { |
... | ... |
@@ -88,25 +102,24 @@ func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string |
88 | 88 |
|
89 | 89 |
// 'docker info': display system-wide information. |
90 | 90 |
func (srv *Server) CmdInfo(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
91 |
- images, _ := srv.images.Images() |
|
92 |
- var imgcount int |
|
93 |
- if images == nil { |
|
94 |
- imgcount = 0 |
|
95 |
- } else { |
|
96 |
- imgcount = len(images) |
|
91 |
+ cmd := rcli.Subcmd(stdout, "info", "", "Display system-wide information.") |
|
92 |
+ if err := cmd.Parse(args); err != nil { |
|
93 |
+ return nil |
|
94 |
+ } |
|
95 |
+ if cmd.NArg() > 1 { |
|
96 |
+ cmd.Usage() |
|
97 |
+ return nil |
|
97 | 98 |
} |
98 |
- |
|
99 | 99 |
fmt.Fprintf(stdout, "containers: %d\nversion: %s\nimages: %d\n", |
100 | 100 |
len(srv.containers.List()), |
101 | 101 |
VERSION, |
102 |
- imgcount) |
|
102 |
+ len(srv.images.ById)) |
|
103 | 103 |
return nil |
104 | 104 |
} |
105 | 105 |
|
106 | 106 |
func (srv *Server) CmdStop(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
107 | 107 |
cmd := rcli.Subcmd(stdout, "stop", "[OPTIONS] NAME", "Stop a running container") |
108 | 108 |
if err := cmd.Parse(args); err != nil { |
109 |
- cmd.Usage() |
|
110 | 109 |
return nil |
111 | 110 |
} |
112 | 111 |
if cmd.NArg() < 1 { |
... | ... |
@@ -129,7 +142,6 @@ func (srv *Server) CmdStop(stdin io.ReadCloser, stdout io.Writer, args ...string |
129 | 129 |
func (srv *Server) CmdRestart(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
130 | 130 |
cmd := rcli.Subcmd(stdout, "restart", "[OPTIONS] NAME", "Restart a running container") |
131 | 131 |
if err := cmd.Parse(args); err != nil { |
132 |
- cmd.Usage() |
|
133 | 132 |
return nil |
134 | 133 |
} |
135 | 134 |
if cmd.NArg() < 1 { |
... | ... |
@@ -152,7 +164,6 @@ func (srv *Server) CmdRestart(stdin io.ReadCloser, stdout io.Writer, args ...str |
152 | 152 |
func (srv *Server) CmdStart(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
153 | 153 |
cmd := rcli.Subcmd(stdout, "start", "[OPTIONS] NAME", "Start a stopped container") |
154 | 154 |
if err := cmd.Parse(args); err != nil { |
155 |
- cmd.Usage() |
|
156 | 155 |
return nil |
157 | 156 |
} |
158 | 157 |
if cmd.NArg() < 1 { |
... | ... |
@@ -175,7 +186,6 @@ func (srv *Server) CmdStart(stdin io.ReadCloser, stdout io.Writer, args ...strin |
175 | 175 |
func (srv *Server) CmdUmount(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
176 | 176 |
cmd := rcli.Subcmd(stdout, "umount", "[OPTIONS] NAME", "umount a container's filesystem (debug only)") |
177 | 177 |
if err := cmd.Parse(args); err != nil { |
178 |
- cmd.Usage() |
|
179 | 178 |
return nil |
180 | 179 |
} |
181 | 180 |
if cmd.NArg() < 1 { |
... | ... |
@@ -198,7 +208,6 @@ func (srv *Server) CmdUmount(stdin io.ReadCloser, stdout io.Writer, args ...stri |
198 | 198 |
func (srv *Server) CmdMount(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
199 | 199 |
cmd := rcli.Subcmd(stdout, "umount", "[OPTIONS] NAME", "mount a container's filesystem (debug only)") |
200 | 200 |
if err := cmd.Parse(args); err != nil { |
201 |
- cmd.Usage() |
|
202 | 201 |
return nil |
203 | 202 |
} |
204 | 203 |
if cmd.NArg() < 1 { |
... | ... |
@@ -221,7 +230,6 @@ func (srv *Server) CmdMount(stdin io.ReadCloser, stdout io.Writer, args ...strin |
221 | 221 |
func (srv *Server) CmdCat(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
222 | 222 |
cmd := rcli.Subcmd(stdout, "cat", "[OPTIONS] CONTAINER PATH", "write the contents of a container's file to standard output") |
223 | 223 |
if err := cmd.Parse(args); err != nil { |
224 |
- cmd.Usage() |
|
225 | 224 |
return nil |
226 | 225 |
} |
227 | 226 |
if cmd.NArg() < 2 { |
... | ... |
@@ -243,7 +251,6 @@ func (srv *Server) CmdCat(stdin io.ReadCloser, stdout io.Writer, args ...string) |
243 | 243 |
func (srv *Server) CmdWrite(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
244 | 244 |
cmd := rcli.Subcmd(stdout, "write", "[OPTIONS] CONTAINER PATH", "write the contents of standard input to a container's file") |
245 | 245 |
if err := cmd.Parse(args); err != nil { |
246 |
- cmd.Usage() |
|
247 | 246 |
return nil |
248 | 247 |
} |
249 | 248 |
if cmd.NArg() < 2 { |
... | ... |
@@ -265,7 +272,6 @@ func (srv *Server) CmdWrite(stdin io.ReadCloser, stdout io.Writer, args ...strin |
265 | 265 |
func (srv *Server) CmdLs(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
266 | 266 |
cmd := rcli.Subcmd(stdout, "ls", "[OPTIONS] CONTAINER PATH", "List the contents of a container's directory") |
267 | 267 |
if err := cmd.Parse(args); err != nil { |
268 |
- cmd.Usage() |
|
269 | 268 |
return nil |
270 | 269 |
} |
271 | 270 |
if cmd.NArg() < 2 { |
... | ... |
@@ -289,7 +295,6 @@ func (srv *Server) CmdLs(stdin io.ReadCloser, stdout io.Writer, args ...string) |
289 | 289 |
func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
290 | 290 |
cmd := rcli.Subcmd(stdout, "inspect", "[OPTIONS] CONTAINER", "Return low-level information on a container") |
291 | 291 |
if err := cmd.Parse(args); err != nil { |
292 |
- cmd.Usage() |
|
293 | 292 |
return nil |
294 | 293 |
} |
295 | 294 |
if cmd.NArg() < 1 { |
... | ... |
@@ -322,7 +327,6 @@ func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...str |
322 | 322 |
func (srv *Server) CmdPort(stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
323 | 323 |
cmd := rcli.Subcmd(stdout, "port", "[OPTIONS] CONTAINER PRIVATE_PORT", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT") |
324 | 324 |
if err := cmd.Parse(args); err != nil { |
325 |
- cmd.Usage() |
|
326 | 325 |
return nil |
327 | 326 |
} |
328 | 327 |
if cmd.NArg() != 2 { |
... | ... |
@@ -459,7 +463,9 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri |
459 | 459 |
cmd := rcli.Subcmd(stdout, "images", "[OPTIONS] [NAME]", "List images") |
460 | 460 |
limit := cmd.Int("l", 0, "Only show the N most recent versions of each image") |
461 | 461 |
quiet := cmd.Bool("q", false, "only show numeric IDs") |
462 |
- cmd.Parse(args) |
|
462 |
+ if err := cmd.Parse(args); err != nil { |
|
463 |
+ return nil |
|
464 |
+ } |
|
463 | 465 |
if cmd.NArg() > 1 { |
464 | 466 |
cmd.Usage() |
465 | 467 |
return nil |
... | ... |
@@ -813,6 +819,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) |
813 | 813 |
fl_stdin := cmd.Bool("i", false, "Keep stdin open even if not attached") |
814 | 814 |
fl_tty := cmd.Bool("t", false, "Allocate a pseudo-tty") |
815 | 815 |
fl_comment := cmd.String("c", "", "Comment") |
816 |
+ fl_memory := cmd.Int64("m", 0, "Memory limit (in bytes)") |
|
816 | 817 |
var fl_ports ports |
817 | 818 |
cmd.Var(&fl_ports, "p", "Map a network port to the container") |
818 | 819 |
if err := cmd.Parse(args); err != nil { |
... | ... |
@@ -842,7 +849,8 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) |
842 | 842 |
return errors.New("No such image: " + name) |
843 | 843 |
} |
844 | 844 |
// Create new container |
845 |
- container, err := srv.CreateContainer(img, fl_ports, *fl_user, *fl_tty, *fl_stdin, *fl_comment, cmdline[0], cmdline[1:]...) |
|
845 |
+ container, err := srv.CreateContainer(img, fl_ports, *fl_user, *fl_tty, |
|
846 |
+ *fl_stdin, *fl_memory, *fl_comment, cmdline[0], cmdline[1:]...) |
|
846 | 847 |
if err != nil { |
847 | 848 |
return errors.New("Error creating container: " + err.Error()) |
848 | 849 |
} |