From f355d33b5fe37ce7c0c25373255ea8afd931f4e7 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 6 Jun 2013 18:16:16 -0700 Subject: [PATCH 01/41] Make the progressbar take the image size into consideration --- registry/registry.go | 30 ++++++++++++++++++------------ server.go | 6 +++--- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/registry/registry.go b/registry/registry.go index bd5c6b79c6..a2b43eeda1 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -12,6 +12,7 @@ import ( "io/ioutil" "net/http" "net/url" + "strconv" "strings" ) @@ -106,40 +107,45 @@ func (r *Registry) getImagesInRepository(repository string, authConfig *auth.Aut } // Retrieve an image from the Registry. -// Returns the Image object as well as the layer as an Archive (io.Reader) -func (r *Registry) GetRemoteImageJSON(imgId, registry string, token []string) ([]byte, error) { +func (r *Registry) GetRemoteImageJSON(imgId, registry string, token []string) ([]byte, int, error) { // Get the JSON req, err := http.NewRequest("GET", registry+"/images/"+imgId+"/json", nil) if err != nil { - return nil, fmt.Errorf("Failed to download json: %s", err) + return nil, -1, fmt.Errorf("Failed to download json: %s", err) } req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) res, err := r.client.Do(req) if err != nil { - return nil, fmt.Errorf("Failed to download json: %s", err) + return nil, -1, fmt.Errorf("Failed to download json: %s", err) } defer res.Body.Close() if res.StatusCode != 200 { - return nil, fmt.Errorf("HTTP code %d", res.StatusCode) + return nil, -1, fmt.Errorf("HTTP code %d", res.StatusCode) } + + imageSize, err := strconv.Atoi(res.Header.Get("X-Docker-Size")) + if err != nil { + return nil, -1, err + } + jsonString, err := ioutil.ReadAll(res.Body) if err != nil { - return nil, fmt.Errorf("Failed to parse downloaded json: %s (%s)", err, jsonString) + return nil, -1, fmt.Errorf("Failed to parse downloaded json: %s (%s)", err, jsonString) } - return jsonString, nil + return jsonString, imageSize, nil } -func (r *Registry) GetRemoteImageLayer(imgId, registry string, token []string) (io.ReadCloser, int, error) { +func (r *Registry) GetRemoteImageLayer(imgId, registry string, token []string) (io.ReadCloser, error) { req, err := http.NewRequest("GET", registry+"/images/"+imgId+"/layer", nil) if err != nil { - return nil, -1, fmt.Errorf("Error while getting from the server: %s\n", err) + return nil, fmt.Errorf("Error while getting from the server: %s\n", err) } req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) res, err := r.client.Do(req) if err != nil { - return nil, -1, err + return nil, err } - return res.Body, int(res.ContentLength), nil + return res.Body, nil } func (r *Registry) GetRemoteTags(registries []string, repository string, token []string) (map[string]string, error) { @@ -479,7 +485,7 @@ func NewRegistry(root string) *Registry { httpTransport := &http.Transport{ DisableKeepAlives: true, - Proxy: http.ProxyFromEnvironment, + Proxy: http.ProxyFromEnvironment, } r := &Registry{ diff --git a/server.go b/server.go index 6666123658..37a053abbb 100644 --- a/server.go +++ b/server.go @@ -305,7 +305,7 @@ func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgId, endpoin for _, id := range history { if !srv.runtime.graph.Exists(id) { out.Write(sf.FormatStatus("Pulling %s metadata", id)) - imgJSON, err := r.GetRemoteImageJSON(id, endpoint, token) + imgJSON, imgSize, err := r.GetRemoteImageJSON(id, endpoint, token) if err != nil { // FIXME: Keep goging in case of error? return err @@ -317,12 +317,12 @@ func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgId, endpoin // Get the layer out.Write(sf.FormatStatus("Pulling %s fs layer", id)) - layer, contentLength, err := r.GetRemoteImageLayer(img.ID, endpoint, token) + layer, err := r.GetRemoteImageLayer(img.ID, endpoint, token) if err != nil { return err } defer layer.Close() - if err := srv.runtime.graph.Register(utils.ProgressReader(layer, contentLength, out, sf.FormatProgress("Downloading", "%v/%v (%v)"), sf), false, img); err != nil { + if err := srv.runtime.graph.Register(utils.ProgressReader(layer, imgSize, out, sf.FormatProgress("Downloading", "%v/%v (%v)"), sf), false, img); err != nil { return err } } From 1e0738f63f55d489d3d96274f312c93cc5d69ffa Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 6 Jun 2013 18:42:52 -0700 Subject: [PATCH 02/41] Make the progressbar human readable --- utils/utils.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/utils/utils.go b/utils/utils.go index c3f9e571d3..b92b30633c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -70,7 +70,7 @@ type progressReader struct { readProgress int // How much has been read so far (bytes) lastUpdate int // How many bytes read at least update template string // Template to print. Default "%v/%v (%v)" - sf *StreamFormatter + sf *StreamFormatter } func (r *progressReader) Read(p []byte) (n int, err error) { @@ -86,7 +86,7 @@ func (r *progressReader) Read(p []byte) (n int, err error) { } if r.readProgress-r.lastUpdate > updateEvery || err != nil { if r.readTotal > 0 { - fmt.Fprintf(r.output, r.template, r.readProgress, r.readTotal, fmt.Sprintf("%.0f%%", float64(r.readProgress)/float64(r.readTotal)*100)) + fmt.Fprintf(r.output, r.template, HumanSize(r.readProgress), HumanSize(r.readTotal), fmt.Sprintf("%.0f%%", float64(r.readProgress)/float64(r.readTotal)*100)) } else { fmt.Fprintf(r.output, r.template, r.readProgress, "?", "n/a") } @@ -103,13 +103,25 @@ func (r *progressReader) Close() error { return io.ReadCloser(r.reader).Close() } func ProgressReader(r io.ReadCloser, size int, output io.Writer, template []byte, sf *StreamFormatter) *progressReader { - tpl := string(template) + tpl := string(template) if tpl == "" { tpl = string(sf.FormatProgress("", "%v/%v (%v)")) } return &progressReader{r, NewWriteFlusher(output), size, 0, 0, tpl, sf} } +func HumanSize(origSize int) string { + size := float64(origSize) + for _, unit := range []string{"b", "Kb", "Mb", "Gb", "Tb"} { + if int(size)/1024 == 0 { + return fmt.Sprintf("%.03f%s", size, unit) + } else { + size = size / 1024 + } + } + return strconv.Itoa(origSize) +} + // HumanDuration returns a human-readable approximation of a duration // (eg. "About a minute", "4 hours ago", etc.) func HumanDuration(d time.Duration) string { @@ -585,7 +597,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte sf.used = true str := fmt.Sprintf(format, a...) if sf.json { - b, err := json.Marshal(&JSONMessage{Status:str}); + b, err := json.Marshal(&JSONMessage{Status: str}) if err != nil { return sf.FormatError(err) } @@ -597,7 +609,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte func (sf *StreamFormatter) FormatError(err error) []byte { sf.used = true if sf.json { - if b, err := json.Marshal(&JSONMessage{Error:err.Error()}); err == nil { + if b, err := json.Marshal(&JSONMessage{Error: err.Error()}); err == nil { return b } return []byte("{\"error\":\"format error\"}") @@ -608,10 +620,10 @@ func (sf *StreamFormatter) FormatError(err error) []byte { func (sf *StreamFormatter) FormatProgress(action, str string) []byte { sf.used = true if sf.json { - b, err := json.Marshal(&JSONMessage{Status: action, Progress:str}) + b, err := json.Marshal(&JSONMessage{Status: action, Progress: str}) if err != nil { - return nil - } + return nil + } return b } return []byte(action + " " + str + "\r") From 0425f65e6373dc38cd18a6d0f2a50671544ad4b2 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 13 Jun 2013 17:53:38 -0700 Subject: [PATCH 03/41] Remove bsdtar by checking magic --- archive.go | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/archive.go b/archive.go index 06466627a1..5686408179 100644 --- a/archive.go +++ b/archive.go @@ -1,8 +1,10 @@ package docker import ( + "bytes" "errors" "fmt" + "github.com/dotcloud/docker/utils" "io" "io/ioutil" "os" @@ -20,6 +22,37 @@ const ( Xz ) +func DetectCompression(source []byte) Compression { + for _, c := range source[:10] { + utils.Debugf("%x", c) + } + + sourceLen := len(source) + for compression, m := range map[Compression][]byte{ + Bzip2: {0x42, 0x5A, 0x68}, + Gzip: {0x1F, 0x8B, 0x08}, + Xz: {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}, + } { + fail := false + if len(m) > sourceLen { + utils.Debugf("Len too short") + continue + } + i := 0 + for _, b := range m { + if b != source[i] { + fail = true + break + } + i++ + } + if !fail { + return compression + } + } + return Uncompressed +} + func (compression *Compression) Flag() string { switch *compression { case Bzip2: @@ -47,12 +80,21 @@ func (compression *Compression) Extension() string { } func Tar(path string, compression Compression) (io.Reader, error) { - cmd := exec.Command("bsdtar", "-f", "-", "-C", path, "-c"+compression.Flag(), ".") - return CmdStream(cmd) + return CmdStream(exec.Command("tar", "-f", "-", "-C", path, "-c"+compression.Flag(), ".")) } func Untar(archive io.Reader, path string) error { - cmd := exec.Command("bsdtar", "-f", "-", "-C", path, "-x") + + buf := make([]byte, 10) + if _, err := archive.Read(buf); err != nil { + return err + } + compression := DetectCompression(buf) + archive = io.MultiReader(bytes.NewReader(buf), archive) + + utils.Debugf("Archive compression detected: %s", compression.Extension()) + + cmd := exec.Command("tar", "-f", "-", "-C", path, "-x"+compression.Flag()) cmd.Stdin = archive // Hardcode locale environment for predictable outcome regardless of host configuration. // (see https://github.com/dotcloud/docker/issues/355) From 6f7de49aa8771ef4bc35548f9aa07fee660f1844 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 14 Jun 2013 10:47:49 -0700 Subject: [PATCH 04/41] Add unit tests for tar/untar with multiple compression + detection --- archive_test.go | 51 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/archive_test.go b/archive_test.go index f583604497..bb4235ad5b 100644 --- a/archive_test.go +++ b/archive_test.go @@ -1,10 +1,13 @@ package docker import ( + "bytes" + "fmt" "io" "io/ioutil" "os" "os/exec" + "path" "testing" "time" ) @@ -58,20 +61,58 @@ func TestCmdStreamGood(t *testing.T) { } } -func TestTarUntar(t *testing.T) { - archive, err := Tar(".", Uncompressed) +func tarUntar(t *testing.T, origin string, compression Compression) error { + archive, err := Tar(origin, compression) if err != nil { t.Fatal(err) } + + buf := make([]byte, 10) + if _, err := archive.Read(buf); err != nil { + return err + } + archive = io.MultiReader(bytes.NewReader(buf), archive) + + detectedCompression := DetectCompression(buf) + if detectedCompression.Extension() != compression.Extension() { + return fmt.Errorf("Wrong compression detected. Actual compression: %s, found %s", compression.Extension(), detectedCompression.Extension()) + } + tmp, err := ioutil.TempDir("", "docker-test-untar") if err != nil { - t.Fatal(err) + return err } defer os.RemoveAll(tmp) if err := Untar(archive, tmp); err != nil { - t.Fatal(err) + return err } if _, err := os.Stat(tmp); err != nil { - t.Fatalf("Error stating %s: %s", tmp, err.Error()) + return err + } + return nil +} + +func TestTarUntar(t *testing.T) { + origin, err := ioutil.TempDir("", "docker-test-untar-origin") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(origin) + if err := ioutil.WriteFile(path.Join(origin, "1"), []byte("hello world"), 0700); err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(path.Join(origin, "2"), []byte("welcome!"), 0700); err != nil { + t.Fatal(err) + } + + for _, c := range []Compression{ + Uncompressed, + Gzip, + Bzip2, + Xz, + } { + if err := tarUntar(t, origin, c); err != nil { + t.Fatalf("Error tar/untar for compression %s: %s", c.Extension(), err) + } } } From 79fe864d9a117193b4dce8b7fe156a55bbadcce6 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 14 Jun 2013 10:58:16 -0700 Subject: [PATCH 05/41] Update docs --- README.md | 2 +- docs/sources/contributing/devenvironment.rst | 2 +- docs/sources/installation/binaries.rst | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1c909e5431..d15ee3cc41 100644 --- a/README.md +++ b/README.md @@ -262,7 +262,7 @@ Setting up a dev environment Instructions that have been verified to work on Ubuntu 12.10, ```bash -sudo apt-get -y install lxc wget bsdtar curl golang git +sudo apt-get -y install lxc curl xz-utils golang git export GOPATH=~/go/ export PATH=$GOPATH/bin:$PATH diff --git a/docs/sources/contributing/devenvironment.rst b/docs/sources/contributing/devenvironment.rst index 5d937c5a44..8b26688bcf 100644 --- a/docs/sources/contributing/devenvironment.rst +++ b/docs/sources/contributing/devenvironment.rst @@ -33,7 +33,7 @@ Installation sudo apt-get install python-software-properties sudo add-apt-repository ppa:gophers/go sudo apt-get update - sudo apt-get -y install lxc wget bsdtar curl golang-stable git + sudo apt-get -y install lxc xz-utils curl golang-stable git export GOPATH=~/go/ export PATH=$GOPATH/bin:$PATH diff --git a/docs/sources/installation/binaries.rst b/docs/sources/installation/binaries.rst index e7a07b6db1..6d87787752 100644 --- a/docs/sources/installation/binaries.rst +++ b/docs/sources/installation/binaries.rst @@ -30,8 +30,7 @@ Dependencies: * 3.8 Kernel (read more about :ref:`kernel`) * AUFS filesystem support * lxc -* bsdtar - +* xz-utils Get the docker binary: ---------------------- From 76a568fc9717ff69999ab54fba9277a0d31c305d Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 14 Jun 2013 16:08:08 -0700 Subject: [PATCH 06/41] Fix merge issue --- utils/utils.go | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/utils/utils.go b/utils/utils.go index 4c9f9eeee1..7e95e074d5 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -86,7 +86,7 @@ func (r *progressReader) Read(p []byte) (n int, err error) { } if r.readProgress-r.lastUpdate > updateEvery || err != nil { if r.readTotal > 0 { - fmt.Fprintf(r.output, r.template, HumanSize(r.readProgress), HumanSize(r.readTotal), fmt.Sprintf("%.0f%%", float64(r.readProgress)/float64(r.readTotal)*100)) + fmt.Fprintf(r.output, r.template, HumanSize(int64(r.readProgress)), HumanSize(int64(r.readTotal)), fmt.Sprintf("%.0f%%", float64(r.readProgress)/float64(r.readTotal)*100)) } else { fmt.Fprintf(r.output, r.template, r.readProgress, "?", "n/a") } @@ -110,18 +110,6 @@ func ProgressReader(r io.ReadCloser, size int, output io.Writer, template []byte return &progressReader{r, NewWriteFlusher(output), size, 0, 0, tpl, sf} } -func HumanSize(origSize int) string { - size := float64(origSize) - for _, unit := range []string{"b", "Kb", "Mb", "Gb", "Tb"} { - if int(size)/1024 == 0 { - return fmt.Sprintf("%.03f%s", size, unit) - } else { - size = size / 1024 - } - } - return strconv.Itoa(origSize) -} - // HumanDuration returns a human-readable approximation of a duration // (eg. "About a minute", "4 hours ago", etc.) func HumanDuration(d time.Duration) string { From 5b8287617de65d4e14ed6affb0eb46867e9ee617 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 14 Jun 2013 16:43:39 -0700 Subject: [PATCH 07/41] + Builder: ADD of a local file will detect tar archives and unpack them into the container instead of copying them as a regular file. * Builder: ADD uses tar/untar for copies instead of calling 'cp -ar'. This is more consistent, reduces the number of dependencies, and fixe #896. --- archive.go | 25 +++++++++++++++++++++++++ buildfile.go | 16 ++++++---------- buildfile_test.go | 6 ++++++ utils/utils.go | 1 + 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/archive.go b/archive.go index 06466627a1..44fdd56be3 100644 --- a/archive.go +++ b/archive.go @@ -51,6 +51,7 @@ func Tar(path string, compression Compression) (io.Reader, error) { return CmdStream(cmd) } +// FIXME: specify behavior when target path exists vs. doesn't exist. func Untar(archive io.Reader, path string) error { cmd := exec.Command("bsdtar", "-f", "-", "-C", path, "-x") cmd.Stdin = archive @@ -64,6 +65,30 @@ func Untar(archive io.Reader, path string) error { return nil } +// UntarPath is a convenience function which looks for an archive +// at filesystem path `src`, and unpacks it at `dst`. +func UntarPath(src, dst string) error { + if archive, err := os.Open(src); err != nil { + return err + } else if err := Untar(archive, dst); err != nil { + return err + } + return nil +} + +// CopyWithTar creates a tar archive of filesystem path `src`, and +// unpacks it at filesystem path `dst`. +// The archive is streamed directly with fixed buffering and no +// intermediary disk IO. +// +func CopyWithTar(src, dst string) error { + archive, err := Tar(src, Uncompressed) + if err != nil { + return err + } + return Untar(archive, dst) +} + // CmdStream executes a command, and returns its stdout as a stream. // If the command fails to run or doesn't complete successfully, an error // will be returned, including anything written on stderr. diff --git a/buildfile.go b/buildfile.go index 3c706b04ba..bb4ae721a9 100644 --- a/buildfile.go +++ b/buildfile.go @@ -200,21 +200,17 @@ func (b *buildFile) CmdAdd(args string) error { if err := os.MkdirAll(destPath, 0700); err != nil { return err } - - files, err := ioutil.ReadDir(path.Join(b.context, orig)) - if err != nil { + if err := CopyWithTar(origPath, destPath); err != nil { return err } - for _, fi := range files { - if err := utils.CopyDirectory(path.Join(origPath, fi.Name()), path.Join(destPath, fi.Name())); err != nil { - return err - } - } - } else { + // First try to unpack the source as an archive + } 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 { return err } - if err := utils.CopyDirectory(origPath, destPath); err != nil { + if err := CopyWithTar(origPath, destPath); err != nil { return err } } diff --git a/buildfile_test.go b/buildfile_test.go index d9c60a70d5..33e6a3146b 100644 --- a/buildfile_test.go +++ b/buildfile_test.go @@ -23,6 +23,12 @@ from ` + unitTestImageName + ` run sh -c 'echo root:testpass > /tmp/passwd' run mkdir -p /var/run/sshd` +// FIXME: test building with a context + +// FIXME: test building with a local ADD as first command + +// FIXME: test building with 2 successive overlapping ADD commands + func TestBuild(t *testing.T) { dockerfiles := []string{Dockerfile, DockerfileNoNewLine} for _, Dockerfile := range dockerfiles { diff --git a/utils/utils.go b/utils/utils.go index 708c8bb19d..b77c1ea053 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -548,6 +548,7 @@ func GetKernelVersion() (*KernelVersionInfo, error) { }, nil } +// FIXME: this is deprecated by CopyWithTar in archive.go func CopyDirectory(source, dest string) error { if output, err := exec.Command("cp", "-ra", source, dest).CombinedOutput(); err != nil { return fmt.Errorf("Error copy: %s (%s)", err, output) From e8f001d45157f2f645e415543d7c3e7bf832c665 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 17 Jun 2013 19:01:21 +0000 Subject: [PATCH 08/41] Bumped version to 0.4.1 --- CHANGELOG.md | 17 +++++++++++++++++ commands.go | 2 +- packaging/ubuntu/changelog | 19 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44e52eecb5..9757fa806c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 0.4.1 (2013-06-17) + + Remote Api: Add flag to enable cross domain requests + + Remote Api/Client: Add images and containers sizes in docker ps and docker images + + Runtime: Configure dns configuration host-wide with 'docker -d -dns' + + Runtime: Detect faulty DNS configuration and replace it with a public default + + Runtime: allow docker run : + + Runtime: you can now specify public port (ex: -p 80:4500) + * Client: allow multiple params in inspect + * Client: Print the container id before the hijack in `docker run` + * Registry: add regexp check on repo's name + * Registry: Move auth to the client + * Runtime: improved image removal to garbage-collect unreferenced parents + * Vagrantfile: Add the rest api port to vagrantfile's port_forward + * Upgrade to Go 1.1 + - Builder: don't ignore last line in Dockerfile when it doesn't end with \n + - Registry: Remove login check on pull + ## 0.4.0 (2013-06-03) + Introducing Builder: 'docker build' builds a container, layer by layer, from a source repository containing a Dockerfile + Introducing Remote API: control Docker programmatically using a simple HTTP/json API diff --git a/commands.go b/commands.go index 04eb994f01..ce15fd6cf1 100644 --- a/commands.go +++ b/commands.go @@ -29,7 +29,7 @@ import ( "unicode" ) -const VERSION = "0.4.0" +const VERSION = "0.4.1" var ( GITCOMMIT string diff --git a/packaging/ubuntu/changelog b/packaging/ubuntu/changelog index 5fc2e49d5e..038422967e 100644 --- a/packaging/ubuntu/changelog +++ b/packaging/ubuntu/changelog @@ -1,3 +1,22 @@ +lxc-docker (0.4.1-1) precise; urgency=low + - Builder: don't ignore last line in Dockerfile when it doesn't end with \n + - Client: allow multiple params in inspect + - Client: Print the container id before the hijack in `docker run` + - Remote Api: Add flag to enable cross domain requests + - Remote Api/Client: Add images and containers sizes in docker ps and docker images + - Registry: add regexp check on repo's name + - Registry: Move auth to the client + - Registry: Remove login check on pull + - Runtime: Configure dns configuration host-wide with 'docker -d -dns' + - Runtime: Detect faulty DNS configuration and replace it with a public default + - Runtime: allow docker run : + - Runtime: you can now specify public port (ex: -p 80:4500) + - Runtime: improved image removal to garbage-collect unreferenced parents + - Vagrantfile: Add the rest api port to vagrantfile's port_forward + - Upgrade to Go 1.1 + + -- dotCloud Mon, 17 Jun 2013 00:00:00 -0700 + lxc-docker (0.4.0-1) precise; urgency=low - Introducing Builder: 'docker build' builds a container, layer by layer, from a source repository containing a Dockerfile - Introducing Remote API: control Docker programmatically using a simple HTTP/json API From 36231345f17e6fdb08b0f756c4872294d4745048 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 17 Jun 2013 22:05:58 +0200 Subject: [PATCH 09/41] add port redirection doc --- docs/sources/use/index.rst | 1 + docs/sources/use/port_redirection.rst | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 docs/sources/use/port_redirection.rst diff --git a/docs/sources/use/index.rst b/docs/sources/use/index.rst index a1086c1fd2..2f74f60718 100644 --- a/docs/sources/use/index.rst +++ b/docs/sources/use/index.rst @@ -14,6 +14,7 @@ Contents: basics workingwithrepository + port_redirection builder puppet diff --git a/docs/sources/use/port_redirection.rst b/docs/sources/use/port_redirection.rst new file mode 100644 index 0000000000..c0b4041e7c --- /dev/null +++ b/docs/sources/use/port_redirection.rst @@ -0,0 +1,23 @@ +:title: Port redirection +:description: usage about port redirection +:keywords: Usage, basic port, docker, documentation, examples + + +Port redirection +================ + +Port redirection is done on ``docker run`` using the -p flag. + +Here are the 3 ways to redirect a port: + +.. code-block:: bash + + # the port 80 in the container is mapped to a random port of the host + docker run -p 80 + + # the port 80 in the container is mapped to the port 80 of the host + docker run -p :80 + + # the port 80 in the container is mapped to the port 5555 of the host + docker run -p 5555:80 + From 862659875335c953bf6974af4cace397c7ec3902 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Mon, 17 Jun 2013 13:25:50 -0700 Subject: [PATCH 10/41] Added content to port redirect doc --- docs/sources/use/port_redirection.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/sources/use/port_redirection.rst b/docs/sources/use/port_redirection.rst index c0b4041e7c..b866fe309d 100644 --- a/docs/sources/use/port_redirection.rst +++ b/docs/sources/use/port_redirection.rst @@ -6,18 +6,20 @@ Port redirection ================ +Docker can redirect public tcp ports to your container, so it can be reached over the network. Port redirection is done on ``docker run`` using the -p flag. -Here are the 3 ways to redirect a port: +A port redirect is specified as PUBLIC:PRIVATE, where tcp port PUBLIC will be redirected to +tcp port PRIVATE. As a special case, the public port can be omitted, in which case a random +public port will be allocated. .. code-block:: bash - # the port 80 in the container is mapped to a random port of the host + # A random PUBLIC port is redirected to PRIVATE port 80 on the container docker run -p 80 - # the port 80 in the container is mapped to the port 80 of the host - docker run -p :80 + # PUBLIC port 80 is redirected to PRIVATE port 80 + docker run -p 80:80 - # the port 80 in the container is mapped to the port 5555 of the host - docker run -p 5555:80 +Default port redirects can be built into a container with the EXPOSE build command. From cb58e63fc54fb3f1c620c8372269a8e308e43bee Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Mon, 17 Jun 2013 14:28:04 -0600 Subject: [PATCH 11/41] Typo --- docs/sources/use/port_redirection.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/use/port_redirection.rst b/docs/sources/use/port_redirection.rst index b866fe309d..5cf848f9ea 100644 --- a/docs/sources/use/port_redirection.rst +++ b/docs/sources/use/port_redirection.rst @@ -19,7 +19,7 @@ public port will be allocated. docker run -p 80 # PUBLIC port 80 is redirected to PRIVATE port 80 - docker run -p 80:80 + docker run -p 80:80 Default port redirects can be built into a container with the EXPOSE build command. From bd9bf9b646837dac5f935e43a4b950d42353676e Mon Sep 17 00:00:00 2001 From: Daniel Mizyrycki Date: Mon, 17 Jun 2013 10:31:27 -0700 Subject: [PATCH 12/41] Packaging|dockerbuilder, issue #761: use docker-golang PPA. Add Dockerfile header --- hack/dockerbuilder/Dockerfile | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/hack/dockerbuilder/Dockerfile b/hack/dockerbuilder/Dockerfile index 50993ed7b5..5ccd293ca2 100644 --- a/hack/dockerbuilder/Dockerfile +++ b/hack/dockerbuilder/Dockerfile @@ -1,5 +1,13 @@ -# This will build a container capable of producing an official binary build of docker and -# uploading it to S3 +# DESCRIPTION Build a container capable of producing official binary and +# PPA packages and uploading them to S3 and Launchpad +# VERSION 1.2 +# DOCKER_VERSION 0.4 +# AUTHOR Solomon Hykes +# Daniel Mizyrycki +# BUILD_CMD docker build -t dockerbuilder . +# RUN_CMD docker run -e AWS_ID="$AWS_ID" -e AWS_KEY="$AWS_KEY" -e GPG_KEY="$GPG_KEY" dockerbuilder +# +# from ubuntu:12.04 maintainer Solomon Hykes # Workaround the upstart issue @@ -8,7 +16,7 @@ run ln -s /bin/true /sbin/initctl # Enable universe and gophers PPA run DEBIAN_FRONTEND=noninteractive apt-get install -y -q python-software-properties run add-apt-repository "deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc) universe" -run add-apt-repository -y ppa:gophers/go/ubuntu +run add-apt-repository -y ppa:dotcloud/docker-golang/ubuntu run apt-get update # Packages required to checkout, build and upload docker run DEBIAN_FRONTEND=noninteractive apt-get install -y -q s3cmd From 2626d88a21f639913f7f8e8b0719fd9e07cfbed4 Mon Sep 17 00:00:00 2001 From: Joseph Anthony Pasquale Holsten Date: Mon, 17 Jun 2013 14:50:58 -0700 Subject: [PATCH 13/41] fix missing command in irc bouncer example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c909e5431..f778ff521d 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,7 @@ Running an irc bouncer ---------------------- ```bash -BOUNCER_ID=$(docker run -d -p 6667 -u irc shykes/znc $USER $PASSWORD) +BOUNCER_ID=$(docker run -d -p 6667 -u irc shykes/znc zncrun $USER $PASSWORD) echo "Configure your irc client to connect to port $(docker port $BOUNCER_ID 6667) of this machine" ``` From c106ed32ea7613573a2081d47ad2498429ac86f2 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 17 Jun 2013 15:40:04 -0700 Subject: [PATCH 14/41] Move the attach prevention from server to client --- commands.go | 4 ++++ server.go | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/commands.go b/commands.go index ce15fd6cf1..4297ac0c11 100644 --- a/commands.go +++ b/commands.go @@ -1058,6 +1058,10 @@ func (cli *DockerCli) CmdAttach(args ...string) error { return err } + if !container.State.Running { + return fmt.Errorf("Impossible to attach to a stopped container, start it first") + } + splitStderr := container.Config.Tty connections := 1 diff --git a/server.go b/server.go index 30e3ec6b3a..ece6a93ceb 100644 --- a/server.go +++ b/server.go @@ -930,9 +930,6 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std if container.State.Ghost { return fmt.Errorf("Impossible to attach to a ghost container") } - if !container.State.Running { - return fmt.Errorf("Impossible to attach to a stopped container, start it first") - } var ( cStdin io.ReadCloser From 2b6ca3872883dcb487d8a39a1a8530be6a62f947 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 17 Jun 2013 15:45:08 -0700 Subject: [PATCH 15/41] Remove Run race condition --- commands.go | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/commands.go b/commands.go index 4297ac0c11..fb8bb528bb 100644 --- a/commands.go +++ b/commands.go @@ -1261,16 +1261,6 @@ func (cli *DockerCli) CmdRun(args ...string) error { fmt.Fprintln(os.Stderr, "WARNING: ", warning) } - splitStderr := !config.Tty - - connections := 0 - if config.AttachStdin || config.AttachStdout || (!splitStderr && config.AttachStderr) { - connections += 1 - } - if splitStderr && config.AttachStderr { - connections += 1 - } - //start the container _, _, err = cli.call("POST", "/containers/"+out.ID+"/start", nil) if err != nil { @@ -1279,19 +1269,12 @@ func (cli *DockerCli) CmdRun(args ...string) error { if !config.AttachStdout && !config.AttachStderr { fmt.Println(out.ID) - } - if connections > 0 { - chErrors := make(chan error, connections) + } else { + chErrors := make(chan error) if config.Tty { cli.monitorTtySize(out.ID) } - if splitStderr && config.AttachStderr { - go func() { - chErrors <- cli.hijack("POST", "/containers/"+out.ID+"/attach?logs=1&stream=1&stderr=1", config.Tty, nil, os.Stderr) - }() - } - v := url.Values{} v.Set("logs", "1") v.Set("stream", "1") @@ -1302,19 +1285,15 @@ func (cli *DockerCli) CmdRun(args ...string) error { if config.AttachStdout { v.Set("stdout", "1") } - if !splitStderr && config.AttachStderr { + if config.AttachStderr { v.Set("stderr", "1") } go func() { chErrors <- cli.hijack("POST", "/containers/"+out.ID+"/attach?"+v.Encode(), config.Tty, os.Stdin, os.Stdout) }() - for connections > 0 { - err := <-chErrors - if err != nil { - utils.Debugf("Error hijack: %s", err) - return err - } - connections -= 1 + if err := <-chErrors; err != nil { + utils.Debugf("Error hijack: %s", err) + return err } } return nil From fe204e6f48eb47a1deb3553003eaf9863a66fd1a Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 17 Jun 2013 16:10:00 -0700 Subject: [PATCH 16/41] - Runtime: Forbid parralel push/pull for a single image/repo. Fixes #311 --- runtime_test.go | 6 ++++- server.go | 62 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/runtime_test.go b/runtime_test.go index d7d9a5a315..db6367dfaf 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -65,7 +65,11 @@ func init() { // Create the "Server" srv := &Server{ - runtime: runtime, + runtime: runtime, + enableCors: false, + lock: &sync.Mutex{}, + pullingPool: make(map[string]struct{}), + pushingPool: make(map[string]struct{}), } // Retrieve the Image if err := srv.ImagePull(unitTestImageName, "", "", os.Stdout, utils.NewStreamFormatter(false), nil); err != nil { diff --git a/server.go b/server.go index 30e3ec6b3a..34040df3a0 100644 --- a/server.go +++ b/server.go @@ -15,6 +15,7 @@ import ( "path" "runtime" "strings" + "sync" ) func (srv *Server) DockerVersion() APIVersion { @@ -401,7 +402,47 @@ func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, local, re return nil } +func (srv *Server) poolAdd(kind, key string) error { + srv.lock.Lock() + defer srv.lock.Unlock() + + if _, exists := srv.pullingPool[key]; exists { + return fmt.Errorf("%s %s is already in progress", key, kind) + } + + switch kind { + case "pull": + srv.pullingPool[key] = struct{}{} + break + case "push": + srv.pushingPool[key] = struct{}{} + break + default: + return fmt.Errorf("Unkown pool type") + } + return nil +} + +func (srv *Server) poolRemove(kind, key string) error { + switch kind { + case "pull": + delete(srv.pullingPool, key) + break + case "push": + delete(srv.pushingPool, key) + break + default: + return fmt.Errorf("Unkown pool type") + } + return nil +} + func (srv *Server) ImagePull(name, tag, endpoint string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig) error { + if err := srv.poolAdd("pull", name+":"+tag); err != nil { + return err + } + defer srv.poolRemove("pull", name+":"+tag) + r := registry.NewRegistry(srv.runtime.root, authConfig) out = utils.NewWriteFlusher(out) if endpoint != "" { @@ -418,7 +459,6 @@ func (srv *Server) ImagePull(name, tag, endpoint string, out io.Writer, sf *util if err := srv.pullRepository(r, out, name, remote, tag, sf); err != nil { return err } - return nil } @@ -593,7 +633,13 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgId, return nil } +// FIXME: Allow to interupt current push when new push of same image is done. func (srv *Server) ImagePush(name, endpoint string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig) error { + if err := srv.poolAdd("push", name); err != nil { + return err + } + defer srv.poolRemove("push", name) + out = utils.NewWriteFlusher(out) img, err := srv.runtime.graph.Get(name) r := registry.NewRegistry(srv.runtime.root, authConfig) @@ -991,14 +1037,20 @@ func NewServer(autoRestart, enableCors bool, dns ListOpts) (*Server, error) { return nil, err } srv := &Server{ - runtime: runtime, - enableCors: enableCors, + runtime: runtime, + enableCors: enableCors, + lock: &sync.Mutex{}, + pullingPool: make(map[string]struct{}), + pushingPool: make(map[string]struct{}), } runtime.srv = srv return srv, nil } type Server struct { - runtime *Runtime - enableCors bool + runtime *Runtime + enableCors bool + lock *sync.Mutex + pullingPool map[string]struct{} + pushingPool map[string]struct{} } From b25bcf1a666ebef26e2acfa132fa2b72d47d0805 Mon Sep 17 00:00:00 2001 From: Marcus Farkas Date: Mon, 17 Jun 2013 23:32:48 +0000 Subject: [PATCH 17/41] fix docker version git output --- AUTHORS | 1 + Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index eb90cd02d9..89fa178c3b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -41,6 +41,7 @@ Jérôme Petazzoni Ken Cochrane Kevin J. Lynagh Louis Opter +Marcus Farkas Maxim Treskin Michael Crosby Mikhail Sobolev diff --git a/Makefile b/Makefile index eca409c967..8676014ad4 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ endif GIT_COMMIT = $(shell git rev-parse --short HEAD) GIT_STATUS = $(shell test -n "`git status --porcelain`" && echo "+CHANGES") -BUILD_OPTIONS = -ldflags "-X main.GIT_COMMIT $(GIT_COMMIT)$(GIT_STATUS)" +BUILD_OPTIONS = -ldflags "-X main.GITCOMMIT $(GIT_COMMIT)$(GIT_STATUS)" SRC_DIR := $(GOPATH)/src From 02c291d13be261f84cdfa1d51513bf4dba31ce72 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 17 Jun 2013 18:11:58 -0700 Subject: [PATCH 18/41] Fix bug on compression detection when chunck < 10bytes --- archive.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/archive.go b/archive.go index 5686408179..1e5b683765 100644 --- a/archive.go +++ b/archive.go @@ -1,7 +1,7 @@ package docker import ( - "bytes" + "bufio" "errors" "fmt" "github.com/dotcloud/docker/utils" @@ -85,17 +85,17 @@ func Tar(path string, compression Compression) (io.Reader, error) { func Untar(archive io.Reader, path string) error { - buf := make([]byte, 10) - if _, err := archive.Read(buf); err != nil { + bufferedArchive := bufio.NewReaderSize(archive, 10) + buf, err := bufferedArchive.Peek(10) + if err != nil { return err } compression := DetectCompression(buf) - archive = io.MultiReader(bytes.NewReader(buf), archive) utils.Debugf("Archive compression detected: %s", compression.Extension()) cmd := exec.Command("tar", "-f", "-", "-C", path, "-x"+compression.Flag()) - cmd.Stdin = archive + cmd.Stdin = bufferedArchive // Hardcode locale environment for predictable outcome regardless of host configuration. // (see https://github.com/dotcloud/docker/issues/355) cmd.Env = []string{"LANG=en_US.utf-8", "LC_ALL=en_US.utf-8"} From 3bfc82257878e55141bb029390574130c3ac0530 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 17 Jun 2013 18:39:30 -0700 Subject: [PATCH 19/41] * API: Add tag lookup to history command. Fixes #882 --- api_params.go | 1 + commands.go | 2 +- server.go | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/api_params.go b/api_params.go index 2a641f8ccd..c3fabb2be0 100644 --- a/api_params.go +++ b/api_params.go @@ -2,6 +2,7 @@ package docker type APIHistory struct { ID string `json:"Id"` + Tag string `json:",omitempty"` Created int64 CreatedBy string `json:",omitempty"` } diff --git a/commands.go b/commands.go index ce15fd6cf1..98be40181c 100644 --- a/commands.go +++ b/commands.go @@ -627,7 +627,7 @@ func (cli *DockerCli) CmdHistory(args ...string) error { fmt.Fprintln(w, "ID\tCREATED\tCREATED BY") for _, out := range outs { - fmt.Fprintf(w, "%s\t%s ago\t%s\n", out.ID, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.CreatedBy) + fmt.Fprintf(w, "%s (%s)\t%s ago\t%s\n", out.ID, out.Tag, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.CreatedBy) } w.Flush() return nil diff --git a/server.go b/server.go index 30e3ec6b3a..912349b82e 100644 --- a/server.go +++ b/server.go @@ -218,12 +218,26 @@ func (srv *Server) ImageHistory(name string) ([]APIHistory, error) { return nil, err } + lookupMap := make(map[string]string) + for name, repository := range srv.runtime.repositories.Repositories { + for tag, id := range repository { + // If the ID already has a reverse lookup, do not update it unless for "latest" + if _, exists := lookupMap[id]; exists { + if tag != "latest" { + continue + } + } + lookupMap[id] = name + ":" + tag + } + } + outs := []APIHistory{} //produce [] when empty instead of 'null' err = image.WalkHistory(func(img *Image) error { var out APIHistory out.ID = srv.runtime.repositories.ImageName(img.ShortID()) out.Created = img.Created.Unix() out.CreatedBy = strings.Join(img.ContainerConfig.Cmd, " ") + out.Tag = lookupMap[img.ID] outs = append(outs, out) return nil }) From 02a002d264faa7b8cdf5c68b7370c31d6794a44d Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 17 Jun 2013 18:41:13 -0700 Subject: [PATCH 20/41] Update documentation --- docs/sources/api/docker_remote_api_v1.2.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sources/api/docker_remote_api_v1.2.rst b/docs/sources/api/docker_remote_api_v1.2.rst index fb69168120..44a397a4db 100644 --- a/docs/sources/api/docker_remote_api_v1.2.rst +++ b/docs/sources/api/docker_remote_api_v1.2.rst @@ -691,6 +691,7 @@ Get the history of an image [ { "Id":"b750fe79269d", + "Tag":"base:latest", "Created":1364102658, "CreatedBy":"/bin/bash" }, From e664a46ff334ff9f7c8dfb438e15950e3cacf184 Mon Sep 17 00:00:00 2001 From: Daniel Mizyrycki Date: Mon, 17 Jun 2013 19:50:31 -0700 Subject: [PATCH 21/41] Packaging, issue 919: Bump version to 0.4.2 --- CHANGELOG.md | 3 +++ commands.go | 2 +- packaging/ubuntu/changelog | 35 ++++++++++++++++++++--------------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9757fa806c..1e2112218b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.4.2 (2013-06-17) + - Packaging: Bumped version to work around an Ubuntu bug + ## 0.4.1 (2013-06-17) + Remote Api: Add flag to enable cross domain requests + Remote Api/Client: Add images and containers sizes in docker ps and docker images diff --git a/commands.go b/commands.go index ce15fd6cf1..cf23a8d65e 100644 --- a/commands.go +++ b/commands.go @@ -29,7 +29,7 @@ import ( "unicode" ) -const VERSION = "0.4.1" +const VERSION = "0.4.2" var ( GITCOMMIT string diff --git a/packaging/ubuntu/changelog b/packaging/ubuntu/changelog index 038422967e..ef7efba473 100644 --- a/packaging/ubuntu/changelog +++ b/packaging/ubuntu/changelog @@ -1,19 +1,24 @@ +lxc-docker (0.4.2-1) precise; urgency=low + - Packaging: Bumped version to work around an Ubuntu bug + + -- dotCloud Mon, 17 Jun 2013 00:00:00 -0700 + lxc-docker (0.4.1-1) precise; urgency=low - - Builder: don't ignore last line in Dockerfile when it doesn't end with \n - - Client: allow multiple params in inspect - - Client: Print the container id before the hijack in `docker run` - - Remote Api: Add flag to enable cross domain requests - - Remote Api/Client: Add images and containers sizes in docker ps and docker images - - Registry: add regexp check on repo's name - - Registry: Move auth to the client - - Registry: Remove login check on pull - - Runtime: Configure dns configuration host-wide with 'docker -d -dns' - - Runtime: Detect faulty DNS configuration and replace it with a public default - - Runtime: allow docker run : - - Runtime: you can now specify public port (ex: -p 80:4500) - - Runtime: improved image removal to garbage-collect unreferenced parents - - Vagrantfile: Add the rest api port to vagrantfile's port_forward - - Upgrade to Go 1.1 + - Builder: don't ignore last line in Dockerfile when it doesn't end with \n + - Client: allow multiple params in inspect + - Client: Print the container id before the hijack in `docker run` + - Remote Api: Add flag to enable cross domain requests + - Remote Api/Client: Add images and containers sizes in docker ps and docker images + - Registry: add regexp check on repo's name + - Registry: Move auth to the client + - Registry: Remove login check on pull + - Runtime: Configure dns configuration host-wide with 'docker -d -dns' + - Runtime: Detect faulty DNS configuration and replace it with a public default + - Runtime: allow docker run : + - Runtime: you can now specify public port (ex: -p 80:4500) + - Runtime: improved image removal to garbage-collect unreferenced parents + - Vagrantfile: Add the rest api port to vagrantfile's port_forward + - Upgrade to Go 1.1 -- dotCloud Mon, 17 Jun 2013 00:00:00 -0700 From 3491d7d2f11246ba4067708a3c5336ba21da4767 Mon Sep 17 00:00:00 2001 From: Thatcher Peskens Date: Mon, 17 Jun 2013 20:16:56 -0700 Subject: [PATCH 22/41] Fixed on documentation. * replaced previously removed concepts/containers and concepts/introcution by a redirect * moved orphan index/varable to workingwiththerepository * added favicon to the layout.html * added redirect_home which is a http refresh redirect. It works like a 301 for google * fixed an issue in the layout that would make it break when on small screens --- docs/sources/concepts/containers.rst | 8 -- docs/sources/concepts/introduction.rst | 125 --------------------- docs/sources/conf.py | 24 +++- docs/sources/index/variable.rst | 27 ----- docs/sources/use/workingwithrepository.rst | 25 +++++ docs/theme/docker/layout.html | 12 +- docs/theme/docker/redirect_home.html | 12 ++ docs/theme/docker/static/css/main.css | 10 +- docs/theme/docker/static/css/main.less | 29 ++--- docs/theme/docker/static/favicon.ico | Bin 1150 -> 0 bytes docs/theme/docker/static/favicon.png | Bin 0 -> 404 bytes 11 files changed, 82 insertions(+), 190 deletions(-) delete mode 100644 docs/sources/concepts/containers.rst delete mode 100644 docs/sources/concepts/introduction.rst delete mode 100644 docs/sources/index/variable.rst create mode 100644 docs/theme/docker/redirect_home.html delete mode 100755 docs/theme/docker/static/favicon.ico create mode 100644 docs/theme/docker/static/favicon.png diff --git a/docs/sources/concepts/containers.rst b/docs/sources/concepts/containers.rst deleted file mode 100644 index e08c3654c0..0000000000 --- a/docs/sources/concepts/containers.rst +++ /dev/null @@ -1,8 +0,0 @@ -:title: Introduction -:description: An introduction to docker and standard containers? -:keywords: containers, lxc, concepts, explanation, docker, documentation - - -:note: This version of the introduction is temporary, just to make sure we don't break the links from the website when the documentation is updated - -This document has been moved to :ref:`introduction`, please update your bookmarks. \ No newline at end of file diff --git a/docs/sources/concepts/introduction.rst b/docs/sources/concepts/introduction.rst deleted file mode 100644 index 7251b51786..0000000000 --- a/docs/sources/concepts/introduction.rst +++ /dev/null @@ -1,125 +0,0 @@ -:title: Introduction -:description: An introduction to docker and standard containers? -:keywords: containers, lxc, concepts, explanation - -Introduction -============ - -Docker -- The Linux container runtime -------------------------------------- - -Docker complements LXC with a high-level API which operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers. - -Docker is a great building block for automating distributed systems: large-scale web deployments, database clusters, continuous deployment systems, private PaaS, service-oriented architectures, etc. - - -- **Heterogeneous payloads** 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. -- **Any server** 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. -- **Isolation** docker isolates processes from each other and from the underlying host, using lightweight containers. -- **Repeatability** Because containers are isolated in their own filesystem, they behave the same regardless of where, when, and alongside what they run. - -.. image:: images/lego_docker.jpg - - -What is a Standard Container? ------------------------------ - -Docker defines a unit of software delivery called a Standard Container. The goal of a Standard Container is to encapsulate a software component and all its dependencies in -a format that is self-describing and portable, so that any compliant runtime can run it without extra dependency, regardless of the underlying machine and the contents of the container. - -The spec for Standard Containers is currently work in progress, but it is very straightforward. It mostly defines 1) an image format, 2) a set of standard operations, and 3) an execution environment. - -A great analogy for this is the shipping container. Just like Standard Containers are a fundamental unit of software delivery, shipping containers (http://bricks.argz.com/ins/7823-1/12) are a fundamental unit of physical delivery. - -Standard operations -~~~~~~~~~~~~~~~~~~~ - -Just like shipping containers, Standard Containers define a set of STANDARD OPERATIONS. Shipping containers can be lifted, stacked, locked, loaded, unloaded and labelled. Similarly, standard containers can be started, stopped, copied, snapshotted, downloaded, uploaded and tagged. - - -Content-agnostic -~~~~~~~~~~~~~~~~~~~ - -Just like shipping containers, Standard Containers are CONTENT-AGNOSTIC: all standard operations have the same effect regardless of the contents. A shipping container will be stacked in exactly the same way whether it contains Vietnamese powder coffee or spare Maserati parts. Similarly, Standard Containers are started or uploaded in the same way whether they contain a postgres database, a php application with its dependencies and application server, or Java build artifacts. - - -Infrastructure-agnostic -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Both types of containers are INFRASTRUCTURE-AGNOSTIC: they can be transported to thousands of facilities around the world, and manipulated by a wide variety of equipment. A shipping container can be packed in a factory in Ukraine, transported by truck to the nearest routing center, stacked onto a train, loaded into a German boat by an Australian-built crane, stored in a warehouse at a US facility, etc. Similarly, a standard container can be bundled on my laptop, uploaded to S3, downloaded, run and snapshotted by a build server at Equinix in Virginia, uploaded to 10 staging servers in a home-made Openstack cluster, then sent to 30 production instances across 3 EC2 regions. - - -Designed for automation -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Because they offer the same standard operations regardless of content and infrastructure, Standard Containers, just like their physical counterpart, are extremely well-suited for automation. In fact, you could say automation is their secret weapon. - -Many things that once required time-consuming and error-prone human effort can now be programmed. Before shipping containers, a bag of powder coffee was hauled, dragged, dropped, rolled and stacked by 10 different people in 10 different locations by the time it reached its destination. 1 out of 50 disappeared. 1 out of 20 was damaged. The process was slow, inefficient and cost a fortune - and was entirely different depending on the facility and the type of goods. - -Similarly, before Standard Containers, by the time a software component ran in production, it had been individually built, configured, bundled, documented, patched, vendored, templated, tweaked and instrumented by 10 different people on 10 different computers. Builds failed, libraries conflicted, mirrors crashed, post-it notes were lost, logs were misplaced, cluster updates were half-broken. The process was slow, inefficient and cost a fortune - and was entirely different depending on the language and infrastructure provider. - - -Industrial-grade delivery -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are 17 million shipping containers in existence, packed with every physical good imaginable. Every single one of them can be loaded on the same boats, by the same cranes, in the same facilities, and sent anywhere in the World with incredible efficiency. It is embarrassing to think that a 30 ton shipment of coffee can safely travel half-way across the World in *less time* than it takes a software team to deliver its code from one datacenter to another sitting 10 miles away. - -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/conf.py b/docs/sources/conf.py index d443d34052..41dba70201 100644 --- a/docs/sources/conf.py +++ b/docs/sources/conf.py @@ -20,6 +20,20 @@ import sys, os # -- General configuration ----------------------------------------------------- + + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# the 'redirect_home.html' page redirects using a http meta refresh which, according +# to official sources is more or less equivalent of a 301. + +html_additional_pages = { + 'concepts/containers': 'redirect_home.html', + 'concepts/introduction': 'redirect_home.html', + } + + + # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' @@ -120,7 +134,11 @@ html_theme_path = ['../theme'] # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None + +# We use a png favicon. This is not compatible with internet explorer, but looks +# much better on all other browsers. However, sphynx doesn't like it (it likes +# .ico better) so we have just put it in the template rather than used this setting +# html_favicon = 'favicon.png' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -138,10 +156,6 @@ html_static_path = ['static_files'] # Custom sidebar templates, maps document names to template names. #html_sidebars = {} -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - # If false, no module index is generated. #html_domain_indices = True diff --git a/docs/sources/index/variable.rst b/docs/sources/index/variable.rst deleted file mode 100644 index 90eac3af8a..0000000000 --- a/docs/sources/index/variable.rst +++ /dev/null @@ -1,27 +0,0 @@ -:title: Index Environment Variable -:description: Setting this environment variable on the docker server will change the URL docker index. -:keywords: docker, index environment variable, documentation - -================================= -Docker Index Environment Variable -================================= - -Variable --------- - -.. code-block:: sh - - DOCKER_INDEX_URL - -Setting this environment variable on the docker server will change the URL docker index. -This address is used in commands such as ``docker login``, ``docker push`` and ``docker pull``. -The docker daemon doesn't need to be restarted for this parameter to take effect. - -Example -------- - -.. code-block:: sh - - docker -d & - export DOCKER_INDEX_URL="https://index.docker.io" - diff --git a/docs/sources/use/workingwithrepository.rst b/docs/sources/use/workingwithrepository.rst index 6fccc01a98..45702597ab 100644 --- a/docs/sources/use/workingwithrepository.rst +++ b/docs/sources/use/workingwithrepository.rst @@ -77,3 +77,28 @@ Now you can commit this image to the repository # for example docker push dhrp/kickassapp docker push + +Changing the server to connect to +---------------------------------- + +When you are running your own index and/or registry, You can change the server the docker client will connect to. + +Variable +^^^^^^^^ + +.. code-block:: sh + + DOCKER_INDEX_URL + +Setting this environment variable on the docker server will change the URL docker index. +This address is used in commands such as ``docker login``, ``docker push`` and ``docker pull``. +The docker daemon doesn't need to be restarted for this parameter to take effect. + +Example +^^^^^^^ + +.. code-block:: sh + + docker -d & + export DOCKER_INDEX_URL="https://index.docker.io" + diff --git a/docs/theme/docker/layout.html b/docs/theme/docker/layout.html index baaaec9155..707888a927 100755 --- a/docs/theme/docker/layout.html +++ b/docs/theme/docker/layout.html @@ -40,6 +40,8 @@ {%- set script_files = script_files + ['_static/js/docs.js'] %} + + {%- for cssfile in css_files %} {%- endfor %} @@ -48,9 +50,8 @@ {%- endfor %} - {%- if favicon %} - - {%- endif %} + + {%- block extrahead %}{% endblock %} @@ -104,11 +105,8 @@
-
-
- -