| ... | ... |
@@ -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 |
} |