Merge pull request #1291 from dotcloud/ensure_mount_commit
*Builder: Allow the commit of a non-started container
diff --git a/.mailmap b/.mailmap
index 452ac41..11ff535 100644
--- a/.mailmap
+++ b/.mailmap
@@ -23,3 +23,5 @@
Walter Stanish <walter@pratyeka.org>
<daniel@gasienica.ch> <dgasienica@zynga.com>
Roberto Hashioka <roberto_hashioka@hotmail.com>
+Konstantin Pelykh <kpelykh@zettaset.com>
+David Sissitka <me@dsissitka.com>
diff --git a/AUTHORS b/AUTHORS
index 86d03f6..773ad6e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -4,12 +4,15 @@
# For a list of active project maintainers, see the MAINTAINERS file.
#
Al Tobey <al@ooyala.com>
+Alex Gaynor <alex.gaynor@gmail.com>
Alexey Shamrin <shamrin@gmail.com>
Andrea Luzzardi <aluzzardi@gmail.com>
Andreas Tiefenthaler <at@an-ti.eu>
Andrew Munsell <andrew@wizardapps.net>
+Andrews Medina <andrewsmedina@gmail.com>
Andy Rothfusz <github@metaliveblog.com>
Andy Smith <github@anarkystic.com>
+Anthony Bishopric <git@anthonybishopric.com>
Antony Messerli <amesserl@rackspace.com>
Barry Allard <barry.allard@gmail.com>
Brandon Liu <bdon@bdon.org>
@@ -23,17 +26,23 @@
Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com>
Daniel Robinson <gottagetmac@gmail.com>
Daniel Von Fange <daniel@leancoder.com>
+Daniel YC Lin <dlin.tw@gmail.com>
+David Calavera <david.calavera@gmail.com>
+David Sissitka <me@dsissitka.com>
Dominik Honnef <dominik@honnef.co>
Don Spaulding <donspauldingii@gmail.com>
Dr Nic Williams <drnicwilliams@gmail.com>
Elias Probst <mail@eliasprobst.eu>
Eric Hanchrow <ehanchrow@ine.com>
-Evan Wies <evan@neomantra.net>
Eric Myhre <hash@exultant.us>
+Erno Hopearuoho <erno.hopearuoho@gmail.com>
+Evan Wies <evan@neomantra.net>
ezbercih <cem.ezberci@gmail.com>
+Fabrizio Regini <freegenie@gmail.com>
Flavio Castelli <fcastelli@suse.com>
Francisco Souza <f@souza.cc>
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
+Gabriel Monroy <gabriel@opdemand.com>
Gareth Rushgrove <gareth@morethanseven.net>
Guillaume J. Charmes <guillaume.charmes@dotcloud.com>
Harley Laue <losinggeneration@gmail.com>
@@ -41,6 +50,7 @@
Jeff Lindsay <progrium@gmail.com>
Jeremy Grosser <jeremy@synack.me>
Joffrey F <joffrey@dotcloud.com>
+Johan Euphrosine <proppy@google.com>
John Costa <john.costa@gmail.com>
Jon Wedaman <jweede@gmail.com>
Jonas Pfenniger <jonas@pfenniger.name>
@@ -48,28 +58,39 @@
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
Julien Barbier <write0@gmail.com>
Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
+Karan Lyons <karan@karanlyons.com>
+Keli Hu <dev@keli.hu>
Ken Cochrane <kencochrane@gmail.com>
Kevin J. Lynagh <kevin@keminglabs.com>
kim0 <email.ahmedkamal@googlemail.com>
+Kimbro Staken <kstaken@kstaken.com>
Kiran Gangadharan <kiran.daredevil@gmail.com>
+Konstantin Pelykh <kpelykh@zettaset.com>
Louis Opter <kalessin@kalessin.fr>
+Marco Hennings <marco.hennings@freiheit.com>
Marcus Farkas <toothlessgear@finitebox.com>
Mark McGranaghan <mmcgrana@gmail.com>
Maxim Treskin <zerthurd@gmail.com>
meejah <meejah@meejah.ca>
Michael Crosby <crosby.michael@gmail.com>
+Mike Gaffney <mike@uberu.com>
Mikhail Sobolev <mss@mawhrin.net>
+Nan Monnand Deng <monnand@gmail.com>
Nate Jones <nate@endot.org>
Nelson Chen <crazysim@gmail.com>
Niall O'Higgins <niallo@unworkable.org>
+Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
+Nick Stinemates <nick@stinemates.org>
odk- <github@odkurzacz.org>
Paul Bowsher <pbowsher@globalpersonals.co.uk>
Paul Hammond <paul@paulhammond.org>
Phil Spitler <pspitler@gmail.com>
Piotr Bogdan <ppbogdan@gmail.com>
Renato Riccieri Santos Zannon <renato.riccieri@gmail.com>
+Rhys Hiltner <rhys@twitch.tv>
Robert Obryk <robryk@gmail.com>
Roberto Hashioka <roberto_hashioka@hotmail.com>
+Ryan Fowler <rwfowler@gmail.com>
Sam Alba <sam.alba@gmail.com>
Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
Shawn Siefkas <shawn.siefkas@meredith.com>
@@ -83,6 +104,8 @@
Tianon Gravi <admwiggin@gmail.com>
Tim Terhorst <mynamewastaken+git@gmail.com>
Tobias Bieniek <Tobias.Bieniek@gmx.de>
+Tobias Schwab <tobias.schwab@dynport.de>
+Tom Hulihan <hulihan.tom159@gmail.com>
unclejack <unclejacksons@gmail.com>
Victor Vieux <victor.vieux@dotcloud.com>
Vivek Agarwal <me@vivek.im>
diff --git a/README.md b/README.md
index 96da13f..5eee1a3 100644
--- a/README.md
+++ b/README.md
@@ -167,7 +167,7 @@
----------------------
1. Make sure you have a [Go language](http://golang.org/doc/install)
-compiler and [git](http://git-scm.com) installed.
+compiler >= 1.1 and [git](http://git-scm.com) installed.
2. Checkout the source code
```bash
@@ -444,51 +444,6 @@
making INDUSTRIAL-GRADE DELIVERY of software a reality.
-
-
-Standard Container Specification
---------------------------------
-
-(TODO)
-
-### Image format
-
-
-### Standard operations
-
-* Copy
-* Run
-* Stop
-* Wait
-* Commit
-* Attach standard streams
-* List filesystem changes
-* ...
-
-### Execution environment
-
-#### Root filesystem
-
-#### Environment variables
-
-#### Process arguments
-
-#### Networking
-
-#### Process namespacing
-
-#### Resource limits
-
-#### Process monitoring
-
-#### Logging
-
-#### Signals
-
-#### Pseudo-terminal allocation
-
-#### Security
-
### Legal
Transfers of Docker shall be in accordance with applicable export
diff --git a/Vagrantfile b/Vagrantfile
index aadabb8..7258af5 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -20,6 +20,8 @@
pkg_cmd = "apt-get update -qq; apt-get install -q -y python-software-properties; " \
"add-apt-repository -y ppa:dotcloud/lxc-docker; apt-get update -qq; " \
"apt-get install -q -y lxc-docker; "
+ # Listen on all interfaces so that the daemon is accessible from the host
+ pkg_cmd << "sed -i -E 's| /usr/bin/docker -d| /usr/bin/docker -d -H 0.0.0.0|' /etc/init/docker.conf;"
# Add X.org Ubuntu backported 3.8 kernel
pkg_cmd << "add-apt-repository -y ppa:ubuntu-x-swat/r-lts-backport; " \
"apt-get update -qq; apt-get install -q -y linux-image-3.8.0-19-generic; "
diff --git a/api.go b/api.go
index 834c41a..4ad2ba4 100644
--- a/api.go
+++ b/api.go
@@ -17,7 +17,7 @@
"strings"
)
-const APIVERSION = 1.3
+const APIVERSION = 1.4
const DEFAULTHTTPHOST string = "127.0.0.1"
const DEFAULTHTTPPORT int = 4243
@@ -271,11 +271,18 @@
}
func getContainersTop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+ if version < 1.4 {
+ return fmt.Errorf("top was improved a lot since 1.3, Please upgrade your docker client.")
+ }
if vars == nil {
return fmt.Errorf("Missing parameter")
}
+ if err := parseForm(r); err != nil {
+ return err
+ }
name := vars["name"]
- procsStr, err := srv.ContainerTop(name)
+ ps_args := r.Form.Get("ps_args")
+ procsStr, err := srv.ContainerTop(name, ps_args)
if err != nil {
return err
}
diff --git a/api_params.go b/api_params.go
index 0214b89..1ae2607 100644
--- a/api_params.go
+++ b/api_params.go
@@ -30,10 +30,8 @@
}
type APITop struct {
- PID string
- Tty string
- Time string
- Cmd string
+ Titles []string
+ Processes [][]string
}
type APIRmi struct {
diff --git a/api_test.go b/api_test.go
index 13731db..be53592 100644
--- a/api_test.go
+++ b/api_test.go
@@ -482,24 +482,33 @@
}
r := httptest.NewRecorder()
- if err := getContainersTop(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil {
+ req, err := http.NewRequest("GET", "/"+container.ID+"/top?ps_args=u", bytes.NewReader([]byte{}))
+ if err != nil {
t.Fatal(err)
}
- procs := []APITop{}
+ if err := getContainersTop(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
+ t.Fatal(err)
+ }
+ procs := APITop{}
if err := json.Unmarshal(r.Body.Bytes(), &procs); err != nil {
t.Fatal(err)
}
- if len(procs) != 2 {
- t.Fatalf("Expected 2 processes, found %d.", len(procs))
+ if len(procs.Titles) != 11 {
+ t.Fatalf("Expected 11 titles, found %d.", len(procs.Titles))
+ }
+ if procs.Titles[0] != "USER" || procs.Titles[10] != "COMMAND" {
+ t.Fatalf("Expected Titles[0] to be USER and Titles[10] to be COMMAND, found %s and %s.", procs.Titles[0], procs.Titles[10])
}
- if procs[0].Cmd != "sh" && procs[0].Cmd != "busybox" {
- t.Fatalf("Expected `busybox` or `sh`, found %s.", procs[0].Cmd)
+ if len(procs.Processes) != 2 {
+ t.Fatalf("Expected 2 processes, found %d.", len(procs.Processes))
}
-
- if procs[1].Cmd != "sh" && procs[1].Cmd != "busybox" {
- t.Fatalf("Expected `busybox` or `sh`, found %s.", procs[1].Cmd)
+ if procs.Processes[0][10] != "/bin/sh" && procs.Processes[0][10] != "sleep" {
+ t.Fatalf("Expected `sleep` or `/bin/sh`, found %s.", procs.Processes[0][10])
+ }
+ if procs.Processes[1][10] != "/bin/sh" && procs.Processes[1][10] != "sleep" {
+ t.Fatalf("Expected `sleep` or `/bin/sh`, found %s.", procs.Processes[1][10])
}
}
@@ -895,6 +904,12 @@
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
+ // Try to avoid the timeoout in destroy. Best effort, don't check error
+ defer func() {
+ closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
+ container.Kill()
+ }()
+
// Attach to it
c1 := make(chan struct{})
go func() {
@@ -934,7 +949,7 @@
}
// Wait for attach to finish, the client disconnected, therefore, Attach finished his job
- setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() {
+ setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
<-c1
})
diff --git a/buildfile.go b/buildfile.go
index 75ebdd7..736725e 100644
--- a/buildfile.go
+++ b/buildfile.go
@@ -11,6 +11,7 @@
"os"
"path"
"reflect"
+ "regexp"
"strings"
)
@@ -67,6 +68,9 @@
}
b.image = image.ID
b.config = &Config{}
+ if b.config.Env == nil || len(b.config.Env) == 0 {
+ b.config.Env = append(b.config.Env, "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
+ }
return nil
}
@@ -112,6 +116,40 @@
return nil
}
+func (b *buildFile) FindEnvKey(key string) int {
+ for k, envVar := range b.config.Env {
+ envParts := strings.SplitN(envVar, "=", 2)
+ if key == envParts[0] {
+ return k
+ }
+ }
+ return -1
+}
+
+func (b *buildFile) ReplaceEnvMatches(value string) (string, error) {
+ exp, err := regexp.Compile("(\\\\\\\\+|[^\\\\]|\\b|\\A)\\$({?)([[:alnum:]_]+)(}?)")
+ if err != nil {
+ return value, err
+ }
+ matches := exp.FindAllString(value, -1)
+ for _, match := range matches {
+ match = match[strings.Index(match, "$"):]
+ matchKey := strings.Trim(match, "${}")
+
+ for _, envVar := range b.config.Env {
+ envParts := strings.SplitN(envVar, "=", 2)
+ envKey := envParts[0]
+ envValue := envParts[1]
+
+ if envKey == matchKey {
+ value = strings.Replace(value, match, envValue, -1)
+ break
+ }
+ }
+ }
+ return value, nil
+}
+
func (b *buildFile) CmdEnv(args string) error {
tmp := strings.SplitN(args, " ", 2)
if len(tmp) != 2 {
@@ -120,14 +158,19 @@
key := strings.Trim(tmp[0], " \t")
value := strings.Trim(tmp[1], " \t")
- for i, elem := range b.config.Env {
- if strings.HasPrefix(elem, key+"=") {
- b.config.Env[i] = key + "=" + value
- return nil
- }
+ envKey := b.FindEnvKey(key)
+ replacedValue, err := b.ReplaceEnvMatches(value)
+ if err != nil {
+ return err
}
- b.config.Env = append(b.config.Env, key+"="+value)
- return b.commit("", b.config.Cmd, fmt.Sprintf("ENV %s=%s", key, value))
+ replacedVar := fmt.Sprintf("%s=%s", key, replacedValue)
+
+ if envKey >= 0 {
+ b.config.Env[envKey] = replacedVar
+ return nil
+ }
+ b.config.Env = append(b.config.Env, replacedVar)
+ return b.commit("", b.config.Cmd, fmt.Sprintf("ENV %s", replacedVar))
}
func (b *buildFile) CmdCmd(args string) error {
@@ -242,7 +285,7 @@
} else if err := UntarPath(origPath, destPath); err != nil {
utils.Debugf("Couldn't untar %s to %s: %s", origPath, destPath, err)
// If that fails, just copy it as a regular file
- if err := os.MkdirAll(path.Dir(destPath), 0700); err != nil {
+ if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil {
return err
}
if err := CopyWithTar(origPath, destPath); err != nil {
@@ -260,8 +303,16 @@
if len(tmp) != 2 {
return fmt.Errorf("Invalid ADD format")
}
- orig := strings.Trim(tmp[0], " \t")
- dest := strings.Trim(tmp[1], " \t")
+
+ orig, err := b.ReplaceEnvMatches(strings.Trim(tmp[0], " \t"))
+ if err != nil {
+ return err
+ }
+
+ dest, err := b.ReplaceEnvMatches(strings.Trim(tmp[1], " \t"))
+ if err != nil {
+ return err
+ }
cmd := b.config.Cmd
b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) ADD %s in %s", orig, dest)}
diff --git a/buildfile_test.go b/buildfile_test.go
index b7eca52..78e53b8 100644
--- a/buildfile_test.go
+++ b/buildfile_test.go
@@ -129,6 +129,38 @@
nil,
nil,
},
+
+ {
+ `
+from {IMAGE}
+env FOO /foo/baz
+env BAR /bar
+env BAZ $BAR
+env FOOPATH $PATH:$FOO
+run [ "$BAR" = "$BAZ" ]
+run [ "$FOOPATH" = "$PATH:/foo/baz" ]
+`,
+ nil,
+ nil,
+ },
+
+ {
+ `
+from {IMAGE}
+env FOO /bar
+env TEST testdir
+env BAZ /foobar
+add testfile $BAZ/
+add $TEST $FOO
+run [ "$(cat /foobar/testfile)" = "test1" ]
+run [ "$(cat /bar/withfile)" = "test2" ]
+`,
+ [][2]string{
+ {"testfile", "test1"},
+ {"testdir/withfile", "test2"},
+ },
+ nil,
+ },
}
// FIXME: test building with 2 successive overlapping ADD commands
@@ -242,8 +274,14 @@
env port 4243
`,
nil, nil}, t)
-
- if img.Config.Env[0] != "port=4243" {
+ hasEnv := false
+ for _, envVar := range img.Config.Env {
+ if envVar == "port=4243" {
+ hasEnv = true
+ break
+ }
+ }
+ if !hasEnv {
t.Fail()
}
}
diff --git a/commands.go b/commands.go
index 10b9e31..95ddca1 100644
--- a/commands.go
+++ b/commands.go
@@ -314,13 +314,21 @@
email string
)
+ var promptDefault = func(prompt string, configDefault string) {
+ if configDefault == "" {
+ fmt.Fprintf(cli.out, "%s: ", prompt)
+ } else {
+ fmt.Fprintf(cli.out, "%s (%s): ", prompt, configDefault)
+ }
+ }
+
authconfig, ok := cli.configFile.Configs[auth.IndexServerAddress()]
if !ok {
authconfig = auth.AuthConfig{}
}
if *flUsername == "" {
- fmt.Fprintf(cli.out, "Username (%s): ", authconfig.Username)
+ promptDefault("Username", authconfig.Username)
username = readAndEchoString(cli.in, cli.out)
if username == "" {
username = authconfig.Username
@@ -340,7 +348,7 @@
}
if *flEmail == "" {
- fmt.Fprintf(cli.out, "Email (%s): ", authconfig.Email)
+ promptDefault("Email", authconfig.Email)
email = readAndEchoString(cli.in, cli.out)
if email == "" {
email = authconfig.Email
@@ -596,23 +604,28 @@
if err := cmd.Parse(args); err != nil {
return nil
}
- if cmd.NArg() != 1 {
+ if cmd.NArg() == 0 {
cmd.Usage()
return nil
}
- body, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top", nil)
+ val := url.Values{}
+ if cmd.NArg() > 1 {
+ val.Set("ps_args", strings.Join(cmd.Args()[1:], " "))
+ }
+
+ body, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil)
if err != nil {
return err
}
- var procs []APITop
+ procs := APITop{}
err = json.Unmarshal(body, &procs)
if err != nil {
return err
}
w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
- fmt.Fprintln(w, "PID\tTTY\tTIME\tCMD")
- for _, proc := range procs {
- fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", proc.PID, proc.Tty, proc.Time, proc.Cmd)
+ fmt.Fprintln(w, strings.Join(procs.Titles, "\t"))
+ for _, proc := range procs.Processes {
+ fmt.Fprintln(w, strings.Join(proc, "\t"))
}
w.Flush()
return nil
@@ -767,7 +780,7 @@
}
func (cli *DockerCli) CmdImport(args ...string) error {
- cmd := Subcmd("import", "URL|- [REPOSITORY [TAG]]", "Create a new filesystem image from the contents of a tarball")
+ cmd := Subcmd("import", "URL|- [REPOSITORY [TAG]]", "Create a new filesystem image from the contents of a tarball(.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz).")
if err := cmd.Parse(args); err != nil {
return nil
@@ -1658,13 +1671,12 @@
}
cli.resizeTty(id)
- c := make(chan os.Signal, 1)
- signal.Notify(c, syscall.SIGWINCH)
+ sigchan := make(chan os.Signal, 1)
+ signal.Notify(sigchan, syscall.SIGWINCH)
go func() {
- for sig := range c {
- if sig == syscall.SIGWINCH {
- cli.resizeTty(id)
- }
+ for {
+ <-sigchan
+ cli.resizeTty(id)
}
}()
return nil
diff --git a/container.go b/container.go
index dea81b6..d610c3c 100644
--- a/container.go
+++ b/container.go
@@ -52,7 +52,7 @@
waitLock chan struct{}
Volumes map[string]string
- // Store rw/ro in a separate structure to preserve reserve-compatibility on-disk.
+ // Store rw/ro in a separate structure to preserve reverse-compatibility on-disk.
// Easier than migrating older container configs :)
VolumesRW map[string]bool
}
@@ -100,7 +100,7 @@
flHostname := cmd.String("h", "", "Container host name")
flUser := cmd.String("u", "", "Username or UID")
- flDetach := cmd.Bool("d", false, "Detached mode: leave the container running in the background")
+ flDetach := cmd.Bool("d", false, "Detached mode: Run container in the background, print new container id")
flAttach := NewAttachOpts()
cmd.Var(flAttach, "a", "Attach to stdin, stdout or stderr.")
flStdin := cmd.Bool("i", false, "Keep stdin open even if not attached")
@@ -379,14 +379,15 @@
utils.Debugf("[start] attach stdin\n")
defer utils.Debugf("[end] attach stdin\n")
// No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
- if cStdout != nil {
- defer cStdout.Close()
- }
- if cStderr != nil {
- defer cStderr.Close()
- }
if container.Config.StdinOnce && !container.Config.Tty {
defer cStdin.Close()
+ } else {
+ if cStdout != nil {
+ defer cStdout.Close()
+ }
+ if cStderr != nil {
+ defer cStderr.Close()
+ }
}
if container.Config.Tty {
_, err = utils.CopyEscapable(cStdin, stdin)
diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst
index 792d43f..193be50 100644
--- a/docs/sources/api/docker_remote_api.rst
+++ b/docs/sources/api/docker_remote_api.rst
@@ -26,15 +26,15 @@
2. Versions
===========
-The current verson of the API is 1.3
+The current verson of the API is 1.4
Calling /images/<name>/insert is the same as calling
-/v1.3/images/<name>/insert
+/v1.4/images/<name>/insert
You can still call an old version of the api using
/v1.0/images/<name>/insert
-:doc:`docker_remote_api_v1.3`
+:doc:`docker_remote_api_v1.4`
*****************************
What's new
@@ -42,7 +42,19 @@
.. http:get:: /containers/(id)/top
- **New!** List the processes running inside a container.
+ **New!** You can now use ps args with docker top, like `docker top <container_id> aux`
+
+:doc:`docker_remote_api_v1.3`
+*****************************
+
+docker v0.5.0 51f6c4a_
+
+What's new
+----------
+
+.. http:get:: /containers/(id)/top
+
+ List the processes running inside a container.
.. http:get:: /events:
@@ -138,6 +150,7 @@
.. _a8ae398: https://github.com/dotcloud/docker/commit/a8ae398bf52e97148ee7bd0d5868de2e15bd297f
.. _8d73740: https://github.com/dotcloud/docker/commit/8d73740343778651c09160cde9661f5f387b36f4
.. _2e7649b: https://github.com/dotcloud/docker/commit/2e7649beda7c820793bd46766cbc2cfeace7b168
+.. _51f6c4a: https://github.com/dotcloud/docker/commit/51f6c4a7372450d164c61e0054daf0223ddbd909
==================================
Docker Remote API Client Libraries
diff --git a/docs/sources/api/docker_remote_api_v1.4.rst b/docs/sources/api/docker_remote_api_v1.4.rst
new file mode 100644
index 0000000..6ee0b35
--- /dev/null
+++ b/docs/sources/api/docker_remote_api_v1.4.rst
@@ -0,0 +1,1093 @@
+:title: Remote API v1.4
+:description: API Documentation for Docker
+:keywords: API, Docker, rcli, REST, documentation
+
+======================
+Docker Remote API v1.4
+======================
+
+.. contents:: Table of Contents
+
+1. Brief introduction
+=====================
+
+- The Remote API is replacing rcli
+- Default port in the docker deamon is 4243
+- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
+
+2. Endpoints
+============
+
+2.1 Containers
+--------------
+
+List containers
+***************
+
+.. http:get:: /containers/json
+
+ List containers
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /containers/json?all=1&before=8dfafdbc3a40&size=1 HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ [
+ {
+ "Id": "8dfafdbc3a40",
+ "Image": "base:latest",
+ "Command": "echo 1",
+ "Created": 1367854155,
+ "Status": "Exit 0",
+ "Ports":"",
+ "SizeRw":12288,
+ "SizeRootFs":0
+ },
+ {
+ "Id": "9cd87474be90",
+ "Image": "base:latest",
+ "Command": "echo 222222",
+ "Created": 1367854155,
+ "Status": "Exit 0",
+ "Ports":"",
+ "SizeRw":12288,
+ "SizeRootFs":0
+ },
+ {
+ "Id": "3176a2479c92",
+ "Image": "base:latest",
+ "Command": "echo 3333333333333333",
+ "Created": 1367854154,
+ "Status": "Exit 0",
+ "Ports":"",
+ "SizeRw":12288,
+ "SizeRootFs":0
+ },
+ {
+ "Id": "4cb07b47f9fb",
+ "Image": "base:latest",
+ "Command": "echo 444444444444444444444444444444444",
+ "Created": 1367854152,
+ "Status": "Exit 0",
+ "Ports":"",
+ "SizeRw":12288,
+ "SizeRootFs":0
+ }
+ ]
+
+ :query all: 1/True/true or 0/False/false, Show all containers. Only running containers are shown by default
+ :query limit: Show ``limit`` last created containers, include non-running ones.
+ :query since: Show only containers created since Id, include non-running ones.
+ :query before: Show only containers created before Id, include non-running ones.
+ :query size: 1/True/true or 0/False/false, Show the containers sizes
+ :statuscode 200: no error
+ :statuscode 400: bad parameter
+ :statuscode 500: server error
+
+
+Create a container
+******************
+
+.. http:post:: /containers/create
+
+ Create a container
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /containers/create HTTP/1.1
+ Content-Type: application/json
+
+ {
+ "Hostname":"",
+ "User":"",
+ "Memory":0,
+ "MemorySwap":0,
+ "AttachStdin":false,
+ "AttachStdout":true,
+ "AttachStderr":true,
+ "PortSpecs":null,
+ "Tty":false,
+ "OpenStdin":false,
+ "StdinOnce":false,
+ "Env":null,
+ "Cmd":[
+ "date"
+ ],
+ "Dns":null,
+ "Image":"base",
+ "Volumes":{},
+ "VolumesFrom":""
+ }
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 201 OK
+ Content-Type: application/json
+
+ {
+ "Id":"e90e34656806"
+ "Warnings":[]
+ }
+
+ :jsonparam config: the container's configuration
+ :statuscode 201: no error
+ :statuscode 404: no such container
+ :statuscode 406: impossible to attach (container not running)
+ :statuscode 500: server error
+
+
+Inspect a container
+*******************
+
+.. http:get:: /containers/(id)/json
+
+ Return low-level information on the container ``id``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /containers/4fa6e0f0c678/json HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {
+ "Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2",
+ "Created": "2013-05-07T14:51:42.041847+02:00",
+ "Path": "date",
+ "Args": [],
+ "Config": {
+ "Hostname": "4fa6e0f0c678",
+ "User": "",
+ "Memory": 0,
+ "MemorySwap": 0,
+ "AttachStdin": false,
+ "AttachStdout": true,
+ "AttachStderr": true,
+ "PortSpecs": null,
+ "Tty": false,
+ "OpenStdin": false,
+ "StdinOnce": false,
+ "Env": null,
+ "Cmd": [
+ "date"
+ ],
+ "Dns": null,
+ "Image": "base",
+ "Volumes": {},
+ "VolumesFrom": ""
+ },
+ "State": {
+ "Running": false,
+ "Pid": 0,
+ "ExitCode": 0,
+ "StartedAt": "2013-05-07T14:51:42.087658+02:01360",
+ "Ghost": false
+ },
+ "Image": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
+ "NetworkSettings": {
+ "IpAddress": "",
+ "IpPrefixLen": 0,
+ "Gateway": "",
+ "Bridge": "",
+ "PortMapping": null
+ },
+ "SysInitPath": "/home/kitty/go/src/github.com/dotcloud/docker/bin/docker",
+ "ResolvConfPath": "/etc/resolv.conf",
+ "Volumes": {}
+ }
+
+ :statuscode 200: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+List processes running inside a container
+*****************************************
+
+.. http:get:: /containers/(id)/top
+
+ List processes running inside the container ``id``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /containers/4fa6e0f0c678/top HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {
+ "Titles":[
+ "USER",
+ "PID",
+ "%CPU",
+ "%MEM",
+ "VSZ",
+ "RSS",
+ "TTY",
+ "STAT",
+ "START",
+ "TIME",
+ "COMMAND"
+ ],
+ "Processes":[
+ ["root","20147","0.0","0.1","18060","1864","pts/4","S","10:06","0:00","bash"],
+ ["root","20271","0.0","0.0","4312","352","pts/4","S+","10:07","0:00","sleep","10"]
+ ]
+ }
+
+ :query ps_args: ps arguments to use (eg. aux)
+ :statuscode 200: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Inspect changes on a container's filesystem
+*******************************************
+
+.. http:get:: /containers/(id)/changes
+
+ Inspect changes on container ``id`` 's filesystem
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /containers/4fa6e0f0c678/changes HTTP/1.1
+
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ [
+ {
+ "Path":"/dev",
+ "Kind":0
+ },
+ {
+ "Path":"/dev/kmsg",
+ "Kind":1
+ },
+ {
+ "Path":"/test",
+ "Kind":1
+ }
+ ]
+
+ :statuscode 200: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Export a container
+******************
+
+.. http:get:: /containers/(id)/export
+
+ Export the contents of container ``id``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /containers/4fa6e0f0c678/export HTTP/1.1
+
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/octet-stream
+
+ {{ STREAM }}
+
+ :statuscode 200: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Start a container
+*****************
+
+.. http:post:: /containers/(id)/start
+
+ Start the container ``id``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /containers/(id)/start HTTP/1.1
+ Content-Type: application/json
+
+ {
+ "Binds":["/tmp:/tmp"]
+ }
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 204 No Content
+ Content-Type: text/plain
+
+ :jsonparam hostConfig: the container's host configuration (optional)
+ :statuscode 200: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Stop a contaier
+***************
+
+.. http:post:: /containers/(id)/stop
+
+ Stop the container ``id``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /containers/e90e34656806/stop?t=5 HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 204 OK
+
+ :query t: number of seconds to wait before killing the container
+ :statuscode 204: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Restart a container
+*******************
+
+.. http:post:: /containers/(id)/restart
+
+ Restart the container ``id``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /containers/e90e34656806/restart?t=5 HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 204 OK
+
+ :query t: number of seconds to wait before killing the container
+ :statuscode 204: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Kill a container
+****************
+
+.. http:post:: /containers/(id)/kill
+
+ Kill the container ``id``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /containers/e90e34656806/kill HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 204 OK
+
+ :statuscode 204: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Attach to a container
+*********************
+
+.. http:post:: /containers/(id)/attach
+
+ Attach to the container ``id``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /containers/16253994b7c4/attach?logs=1&stream=0&stdout=1 HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/vnd.docker.raw-stream
+
+ {{ STREAM }}
+
+ :query logs: 1/True/true or 0/False/false, return logs. Default false
+ :query stream: 1/True/true or 0/False/false, return stream. Default false
+ :query stdin: 1/True/true or 0/False/false, if stream=true, attach to stdin. Default false
+ :query stdout: 1/True/true or 0/False/false, if logs=true, return stdout log, if stream=true, attach to stdout. Default false
+ :query stderr: 1/True/true or 0/False/false, if logs=true, return stderr log, if stream=true, attach to stderr. Default false
+ :statuscode 200: no error
+ :statuscode 400: bad parameter
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Wait a container
+****************
+
+.. http:post:: /containers/(id)/wait
+
+ Block until container ``id`` stops, then returns the exit code
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /containers/16253994b7c4/wait HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {"StatusCode":0}
+
+ :statuscode 200: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+Remove a container
+*******************
+
+.. http:delete:: /containers/(id)
+
+ Remove the container ``id`` from the filesystem
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ DELETE /containers/16253994b7c4?v=1 HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 204 OK
+
+ :query v: 1/True/true or 0/False/false, Remove the volumes associated to the container. Default false
+ :statuscode 204: no error
+ :statuscode 400: bad parameter
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+2.2 Images
+----------
+
+List Images
+***********
+
+.. http:get:: /images/(format)
+
+ List images ``format`` could be json or viz (json default)
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /images/json?all=0 HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ [
+ {
+ "Repository":"base",
+ "Tag":"ubuntu-12.10",
+ "Id":"b750fe79269d",
+ "Created":1364102658,
+ "Size":24653,
+ "VirtualSize":180116135
+ },
+ {
+ "Repository":"base",
+ "Tag":"ubuntu-quantal",
+ "Id":"b750fe79269d",
+ "Created":1364102658,
+ "Size":24653,
+ "VirtualSize":180116135
+ }
+ ]
+
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /images/viz HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: text/plain
+
+ digraph docker {
+ "d82cbacda43a" -> "074be284591f"
+ "1496068ca813" -> "08306dc45919"
+ "08306dc45919" -> "0e7893146ac2"
+ "b750fe79269d" -> "1496068ca813"
+ base -> "27cf78414709" [style=invis]
+ "f71189fff3de" -> "9a33b36209ed"
+ "27cf78414709" -> "b750fe79269d"
+ "0e7893146ac2" -> "d6434d954665"
+ "d6434d954665" -> "d82cbacda43a"
+ base -> "e9aa60c60128" [style=invis]
+ "074be284591f" -> "f71189fff3de"
+ "b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
+ "e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
+ "9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
+ base [style=invisible]
+ }
+
+ :query all: 1/True/true or 0/False/false, Show all containers. Only running containers are shown by default
+ :statuscode 200: no error
+ :statuscode 400: bad parameter
+ :statuscode 500: server error
+
+
+Create an image
+***************
+
+.. http:post:: /images/create
+
+ Create an image, either by pull it from the registry or by importing it
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /images/create?fromImage=base HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {"status":"Pulling..."}
+ {"status":"Pulling", "progress":"1/? (n/a)"}
+ {"error":"Invalid..."}
+ ...
+
+ :query fromImage: name of the image to pull
+ :query fromSrc: source to import, - means stdin
+ :query repo: repository
+ :query tag: tag
+ :query registry: the registry to pull from
+ :statuscode 200: no error
+ :statuscode 500: server error
+
+
+Insert a file in a image
+************************
+
+.. http:post:: /images/(name)/insert
+
+ Insert a file from ``url`` in the image ``name`` at ``path``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /images/test/insert?path=/usr&url=myurl HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {"status":"Inserting..."}
+ {"status":"Inserting", "progress":"1/? (n/a)"}
+ {"error":"Invalid..."}
+ ...
+
+ :statuscode 200: no error
+ :statuscode 500: server error
+
+
+Inspect an image
+****************
+
+.. http:get:: /images/(name)/json
+
+ Return low-level information on the image ``name``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /images/base/json HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {
+ "id":"b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
+ "parent":"27cf784147099545",
+ "created":"2013-03-23T22:24:18.818426-07:00",
+ "container":"3d67245a8d72ecf13f33dffac9f79dcdf70f75acb84d308770391510e0c23ad0",
+ "container_config":
+ {
+ "Hostname":"",
+ "User":"",
+ "Memory":0,
+ "MemorySwap":0,
+ "AttachStdin":false,
+ "AttachStdout":false,
+ "AttachStderr":false,
+ "PortSpecs":null,
+ "Tty":true,
+ "OpenStdin":true,
+ "StdinOnce":false,
+ "Env":null,
+ "Cmd": ["/bin/bash"]
+ ,"Dns":null,
+ "Image":"base",
+ "Volumes":null,
+ "VolumesFrom":""
+ },
+ "Size": 6824592
+ }
+
+ :statuscode 200: no error
+ :statuscode 404: no such image
+ :statuscode 500: server error
+
+
+Get the history of an image
+***************************
+
+.. http:get:: /images/(name)/history
+
+ Return the history of the image ``name``
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /images/base/history HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ [
+ {
+ "Id":"b750fe79269d",
+ "Created":1364102658,
+ "CreatedBy":"/bin/bash"
+ },
+ {
+ "Id":"27cf78414709",
+ "Created":1364068391,
+ "CreatedBy":""
+ }
+ ]
+
+ :statuscode 200: no error
+ :statuscode 404: no such image
+ :statuscode 500: server error
+
+
+Push an image on the registry
+*****************************
+
+.. http:post:: /images/(name)/push
+
+ Push the image ``name`` on the registry
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /images/test/push HTTP/1.1
+ {{ authConfig }}
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {"status":"Pushing..."}
+ {"status":"Pushing", "progress":"1/? (n/a)"}
+ {"error":"Invalid..."}
+ ...
+
+ :query registry: the registry you wan to push, optional
+ :statuscode 200: no error
+ :statuscode 404: no such image
+ :statuscode 500: server error
+
+
+Tag an image into a repository
+******************************
+
+.. http:post:: /images/(name)/tag
+
+ Tag the image ``name`` into a repository
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /images/test/tag?repo=myrepo&force=0 HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+
+ :query repo: The repository to tag in
+ :query force: 1/True/true or 0/False/false, default false
+ :statuscode 200: no error
+ :statuscode 400: bad parameter
+ :statuscode 404: no such image
+ :statuscode 409: conflict
+ :statuscode 500: server error
+
+
+Remove an image
+***************
+
+.. http:delete:: /images/(name)
+
+ Remove the image ``name`` from the filesystem
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ DELETE /images/test HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-type: application/json
+
+ [
+ {"Untagged":"3e2f21a89f"},
+ {"Deleted":"3e2f21a89f"},
+ {"Deleted":"53b4f83ac9"}
+ ]
+
+ :statuscode 200: no error
+ :statuscode 404: no such image
+ :statuscode 409: conflict
+ :statuscode 500: server error
+
+
+Search images
+*************
+
+.. http:get:: /images/search
+
+ Search for an image in the docker index
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /images/search?term=sshd HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ [
+ {
+ "Name":"cespare/sshd",
+ "Description":""
+ },
+ {
+ "Name":"johnfuller/sshd",
+ "Description":""
+ },
+ {
+ "Name":"dhrp/mongodb-sshd",
+ "Description":""
+ }
+ ]
+
+ :query term: term to search
+ :statuscode 200: no error
+ :statuscode 500: server error
+
+
+2.3 Misc
+--------
+
+Build an image from Dockerfile via stdin
+****************************************
+
+.. http:post:: /build
+
+ Build an image from Dockerfile via stdin
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /build HTTP/1.1
+
+ {{ STREAM }}
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+
+ {{ STREAM }}
+
+
+ The stream must be a tar archive compressed with one of the following algorithms:
+ identity (no compression), gzip, bzip2, xz. The archive must include a file called
+ `Dockerfile` at its root. It may include any number of other files, which will be
+ accessible in the build context (See the ADD build command).
+
+ The Content-type header should be set to "application/tar".
+
+ :query t: tag to be applied to the resulting image in case of success
+ :query q: suppress verbose build output
+ :statuscode 200: no error
+ :statuscode 500: server error
+
+
+Check auth configuration
+************************
+
+.. http:post:: /auth
+
+ Get the default username and email
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /auth HTTP/1.1
+ Content-Type: application/json
+
+ {
+ "username":"hannibal",
+ "password:"xxxx",
+ "email":"hannibal@a-team.com"
+ }
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+
+ :statuscode 200: no error
+ :statuscode 204: no error
+ :statuscode 500: server error
+
+
+Display system-wide information
+*******************************
+
+.. http:get:: /info
+
+ Display system-wide information
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /info HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {
+ "Containers":11,
+ "Images":16,
+ "Debug":false,
+ "NFd": 11,
+ "NGoroutines":21,
+ "MemoryLimit":true,
+ "SwapLimit":false
+ }
+
+ :statuscode 200: no error
+ :statuscode 500: server error
+
+
+Show the docker version information
+***********************************
+
+.. http:get:: /version
+
+ Show the docker version information
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ GET /version HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 200 OK
+ Content-Type: application/json
+
+ {
+ "Version":"0.2.2",
+ "GitCommit":"5a2a5cc+CHANGES",
+ "GoVersion":"go1.0.3"
+ }
+
+ :statuscode 200: no error
+ :statuscode 500: server error
+
+
+Create a new image from a container's changes
+*********************************************
+
+.. http:post:: /commit
+
+ Create a new image from a container's changes
+
+ **Example request**:
+
+ .. sourcecode:: http
+
+ POST /commit?container=44c004db4b17&m=message&repo=myrepo HTTP/1.1
+
+ **Example response**:
+
+ .. sourcecode:: http
+
+ HTTP/1.1 201 OK
+ Content-Type: application/vnd.docker.raw-stream
+
+ {"Id":"596069db4bf5"}
+
+ :query container: source container
+ :query repo: repository
+ :query tag: tag
+ :query m: commit message
+ :query author: author (eg. "John Hannibal Smith <hannibal@a-team.com>")
+ :query run: config automatically applied when the image is run. (ex: {"Cmd": ["cat", "/world"], "PortSpecs":["22"]})
+ :statuscode 201: no error
+ :statuscode 404: no such container
+ :statuscode 500: server error
+
+
+3. Going further
+================
+
+3.1 Inside 'docker run'
+-----------------------
+
+Here are the steps of 'docker run' :
+
+* Create the container
+* If the status code is 404, it means the image doesn't exists:
+ * Try to pull it
+ * Then retry to create the container
+* Start the container
+* If you are not in detached mode:
+ * Attach to the container, using logs=1 (to have stdout and stderr from the container's start) and stream=1
+* If in detached mode or only stdin is attached:
+ * Display the container's id
+
+
+3.2 Hijacking
+-------------
+
+In this version of the API, /attach, uses hijacking to transport stdin, stdout and stderr on the same socket. This might change in the future.
+
+3.3 CORS Requests
+-----------------
+
+To enable cross origin requests to the remote api add the flag "-api-enable-cors" when running docker in daemon mode.
+
+ docker -d -H="192.168.1.9:4243" -api-enable-cors
+
diff --git a/docs/sources/commandline/command/import.rst b/docs/sources/commandline/command/import.rst
index 66bcf5d..0083068 100644
--- a/docs/sources/commandline/command/import.rst
+++ b/docs/sources/commandline/command/import.rst
@@ -12,8 +12,9 @@
Create a new filesystem image from the contents of a tarball
-At this time, the URL must start with ``http`` and point to a single file archive (.tar, .tar.gz, .bzip)
-containing a root filesystem. If you would like to import from a local directory or archive,
+At this time, the URL must start with ``http`` and point to a single file archive
+(.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz)
+containing a root filesystem. If you would like to import from a local directory or archive,
you can use the ``-`` parameter to take the data from standard in.
Examples
@@ -30,7 +31,7 @@
Import to docker via pipe and standard in
``$ cat exampleimage.tgz | docker import - exampleimagelocal``
-
+
Import from a local directory
.............................
diff --git a/docs/sources/commandline/command/run.rst b/docs/sources/commandline/command/run.rst
index db67ef0..db043c3 100644
--- a/docs/sources/commandline/command/run.rst
+++ b/docs/sources/commandline/command/run.rst
@@ -15,7 +15,7 @@
-a=map[]: Attach to stdin, stdout or stderr.
-c=0: CPU shares (relative weight)
-cidfile="": Write the container ID to the file
- -d=false: Detached mode: leave the container running in the background
+ -d=false: Detached mode: Run container in the background, print new container id
-e=[]: Set environment variables
-h="": Container host name
-i=false: Keep stdin open even if not attached
diff --git a/docs/sources/concepts/manifesto.rst b/docs/sources/concepts/manifesto.rst
index ae09647..7dd4b4b 100644
--- a/docs/sources/concepts/manifesto.rst
+++ b/docs/sources/concepts/manifesto.rst
@@ -4,10 +4,6 @@
.. _dockermanifesto:
-*(This was our original Welcome page, but it is a bit forward-looking
-for docs, and maybe not enough vision for a true manifesto. We'll
-reveal more vision in the future to make it more Manifesto-y.)*
-
Docker Manifesto
----------------
@@ -131,60 +127,3 @@
With Standard Containers we can put an end to that embarrassment, by
making INDUSTRIAL-GRADE DELIVERY of software a reality.
-
-Standard Container Specification
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-(TODO)
-
-Image format
-~~~~~~~~~~~~
-
-Standard operations
-~~~~~~~~~~~~~~~~~~~
-
-- Copy
-- Run
-- Stop
-- Wait
-- Commit
-- Attach standard streams
-- List filesystem changes
-- ...
-
-Execution environment
-~~~~~~~~~~~~~~~~~~~~~
-
-Root filesystem
-^^^^^^^^^^^^^^^
-
-Environment variables
-^^^^^^^^^^^^^^^^^^^^^
-
-Process arguments
-^^^^^^^^^^^^^^^^^
-
-Networking
-^^^^^^^^^^
-
-Process namespacing
-^^^^^^^^^^^^^^^^^^^
-
-Resource limits
-^^^^^^^^^^^^^^^
-
-Process monitoring
-^^^^^^^^^^^^^^^^^^
-
-Logging
-^^^^^^^
-
-Signals
-^^^^^^^
-
-Pseudo-terminal allocation
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Security
-^^^^^^^^
-
diff --git a/docs/sources/examples/couchdb_data_volumes.rst b/docs/sources/examples/couchdb_data_volumes.rst
index d6babe5..97af733 100644
--- a/docs/sources/examples/couchdb_data_volumes.rst
+++ b/docs/sources/examples/couchdb_data_volumes.rst
@@ -39,7 +39,7 @@
.. code-block:: bash
- COUCH2=$(docker run -d -volumes-from $COUCH1) shykes/couchdb:2013-05-03)
+ COUCH2=$(docker run -d -volumes-from $COUCH1 shykes/couchdb:2013-05-03)
Browse data on the second database
----------------------------------
@@ -48,6 +48,6 @@
HOST=localhost
URL="http://$HOST:$(docker port $COUCH2 5984)/_utils/"
- echo "Navigate to $URL in your browser. You should see the same data as in the first database!"
+ echo "Navigate to $URL in your browser. You should see the same data as in the first database"'!'
Congratulations, you are running 2 Couchdb containers, completely isolated from each other *except* for their data.
diff --git a/docs/theme/MAINTAINERS b/docs/theme/MAINTAINERS
index 6df367c..606a1dd 100644
--- a/docs/theme/MAINTAINERS
+++ b/docs/theme/MAINTAINERS
@@ -1 +1 @@
-Thatcher Penskens <thatcher@dotcloud.com>
+Thatcher Peskens <thatcher@dotcloud.com>
diff --git a/docs/theme/docker/layout.html b/docs/theme/docker/layout.html
index 198cd5d..0b22f22 100755
--- a/docs/theme/docker/layout.html
+++ b/docs/theme/docker/layout.html
@@ -68,12 +68,12 @@
<div style="float: right" class="pull-right">
<ul class="nav">
- <li id="nav-introduction"><a href="http://www.docker.io/">Home</a></li>
- <li id="nav-about"><a href="http://www.docker.io/">About</a></li>
- <li id="nav-community"><a href="http://www.docker.io/">Community</a></li>
+ <li id="nav-introduction"><a href="http://www.docker.io/" title="Docker Homepage">Home</a></li>
+ <li id="nav-about"><a href="http://www.docker.io/about/" title="About">About</a></li>
+ <li id="nav-community"><a href="http://www.docker.io/community/" title="Community">Community</a></li>
<li id="nav-gettingstarted"><a href="http://www.docker.io/gettingstarted/">Getting started</a></li>
<li id="nav-documentation" class="active"><a href="http://docs.docker.io/en/latest/">Documentation</a></li>
- <li id="nav-blog"><a href="http://blog.docker.io/">Blog</a></li>
+ <li id="nav-blog"><a href="http://blog.docker.io/" title="Docker Blog">Blog</a></li>
<li id="nav-index"><a href="http://index.docker.io/" title="Docker Image Index, find images here">INDEX <img class="inline-icon" src="{{ pathto('_static/img/external-link-icon.png', 1) }}" title="external link"> </a></li>
</ul>
</div>
diff --git a/docs/website/MAINTAINERS b/docs/website/MAINTAINERS
deleted file mode 100644
index 6df367c..0000000
--- a/docs/website/MAINTAINERS
+++ /dev/null
@@ -1 +0,0 @@
-Thatcher Penskens <thatcher@dotcloud.com>
diff --git a/docs/website/dotcloud.yml b/docs/website/dotcloud.yml
deleted file mode 100644
index 5a8f50f..0000000
--- a/docs/website/dotcloud.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-www:
- type: static
\ No newline at end of file
diff --git a/docs/website/gettingstarted/index.html b/docs/website/gettingstarted/index.html
deleted file mode 100644
index de0cc35..0000000
--- a/docs/website/gettingstarted/index.html
+++ /dev/null
@@ -1,220 +0,0 @@
-<!DOCTYPE html>
-<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
-<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
-<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
-<!--[if gt IE 8]><!-->
-<html class="no-js" xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html"> <!--<![endif]-->
-<head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
- <title>Docker - the Linux container runtime</title>
-
- <meta name="description" content="Docker encapsulates heterogeneous payloads in standard containers">
- <meta name="viewport" content="width=device-width">
-
- <!-- twitter bootstrap -->
- <link rel="stylesheet" href="../static/css/bootstrap.min.css">
- <link rel="stylesheet" href="../static/css/bootstrap-responsive.min.css">
-
- <!-- main style file -->
- <link rel="stylesheet" href="../static/css/main.css">
-
- <!-- vendor scripts -->
- <script src="../static/js/vendor/jquery-1.9.1.min.js" type="text/javascript" ></script>
- <script src="../static/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js" type="text/javascript" ></script>
-
-</head>
-
-
-<body>
-
-<div class="navbar navbar-fixed-top">
- <div class="navbar-dotcloud">
- <div class="container" style="text-align: center;">
-
- <div style="float: right" class="pull-right">
- <ul class="nav">
- <li id="nav-introduction"><a href="../">Introduction</a></li>
- <li id="nav-gettingstarted" class="active"><a href="">Getting started</a></li>
- <li id="nav-documentation" class=""><a href="http://docs.docker.io/en/latest/">Documentation</a></li>
- <li id="nav-blog"><a href="http://blog.docker.io/">Blog</a></li>
- </ul>
- </div>
-
- <div style="margin-left: -12px; float: left;">
- <a href="../index.html"><img style="margin-top: 12px; height: 38px" src="../static/img/docker-letters-logo.gif"></a>
- </div>
- </div>
- </div>
-</div>
-
-
-<div class="container">
- <div class="row">
-
- <div class="span12 titlebar">
-
- <div class="pull-right" id="fork-us" style="margin-top: 16px; margin-right: 16px;">
- <a href="http://github.com/dotcloud/docker/"><img src="../static/img/fork-us.png"> Fork us on Github</a>
- </div>
-
- <h1 class="pageheader"> GETTING STARTED</h1>
- </div>
-
- </div>
-
-</div>
-
-<div class="container">
- <div class="alert alert-info" style="margin-bottom: 0;">
- <strong>Docker is still under heavy development.</strong> It should not yet be used in production. Check <a href="http://github.com/dotcloud/docker">the repo</a> for recent progress.
- </div>
- <div class="row">
- <div class="span6">
- <section class="contentblock">
- <h2>
- <a name="installing-on-ubuntu-1204-and-1210" class="anchor" href="#installing-on-ubuntu-1204-and-1210"><span class="mini-icon mini-icon-link"></span>
- </a>Installing on Ubuntu</h2>
-
- <p><strong>Requirements</strong></p>
- <ul>
- <li>Ubuntu 12.04 (LTS) (64-bit)</li>
- <li> or Ubuntu 12.10 (quantal) (64-bit)</li>
- <li>The 3.8 Linux Kernel</li>
- </ul>
- <ol>
- <li>
- <p><strong>Install dependencies</strong></p>
- The linux-image-extra package is only needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module.
- <pre>sudo apt-get install linux-image-extra-`uname -r`</pre>
-
-
- </li>
- <li>
- <p><strong>Install Docker</strong></p>
- <p>Add the Ubuntu PPA (Personal Package Archive) sources to your apt sources list, update and install.</p>
- <p>This may import a new GPG key (key 63561DC6: public key "Launchpad PPA for dotcloud team" imported).</p>
- <div class="highlight">
- <pre>sudo apt-get install software-properties-common</pre>
- <pre>sudo add-apt-repository ppa:dotcloud/lxc-docker</pre>
- <pre>sudo apt-get update</pre>
- <pre>sudo apt-get install lxc-docker</pre>
- </div>
-
-
- </li>
-
- <li>
- <p><strong>Run!</strong></p>
-
- <div class="highlight">
- <pre>docker run -i -t ubuntu /bin/bash</pre>
- </div>
- </li>
- Continue with the <a href="http://docs.docker.io/en/latest/examples/hello_world/">Hello world</a> example.<br>
- Or check <a href="http://docs.docker.io/en/latest/installation/ubuntulinux/">more detailed installation instructions</a>
- </ol>
- </section>
-
- <section class="contentblock">
- <h2>Contributing to Docker</h2>
-
- <p>Want to hack on Docker? Awesome! We have some <a href="http://docs.docker.io/en/latest/contributing/contributing/">instructions to get you started</a>. They are probably not perfect, please let us know if anything feels wrong or incomplete.</p>
- </section>
-
- </div>
- <div class="span6">
- <section class="contentblock">
- <h2>Quick install on other operating systems</h2>
- <p><strong>For other operating systems we recommend and provide a streamlined install with virtualbox,
- vagrant and an Ubuntu virtual machine.</strong></p>
-
- <ul>
- <li><a href="http://docs.docker.io/en/latest/installation/vagrant/">Mac OS X and other linuxes</a></li>
- <li><a href="http://docs.docker.io/en/latest/installation/windows/">Windows</a></li>
- </ul>
-
- </section>
-
- <section class="contentblock">
- <h2>Questions? Want to get in touch?</h2>
- <p>There are several ways to get in touch:</p>
- <p><strong>Join the discussion on IRC.</strong> We can be found in the <a href="irc://chat.freenode.net#docker">#docker</a> channel on chat.freenode.net</p>
- <p><strong>Discussions</strong> happen on our google group: <a href="https://groups.google.com/d/forum/docker-club">docker-club at googlegroups.com</a></p>
- <p>All our <strong>development and decisions</strong> are made out in the open on Github <a href="http://www.github.com/dotcloud/docker">github.com/dotcloud/docker</a></p>
- <p><strong>Get help on using Docker</strong> by asking on <a href="http://stackoverflow.com/tags/docker/">Stackoverflow</a></p>
- <p>And of course, <strong>tweet</strong> your tweets to <a href="http://twitter.com/getdocker/">twitter.com/getdocker</a></p>
- </section>
-
-
- <section class="contentblock">
- <div id="wufoo-z7x3p3">
- Fill out my <a href="http://dotclouddocker.wufoo.com/forms/z7x3p3">online form</a>.
- </div>
- <script type="text/javascript">var z7x3p3;(function(d, t) {
- var s = d.createElement(t), options = {
- 'userName':'dotclouddocker',
- 'formHash':'z7x3p3',
- 'autoResize':true,
- 'height':'577',
- 'async':true,
- 'header':'show'};
- s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
- s.onload = s.onreadystatechange = function() {
- var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
- try { z7x3p3 = new WufooForm();z7x3p3.initialize(options);z7x3p3.display(); } catch (e) {}};
- var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
- })(document, 'script');</script>
- </section>
-
- </div>
- </div>
-</div>
-
-
-<div class="container">
- <footer id="footer" class="footer">
- <div class="row">
- <div class="span12 social">
- <div class="tbox textright forceleftmargin social links pull-right">
- <a class="twitter" href="http://twitter.com/getdocker">Twitter</a>
- <a class="github" href="https://github.com/dotcloud/docker/">GitHub</a>
- </div>
- Docker is a project by <a href="http://www.dotcloud.com">dotCloud</a>
-
- </div>
- </div>
-
- <div class="row">
- <div class="emptyspace" style="height: 40px">
-
- </div>
- </div>
-
- </footer>
-</div>
-
-
-<!-- bootstrap javascipts -->
-<script src="../static/js/vendor/bootstrap.min.js" type="text/javascript"></script>
-
-<!-- Google analytics -->
-<script type="text/javascript">
-
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-6096819-11']);
- _gaq.push(['_setDomainName', 'docker.io']);
- _gaq.push(['_setAllowLinker', true]);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-
-</script>
-
-
-</body>
-</html>
diff --git a/docs/website/index.html b/docs/website/index.html
deleted file mode 100644
index f6f4efb..0000000
--- a/docs/website/index.html
+++ /dev/null
@@ -1,359 +0,0 @@
-<!DOCTYPE html>
-<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
-<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
-<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
-<!--[if gt IE 8]><!-->
-<html class="no-js" xmlns="http://www.w3.org/1999/html"> <!--<![endif]-->
-<head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
- <meta name="google-site-verification" content="UxV66EKuPe87dgnH1sbrldrx6VsoWMrx5NjwkgUFxXI" />
- <title>Docker - the Linux container engine</title>
-
- <meta name="description" content="Docker encapsulates heterogeneous payloads in standard containers">
- <meta name="viewport" content="width=device-width">
-
- <!-- twitter bootstrap -->
- <link rel="stylesheet" href="static/css/bootstrap.min.css">
- <link rel="stylesheet" href="static/css/bootstrap-responsive.min.css">
-
- <!-- main style file -->
- <link rel="stylesheet" href="static/css/main.css">
-
- <!-- vendor scripts -->
- <script src="static/js/vendor/jquery-1.9.1.min.js" type="text/javascript" ></script>
- <script src="static/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js" type="text/javascript" ></script>
-
- <style>
- .indexlabel {
- float: left;
- width: 150px;
- display: block;
- padding: 10px 20px 10px;
- font-size: 20px;
- font-weight: 200;
- background-color: #a30000;
- color: white;
- height: 22px;
- }
- .searchbutton {
- font-size: 20px;
- height: 40px;
- }
-
- .debug {
- border: 1px red dotted;
- }
- .twitterblock {
- min-height: 75px;
- }
-
- .twitterblock img {
- float: left;
- margin-right: 10px;
- }
-
- </style>
-
-
-</head>
-
-
-<body>
-
-<div class="navbar navbar-fixed-top">
- <div class="navbar-dotcloud">
- <div class="container" style="text-align: center;">
-
-
- <div class="pull-left" id="fork-us" style="margin-top: 16px;">
- <a href="http://github.com/dotcloud/docker/"><img src="static/img/fork-us.png" alt="fork-icon"> Fork us on Github</a>
- </div>
-
- <div class="pull-right" >
- <ul class="nav">
- <li id="nav-introduction" class="active"><a href="/">Introduction</a></li>
- <li id="nav-gettingstarted"><a href="gettingstarted">Getting started</a></li>
- <li id="nav-documentation" class=""><a href="http://docs.docker.io/en/latest/">Documentation</a></li>
- <li id="nav-blog"><a href="http://blog.docker.io/">Blog</a></li>
- </ul>
- </div>
- </div>
- </div>
-</div>
-
-
-<div class="container" style="margin-top: 30px;">
- <div class="row">
-
- <div class="span12">
- <section class="contentblock header">
-
- <div class="span5" style="margin-bottom: 15px;">
- <div style="text-align: center;" >
- <img src="static/img/docker_letters_500px.png" alt="docker letters">
-
- <h2>The Linux container engine</h2>
- </div>
-
- <div style="display: block; text-align: center; margin-top: 20px;">
-
- <h5>
- Docker is an open-source engine which automates the deployment of applications as highly portable, self-sufficient containers which are independent of hardware, language, framework, packaging system and hosting provider.
- </h5>
-
- </div>
-
-
- <div style="display: block; text-align: center; margin-top: 30px;">
- <a class="btn btn-custom btn-large" href="gettingstarted/">Let's get started</a>
- </div>
-
- </div>
-
- <div class="span6" >
- <div class="js-video" >
- <iframe width="600" height="360" src="http://www.youtube.com/embed/wW9CAH9nSLs?feature=player_detailpage&rel=0&modestbranding=1&start=11" frameborder="0" allowfullscreen></iframe>
- </div>
- </div>
-
- <br style="clear: both"/>
- </section>
- </div>
- </div>
-</div>
-
-<div class="container">
- <div class="row">
-
- <div class="span6">
- <section class="contentblock">
- <h4>Heterogeneous payloads</h4>
- <p>Any combination of binaries, libraries, configuration files, scripts, virtualenvs, jars, gems, tarballs, you name it. No more juggling between domain-specific tools. Docker can deploy and run them all.</p>
- <h4>Any server</h4>
- <p>Docker can run on any x64 machine with a modern linux kernel - whether it's a laptop, a bare metal server or a VM. This makes it perfect for multi-cloud deployments.</p>
- <h4>Isolation</h4>
- <p>Docker isolates processes from each other and from the underlying host, using lightweight containers.</p>
- <h4>Repeatability</h4>
- <p>Because each container is isolated in its own filesystem, they behave the same regardless of where, when, and alongside what they run.</p>
- </section>
- <section class="contentblock">
- <div class="container">
- <div class="span2" style="margin-left: 0" >
- <a href="http://dotcloud.theresumator.com/apply/mWjkD4/Software-Engineer.html" title="Job description"><img src="static/img/hiring_graphic.png" alt="we're hiring" width="140" style="margin-top: 25px"></a>
- </div>
- <div class="span4" style="margin-left: 0">
- <h4>Do you think it is cool to hack on docker? Join us!</h4>
- <ul>
- <li>Work on open source</li>
- <li>Program in Go</li>
- </ul>
- <a href="http://dotcloud.theresumator.com/apply/mWjkD4/Software-Engineer.html" title="Job description">read more</a>
- </div>
- </div>
-
- </section>
- </div>
- <div class="span6">
- <section class="contentblock">
- <h1>New! Docker Index</h1>
- On the Docker Index you can find and explore pre-made container images. It allows you to share your images and download them.
-
- <br><br>
- <a href="https://index.docker.io" target="_blank">
- <div class="indexlabel">
- DOCKER index
- </div>
- </a>
-
- <input type="button" class="searchbutton" value="Search images"
- onClick="window.open('https://index.docker.io')" />
-
- </section>
- <section class="contentblock">
- <div id="wufoo-z7x3p3">
- Fill out my <a href="http://dotclouddocker.wufoo.com/forms/z7x3p3">online form</a>.
- </div>
- <script type="text/javascript">var z7x3p3;(function(d, t) {
- var s = d.createElement(t), options = {
- 'userName':'dotclouddocker',
- 'formHash':'z7x3p3',
- 'autoResize':true,
- 'height':'577',
- 'async':true,
- 'header':'show'};
- s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
- s.onload = s.onreadystatechange = function() {
- var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
- try { z7x3p3 = new WufooForm();z7x3p3.initialize(options);z7x3p3.display(); } catch (e) {}};
- var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
- })(document, 'script');</script>
- </section>
- </div>
- </div>
-
-</div>
-
-<div class="container">
-
- <div class="row">
- <div class="span6">
- <section class="contentblock twitterblock">
- <img src="https://si0.twimg.com/profile_images/2707460527/252a64411a339184ff375a96fb68dcb0_bigger.png">
- <em>Mitchell Hashimoto @mitchellh:</em> Docker launched today. It is incredible. They’re also working RIGHT NOW on a Vagrant provider. LXC is COMING!!
- </section>
- </div>
- <div class="span6">
- <section class="contentblock twitterblock">
- <img src="https://si0.twimg.com/profile_images/1108290260/Adam_Jacob-114x150_original_bigger.jpg">
- <em>Adam Jacob @adamhjk:</em> Docker is clearly the right idea. @solomonstre absolutely killed it. Containerized app deployment is the future, I think.
- </section>
- </div>
- </div>
- <div class="row">
- <div class="span6">
- <section class="contentblock twitterblock">
- <img src="https://si0.twimg.com/profile_images/14872832/twitter_pic_bigger.jpg">
- <em>Matt Townsend @mtownsend:</em> I have a serious code crush on docker.io - it's Lego for PaaS. Motherfucking awesome Lego.
- </section>
- </div>
- <div class="span6">
- <section class="contentblock twitterblock">
- <img src="https://si0.twimg.com/profile_images/1312352395/rupert-259x300_bigger.jpg">
- <em>Rob Harrop @robertharrop:</em> Impressed by @getdocker - it's all kinds of magic. Serious rethink of AWS architecture happening @skillsmatter.
- </section>
- </div>
- </div>
- <div class="row">
- <div class="span6">
- <section class="contentblock twitterblock">
- <img src="https://twimg0-a.akamaihd.net/profile_images/2491994496/rbevyyq6ykp6bnoby2je_bigger.jpeg">
- <em>John Willis @botchagalupe:</em> IMHO docker is to paas what chef was to Iaas 4 years ago
- </section>
- </div>
- <div class="span6">
- <section class="contentblock twitterblock">
- <img src="https://twimg0-a.akamaihd.net/profile_images/3348427561/9d7f08f1e103a16c8debd169301b9944_bigger.jpeg">
- <em>John Feminella @superninjarobot:</em> So, @getdocker is pure excellence. If you've ever wished for arbitrary, PaaS-agnostic, lxc/aufs Linux containers, this is your jam!
- </section>
- </div>
- </div>
- <div class="row">
- <div class="span6">
- <section class="contentblock twitterblock">
- <img src="https://si0.twimg.com/profile_images/3408403010/4496ccdd14e9b7285eca04c31a740207_bigger.jpeg">
- <em>David Romulan @destructuring:</em> I haven't had this much fun since AWS
- </section>
- </div>
- <div class="span6">
- <section class="contentblock twitterblock">
- <img src="https://si0.twimg.com/profile_images/780893320/My_Avatar_bigger.jpg">
- <em>Ricardo Gladwell @rgladwell:</em> wow @getdocker is either amazing or totally stupid
- </section>
- </div>
-
- </div>
-</div>
-
-<div class="container">
- <div class="row">
- <div class="span6">
-
- <section class="contentblock">
-
- <h2>Notable features</h2>
-
- <ul>
- <li>Filesystem isolation: each process container runs in a completely separate root filesystem.</li>
- <li>Resource isolation: system resources like cpu and memory can be allocated differently to each process container, using cgroups.</li>
- <li>Network isolation: each process container runs in its own network namespace, with a virtual interface and IP address of its own.</li>
- <li>Copy-on-write: root filesystems are created using copy-on-write, which makes deployment extremely fast, memory-cheap and disk-cheap.</li>
- <li>Logging: the standard streams (stdout/stderr/stdin) of each process container is collected and logged for real-time or batch retrieval.</li>
- <li>Change management: changes to a container's filesystem can be committed into a new image and re-used to create more containers. No templating or manual configuration required.</li>
- <li>Interactive shell: docker can allocate a pseudo-tty and attach to the standard input of any container, for example to run a throwaway interactive shell.</li>
- </ul>
-
- <h2>Under the hood</h2>
-
- <p>Under the hood, Docker is built on the following components:</p>
-
- <ul>
- <li>The <a href="http://blog.dotcloud.com/kernel-secrets-from-the-paas-garage-part-24-c">cgroup</a> and <a href="http://blog.dotcloud.com/under-the-hood-linux-kernels-on-dotcloud-part">namespacing</a> capabilities of the Linux kernel;</li>
- <li><a href="http://aufs.sourceforge.net/aufs.html">AUFS</a>, a powerful union filesystem with copy-on-write capabilities;</li>
- <li>The <a href="http://golang.org">Go</a> programming language;</li>
- <li><a href="http://lxc.sourceforge.net/">lxc</a>, a set of convenience scripts to simplify the creation of linux containers.</li>
- </ul>
-
- <h2>Who started it</h2>
- <p>
- Docker is an open-source implementation of the deployment engine which powers <a href="http://dotcloud.com">dotCloud</a>, a popular Platform-as-a-Service.</p>
-
- <p>It benefits directly from the experience accumulated over several years of large-scale operation and support of hundreds of thousands
- of applications and databases.
- </p>
-
- </section>
- </div>
-
- <div class="span6">
-
-
- <section class="contentblock">
- <h3 id="twitter">Twitter</h3>
- <a class="twitter-timeline" href="https://twitter.com/getdocker" data-widget-id="312730839718957056">Tweets by @getdocker</a>
- <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
- </section>
-
- </div>
- </div>
-
-</div> <!-- end container -->
-
-
-<div class="container">
- <footer id="footer" class="footer">
- <div class="row">
- <div class="span12">
- <div class="tbox textright forceleftmargin social links pull-right">
- <a class="twitter" href="http://twitter.com/getdocker">Twitter</a>
- <a class="github" href="https://github.com/dotcloud/docker/">GitHub</a>
- </div>
- Docker is a project by <a href="http://www.dotcloud.com">dotCloud</a>
-
- </div>
- </div>
-
- <div class="row">
- <div class="emptyspace" style="height: 40px">
-
- </div>
- </div>
-
- </footer>
-</div>
-
-
-
-<!-- bootstrap javascipts -->
-<script src="static/js/vendor/bootstrap.min.js" type="text/javascript"></script>
-
-<!-- Google analytics -->
-<script type="text/javascript">
-
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-6096819-11']);
- _gaq.push(['_setDomainName', 'docker.io']);
- _gaq.push(['_setAllowLinker', true]);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-
-</script>
-
-
-</body>
-</html>
diff --git a/docs/website/nginx.conf b/docs/website/nginx.conf
deleted file mode 100644
index 97ffd2c..0000000
--- a/docs/website/nginx.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-
-# rule to redirect original links created when hosted on github pages
-rewrite ^/documentation/(.*).html http://docs.docker.io/en/latest/$1/ permanent;
-
-# rewrite the stuff which was on the current page
-rewrite ^/gettingstarted.html$ /gettingstarted/ permanent;
diff --git a/docs/website/static b/docs/website/static
deleted file mode 120000
index 95bc97a..0000000
--- a/docs/website/static
+++ /dev/null
@@ -1 +0,0 @@
-../theme/docker/static
\ No newline at end of file
diff --git a/image.go b/image.go
index e1b1ac0..5240ec7 100644
--- a/image.go
+++ b/image.go
@@ -68,7 +68,7 @@
}
// Store the layer
layer := layerPath(root)
- if err := os.MkdirAll(layer, 0700); err != nil {
+ if err := os.MkdirAll(layer, 0755); err != nil {
return err
}
diff --git a/packaging/debian/lxc-docker.1 b/packaging/debian/lxc-docker.1
index 8f98785..cc20299 100644
--- a/packaging/debian/lxc-docker.1
+++ b/packaging/debian/lxc-docker.1
@@ -923,6 +923,12 @@
Usage: docker import [OPTIONS] URL|\- [REPOSITORY [TAG]]
.sp
Create a new filesystem image from the contents of a tarball
+
+At this time, the URL must start with ``http`` and point to a single file archive
+(.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz)
+containing a root filesystem. If you would like to import from a local directory or archive,
+you can use the ``-`` parameter to take the data from standard in.
+
.SS info
.sp
.nf
diff --git a/packaging/ubuntu/docker.upstart b/packaging/ubuntu/docker.upstart
index 2bd5565..f4d2fbe 100644
--- a/packaging/ubuntu/docker.upstart
+++ b/packaging/ubuntu/docker.upstart
@@ -1,9 +1,8 @@
description "Run docker"
-start on runlevel [2345]
-stop on starting rc RUNLEVEL=[016]
+start on filesystem or runlevel [2345]
+stop on runlevel [!2345]
+
respawn
-script
- /usr/bin/docker -d
-end script
+exec /usr/bin/docker -d
diff --git a/registry/registry.go b/registry/registry.go
index e6f4f59..adef1c7 100644
--- a/registry/registry.go
+++ b/registry/registry.go
@@ -109,7 +109,14 @@
for _, cookie := range c.Jar.Cookies(req.URL) {
req.AddCookie(cookie)
}
- return c.Do(req)
+ res, err := c.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ if len(res.Cookies()) > 0 {
+ c.Jar.SetCookies(req.URL, res.Cookies())
+ }
+ return res, err
}
// Set the user agent field in the header based on the versions provided
@@ -135,7 +142,7 @@
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
r.setUserAgent(req)
- res, err := r.client.Do(req)
+ res, err := doWithCookies(r.client, req)
if err != nil || res.StatusCode != 200 {
if res != nil {
return nil, fmt.Errorf("Internal server error: %d trying to fetch remote history for %s", res.StatusCode, imgID)
@@ -182,7 +189,7 @@
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
r.setUserAgent(req)
- res, err := r.client.Do(req)
+ res, err := doWithCookies(r.client, req)
if err != nil {
return nil, -1, fmt.Errorf("Failed to download json: %s", err)
}
@@ -210,7 +217,7 @@
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
r.setUserAgent(req)
- res, err := r.client.Do(req)
+ res, err := doWithCookies(r.client, req)
if err != nil {
return nil, err
}
@@ -231,7 +238,7 @@
}
req.Header.Set("Authorization", "Token "+strings.Join(token, ", "))
r.setUserAgent(req)
- res, err := r.client.Do(req)
+ res, err := doWithCookies(r.client, req)
if err != nil {
return nil, err
}
@@ -326,7 +333,7 @@
// Push a local image to the registry
func (r *Registry) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, registry string, token []string) error {
// FIXME: try json with UTF8
- req, err := http.NewRequest("PUT", registry+"images/"+imgData.ID+"/json", strings.NewReader(string(jsonRaw)))
+ req, err := http.NewRequest("PUT", registry+"images/"+imgData.ID+"/json", bytes.NewReader(jsonRaw))
if err != nil {
return err
}
@@ -341,9 +348,6 @@
return fmt.Errorf("Failed to upload metadata: %s", err)
}
defer res.Body.Close()
- if len(res.Cookies()) > 0 {
- r.client.Jar.SetCookies(req.URL, res.Cookies())
- }
if res.StatusCode != 200 {
errBody, err := ioutil.ReadAll(res.Body)
if err != nil {
diff --git a/runtime_test.go b/runtime_test.go
index 8070974..0b0f62f 100644
--- a/runtime_test.go
+++ b/runtime_test.go
@@ -8,6 +8,7 @@
"log"
"net"
"os"
+ "runtime"
"strconv"
"strings"
"sync"
@@ -25,7 +26,11 @@
testDaemonProto = "tcp"
)
-var globalRuntime *Runtime
+var (
+ globalRuntime *Runtime
+ startFds int
+ startGoroutines int
+)
func nuke(runtime *Runtime) error {
var wg sync.WaitGroup
@@ -80,21 +85,21 @@
NetworkBridgeIface = unitTestNetworkBridge
// Make it our Store root
- runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false)
- if err != nil {
+ if runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false); err != nil {
panic(err)
+ } else {
+ globalRuntime = runtime
}
- globalRuntime = runtime
// Create the "Server"
srv := &Server{
- runtime: runtime,
+ runtime: globalRuntime,
enableCors: false,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
// If the unit test is not found, try to download it.
- if img, err := runtime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID {
+ if img, err := globalRuntime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID {
// Retrieve the Image
if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil); err != nil {
panic(err)
@@ -109,6 +114,8 @@
// Give some time to ListenAndServer to actually start
time.Sleep(time.Second)
+
+ startFds, startGoroutines = utils.GetTotalUsedFds(), runtime.NumGoroutine()
}
// FIXME: test that ImagePull(json=true) send correct json output
diff --git a/server.go b/server.go
index ce1fc8e..af9928c 100644
--- a/server.go
+++ b/server.go
@@ -309,35 +309,34 @@
}
-func (srv *Server) ContainerTop(name string) ([]APITop, error) {
+func (srv *Server) ContainerTop(name, ps_args string) (*APITop, error) {
if container := srv.runtime.Get(name); container != nil {
- output, err := exec.Command("lxc-ps", "--name", container.ID).CombinedOutput()
+ output, err := exec.Command("lxc-ps", "--name", container.ID, "--", ps_args).CombinedOutput()
if err != nil {
return nil, fmt.Errorf("Error trying to use lxc-ps: %s (%s)", err, output)
}
- var procs []APITop
+ procs := APITop{}
for i, line := range strings.Split(string(output), "\n") {
- if i == 0 || len(line) == 0 {
+ if len(line) == 0 {
continue
}
- proc := APITop{}
+ words := []string{}
scanner := bufio.NewScanner(strings.NewReader(line))
scanner.Split(bufio.ScanWords)
if !scanner.Scan() {
return nil, fmt.Errorf("Error trying to use lxc-ps")
}
// no scanner.Text because we skip container id
- scanner.Scan()
- proc.PID = scanner.Text()
- scanner.Scan()
- proc.Tty = scanner.Text()
- scanner.Scan()
- proc.Time = scanner.Text()
- scanner.Scan()
- proc.Cmd = scanner.Text()
- procs = append(procs, proc)
+ for scanner.Scan() {
+ words = append(words, scanner.Text())
+ }
+ if i == 0 {
+ procs.Titles = words
+ } else {
+ procs.Processes = append(procs.Processes, words)
+ }
}
- return procs, nil
+ return &procs, nil
}
return nil, fmt.Errorf("No such container: %s", name)
@@ -995,6 +994,9 @@
parsedRepo := strings.Split(repoAndTag, ":")[0]
if strings.Contains(img.ID, repoName) {
repoName = parsedRepo
+ if len(srv.runtime.repositories.ByID()[img.ID]) == 1 && len(strings.Split(repoAndTag, ":")) > 1 {
+ tag = strings.Split(repoAndTag, ":")[1]
+ }
} else if repoName != parsedRepo {
// the id belongs to multiple repos, like base:latest and user:test,
// in that case return conflict
diff --git a/server_test.go b/server_test.go
index f67b8fb..57e2376 100644
--- a/server_test.go
+++ b/server_test.go
@@ -2,6 +2,7 @@
import (
"github.com/dotcloud/docker/utils"
+ "strings"
"testing"
"time"
)
@@ -224,3 +225,88 @@
})
}
+
+func TestRmi(t *testing.T) {
+ runtime := mkRuntime(t)
+ defer nuke(runtime)
+ srv := &Server{runtime: runtime}
+
+ initialImages, err := srv.Images(false, "")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ config, hostConfig, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ containerID, err := srv.ContainerCreate(config)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ //To remove
+ err = srv.ContainerStart(containerID, hostConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ imageID, err := srv.ContainerCommit(containerID, "test", "", "", "", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = srv.ContainerTag(imageID, "test", "0.1", false)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ containerID, err = srv.ContainerCreate(config)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ //To remove
+ err = srv.ContainerStart(containerID, hostConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = srv.ContainerCommit(containerID, "test", "", "", "", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ images, err := srv.Images(false, "")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(images)-len(initialImages) != 2 {
+ t.Fatalf("Expected 2 new images, found %d.", len(images)-len(initialImages))
+ }
+
+ _, err = srv.ImageDelete(imageID, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ images, err = srv.Images(false, "")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(images)-len(initialImages) != 1 {
+ t.Fatalf("Expected 1 new image, found %d.", len(images)-len(initialImages))
+ }
+
+ for _, image := range images {
+ if strings.Contains(unitTestImageID, image.ID) {
+ continue
+ }
+ if image.Repository == "" {
+ t.Fatalf("Expected tagged image, got untagged one.")
+ }
+ }
+}
diff --git a/z_final_test.go b/z_final_test.go
index 78a7acf..08a180b 100644
--- a/z_final_test.go
+++ b/z_final_test.go
@@ -6,7 +6,12 @@
"testing"
)
+func displayFdGoroutines(t *testing.T) {
+ t.Logf("Fds: %d, Goroutines: %d", utils.GetTotalUsedFds(), runtime.NumGoroutine())
+}
+
func TestFinal(t *testing.T) {
cleanup(globalRuntime)
- t.Logf("Fds: %d, Goroutines: %d", utils.GetTotalUsedFds(), runtime.NumGoroutine())
+ t.Logf("Start Fds: %d, Start Goroutines: %d", startFds, startGoroutines)
+ displayFdGoroutines(t)
}