From e0c6a8e8bb4343d85eb04095e61f9d22e911f575 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 13 May 2013 15:10:26 +0200 Subject: [PATCH 01/17] add sizes in images and containers Upstream-commit: a91b710961b74341543a81b9d16f66d65b1907f1 Component: engine --- components/engine/api_params.go | 16 ++++++++++------ components/engine/api_test.go | 2 +- components/engine/commands.go | 13 +++++++++---- components/engine/container.go | 24 ++++++++++++++++++++++++ components/engine/graph.go | 9 +++++++++ components/engine/image.go | 24 ++++++++++++++++++++++++ components/engine/server.go | 5 +++++ components/engine/utils.go | 23 +++++++++++++++++++++++ 8 files changed, 105 insertions(+), 11 deletions(-) diff --git a/components/engine/api_params.go b/components/engine/api_params.go index c7c15585f9..c4942b50e1 100644 --- a/components/engine/api_params.go +++ b/components/engine/api_params.go @@ -11,6 +11,8 @@ type ApiImages struct { Tag string `json:",omitempty"` Id string Created int64 `json:",omitempty"` + Size int64 + ParentSize int64 } type ApiInfo struct { @@ -24,12 +26,14 @@ type ApiInfo struct { } type ApiContainers struct { - Id string - Image string `json:",omitempty"` - Command string `json:",omitempty"` - Created int64 `json:",omitempty"` - Status string `json:",omitempty"` - Ports string `json:",omitempty"` + Id string + Image string `json:",omitempty"` + Command string `json:",omitempty"` + Created int64 `json:",omitempty"` + Status string `json:",omitempty"` + Ports string `json:",omitempty"` + SizeRw int64 + SizeRootFs int64 } type ApiSearch struct { diff --git a/components/engine/api_test.go b/components/engine/api_test.go index 68e60adc21..2128f3ef35 100644 --- a/components/engine/api_test.go +++ b/components/engine/api_test.go @@ -1194,7 +1194,7 @@ func TestDeleteContainers(t *testing.T) { func TestDeleteImages(t *testing.T) { //FIXME: Implement this test - t.Skip("Test not implemented") + t.Log("Test not implemented") } // Mocked types for tests diff --git a/components/engine/commands.go b/components/engine/commands.go index dc3f8c4e87..736aee2f7a 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -728,12 +728,12 @@ func CmdImages(args ...string) error { w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0) if !*quiet { - fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED") + fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED\tSIZE") } for _, out := range outs { if !*quiet { - fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\n", out.Repository, out.Tag, out.Id, HumanDuration(time.Now().Sub(time.Unix(out.Created, 0)))) + fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s (virtual %s)\n", out.Repository, out.Tag, out.Id, HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), HumanSize(out.Size), HumanSize(out.ParentSize)) } else { fmt.Fprintln(w, out.Id) } @@ -794,12 +794,17 @@ func CmdPs(args ...string) error { } w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0) if !*quiet { - fmt.Fprintln(w, "ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS") + fmt.Fprintln(w, "ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tSIZE") } for _, out := range outs { if !*quiet { - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", out.Id, out.Image, out.Command, out.Status, HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Ports) + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\t", out.Id, out.Image, out.Command, out.Status, HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Ports) + if out.SizeRootFs > 0 { + fmt.Fprintf(w, "%s (virtual %s)\n", HumanSize(out.SizeRw), HumanSize(out.SizeRootFs)) + } else { + fmt.Fprintf(w, "%s\n", HumanSize(out.SizeRw)) + } } else { fmt.Fprintln(w, out.Id) } diff --git a/components/engine/container.go b/components/engine/container.go index c49441e5da..8ccdfb2a43 100644 --- a/components/engine/container.go +++ b/components/engine/container.go @@ -11,6 +11,7 @@ import ( "os" "os/exec" "path" + "path/filepath" "sort" "strconv" "strings" @@ -879,3 +880,26 @@ func validateId(id string) error { } return nil } + +// GetSize, return real size, virtual size +func (container *Container) GetSize() (int64, int64) { + var sizeRw, sizeRootfs int64 + + filepath.Walk(container.rwPath(), func(path string, fileInfo os.FileInfo, err error) error { + if fileInfo != nil { + sizeRw += fileInfo.Size() + } + return nil + }) + + _, err := os.Stat(container.RootfsPath()) + if err == nil { + filepath.Walk(container.RootfsPath(), func(path string, fileInfo os.FileInfo, err error) error { + if fileInfo != nil { + sizeRootfs += fileInfo.Size() + } + return nil + }) + } + return sizeRw, sizeRootfs +} diff --git a/components/engine/graph.go b/components/engine/graph.go index d9b4f5ac5c..b4a0b57504 100644 --- a/components/engine/graph.go +++ b/components/engine/graph.go @@ -89,6 +89,15 @@ func (graph *Graph) Get(name string) (*Image, error) { if img.Id != id { return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.Id) } + if img.Size == 0 { + root, err := img.root() + if err != nil { + return nil, err + } + if err := StoreSize(img, root); err != nil { + return nil, err + } + } img.graph = graph graph.lockSumMap.Lock() defer graph.lockSumMap.Unlock() diff --git a/components/engine/image.go b/components/engine/image.go index 413d95673b..76ebdab33d 100644 --- a/components/engine/image.go +++ b/components/engine/image.go @@ -12,6 +12,7 @@ import ( "os" "os/exec" "path" + "path/filepath" "strings" "time" ) @@ -27,6 +28,8 @@ type Image struct { Author string `json:"author,omitempty"` Config *Config `json:"config,omitempty"` graph *Graph + Size int64 + ParentSize int64 } func LoadImage(root string) (*Image, error) { @@ -93,6 +96,18 @@ func StoreImage(img *Image, layerData Archive, root string, store bool) error { if err := Untar(layerData, layer); err != nil { return err } + + return StoreSize(img, root) +} + +func StoreSize(img *Image, root string) error { + layer := layerPath(root) + + filepath.Walk(layer, func(path string, fileInfo os.FileInfo, err error) error { + img.Size += fileInfo.Size() + return nil + }) + // Store the json ball jsonData, err := json.Marshal(img) if err != nil { @@ -359,3 +374,12 @@ func (img *Image) Checksum() (string, error) { return hash, nil } + +func (img *Image) getVirtualSize(size int64) int64 { + parentImage, err := img.GetParent() + if err != nil || parentImage == nil { + return size + } + size += parentImage.Size + return parentImage.getVirtualSize(size) +} diff --git a/components/engine/server.go b/components/engine/server.go index e96497bff3..cb030fcfa0 100644 --- a/components/engine/server.go +++ b/components/engine/server.go @@ -164,6 +164,8 @@ func (srv *Server) Images(all, only_ids bool, filter string) ([]ApiImages, error out.Tag = tag out.Id = TruncateId(id) out.Created = image.Created.Unix() + out.Size = image.Size + out.ParentSize = image.getVirtualSize(0) } else { out.Id = image.ShortId() } @@ -179,6 +181,8 @@ func (srv *Server) Images(all, only_ids bool, filter string) ([]ApiImages, error out.Tag = "" out.Id = TruncateId(id) out.Created = image.Created.Unix() + out.Size = image.Size + out.ParentSize = image.getVirtualSize(0) } else { out.Id = image.ShortId() } @@ -280,6 +284,7 @@ func (srv *Server) Containers(all, trunc_cmd, only_ids bool, n int, since, befor c.Created = container.Created.Unix() c.Status = container.State.String() c.Ports = container.NetworkSettings.PortMappingHuman() + c.SizeRw, c.SizeRootFs = container.GetSize() } retContainers = append(retContainers, c) } diff --git a/components/engine/utils.go b/components/engine/utils.go index 4b416cd1e6..5daf3a3c3d 100644 --- a/components/engine/utils.go +++ b/components/engine/utils.go @@ -16,6 +16,7 @@ import ( "os/signal" "path/filepath" "runtime" + _ "strconv" "strings" "sync" "time" @@ -133,6 +134,28 @@ func HumanDuration(d time.Duration) string { return fmt.Sprintf("%d years", d.Hours()/24/365) } +// HumanSize returns a human-readabla approximation of a size +// (eg. "44K", "17M") +func HumanSize(size int64) string { + i := 0 + var sizef float64 + sizef = float64(size) + units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} + for sizef > 1024.0 { + sizef = sizef / 1024.0 + i++ + } + return fmt.Sprintf("%.*f %s", i, sizef, units[i]) + // sprintf(buf, "%.*f %s", i, size, units[i]); + // if size/1024/1024 > 1000 { + // return strconv.FormatFloat((float64)(size/1024/1024), 'f', 2, 32) + "G" + // } + // if size/1024 > 1024 { + // return strconv.FormatInt(size/1024/1024, 10) + "M" + // } + // return strconv.FormatInt(size/1024, 10) + "K" +} + func Trunc(s string, maxlen int) string { if len(s) <= maxlen { return s From 22c50f73c6539c8a2f2d6da11d29509ea0432391 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 21 May 2013 12:53:05 +0000 Subject: [PATCH 02/17] add regexp check on repo's name Upstream-commit: 4489005cb2f11fe6e2dcdb181b4834791de3b73f Component: engine --- components/engine/commands.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/engine/commands.go b/components/engine/commands.go index 5e459a1d94..98e665cd40 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -17,6 +17,7 @@ import ( "os" "path/filepath" "reflect" + "regexp" "strconv" "strings" "text/tabwriter" @@ -641,6 +642,10 @@ func (cli *DockerCli) CmdPush(args ...string) error { if len(strings.SplitN(name, "/", 2)) == 1 { return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in / (ex: %s/%s)", out.Username, name) } + validRepo := regexp.MustCompile(`^([a-z0-9]{4,30})/([a-z0-9-.]+)$`) + if !validRepo.MatchString(name) { + return fmt.Errorf("Invalid repository name, only alphanum, - and . are allowed") + } v := url.Values{} v.Set("registry", *registry) From 87ab4000addac74e18feda383110ca9e71db2914 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Thu, 23 May 2013 09:35:20 +0000 Subject: [PATCH 03/17] fix typo Upstream-commit: ed56b6a905d5e9f443cb0c5c949965f848abbe8d Component: engine --- components/engine/utils/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/utils/utils.go b/components/engine/utils/utils.go index ec189cb002..360e4ec31b 100644 --- a/components/engine/utils/utils.go +++ b/components/engine/utils/utils.go @@ -132,7 +132,7 @@ func HumanDuration(d time.Duration) string { return fmt.Sprintf("%d years", d.Hours()/24/365) } -// HumanSize returns a human-readabla approximation of a size +// HumanSize returns a human-readable approximation of a size // (eg. "44kB", "17MB") func HumanSize(size int64) string { i := 0 From 183381f196cb3ddccbb43143e2c5c859c16f3e5a Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Thu, 23 May 2013 10:29:09 +0000 Subject: [PATCH 04/17] switch to SI standard and add test Upstream-commit: b45143da9b275b5003c23667b0988ad93f383b11 Component: engine --- components/engine/utils/utils.go | 9 ++++----- components/engine/utils/utils_test.go | 13 +++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/components/engine/utils/utils.go b/components/engine/utils/utils.go index 360e4ec31b..170d34dd7a 100644 --- a/components/engine/utils/utils.go +++ b/components/engine/utils/utils.go @@ -133,20 +133,19 @@ func HumanDuration(d time.Duration) string { } // HumanSize returns a human-readable approximation of a size -// (eg. "44kB", "17MB") +// using SI standard (eg. "44kB", "17MB") func HumanSize(size int64) string { i := 0 var sizef float64 sizef = float64(size) units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} - for sizef > 1024.0 { - sizef = sizef / 1024.0 + for sizef >= 1000.0 { + sizef = sizef / 1000.0 i++ } - return fmt.Sprintf("%.*f %s", i, sizef, units[i]) + return fmt.Sprintf("%.4g %s", sizef, units[i]) } - func Trunc(s string, maxlen int) string { if len(s) <= maxlen { return s diff --git a/components/engine/utils/utils_test.go b/components/engine/utils/utils_test.go index 4413f44efc..eec06d5134 100644 --- a/components/engine/utils/utils_test.go +++ b/components/engine/utils/utils_test.go @@ -261,3 +261,16 @@ func TestCompareKernelVersion(t *testing.T) { &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "0"}, -1) } + +func TestHumanSize(t *testing.T) { + + size1000 := HumanSize(1000) + if size1000 != "1 kB" { + t.Errorf("1000 -> expected 1 kB, got %s", size1000) + } + + size1024 := HumanSize(1024) + if size1024 != "1.024 kB" { + t.Errorf("1024 -> expected 1.024 kB, got %s", size1024) + } +} From 317a0269763e28403bfa7e4d15d2b2e173b4a241 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 24 May 2013 13:03:09 +0000 Subject: [PATCH 05/17] fix: Can't lookup root of unregistered image Upstream-commit: 1c946ef0038a27d134f497ed72352136c0a4bb9e Component: engine --- components/engine/graph.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/graph.go b/components/engine/graph.go index 85a33a32a5..86c12b8f8b 100644 --- a/components/engine/graph.go +++ b/components/engine/graph.go @@ -89,6 +89,7 @@ func (graph *Graph) Get(name string) (*Image, error) { if img.Id != id { return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.Id) } + img.graph = graph if img.Size == 0 { root, err := img.root() if err != nil { @@ -98,7 +99,6 @@ func (graph *Graph) Get(name string) (*Image, error) { return nil, err } } - img.graph = graph graph.lockSumMap.Lock() defer graph.lockSumMap.Unlock() if _, exists := graph.checksumLock[img.Id]; !exists { From 2315df225ece56333c87857fb42e3ef77cdd8ba1 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 3 Jun 2013 14:23:57 +0000 Subject: [PATCH 06/17] ([a-z0-9_]{4,30})/([a-zA-Z0-9-_.]+) Upstream-commit: a55a0d370dfca169e0220a01c292c7d41ad0b557 Component: engine --- components/engine/commands.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/engine/commands.go b/components/engine/commands.go index 98e665cd40..1ab713ce5d 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -642,9 +642,14 @@ func (cli *DockerCli) CmdPush(args ...string) error { if len(strings.SplitN(name, "/", 2)) == 1 { return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in / (ex: %s/%s)", out.Username, name) } - validRepo := regexp.MustCompile(`^([a-z0-9]{4,30})/([a-z0-9-.]+)$`) - if !validRepo.MatchString(name) { - return fmt.Errorf("Invalid repository name, only alphanum, - and . are allowed") + nameParts := strings.SplitN(name, "/", 2) + validNamespace := regexp.MustCompile(`^([a-z0-9_]{4,30})$`) + if !validNamespace.MatchString(nameParts[0]) { + return fmt.Errorf("Invalid namespace name (%s), only [a-z0-9_] are allowed, size between 4 and 30", nameParts[0]) + } + validRepo := regexp.MustCompile(`^([a-zA-Z0-9-_.]+)$`) + if !validRepo.MatchString(nameParts[1]) { + return fmt.Errorf("Invalid repository name (%s), only [a-zA-Z0-9-_.] are allowed", nameParts[1]) } v := url.Values{} From 398ed3eba04467f12e1ae8deffebf9ebe2284db3 Mon Sep 17 00:00:00 2001 From: shin- Date: Mon, 10 Jun 2013 11:21:56 -0700 Subject: [PATCH 07/17] Send X-Docker-Endpoints header when validating the images upload with the index at the end of a push Upstream-commit: db3242e4bb1c31a7319e6273235a9ba6b29a61d4 Component: engine --- components/engine/registry/registry.go | 9 +++++++-- components/engine/server.go | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/components/engine/registry/registry.go b/components/engine/registry/registry.go index bd5c6b79c6..0ae37f7a9d 100644 --- a/components/engine/registry/registry.go +++ b/components/engine/registry/registry.go @@ -328,7 +328,7 @@ func (r *Registry) PushRegistryTag(remote, revision, tag, registry string, token return nil } -func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validate bool) (*RepositoryData, error) { +func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validate bool, regs []string) (*RepositoryData, error) { imgListJSON, err := json.Marshal(imgList) if err != nil { return nil, err @@ -347,6 +347,9 @@ func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validat req.SetBasicAuth(r.authConfig.Username, r.authConfig.Password) req.ContentLength = int64(len(imgListJSON)) req.Header.Set("X-Docker-Token", "true") + if validate { + req.Header["X-Docker-Endpoints"] = regs + } res, err := r.client.Do(req) if err != nil { @@ -364,7 +367,9 @@ func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validat req.SetBasicAuth(r.authConfig.Username, r.authConfig.Password) req.ContentLength = int64(len(imgListJSON)) req.Header.Set("X-Docker-Token", "true") - + if validate { + req.Header["X-Docker-Endpoints"] = regs + } res, err = r.client.Do(req) if err != nil { return nil, err diff --git a/components/engine/server.go b/components/engine/server.go index 6666123658..7cac30ae35 100644 --- a/components/engine/server.go +++ b/components/engine/server.go @@ -489,7 +489,7 @@ func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, name stri } out.Write(sf.FormatStatus("Sending image list")) - repoData, err := r.PushImageJSONIndex(name, imgList, false) + repoData, err := r.PushImageJSONIndex(name, imgList, false, nil) if err != nil { return err } @@ -513,7 +513,7 @@ func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, name stri } } - if _, err := r.PushImageJSONIndex(name, imgList, true); err != nil { + if _, err := r.PushImageJSONIndex(name, imgList, true, repoData.Endpoints); err != nil { return err } return nil From 5bf955bfcc245bc7e8a4a5577ba8dd05ef6a7f36 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 14 Jun 2013 10:05:01 +0000 Subject: [PATCH 08/17] fix virtual size on images Upstream-commit: 00cf2a1fa264c167dff0dd50e296c93d4c59908f Component: engine --- components/engine/api_params.go | 23 +++++++++++------------ components/engine/commands.go | 4 ++-- components/engine/image.go | 5 ++--- components/engine/server.go | 4 ++-- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/components/engine/api_params.go b/components/engine/api_params.go index 96a731c98f..9a689a04c3 100644 --- a/components/engine/api_params.go +++ b/components/engine/api_params.go @@ -7,13 +7,12 @@ type APIHistory struct { } type APIImages struct { - Repository string `json:",omitempty"` - Tag string `json:",omitempty"` - ID string `json:"Id"` - Created int64 - Size int64 - ParentSize int64 - + Repository string `json:",omitempty"` + Tag string `json:",omitempty"` + ID string `json:"Id"` + Created int64 + Size int64 + VirtualSize int64 } type APIInfo struct { @@ -28,11 +27,11 @@ type APIInfo struct { type APIContainers struct { ID string `json:"Id"` - Image string - Command string - Created int64 - Status string - Ports string + Image string + Command string + Created int64 + Status string + Ports string SizeRw int64 SizeRootFs int64 } diff --git a/components/engine/commands.go b/components/engine/commands.go index 1278892117..326a436ce2 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -812,8 +812,8 @@ func (cli *DockerCli) CmdImages(args ...string) error { fmt.Fprintf(w, "%s\t", utils.TruncateID(out.ID)) } fmt.Fprintf(w, "%s ago\t", utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0)))) - if out.ParentSize > 0 { - fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.Size), utils.HumanSize(out.ParentSize)) + if out.VirtualSize > 0 { + fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.Size), utils.HumanSize(out.VirtualSize)) } else { fmt.Fprintf(w, "%s\n", utils.HumanSize(out.Size)) } diff --git a/components/engine/image.go b/components/engine/image.go index f19667e7ec..8d4c42e733 100644 --- a/components/engine/image.go +++ b/components/engine/image.go @@ -31,7 +31,6 @@ type Image struct { Architecture string `json:"architecture,omitempty"` graph *Graph Size int64 - ParentSize int64 } func LoadImage(root string) (*Image, error) { @@ -376,13 +375,13 @@ func (img *Image) Checksum() (string, error) { return hash, nil } -func (img *Image) getVirtualSize(size int64) int64 { +func (img *Image) getParentsSize(size int64) int64 { parentImage, err := img.GetParent() if err != nil || parentImage == nil { return size } size += parentImage.Size - return parentImage.getVirtualSize(size) + return parentImage.getParentsSize(size) } // Build an Image object from raw json data diff --git a/components/engine/server.go b/components/engine/server.go index efd2850079..5e1459a861 100644 --- a/components/engine/server.go +++ b/components/engine/server.go @@ -177,7 +177,7 @@ func (srv *Server) Images(all bool, filter string) ([]APIImages, error) { out.ID = image.ID out.Created = image.Created.Unix() out.Size = image.Size - out.ParentSize = image.getVirtualSize(0) + out.VirtualSize = image.getParentsSize(0) + image.Size outs = append(outs, out) } } @@ -188,7 +188,7 @@ func (srv *Server) Images(all bool, filter string) ([]APIImages, error) { out.ID = image.ID out.Created = image.Created.Unix() out.Size = image.Size - out.ParentSize = image.getVirtualSize(0) + out.VirtualSize = image.getParentsSize(0) + image.Size outs = append(outs, out) } } From b78bf5bb715a4b8189e886a25aedbf5f81d407a8 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 14 Jun 2013 10:10:26 +0000 Subject: [PATCH 09/17] update docs Upstream-commit: e49f82b9e1a920c902c1cd813596dc1a78817e63 Component: engine --- .../sources/api/docker_remote_api_v1.2.rst | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/components/engine/docs/sources/api/docker_remote_api_v1.2.rst b/components/engine/docs/sources/api/docker_remote_api_v1.2.rst index 8354760e2f..fb69168120 100644 --- a/components/engine/docs/sources/api/docker_remote_api_v1.2.rst +++ b/components/engine/docs/sources/api/docker_remote_api_v1.2.rst @@ -47,28 +47,40 @@ List containers "Image": "base:latest", "Command": "echo 1", "Created": 1367854155, - "Status": "Exit 0" + "Status": "Exit 0", + "Ports":"", + "SizeRw":12288, + "SizeRootFs":0 }, { "Id": "9cd87474be90", "Image": "base:latest", "Command": "echo 222222", "Created": 1367854155, - "Status": "Exit 0" + "Status": "Exit 0", + "Ports":"", + "SizeRw":12288, + "SizeRootFs":0 }, { "Id": "3176a2479c92", "Image": "base:latest", "Command": "echo 3333333333333333", "Created": 1367854154, - "Status": "Exit 0" + "Status": "Exit 0", + "Ports":"", + "SizeRw":12288, + "SizeRootFs":0 }, { "Id": "4cb07b47f9fb", "Image": "base:latest", "Command": "echo 444444444444444444444444444444444", "Created": 1367854152, - "Status": "Exit 0" + "Status": "Exit 0", + "Ports":"", + "SizeRw":12288, + "SizeRootFs":0 } ] @@ -488,13 +500,17 @@ List Images "Repository":"base", "Tag":"ubuntu-12.10", "Id":"b750fe79269d", - "Created":1364102658 + "Created":1364102658, + "Size":24653, + "VirtualSize":180116135 }, { "Repository":"base", "Tag":"ubuntu-quantal", "Id":"b750fe79269d", - "Created":1364102658 + "Created":1364102658, + "Size":24653, + "VirtualSize":180116135 } ] @@ -643,7 +659,8 @@ Inspect an image "Image":"base", "Volumes":null, "VolumesFrom":"" - } + }, + "Size": 6824592 } :statuscode 200: no error From d7771969bfc5969c9aecf83973d413f6dd1629c4 Mon Sep 17 00:00:00 2001 From: unclejack Date: Fri, 14 Jun 2013 19:46:04 +0300 Subject: [PATCH 10/17] validate memory limits & error out if less than 512 KB Upstream-commit: 9ee11161bf0c635a0b0164ae1dee806c6fcfe7b7 Component: engine --- components/engine/server.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/engine/server.go b/components/engine/server.go index 34d525a35a..330c9fbb89 100644 --- a/components/engine/server.go +++ b/components/engine/server.go @@ -652,6 +652,10 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write func (srv *Server) ContainerCreate(config *Config) (string, error) { + if config.Memory != 0 && config.Memory < 524288 { + return "", fmt.Errorf("Memory limit must be given in bytes (minimum 524288 bytes)") + } + if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit { config.Memory = 0 } From 5f39923376d91dd1eb87bf1e35b9abb5523f6df6 Mon Sep 17 00:00:00 2001 From: unclejack Date: Tue, 4 Jun 2013 21:30:47 +0300 Subject: [PATCH 11/17] run auplink before unmounting aufs Upstream-commit: 2f67a62b5b48862948b1ce92aeffbb83c3707ee0 Component: engine --- components/engine/mount.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/engine/mount.go b/components/engine/mount.go index bb1a40eddb..541c29c13a 100644 --- a/components/engine/mount.go +++ b/components/engine/mount.go @@ -2,13 +2,18 @@ package docker import ( "fmt" + "github.com/dotcloud/docker/utils" "os" + "os/exec" "path/filepath" "syscall" "time" ) func Unmount(target string) error { + if err := exec.Command("auplink", target, "flush").Run(); err != nil { + utils.Debugf("[warning]: couldn't run auplink before unmount: %s", err) + } if err := syscall.Unmount(target, 0); err != nil { return err } From 1ee51a2d561e5f12f243b6a14215e8e43b039f0c Mon Sep 17 00:00:00 2001 From: unclejack Date: Tue, 4 Jun 2013 21:35:41 +0300 Subject: [PATCH 12/17] add aufs-tools to lxc-docker dependencies Upstream-commit: e53721ef69b13365c18c9189145ae1fadb931f01 Component: engine --- components/engine/packaging/debian/control | 2 +- components/engine/packaging/ubuntu/control | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/engine/packaging/debian/control b/components/engine/packaging/debian/control index 35a2a28cd1..62a963f59e 100644 --- a/components/engine/packaging/debian/control +++ b/components/engine/packaging/debian/control @@ -10,7 +10,7 @@ Homepage: http://github.com/dotcloud/docker Package: lxc-docker Architecture: linux-any -Depends: ${shlibs:Depends}, ${misc:Depends}, lxc, bsdtar +Depends: ${shlibs:Depends}, ${misc:Depends}, lxc, bsdtar, aufs-tools Description: 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 diff --git a/components/engine/packaging/ubuntu/control b/components/engine/packaging/ubuntu/control index b0560ebf70..404f38a16d 100644 --- a/components/engine/packaging/ubuntu/control +++ b/components/engine/packaging/ubuntu/control @@ -8,7 +8,7 @@ Homepage: http://github.com/dotcloud/docker Package: lxc-docker Architecture: linux-any -Depends: ${misc:Depends},${shlibs:Depends},lxc,bsdtar +Depends: ${misc:Depends},${shlibs:Depends},lxc,bsdtar,aufs-tools Conflicts: docker Description: lxc-docker is a Linux container runtime Docker complements LXC with a high-level API which operates at the process From 1d89b8f78f0063acd102be09ee2993e489e51edf Mon Sep 17 00:00:00 2001 From: unclejack Date: Fri, 14 Jun 2013 15:07:43 +0300 Subject: [PATCH 13/17] add aufs-tools package to dev env docs page Upstream-commit: fb7eaf67d1c01eea28fcbed61d6d8abd8117c965 Component: engine --- components/engine/docs/sources/contributing/devenvironment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/docs/sources/contributing/devenvironment.rst b/components/engine/docs/sources/contributing/devenvironment.rst index 5d937c5a44..ce2ecd41e8 100644 --- a/components/engine/docs/sources/contributing/devenvironment.rst +++ b/components/engine/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 wget bsdtar curl golang-stable git aufs-tools export GOPATH=~/go/ export PATH=$GOPATH/bin:$PATH From 9b310a0f72c7181541278db79a0e1035322125c7 Mon Sep 17 00:00:00 2001 From: unclejack Date: Fri, 14 Jun 2013 15:09:07 +0300 Subject: [PATCH 14/17] install aufs-tools when setting up the hack vagrant box Upstream-commit: f1d16ea0035ee45341e5d4a143cdce5798847cb5 Component: engine --- components/engine/hack/Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/hack/Vagrantfile b/components/engine/hack/Vagrantfile index 250731ef47..318f835f4f 100644 --- a/components/engine/hack/Vagrantfile +++ b/components/engine/hack/Vagrantfile @@ -22,7 +22,7 @@ Vagrant::Config.run do |config| pkg_cmd = "touch #{DOCKER_PATH}; " # Install docker dependencies pkg_cmd << "export DEBIAN_FRONTEND=noninteractive; apt-get -qq update; " \ - "apt-get install -q -y lxc bsdtar git golang make linux-image-extra-3.8.0-19-generic; " \ + "apt-get install -q -y lxc bsdtar git aufs-tools golang make linux-image-extra-3.8.0-19-generic; " \ "chown -R #{USER}.#{USER} #{GOPATH}; " \ "install -m 0664 #{CFG_PATH}/bash_profile /home/#{USER}/.bash_profile" config.vm.provision :shell, :inline => pkg_cmd From 25419889e5264e224df1f9c4bd7c831f8f9767b0 Mon Sep 17 00:00:00 2001 From: unclejack Date: Fri, 14 Jun 2013 15:13:27 +0300 Subject: [PATCH 15/17] install aufs-tools when setting up the testing vagrant box Upstream-commit: 822abab17e33a0f87ef1d785a9148d3ea11cbb60 Component: engine --- components/engine/testing/Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/testing/Vagrantfile b/components/engine/testing/Vagrantfile index 7556b191ac..e304a8d087 100644 --- a/components/engine/testing/Vagrantfile +++ b/components/engine/testing/Vagrantfile @@ -30,7 +30,7 @@ Vagrant::Config.run do |config| # Install docker dependencies pkg_cmd << "apt-get install -q -y python-software-properties; " \ "add-apt-repository -y ppa:gophers/go/ubuntu; apt-get update -qq; " \ - "DEBIAN_FRONTEND=noninteractive apt-get install -q -y lxc bsdtar git golang-stable make; " + "DEBIAN_FRONTEND=noninteractive apt-get install -q -y lxc bsdtar git golang-stable aufs-tools make; " # Activate new kernel pkg_cmd << "shutdown -r +1; " config.vm.provision :shell, :inline => pkg_cmd From 4bc27f700a083574edb00d8af408198036b3ac0e Mon Sep 17 00:00:00 2001 From: Andy Rothfusz Date: Fri, 14 Jun 2013 13:42:59 -0600 Subject: [PATCH 16/17] Add examples for local import. Upstream-commit: 7958f1f694ac411dcfeb8fbf0d702a7c552306ae Component: engine --- .../sources/commandline/command/import.rst | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/components/engine/docs/sources/commandline/command/import.rst b/components/engine/docs/sources/commandline/command/import.rst index 34a7138e07..66bcf5de52 100644 --- a/components/engine/docs/sources/commandline/command/import.rst +++ b/components/engine/docs/sources/commandline/command/import.rst @@ -8,6 +8,33 @@ :: - Usage: docker import [OPTIONS] URL|- [REPOSITORY [TAG]] + Usage: docker import URL|- [REPOSITORY [TAG]] 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, +you can use the ``-`` parameter to take the data from standard in. + +Examples +-------- + +Import from a remote location +............................. + +``$ docker import http://example.com/exampleimage.tgz exampleimagerepo`` + +Import from a local file +........................ + +Import to docker via pipe and standard in + +``$ cat exampleimage.tgz | docker import - exampleimagelocal`` + +Import from a local directory +............................. + +``$ sudo tar -c . | docker import - exampleimagedir`` + +Note the ``sudo`` in this example -- you must preserve the ownership of the files (especially root ownership) +during the archiving with tar. If you are not root (or sudo) when you tar, then the ownerships might not get preserved. From f884195c2832c4773a77b3b105abdcff1a1a40f3 Mon Sep 17 00:00:00 2001 From: unclejack Date: Fri, 14 Jun 2013 22:55:00 +0300 Subject: [PATCH 17/17] add test: fail to create container if mem limit < 512KB Upstream-commit: d3f83a6592e3d79768d9d3805edec80642b69c4b Component: engine --- components/engine/server_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/components/engine/server_test.go b/components/engine/server_test.go index 532757c61e..7fdec18f61 100644 --- a/components/engine/server_test.go +++ b/components/engine/server_test.go @@ -147,3 +147,25 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) { } } + +func TestRunWithTooLowMemoryLimit(t *testing.T) { + runtime, err := newTestRuntime() + srv := &Server{runtime: runtime} + if err != nil { + t.Fatal(err) + } + defer nuke(runtime) + // Try to create a container with a memory limit of 1 byte less than the minimum allowed limit. + _, err = srv.ContainerCreate( + &Config{ + Image: GetTestImage(runtime).ID, + Memory: 524287, + CpuShares: 1000, + Cmd: []string{"/bin/cat"}, + }, + ) + if err == nil { + t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!") + } + +}