From 528da23d6a5e0b6f37c1241c982bb49f301632cc Mon Sep 17 00:00:00 2001 From: unclejack Date: Thu, 2 May 2013 15:27:37 +0300 Subject: [PATCH 01/28] use Go 1.0.3 to build docker --- hack/dockerbuilder/Dockerfile | 6 +++++- hack/dockerbuilder/dockerbuilder | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hack/dockerbuilder/Dockerfile b/hack/dockerbuilder/Dockerfile index 55540984fd..af8dce108c 100644 --- a/hack/dockerbuilder/Dockerfile +++ b/hack/dockerbuilder/Dockerfile @@ -4,8 +4,12 @@ maintainer Solomon Hykes from ubuntu:12.10 run apt-get update run DEBIAN_FRONTEND=noninteractive apt-get install -y -q s3cmd +run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl # Packages required to checkout and build docker -run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang +run curl -s -o /go.tar.gz https://go.googlecode.com/files/go1.0.3.linux-amd64.tar.gz +run tar -C /usr/local -xzf /go.tar.gz +run echo "export PATH=$PATH:/usr/local/go/bin" > /.bashrc +run echo "export PATH=$PATH:/usr/local/go/bin" > /.bash_profile run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git run DEBIAN_FRONTEND=noninteractive apt-get install -y -q build-essential # Packages required to build an ubuntu package diff --git a/hack/dockerbuilder/dockerbuilder b/hack/dockerbuilder/dockerbuilder index 5e803aa0b2..500a82db9f 100644 --- a/hack/dockerbuilder/dockerbuilder +++ b/hack/dockerbuilder/dockerbuilder @@ -2,6 +2,8 @@ set -x set -e +export PATH=$PATH:/usr/local/go/bin + PACKAGE=github.com/dotcloud/docker if [ $# -gt 1 ]; then From 1df5f4094bf31edba6f2a2f07bfdada54340c1e4 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 5 Apr 2013 18:00:10 -0700 Subject: [PATCH 02/28] docker run -v PATH: bind a new data volume to a container --- commands.go | 20 ++++++++++++++++++++ container.go | 5 +++++ runtime.go | 6 ++++++ 3 files changed, 31 insertions(+) diff --git a/commands.go b/commands.go index 4be282bce2..cb7b57ff00 100644 --- a/commands.go +++ b/commands.go @@ -10,6 +10,7 @@ import ( "log" "net/http" "net/url" + "path/filepath" "runtime" "strconv" "strings" @@ -913,6 +914,25 @@ func (opts AttachOpts) Get(val string) bool { return false } +// PathOpts stores a unique set of absolute paths +type PathOpts map[string]struct{} + +func NewPathOpts() PathOpts { + return make(PathOpts) +} + +func (opts PathOpts) String() string { + return fmt.Sprintf("%v", map[string]struct{}(opts)) +} + +func (opts PathOpts) Set(val string) error { + if !filepath.IsAbs(val) { + return fmt.Errorf("%s is not an absolute path", val) + } + opts[filepath.Clean(val)] = struct{}{} + return nil +} + func (srv *Server) CmdTag(stdin io.ReadCloser, stdout io.Writer, args ...string) error { cmd := rcli.Subcmd(stdout, "tag", "[OPTIONS] IMAGE REPOSITORY [TAG]", "Tag an image into a repository") force := cmd.Bool("f", false, "Force") diff --git a/container.go b/container.go index bac0951da4..109c8b158b 100644 --- a/container.go +++ b/container.go @@ -66,6 +66,7 @@ type Config struct { Cmd []string Dns []string Image string // Name of the image as it was passed by the operator (eg. could be symbolic) + Volumes map[string]struct{} } func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Config, error) { @@ -97,6 +98,9 @@ func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Con var flDns ListOpts cmd.Var(&flDns, "dns", "Set custom dns servers") + flVolumes := NewPathOpts() + cmd.Var(flVolumes, "v", "Attach a data volume") + if err := cmd.Parse(args); err != nil { return nil, err } @@ -136,6 +140,7 @@ func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Con Cmd: runCmd, Dns: flDns, Image: image, + Volumes: flVolumes, } if *flMemory > 0 && !capabilities.SwapLimit { diff --git a/runtime.go b/runtime.go index 6e03226b36..16c98117fd 100644 --- a/runtime.go +++ b/runtime.go @@ -32,6 +32,7 @@ type Runtime struct { capabilities *Capabilities kernelVersion *KernelVersionInfo autoRestart bool + volumes *Graph } var sysInitPath string @@ -405,6 +406,10 @@ func NewRuntimeFromDirectory(root string, autoRestart bool) (*Runtime, error) { if err != nil { return nil, err } + volumes, err := NewGraph(path.Join(root, "volumes")) + if err != nil { + return nil, err + } repositories, err := NewTagStore(path.Join(root, "repositories"), g) if err != nil { return nil, fmt.Errorf("Couldn't create Tag store: %s", err) @@ -432,6 +437,7 @@ func NewRuntimeFromDirectory(root string, autoRestart bool) (*Runtime, error) { idIndex: NewTruncIndex(), capabilities: &Capabilities{}, autoRestart: autoRestart, + volumes: volumes, } if err := runtime.restore(); err != nil { From 35d704c8a006263d1539994f02c7bfbe97202528 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Tue, 9 Apr 2013 18:08:03 -0700 Subject: [PATCH 03/28] Change the volumes type to map[string]string to store both source and destination --- commands.go | 6 +++--- container.go | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/commands.go b/commands.go index cb7b57ff00..5f5f8d36f9 100644 --- a/commands.go +++ b/commands.go @@ -915,21 +915,21 @@ func (opts AttachOpts) Get(val string) bool { } // PathOpts stores a unique set of absolute paths -type PathOpts map[string]struct{} +type PathOpts map[string]string func NewPathOpts() PathOpts { return make(PathOpts) } func (opts PathOpts) String() string { - return fmt.Sprintf("%v", map[string]struct{}(opts)) + return fmt.Sprintf("%v", map[string]string(opts)) } func (opts PathOpts) Set(val string) error { if !filepath.IsAbs(val) { return fmt.Errorf("%s is not an absolute path", val) } - opts[filepath.Clean(val)] = struct{}{} + opts[filepath.Clean(val)] = "" return nil } diff --git a/container.go b/container.go index 109c8b158b..aaa8723662 100644 --- a/container.go +++ b/container.go @@ -66,7 +66,7 @@ type Config struct { Cmd []string Dns []string Image string // Name of the image as it was passed by the operator (eg. could be symbolic) - Volumes map[string]struct{} + Volumes map[string]string } func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Config, error) { @@ -461,6 +461,7 @@ func (container *Container) Start() error { // Init the lock container.waitLock = make(chan struct{}) + container.ToDisk() go container.monitor() return nil From 8d9aaee60bf03397e51e8c84232a73fcb3baf36c Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Tue, 9 Apr 2013 18:19:55 -0700 Subject: [PATCH 04/28] Handle data volumes mount points --- container.go | 17 +++++++++++++++++ lxc_template.go | 6 +++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/container.go b/container.go index aaa8723662..4475fdac40 100644 --- a/container.go +++ b/container.go @@ -400,9 +400,26 @@ func (container *Container) Start() error { container.Config.MemorySwap = -1 } + // Create the requested volumes volumes + for volPath := range container.Config.Volumes { + if c, err := container.runtime.volumes.Create(nil, container, ""); err != nil { + return err + } else { + if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { + return nil + } + root, err := c.root() + if err != nil { + return err + } + container.Config.Volumes[volPath] = root + } + } + if err := container.generateLXCConfig(); err != nil { return err } + params := []string{ "-n", container.Id, "-f", container.lxcConfigPath(), diff --git a/lxc_template.go b/lxc_template.go index 5ac62f52af..fd6461bb13 100644 --- a/lxc_template.go +++ b/lxc_template.go @@ -79,7 +79,11 @@ lxc.mount.entry = {{.SysInitPath}} {{$ROOTFS}}/sbin/init none bind,ro 0 0 # In order to get a working DNS environment, mount bind (ro) the host's /etc/resolv.conf into the container lxc.mount.entry = {{.ResolvConfPath}} {{$ROOTFS}}/etc/resolv.conf none bind,ro 0 0 - +{{if .Config.Volumes}} +{{range $T0, $T1 := .Config.Volumes}} +lxc.mount.entry = {{$T1}}/layer {{$ROOTFS}}/{{$T0}} none bind,rw 0 0 +{{end}} +{{end}} # drop linux capabilities (apply mainly to the user root in the container) lxc.cap.drop = audit_control audit_write mac_admin mac_override mknod setfcap setpcap sys_admin sys_boot sys_module sys_nice sys_pacct sys_rawio sys_resource sys_time sys_tty_config From faf8daa7c68f2511dedfad15e1fd05f9eff077a2 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 10 Apr 2013 16:09:34 -0700 Subject: [PATCH 05/28] Switch back config to map[string]struct{} --- commands.go | 6 +++--- container.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/commands.go b/commands.go index 5f5f8d36f9..cb7b57ff00 100644 --- a/commands.go +++ b/commands.go @@ -915,21 +915,21 @@ func (opts AttachOpts) Get(val string) bool { } // PathOpts stores a unique set of absolute paths -type PathOpts map[string]string +type PathOpts map[string]struct{} func NewPathOpts() PathOpts { return make(PathOpts) } func (opts PathOpts) String() string { - return fmt.Sprintf("%v", map[string]string(opts)) + return fmt.Sprintf("%v", map[string]struct{}(opts)) } func (opts PathOpts) Set(val string) error { if !filepath.IsAbs(val) { return fmt.Errorf("%s is not an absolute path", val) } - opts[filepath.Clean(val)] = "" + opts[filepath.Clean(val)] = struct{}{} return nil } diff --git a/container.go b/container.go index 4475fdac40..2edcd6776b 100644 --- a/container.go +++ b/container.go @@ -66,7 +66,7 @@ type Config struct { Cmd []string Dns []string Image string // Name of the image as it was passed by the operator (eg. could be symbolic) - Volumes map[string]string + Volumes map[string]struct{} } func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Config, error) { From 6fb495bf6ff545753518e9b9ed39c2676230c277 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 10 Apr 2013 16:10:53 -0700 Subject: [PATCH 06/28] Move the id of volumes to Container (instead of Container.Config) --- container.go | 24 +++++++++++++++++++----- lxc_template.go | 6 +++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/container.go b/container.go index 2edcd6776b..5de931dc43 100644 --- a/container.go +++ b/container.go @@ -48,6 +48,7 @@ type Container struct { runtime *Runtime waitLock chan struct{} + Volumes map[string]string } type Config struct { @@ -399,6 +400,7 @@ func (container *Container) Start() error { log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n") container.Config.MemorySwap = -1 } + container.Volumes = make(map[string]string) // Create the requested volumes volumes for volPath := range container.Config.Volumes { @@ -408,11 +410,7 @@ func (container *Container) Start() error { if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { return nil } - root, err := c.root() - if err != nil { - return err - } - container.Config.Volumes[volPath] = root + container.Volumes[volPath] = c.Id } } @@ -810,6 +808,22 @@ func (container *Container) RootfsPath() string { return path.Join(container.root, "rootfs") } +func (container *Container) GetVolumes() (map[string]string, error) { + ret := make(map[string]string) + for volPath, id := range container.Volumes { + volume, err := container.runtime.volumes.Get(id) + if err != nil { + return nil, err + } + root, err := volume.root() + if err != nil { + return nil, err + } + ret[volPath] = path.Join(root, "layer") + } + return ret, nil +} + func (container *Container) rwPath() string { return path.Join(container.root, "rw") } diff --git a/lxc_template.go b/lxc_template.go index fd6461bb13..e2be3f21cd 100644 --- a/lxc_template.go +++ b/lxc_template.go @@ -79,9 +79,9 @@ lxc.mount.entry = {{.SysInitPath}} {{$ROOTFS}}/sbin/init none bind,ro 0 0 # In order to get a working DNS environment, mount bind (ro) the host's /etc/resolv.conf into the container lxc.mount.entry = {{.ResolvConfPath}} {{$ROOTFS}}/etc/resolv.conf none bind,ro 0 0 -{{if .Config.Volumes}} -{{range $T0, $T1 := .Config.Volumes}} -lxc.mount.entry = {{$T1}}/layer {{$ROOTFS}}/{{$T0}} none bind,rw 0 0 +{{if .Volumes}} +{{range $virtualPath, $realPath := .GetVolumes}} +lxc.mount.entry = {{$realPath}} {{$ROOTFS}}/{{$virtualPath}} none bind,rw 0 0 {{end}} {{end}} From 4099a31304863edf5b4d1b594b41c7ce1a33c5e1 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 10 Apr 2013 16:23:30 -0700 Subject: [PATCH 07/28] Implement the -volumes-from in order to mount volumes from an other container --- container.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/container.go b/container.go index 5de931dc43..7bd5a791ac 100644 --- a/container.go +++ b/container.go @@ -68,6 +68,7 @@ type Config struct { Dns []string Image string // Name of the image as it was passed by the operator (eg. could be symbolic) Volumes map[string]struct{} + VolumesFrom string } func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Config, error) { @@ -102,6 +103,8 @@ func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Con flVolumes := NewPathOpts() cmd.Var(flVolumes, "v", "Attach a data volume") + flVolumesFrom := cmd.String("volumes-from", "", "Mount volumes from the specified container") + if err := cmd.Parse(args); err != nil { return nil, err } @@ -142,6 +145,7 @@ func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Con Dns: flDns, Image: image, Volumes: flVolumes, + VolumesFrom: *flVolumesFrom, } if *flMemory > 0 && !capabilities.SwapLimit { @@ -414,6 +418,22 @@ func (container *Container) Start() error { } } + if container.Config.VolumesFrom != "" { + c := container.runtime.Get(container.Config.VolumesFrom) + if c == nil { + return fmt.Errorf("Container %s not found. Impossible to mount its volumes") + } + for volPath, id := range c.Volumes { + if _, exists := container.Volumes[volPath]; exists { + return fmt.Errorf("The requested volume %s overlap one of the volume of the container %s", volPath, c.Id) + } + if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { + return nil + } + container.Volumes[volPath] = id + } + } + if err := container.generateLXCConfig(); err != nil { return err } From 3edd14b8c2eb13f45834f5d9306a579b256f9348 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 12 Apr 2013 09:23:57 -0700 Subject: [PATCH 08/28] Implement the data volume removal --- commands.go | 28 +++++++++++++++++++++++++++- container.go | 2 +- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/commands.go b/commands.go index cb7b57ff00..732fdcaaaa 100644 --- a/commands.go +++ b/commands.go @@ -401,7 +401,8 @@ func (srv *Server) CmdHistory(stdin io.ReadCloser, stdout io.Writer, args ...str } func (srv *Server) CmdRm(stdin io.ReadCloser, stdout io.Writer, args ...string) error { - cmd := rcli.Subcmd(stdout, "rm", "CONTAINER [CONTAINER...]", "Remove a container") + cmd := rcli.Subcmd(stdout, "rm", "[OPTIONS] CONTAINER [CONTAINER...]", "Remove a container") + v := cmd.Bool("v", false, "Remove the volumes associated to the container") if err := cmd.Parse(args); err != nil { return nil } @@ -409,15 +410,40 @@ func (srv *Server) CmdRm(stdin io.ReadCloser, stdout io.Writer, args ...string) cmd.Usage() return nil } + volumes := make(map[string]struct{}) for _, name := range cmd.Args() { container := srv.runtime.Get(name) if container == nil { return fmt.Errorf("No such container: %s", name) } + // Store all the deleted containers volumes + for _, volumeId := range container.Volumes { + volumes[volumeId] = struct{}{} + } if err := srv.runtime.Destroy(container); err != nil { fmt.Fprintln(stdout, "Error destroying container "+name+": "+err.Error()) } } + if *v { + // Retrieve all volumes from all remaining containers + usedVolumes := make(map[string]*Container) + for _, container := range srv.runtime.List() { + for _, containerVolumeId := range container.Volumes { + usedVolumes[containerVolumeId] = container + } + } + + for volumeId := range volumes { + // If the requested volu + if c, exists := usedVolumes[volumeId]; exists { + fmt.Fprintf(stdout, "The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.Id) + continue + } + if err := srv.runtime.volumes.Delete(volumeId); err != nil { + return err + } + } + } return nil } diff --git a/container.go b/container.go index 7bd5a791ac..92bcc2506d 100644 --- a/container.go +++ b/container.go @@ -421,7 +421,7 @@ func (container *Container) Start() error { if container.Config.VolumesFrom != "" { c := container.runtime.Get(container.Config.VolumesFrom) if c == nil { - return fmt.Errorf("Container %s not found. Impossible to mount its volumes") + return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.Id) } for volPath, id := range c.Volumes { if _, exists := container.Volumes[volPath]; exists { From b0459adc271b20cde11da6a74cc5a71bab23f2ac Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 22 Apr 2013 18:00:10 -0700 Subject: [PATCH 09/28] Comply to the new graph.Create() prototype --- container.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container.go b/container.go index 92bcc2506d..98e62c8849 100644 --- a/container.go +++ b/container.go @@ -408,7 +408,7 @@ func (container *Container) Start() error { // Create the requested volumes volumes for volPath := range container.Config.Volumes { - if c, err := container.runtime.volumes.Create(nil, container, ""); err != nil { + if c, err := container.runtime.volumes.Create(nil, container, "", ""); err != nil { return err } else { if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { From 897cc573f051f1d88be0fde05946e66d0c86c43e Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 2 May 2013 09:23:29 -0700 Subject: [PATCH 10/28] Fix the graph.Create prototype --- container.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container.go b/container.go index 98e62c8849..dc57a31135 100644 --- a/container.go +++ b/container.go @@ -408,7 +408,7 @@ func (container *Container) Start() error { // Create the requested volumes volumes for volPath := range container.Config.Volumes { - if c, err := container.runtime.volumes.Create(nil, container, "", ""); err != nil { + if c, err := container.runtime.volumes.Create(nil, container, "", "", nil); err != nil { return err } else { if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { From 21b9dcd518871088086943f95bf39f068b30691f Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 2 May 2013 09:26:29 -0700 Subject: [PATCH 11/28] Update docs for Command Run --- docs/sources/commandline/command/run.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sources/commandline/command/run.rst b/docs/sources/commandline/command/run.rst index c2096b3bd9..7d394c0d9d 100644 --- a/docs/sources/commandline/command/run.rst +++ b/docs/sources/commandline/command/run.rst @@ -17,3 +17,5 @@ -p=[]: Map a network port to the container -t=false: Allocate a pseudo-tty -u="": Username or UID + -d=[]: Set custom dns servers for the container + -v=[]: Creates a new volumes and mount it at the specified path. A container ID can be passed instead of a path in order to mount all volumes from the given container. From 74cd7e822d4fbac96faab1173cf2fc4e95658901 Mon Sep 17 00:00:00 2001 From: Bruno Bigras Date: Tue, 30 Apr 2013 09:54:22 -0300 Subject: [PATCH 12/28] Use only one deb line in /etc/apt This prevents the script from filling up /etc/apt/sources.list with more than one deb line which cause a warning when updating. --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 319fbc7530..95bd8c0f93 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -11,7 +11,7 @@ Vagrant::Config.run do |config| config.vm.box_url = BOX_URI # Add docker PPA key to the local repository and install docker pkg_cmd = "apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys #{PPA_KEY}; " - pkg_cmd << "echo 'deb http://ppa.launchpad.net/dotcloud/lxc-docker/ubuntu precise main' >>/etc/apt/sources.list; " + pkg_cmd << "echo 'deb http://ppa.launchpad.net/dotcloud/lxc-docker/ubuntu precise main' >/etc/apt/sources.list.d/lxc-docker.list; " pkg_cmd << "apt-get update -qq; apt-get install -q -y lxc-docker" if ARGV.include?("--provider=aws".downcase) # Add AUFS dependency to amazon's VM From 6e486b638b6674694fe02d2661bd93f0ee08d425 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 2 May 2013 11:25:49 -0700 Subject: [PATCH 13/28] + Hack: 'make s3release' uploads a clean build to s3 --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 2d9ba2c605..d4aa4b4721 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,9 @@ $(BINRELEASE): $(SRCRELEASE) rm -f $(BINRELEASE) cd $(SRCRELEASE); make; cp -R bin docker-$(RELEASE_VERSION); tar -f ../$(BINRELEASE) -zv -c docker-$(RELEASE_VERSION) +s3release: $(BINRELEASE) + s3cmd -P put $(BINRELEASE) s3://get.docker.io/builds/`uname -s`/`uname -m`/docker-$(RELEASE_VERSION).tgz + clean: @rm -rf $(dir $(DOCKER_BIN)) ifeq ($(GOPATH), $(BUILD_DIR)) From b6a5e604ab2205a547ac5b4f743cf3c4b93ffccf Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 2 May 2013 11:32:55 -0700 Subject: [PATCH 14/28] Add s3 upload to 'make release' --- Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index d4aa4b4721..f35362d2ca 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,8 @@ whichrelease: echo $(RELEASE_VERSION) release: $(BINRELEASE) + s3cmd -P put $(BINRELEASE) s3://get.docker.io/builds/`uname -s`/`uname -m`/docker-$(RELEASE_VERSION).tgz + srcrelease: $(SRCRELEASE) deps: $(DOCKER_DIR) @@ -59,9 +61,6 @@ $(BINRELEASE): $(SRCRELEASE) rm -f $(BINRELEASE) cd $(SRCRELEASE); make; cp -R bin docker-$(RELEASE_VERSION); tar -f ../$(BINRELEASE) -zv -c docker-$(RELEASE_VERSION) -s3release: $(BINRELEASE) - s3cmd -P put $(BINRELEASE) s3://get.docker.io/builds/`uname -s`/`uname -m`/docker-$(RELEASE_VERSION).tgz - clean: @rm -rf $(dir $(DOCKER_BIN)) ifeq ($(GOPATH), $(BUILD_DIR)) From 701132259d843087fafb30d7a1feb05d1b4f7a8e Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 3 May 2013 15:13:12 -0700 Subject: [PATCH 15/28] + Documentation: new example: sharing data between 2 couchdb databases --- .../sources/examples/couchdb_data_volumes.rst | 53 +++++++++++++++++++ docs/sources/examples/index.rst | 1 + 2 files changed, 54 insertions(+) create mode 100644 docs/sources/examples/couchdb_data_volumes.rst diff --git a/docs/sources/examples/couchdb_data_volumes.rst b/docs/sources/examples/couchdb_data_volumes.rst new file mode 100644 index 0000000000..5b50c73e38 --- /dev/null +++ b/docs/sources/examples/couchdb_data_volumes.rst @@ -0,0 +1,53 @@ +:title: Sharing data between 2 couchdb databases +:description: Sharing data between 2 couchdb databases +:keywords: docker, example, package installation, networking, couchdb, data volumes + +.. _running_redis_service: + +Create a redis service +====================== + +.. include:: example_header.inc + +Here's an example of using data volumes to share the same data between 2 couchdb containers. +This could be used for hot upgrades, testing different versions of couchdb on the same data, etc. + +Create first database +--------------------- + +Note that we're marking /var/lib/couchdb as a data volume. + +.. code-block:: bash + + COUCH1=$(docker run -d -v /var/lib/couchdb shykes/couchdb:2013-05-03) + +Add data to the first database +------------------------------ + +We're assuming your docker host is reachable at `localhost`. If not, replace `localhost` with the public IP of your docker host. + +.. code-block:: bash + + HOST=localhost + URL="http://$HOST:$(docker port $COUCH1 5984)/_utils/" + echo "Navigate to $URL in your browser, and use the couch interface to add data" + +Create second database +---------------------- + +This time, we're requesting shared access to $COUCH1's volumes. + +.. code-block:: bash + + COUCH2=$(docker run -d -volumes-from $COUCH1) shykes/couchdb:2013-05-03) + +Browse data on the second database +---------------------------------- + +.. code-block:: bash + + 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!" + +Congratulations, you are running 2 Couchdb containers, completely isolated from each other *except* for their data. diff --git a/docs/sources/examples/index.rst b/docs/sources/examples/index.rst index 6a616ec8ff..7eb2ecbe94 100644 --- a/docs/sources/examples/index.rst +++ b/docs/sources/examples/index.rst @@ -18,3 +18,4 @@ Contents: python_web_app running_redis_service running_ssh_service + couchdb_data_volumes From 5ffd63070f9b4d7516d58a4b3691be36d5ae93c6 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 3 May 2013 15:19:20 -0700 Subject: [PATCH 16/28] Bumped version to 0.2.2 --- CHANGELOG.md | 7 +++++++ commands.go | 2 +- packaging/ubuntu/changelog | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72bf381fa8..847dbce535 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.2.2 (2012-05-03) + + Support for data volumes ('docker run -v=PATH') + + Share data volumes between containers ('docker run -volumes-from') + + Improved documentation + * Upgrade to Go 1.0.3 + * Various upgrades to the dev environment for contributors + ## 0.2.1 (2012-05-01) + 'docker commit -run' bundles a layer with default runtime options: command, ports etc. * Improve install process on Vagrant diff --git a/commands.go b/commands.go index 732fdcaaaa..95a6753b95 100644 --- a/commands.go +++ b/commands.go @@ -19,7 +19,7 @@ import ( "unicode" ) -const VERSION = "0.2.1" +const VERSION = "0.2.2" var ( GIT_COMMIT string diff --git a/packaging/ubuntu/changelog b/packaging/ubuntu/changelog index 88f6c5021e..49eabfbb32 100644 --- a/packaging/ubuntu/changelog +++ b/packaging/ubuntu/changelog @@ -1,3 +1,12 @@ +lxc-docker (0.2.2-1) precise; urgency=low + - Support for data volumes ('docker run -v=PATH') + - Share data volumes between containers ('docker run -volumes-from') + - Improved documentation + - Upgrade to Go 1.0.3 + - Various upgrades to the dev environment for contributors + + -- dotCloud Fri, 3 May 2013 00:00:00 -0700 + lxc-docker (0.2.1-1) precise; urgency=low From 6c1bb39c09446a608d48334fdf2b06cf0fac8d1a Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 3 May 2013 15:40:32 -0700 Subject: [PATCH 17/28] Fix date typos in changelog --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 847dbce535..93c3997608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,13 @@ # Changelog -## 0.2.2 (2012-05-03) +## 0.2.2 (2013-05-03) + Support for data volumes ('docker run -v=PATH') + Share data volumes between containers ('docker run -volumes-from') + Improved documentation * Upgrade to Go 1.0.3 * Various upgrades to the dev environment for contributors -## 0.2.1 (2012-05-01) +## 0.2.1 (2013-05-01) + 'docker commit -run' bundles a layer with default runtime options: command, ports etc. * Improve install process on Vagrant + New Dockerfile operation: "maintainer" @@ -17,7 +17,7 @@ + 'docker -d -r': restart crashed containers at daemon startup * Runtime: improve test coverage -## 0.2.0 (2012-04-23) +## 0.2.0 (2013-04-23) - Runtime: ghost containers can be killed and waited for * Documentation: update install intructions - Packaging: fix Vagrantfile From 1617a18258ccc7e07f30aef02a9b085627eb388a Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 2 May 2013 12:11:57 -0700 Subject: [PATCH 18/28] Fix typo for command run docs --- docs/sources/commandline/command/run.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/sources/commandline/command/run.rst b/docs/sources/commandline/command/run.rst index 7d394c0d9d..d5e571b41b 100644 --- a/docs/sources/commandline/command/run.rst +++ b/docs/sources/commandline/command/run.rst @@ -18,4 +18,5 @@ -t=false: Allocate a pseudo-tty -u="": Username or UID -d=[]: Set custom dns servers for the container - -v=[]: Creates a new volumes and mount it at the specified path. A container ID can be passed instead of a path in order to mount all volumes from the given container. + -v=[]: Creates a new volumes and mount it at the specified path. + -volumes-from="": Mount all volumes from the given container. From 83784989514ca010bf6c292b01482e0baa14ff85 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 2 May 2013 12:32:10 -0700 Subject: [PATCH 19/28] Fix issue within mergeConfig preventing hostname and user to be set --- runtime.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime.go b/runtime.go index 16c98117fd..7ad0c395e8 100644 --- a/runtime.go +++ b/runtime.go @@ -80,10 +80,10 @@ func (runtime *Runtime) containerRoot(id string) string { } func (runtime *Runtime) mergeConfig(userConf, imageConf *Config) { - if userConf.Hostname != "" { + if userConf.Hostname == "" { userConf.Hostname = imageConf.Hostname } - if userConf.User != "" { + if userConf.User == "" { userConf.User = imageConf.User } if userConf.Memory == 0 { From 4bc8ef42d4f294bf6fec6d728ef27abbb638b98d Mon Sep 17 00:00:00 2001 From: Harley Laue Date: Thu, 2 May 2013 14:44:41 -0500 Subject: [PATCH 20/28] strings.Split may return an empty string on no match * This fixes an index out of range crash if cgroup memory is not enabled. --- utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.go b/utils.go index 297b798af8..feee84077c 100644 --- a/utils.go +++ b/utils.go @@ -445,7 +445,7 @@ func FindCgroupMountpoint(cgroupType string) (string, error) { // cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0 for _, line := range strings.Split(string(output), "\n") { parts := strings.Split(line, " ") - if parts[2] == "cgroup" { + if len(parts) > 1 && parts[2] == "cgroup" { for _, opt := range strings.Split(parts[3], ",") { if opt == cgroupType { return parts[1], nil From 64d7bc442daa012683b38183c71674b9ecd660c2 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 2 May 2013 13:56:45 -0700 Subject: [PATCH 21/28] Fix server crash when running an image without command without autorun --- runtime.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.go b/runtime.go index 7ad0c395e8..b246f74a5c 100644 --- a/runtime.go +++ b/runtime.go @@ -127,7 +127,7 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) { runtime.mergeConfig(config, img.Config) } - if config.Cmd == nil { + if config.Cmd == nil || len(config.Cmd) < 2 { return nil, fmt.Errorf("No command specified") } From c08d245539ef4d721b874392097016a1c8c8fb81 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 2 May 2013 18:11:54 -0700 Subject: [PATCH 22/28] dockerbuilder: let the Makefile upload to s3 with 'make release' --- hack/dockerbuilder/dockerbuilder | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/hack/dockerbuilder/dockerbuilder b/hack/dockerbuilder/dockerbuilder index 500a82db9f..4287e0b336 100644 --- a/hack/dockerbuilder/dockerbuilder +++ b/hack/dockerbuilder/dockerbuilder @@ -15,12 +15,10 @@ export REVISION=$1 if [ -z "$AWS_ID" ]; then echo "Warning: environment variable AWS_ID is not set. Won't upload to S3." - NO_S3=1 fi if [ -z "$AWS_KEY" ]; then echo "Warning: environment variable AWS_KEY is not set. Won't upload to S3." - NO_S3=1 fi if [ -z "$GPG_KEY" ]; then @@ -28,28 +26,15 @@ if [ -z "$GPG_KEY" ]; then NO_UBUNTU=1 fi -if [ -z "$REVISION" ]; then - rm -fr docker-master - git clone https://github.com/dotcloud/docker docker-master - cd docker-master -else - rm -fr docker-$REVISION - git init docker-$REVISION - cd docker-$REVISION - git fetch -t https://github.com/dotcloud/docker $REVISION:$REVISION - git reset --hard FETCH_HEAD -fi - +rm -fr docker-release +git clone https://github.com/dotcloud/docker docker-release +cd docker-release if [ -z "$REVISION" ]; then make release else make release RELEASE_VERSION=$REVISION fi -if [ -z "$NO_S3" ]; then - s3cmd -P put docker-$REVISION.tgz s3://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-$REVISION.tgz -fi - if [ -z "$NO_UBUNTU" ]; then (cd packaging/ubuntu && make ubuntu) fi From a82b60b30dd9b07d6ea8cd96555a798900c17caa Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 2 May 2013 19:22:41 -0700 Subject: [PATCH 23/28] dockerbuilder: change order of dependencies --- hack/dockerbuilder/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hack/dockerbuilder/Dockerfile b/hack/dockerbuilder/Dockerfile index af8dce108c..98dde05f27 100644 --- a/hack/dockerbuilder/Dockerfile +++ b/hack/dockerbuilder/Dockerfile @@ -15,9 +15,9 @@ run DEBIAN_FRONTEND=noninteractive apt-get install -y -q build-essential # Packages required to build an ubuntu package run DEBIAN_FRONTEND=noninteractive apt-get install -y -q debhelper run DEBIAN_FRONTEND=noninteractive apt-get install -y -q autotools-dev +copy fake_initctl /usr/local/bin/initctl +run apt-get install -y -q devscripts add . /src run cp /src/dockerbuilder /usr/local/bin/ && chmod +x /usr/local/bin/dockerbuilder -run cp /src/fake_initctl /usr/local/bin/initctl && chmod +x /usr/local/bin/initctl run cp /src/s3cfg /.s3cfg -run DEBIAN_FRONTEND=noninteractive apt-get install -y -q devscripts cmd ["dockerbuilder"] From 6cbe27b7a53e5818d1f5e193db00a58e3165557f Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Thu, 2 May 2013 20:37:08 -0700 Subject: [PATCH 24/28] correct documentation for where images are stored on filesystem. --- docs/sources/concepts/buildingblocks.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/concepts/buildingblocks.rst b/docs/sources/concepts/buildingblocks.rst index d422e6eef3..154ef00f45 100644 --- a/docs/sources/concepts/buildingblocks.rst +++ b/docs/sources/concepts/buildingblocks.rst @@ -12,7 +12,7 @@ Images ------ An original container image. These are stored on disk and are comparable with what you normally expect from a stopped virtual machine image. Images are stored (and retrieved from) repository -Images are stored on your local file system under /var/lib/docker/images +Images are stored on your local file system under /var/lib/docker/graph .. _containers: From b9ec03c21b8fdbc54fdd7a3cb86f3c555e91f989 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 2 May 2013 20:50:28 -0700 Subject: [PATCH 25/28] Fix the command existance check --- runtime.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.go b/runtime.go index b246f74a5c..79a7170c7d 100644 --- a/runtime.go +++ b/runtime.go @@ -127,7 +127,7 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) { runtime.mergeConfig(config, img.Config) } - if config.Cmd == nil || len(config.Cmd) < 2 { + if config.Cmd == nil || len(config.Cmd) == 0 { return nil, fmt.Errorf("No command specified") } From 589d7c68dbfe0cf4a84b96b799871bfbff4a5970 Mon Sep 17 00:00:00 2001 From: Harley Laue Date: Fri, 3 May 2013 13:49:10 -0500 Subject: [PATCH 26/28] Check that the line is valid with 6 parts after split --- utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.go b/utils.go index feee84077c..4bdbd1253b 100644 --- a/utils.go +++ b/utils.go @@ -445,7 +445,7 @@ func FindCgroupMountpoint(cgroupType string) (string, error) { // cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0 for _, line := range strings.Split(string(output), "\n") { parts := strings.Split(line, " ") - if len(parts) > 1 && parts[2] == "cgroup" { + if len(parts) == 6 && parts[2] == "cgroup" { for _, opt := range strings.Split(parts[3], ",") { if opt == cgroupType { return parts[1], nil From a7c0e9a355216048063894a3d47aac2d81c42c3f Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 3 May 2013 12:58:44 -0700 Subject: [PATCH 27/28] Fix a bug in the Makefile which caused dependency download to fail --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f35362d2ca..bae7d64909 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ $(DOCKER_BIN): $(DOCKER_DIR) $(DOCKER_DIR): @mkdir -p $(dir $@) - @if [ -h $@ ]; then rm -f $@; ln -sf $(CURDIR)/ $@; fi + @if [ -h $@ ]; then rm -f $@; fi; ln -sf $(CURDIR)/ $@ @(cd $(DOCKER_MAIN); go get $(GO_OPTIONS)) whichrelease: From 04f41ebdbca8969a97cd5366fbf55e1a5d521ead Mon Sep 17 00:00:00 2001 From: Dr Nic Williams Date: Fri, 3 May 2013 15:35:51 -0700 Subject: [PATCH 28/28] Allow reuse of existing vagrant boxes by env variables Usage: BOX_NAME=precise64 vagrant up --- Vagrantfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index 95bd8c0f93..06e8b47a4c 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,8 +1,8 @@ # -*- mode: ruby -*- # vi: set ft=ruby : -BOX_NAME = "ubuntu" -BOX_URI = "http://files.vagrantup.com/precise64.box" +BOX_NAME = ENV['BOX_NAME'] || "ubuntu" +BOX_URI = ENV['BOX_URI'] || "http://files.vagrantup.com/precise64.box" PPA_KEY = "E61D797F63561DC6" Vagrant::Config.run do |config|