Merge master within fs

This commit is contained in:
creack 2013-03-12 08:33:21 -07:00
commit 150a4fe7e5
9 changed files with 199 additions and 79 deletions

4
Vagrantfile vendored
View File

@ -7,11 +7,11 @@ Vagrant::Config.run do |config|
# please see the online documentation at vagrantup.com. # please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of. # Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "quantal64" config.vm.box = "quantal64_3.5.0-25"
# The url from where the 'config.vm.box' box will be fetched if it # The url from where the 'config.vm.box' box will be fetched if it
# doesn't already exist on the user's system. # doesn't already exist on the user's system.
config.vm.box_url = "http://unworkable.org/~niallo/quantal64.box" config.vm.box_url = "http://get.docker.io/vbox/ubuntu/12.10/quantal64_3.5.0-25.box"
# Boot with a GUI so you can see the screen. (Default is headless) # Boot with a GUI so you can see the screen. (Default is headless)
# config.vm.boot_mode = :gui # config.vm.boot_mode = :gui

View File

@ -111,6 +111,7 @@ func InteractiveMode(scripts ...string) error {
if err != nil { if err != nil {
return err return err
} }
defer os.Remove(rcfile.Name())
io.WriteString(rcfile, "enable -n help\n") io.WriteString(rcfile, "enable -n help\n")
os.Setenv("PATH", tmp+":"+os.Getenv("PATH")) os.Setenv("PATH", tmp+":"+os.Getenv("PATH"))
os.Setenv("PS1", "\\h docker> ") os.Setenv("PS1", "\\h docker> ")

View File

@ -55,7 +55,8 @@ type Container struct {
type Config struct { type Config struct {
Hostname string Hostname string
User string User string
Ram int64 Memory int64 // Memory limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
Ports []int Ports []int
Tty bool // Attach standard streams to a tty, including stdin if it is not closed. Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
OpenStdin bool // Open stdin OpenStdin bool // Open stdin

View File

@ -2,9 +2,12 @@ package docker
import ( import (
"./fs" "./fs"
"bufio"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"math/rand"
"os"
"sort" "sort"
"strings" "strings"
"testing" "testing"
@ -23,7 +26,7 @@ func TestCommitRun(t *testing.T) {
[]string{"-c", "echo hello > /world"}, []string{"-c", "echo hello > /world"},
GetTestImage(docker), GetTestImage(docker),
&Config{ &Config{
Ram: 33554432, Memory: 33554432,
}, },
) )
if err != nil { if err != nil {
@ -65,7 +68,7 @@ func TestCommitRun(t *testing.T) {
[]string{"/world"}, []string{"/world"},
img, img,
&Config{ &Config{
Ram: 33554432, Memory: 33554432,
}, },
) )
if err != nil { if err != nil {
@ -100,7 +103,7 @@ func TestRun(t *testing.T) {
[]string{"-al"}, []string{"-al"},
GetTestImage(docker), GetTestImage(docker),
&Config{ &Config{
Ram: 33554432, Memory: 33554432,
}, },
) )
if err != nil { if err != nil {
@ -349,7 +352,7 @@ func TestUser(t *testing.T) {
// Set a username // Set a username
container, err = docker.Create( container, err = docker.Create(
"user_root", "user_root",
"/bin/id", "id",
[]string{}, []string{},
GetTestImage(docker), GetTestImage(docker),
&Config{ &Config{
@ -393,7 +396,7 @@ func TestUser(t *testing.T) {
// Set a different user by uid // Set a different user by uid
container, err = docker.Create( container, err = docker.Create(
"user_uid1", "user_uid1",
"/usr/bin/id", "id",
[]string{}, []string{},
GetTestImage(docker), GetTestImage(docker),
&Config{ &Config{
@ -417,7 +420,7 @@ func TestUser(t *testing.T) {
// Set a different user by username // Set a different user by username
container, err = docker.Create( container, err = docker.Create(
"user_daemon", "user_daemon",
"/usr/bin/id", "id",
[]string{}, []string{},
GetTestImage(docker), GetTestImage(docker),
&Config{ &Config{
@ -616,6 +619,59 @@ func TestEnv(t *testing.T) {
} }
} }
func grepFile(t *testing.T, path string, pattern string) {
f, err := os.Open(path)
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := bufio.NewReader(f)
var (
line string
)
err = nil
for err == nil {
line, err = r.ReadString('\n')
if strings.Contains(line, pattern) == true {
return
}
}
t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path)
}
func TestLXCConfig(t *testing.T) {
docker, err := newTestDocker()
if err != nil {
t.Fatal(err)
}
defer nuke(docker)
// Memory is allocated randomly for testing
rand.Seed(time.Now().UTC().UnixNano())
memMin := 33554432
memMax := 536870912
mem := memMin + rand.Intn(memMax-memMin)
container, err := docker.Create(
"config_test",
"/bin/true",
[]string{},
GetTestImage(docker),
&Config{
Hostname: "foobar",
Memory: int64(mem),
},
)
if err != nil {
t.Fatal(err)
}
defer docker.Destroy(container)
container.generateLXCConfig()
grepFile(t, container.lxcConfigPath, "lxc.utsname = foobar")
grepFile(t, container.lxcConfigPath,
fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
grepFile(t, container.lxcConfigPath,
fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
}
func BenchmarkRunSequencial(b *testing.B) { func BenchmarkRunSequencial(b *testing.B) {
docker, err := newTestDocker() docker, err := newTestDocker()
if err != nil { if err != nil {

View File

@ -1,20 +1,46 @@
# This script is meant for quick & easy install via 'curl URL-OF-SCRIPPT | bash' #!/bin/sh
# Courtesy of Jeff Lindsay <progrium@gmail.com> # This script is meant for quick & easy install via 'curl URL-OF-SCRIPT | sh'
# Original version by Jeff Lindsay <progrium@gmail.com>
# Revamped by Jerome Petazzoni <jerome@dotcloud.com>
#
# This script canonical location is http://get.docker.io/; to update it, run:
# s3cmd put -m text/x-shellscript -P install.sh s3://get.docker.io/index
cd /tmp echo "Ensuring basic dependencies are installed..."
apt-get -qq update
apt-get -qq install lxc wget bsdtar
echo "Ensuring dependencies are installed..." echo "Looking in /proc/filesystems to see if we have AUFS support..."
apt-get --yes install lxc wget bsdtar 2>&1 > /dev/null if grep -q aufs /proc/filesystems
then
echo "Found."
else
echo "Ahem, it looks like the current kernel does not support AUFS."
echo "Let's see if we can load the AUFS module with modprobe..."
if modprobe aufs
then
echo "Module loaded."
else
echo "Ahem, things didn't turn out as expected."
KPKG=linux-image-extra-$(uname -r)
echo "Trying to install $KPKG..."
if apt-get -qq install $KPKG
then
echo "Installed."
else
echo "Oops, we couldn't install the -extra kernel."
echo "Are you sure you are running a supported version of Ubuntu?"
echo "Proceeding anyway, but Docker will probably NOT WORK!"
fi
fi
fi
echo "Downloading docker binary..." echo "Downloading docker binary and uncompressing into /usr/local/bin..."
wget -q https://dl.dropbox.com/u/20637798/docker.tar.gz 2>&1 > /dev/null curl -s http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz |
tar -xf docker.tar.gz 2>&1 > /dev/null tar -C /usr/local/bin --strip-components=1 -zxf- \
docker-master/docker docker-master/dockerd
echo "Installing into /usr/local/bin..." if [ -f /etc/init/dockerd.conf ]
mv docker/docker /usr/local/bin
mv dockerd/dockerd /usr/local/bin
if [[ -f /etc/init/dockerd.conf ]]
then then
echo "Upstart script already exists." echo "Upstart script already exists."
else else
@ -22,13 +48,8 @@ else
echo "exec /usr/local/bin/dockerd" > /etc/init/dockerd.conf echo "exec /usr/local/bin/dockerd" > /etc/init/dockerd.conf
fi fi
echo "Restarting dockerd..." echo "Starting dockerd..."
restart dockerd > /dev/null start dockerd > /dev/null
echo "Cleaning up..." echo "Done."
rmdir docker
rmdir dockerd
rm docker.tar.gz
echo "Finished!"
echo echo

View File

@ -85,16 +85,32 @@ lxc.mount.entry = /etc/resolv.conf {{$ROOTFS}}/etc/resolv.conf none bind,ro 0 0
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 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
# limits # limits
{{if .Config.Ram}} {{if .Config.Memory}}
lxc.cgroup.memory.limit_in_bytes = {{.Config.Ram}} lxc.cgroup.memory.limit_in_bytes = {{.Config.Memory}}
lxc.cgroup.memory.soft_limit_in_bytes = {{.Config.Memory}}
{{with $memSwap := getMemorySwap .Config}}
lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
{{end}}
{{end}} {{end}}
` `
var LxcTemplateCompiled *template.Template var LxcTemplateCompiled *template.Template
func getMemorySwap(config *Config) int64 {
// By default, MemorySwap is set to twice the size of RAM.
// If you want to omit MemorySwap, set it to `-1'.
if config.MemorySwap < 0 {
return 0
}
return config.Memory * 2
}
func init() { func init() {
var err error var err error
LxcTemplateCompiled, err = template.New("lxc").Parse(LxcTemplate) funcMap := template.FuncMap{
"getMemorySwap": getMemorySwap,
}
LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -1,14 +1,19 @@
class docker { class docker {
# update this with latest docker binary distro # update this with latest docker binary distro
$docker_url = "https://dl.dropbox.com/u/20637798/docker.tar.gz" $docker_url = "http://docker.io.s3.amazonaws.com/builds/$kernel/$hardwaremodel/docker-master.tgz"
# update this with latest go binary distry # update this with latest go binary distry
$go_url = "http://go.googlecode.com/files/go1.0.3.linux-amd64.tar.gz" $go_url = "http://go.googlecode.com/files/go1.0.3.linux-amd64.tar.gz"
Package { ensure => "installed" } Package { ensure => "installed" }
package { ["lxc", "debootstrap", "wget", "bsdtar"]: } package { ["lxc", "debootstrap", "wget", "bsdtar", "git",
"linux-image-3.5.0-25-generic",
"linux-image-extra-3.5.0-25-generic",
"virtualbox-guest-utils",
"linux-headers-3.5.0-25-generic"]: }
notify { "docker_url = $docker_url": withpath => true }
exec { "debootstrap" : exec { "debootstrap" :
require => Package["debootstrap"], require => Package["debootstrap"],
@ -26,7 +31,7 @@ class docker {
exec { "fetch-docker" : exec { "fetch-docker" :
require => Package["wget"], require => Package["wget"],
command => "/usr/bin/wget -O - $docker_url | /bin/tar xz -C /home/vagrant", command => "/usr/bin/wget -O - $docker_url | /bin/tar xz -C /home/vagrant",
creates => "/home/vagrant/docker/dockerd" creates => "/home/vagrant/docker-master"
} }
file { "/etc/init/dockerd.conf": file { "/etc/init/dockerd.conf":
@ -39,10 +44,21 @@ class docker {
exec { "copy-docker-bin" : exec { "copy-docker-bin" :
require => Exec["fetch-docker"], require => Exec["fetch-docker"],
command => "/bin/cp /home/vagrant/docker/docker /usr/local/bin", command => "/bin/cp /home/vagrant/docker-master/docker /usr/local/bin",
creates => "/usr/local/bin/docker" creates => "/usr/local/bin/docker"
} }
exec { "copy-dockerd-bin" :
require => Exec["fetch-docker"],
command => "/bin/cp /home/vagrant/docker-master/dockerd /usr/local/bin",
creates => "/usr/local/bin/dockerd"
}
exec { "vbox-add" :
require => Package["linux-headers-3.5.0-25-generic"],
command => "/etc/init.d/vboxadd setup",
}
service { "dockerd" : service { "dockerd" :
ensure => "running", ensure => "running",
start => "/sbin/initctl start dockerd", start => "/sbin/initctl start dockerd",

View File

@ -7,5 +7,6 @@ start on runlevel [3]
respawn respawn
script script
/home/vagrant/dockerd/dockerd test -f /etc/default/locale && . /etc/default/locale || true
LANG=$LANG LC_ALL=$LANG /usr/local/bin/dockerd
end script end script

View File

@ -37,28 +37,43 @@ func (srv *Server) Name() string {
return "docker" return "docker"
} }
// FIXME: Stop violating DRY by repeating usage here and in Subcmd declarations
func (srv *Server) Help() string { func (srv *Server) Help() string {
help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n" help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n"
for _, cmd := range [][]interface{}{ for _, cmd := range [][]interface{}{
{"run", "Run a command in a container"}, {"run", "Run a command in a container"},
{"ps", "Display a list of containers"}, {"ps", "Display a list of containers"},
{"import", "Create a new filesystem image from the contents of a tarball"}, {"import", "Create a new filesystem image from the contents of a tarball"},
{"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"}, {"attach", "Attach to a running container"},
{"rm", "Remove containers"}, {"cat", "Write the contents of a container's file to standard output"},
{"kill", "Kill a running container"}, {"commit", "Create a new image from a container's changes"},
{"wait", "Wait for the state of a container to change"}, {"cp", "Create a copy of IMAGE and call it NAME"},
{"stop", "Stop a running container"}, {"debug", "(debug only) (No documentation available)"},
{"start", "Start a stopped container"},
{"restart", "Restart a running container"},
{"logs", "Fetch the logs of a container"},
{"diff", "Inspect changes on a container's filesystem"}, {"diff", "Inspect changes on a container's filesystem"},
{"commit", "Save the state of a container"},
{"attach", "Attach to the standard inputs and outputs of a running container"},
{"wait", "Block until a container exits, then print its exit code"},
{"info", "Display system-wide information"},
{"tar", "Stream the contents of a container as a tar archive"},
{"web", "Generate a web UI"},
{"images", "List images"}, {"images", "List images"},
{"info", "Display system-wide information"},
{"inspect", "Return low-level information on a container"},
{"kill", "Kill a running container"},
{"layers", "(debug only) List filesystem layers"},
{"logs", "Fetch the logs of a container"},
{"ls", "List the contents of a container's directory"},
{"mirror", "(debug only) (No documentation available)"},
{"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"},
{"ps", "List containers"},
{"pull", "Download a new image from a remote location"},
{"put", "Import a new image from a local archive"},
{"reset", "Reset changes to a container's filesystem"},
{"restart", "Restart a running container"},
{"rm", "Remove a container"},
{"rmimage", "Remove an image"},
{"run", "Run a command in a new container"},
{"start", "Start a stopped container"},
{"stop", "Stop a running container"},
{"tar", "Stream the contents of a container as a tar archive"},
{"umount", "(debug only) Mount a container's filesystem"},
{"wait", "Block until a container stops, then print its exit code"},
{"web", "A web UI for docker"},
{"write", "Write the contents of standard input to a container's file"},
} { } {
help += fmt.Sprintf(" %-10.10s%s\n", cmd...) help += fmt.Sprintf(" %-10.10s%s\n", cmd...)
} }
@ -69,7 +84,6 @@ func (srv *Server) Help() string {
func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "wait", "[OPTIONS] NAME", "Block until a container stops, then print its exit code.") cmd := rcli.Subcmd(stdout, "wait", "[OPTIONS] NAME", "Block until a container stops, then print its exit code.")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 1 { if cmd.NArg() < 1 {
@ -88,25 +102,24 @@ func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string
// 'docker info': display system-wide information. // 'docker info': display system-wide information.
func (srv *Server) CmdInfo(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdInfo(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
images, _ := srv.images.Images() cmd := rcli.Subcmd(stdout, "info", "", "Display system-wide information.")
var imgcount int if err := cmd.Parse(args); err != nil {
if images == nil { return nil
imgcount = 0 }
} else { if cmd.NArg() > 1 {
imgcount = len(images) cmd.Usage()
return nil
} }
fmt.Fprintf(stdout, "containers: %d\nversion: %s\nimages: %d\n", fmt.Fprintf(stdout, "containers: %d\nversion: %s\nimages: %d\n",
len(srv.containers.List()), len(srv.containers.List()),
VERSION, VERSION,
imgcount) len(srv.images.ById))
return nil return nil
} }
func (srv *Server) CmdStop(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdStop(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "stop", "[OPTIONS] NAME", "Stop a running container") cmd := rcli.Subcmd(stdout, "stop", "[OPTIONS] NAME", "Stop a running container")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 1 { if cmd.NArg() < 1 {
@ -129,7 +142,6 @@ func (srv *Server) CmdStop(stdin io.ReadCloser, stdout io.Writer, args ...string
func (srv *Server) CmdRestart(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdRestart(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "restart", "[OPTIONS] NAME", "Restart a running container") cmd := rcli.Subcmd(stdout, "restart", "[OPTIONS] NAME", "Restart a running container")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 1 { if cmd.NArg() < 1 {
@ -152,7 +164,6 @@ func (srv *Server) CmdRestart(stdin io.ReadCloser, stdout io.Writer, args ...str
func (srv *Server) CmdStart(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdStart(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "start", "[OPTIONS] NAME", "Start a stopped container") cmd := rcli.Subcmd(stdout, "start", "[OPTIONS] NAME", "Start a stopped container")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 1 { if cmd.NArg() < 1 {
@ -175,7 +186,6 @@ func (srv *Server) CmdStart(stdin io.ReadCloser, stdout io.Writer, args ...strin
func (srv *Server) CmdUmount(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdUmount(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "umount", "[OPTIONS] NAME", "umount a container's filesystem (debug only)") cmd := rcli.Subcmd(stdout, "umount", "[OPTIONS] NAME", "umount a container's filesystem (debug only)")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 1 { if cmd.NArg() < 1 {
@ -198,7 +208,6 @@ func (srv *Server) CmdUmount(stdin io.ReadCloser, stdout io.Writer, args ...stri
func (srv *Server) CmdMount(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdMount(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "umount", "[OPTIONS] NAME", "mount a container's filesystem (debug only)") cmd := rcli.Subcmd(stdout, "umount", "[OPTIONS] NAME", "mount a container's filesystem (debug only)")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 1 { if cmd.NArg() < 1 {
@ -221,7 +230,6 @@ func (srv *Server) CmdMount(stdin io.ReadCloser, stdout io.Writer, args ...strin
func (srv *Server) CmdCat(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdCat(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "cat", "[OPTIONS] CONTAINER PATH", "write the contents of a container's file to standard output") cmd := rcli.Subcmd(stdout, "cat", "[OPTIONS] CONTAINER PATH", "write the contents of a container's file to standard output")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 2 { if cmd.NArg() < 2 {
@ -243,7 +251,6 @@ func (srv *Server) CmdCat(stdin io.ReadCloser, stdout io.Writer, args ...string)
func (srv *Server) CmdWrite(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdWrite(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "write", "[OPTIONS] CONTAINER PATH", "write the contents of standard input to a container's file") cmd := rcli.Subcmd(stdout, "write", "[OPTIONS] CONTAINER PATH", "write the contents of standard input to a container's file")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 2 { if cmd.NArg() < 2 {
@ -265,7 +272,6 @@ func (srv *Server) CmdWrite(stdin io.ReadCloser, stdout io.Writer, args ...strin
func (srv *Server) CmdLs(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdLs(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "ls", "[OPTIONS] CONTAINER PATH", "List the contents of a container's directory") cmd := rcli.Subcmd(stdout, "ls", "[OPTIONS] CONTAINER PATH", "List the contents of a container's directory")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 2 { if cmd.NArg() < 2 {
@ -289,7 +295,6 @@ func (srv *Server) CmdLs(stdin io.ReadCloser, stdout io.Writer, args ...string)
func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "inspect", "[OPTIONS] CONTAINER", "Return low-level information on a container") cmd := rcli.Subcmd(stdout, "inspect", "[OPTIONS] CONTAINER", "Return low-level information on a container")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() < 1 { if cmd.NArg() < 1 {
@ -322,7 +327,6 @@ func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...str
func (srv *Server) CmdPort(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (srv *Server) CmdPort(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "port", "[OPTIONS] CONTAINER PRIVATE_PORT", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT") cmd := rcli.Subcmd(stdout, "port", "[OPTIONS] CONTAINER PRIVATE_PORT", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
cmd.Usage()
return nil return nil
} }
if cmd.NArg() != 2 { if cmd.NArg() != 2 {
@ -459,7 +463,9 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri
cmd := rcli.Subcmd(stdout, "images", "[OPTIONS] [NAME]", "List images") cmd := rcli.Subcmd(stdout, "images", "[OPTIONS] [NAME]", "List images")
limit := cmd.Int("l", 0, "Only show the N most recent versions of each image") limit := cmd.Int("l", 0, "Only show the N most recent versions of each image")
quiet := cmd.Bool("q", false, "only show numeric IDs") quiet := cmd.Bool("q", false, "only show numeric IDs")
cmd.Parse(args) if err := cmd.Parse(args); err != nil {
return nil
}
if cmd.NArg() > 1 { if cmd.NArg() > 1 {
cmd.Usage() cmd.Usage()
return nil return nil
@ -813,6 +819,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string)
fl_stdin := cmd.Bool("i", false, "Keep stdin open even if not attached") fl_stdin := cmd.Bool("i", false, "Keep stdin open even if not attached")
fl_tty := cmd.Bool("t", false, "Allocate a pseudo-tty") fl_tty := cmd.Bool("t", false, "Allocate a pseudo-tty")
fl_comment := cmd.String("c", "", "Comment") fl_comment := cmd.String("c", "", "Comment")
fl_memory := cmd.Int64("m", 0, "Memory limit (in bytes)")
var fl_ports ports var fl_ports ports
cmd.Var(&fl_ports, "p", "Map a network port to the container") cmd.Var(&fl_ports, "p", "Map a network port to the container")
if err := cmd.Parse(args); err != nil { if err := cmd.Parse(args); err != nil {
@ -842,7 +849,8 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string)
return errors.New("No such image: " + name) return errors.New("No such image: " + name)
} }
// Create new container // Create new container
container, err := srv.CreateContainer(img, fl_ports, *fl_user, *fl_tty, *fl_stdin, *fl_comment, cmdline[0], cmdline[1:]...) container, err := srv.CreateContainer(img, fl_ports, *fl_user, *fl_tty,
*fl_stdin, *fl_memory, *fl_comment, cmdline[0], cmdline[1:]...)
if err != nil { if err != nil {
return errors.New("Error creating container: " + err.Error()) return errors.New("Error creating container: " + err.Error())
} }