From 4bb19500892281d7c0ad47d2a826e4ec3b6d873a Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Tue, 11 Mar 2014 11:39:28 -0700 Subject: [PATCH 01/35] Remove goroutine leak upon error Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- execdriver/lxc/driver.go | 3 +++ server.go | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/execdriver/lxc/driver.go b/execdriver/lxc/driver.go index 765a52ee4..b398cb1a3 100644 --- a/execdriver/lxc/driver.go +++ b/execdriver/lxc/driver.go @@ -168,6 +168,9 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba // Poll lxc for RUNNING status pid, err := d.waitForStart(c, waitLock) if err != nil { + if c.Process != nil { + c.Process.Kill() + } return -1, err } c.ContainerPid = pid diff --git a/server.go b/server.go index 2c8a7ee4f..7fb70bacc 100644 --- a/server.go +++ b/server.go @@ -2390,7 +2390,13 @@ func (srv *Server) IsRunning() bool { } func (srv *Server) Close() error { + if srv == nil { + return nil + } srv.SetRunning(false) + if srv.runtime == nil { + return nil + } return srv.runtime.Close() } From 0225a379518fa292d5808fe1ef31947d0ce30577 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Tue, 11 Mar 2014 12:08:32 -0700 Subject: [PATCH 02/35] Update parseLxcInfo to comply with new lxc1.0 format Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- execdriver/lxc/info.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execdriver/lxc/info.go b/execdriver/lxc/info.go index 3b2ea0d07..27b4c5860 100644 --- a/execdriver/lxc/info.go +++ b/execdriver/lxc/info.go @@ -36,7 +36,7 @@ func parseLxcInfo(raw string) (*lxcInfo, error) { if len(parts) < 2 { continue } - switch strings.TrimSpace(parts[0]) { + switch strings.ToLower(strings.TrimSpace(parts[0])) { case "state": info.Running = strings.TrimSpace(parts[1]) == "RUNNING" case "pid": From 70ec7c6355ec2eefbd9d130381742881afa2a21b Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 11 Mar 2014 01:21:59 -0600 Subject: [PATCH 03/35] Fix init script cgroup mounting workarounds to be more similar to cgroupfs-mount and thus work properly Docker-DCO-1.1-Signed-off-by: Andrew Page (github: tianon) --- contrib/init/sysvinit-debian/docker | 34 ++++++++++++++++++++--------- contrib/init/upstart/docker.conf | 33 +++++++++++++++++++--------- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/contrib/init/sysvinit-debian/docker b/contrib/init/sysvinit-debian/docker index 510683a45..62e8f5f0a 100755 --- a/contrib/init/sysvinit-debian/docker +++ b/contrib/init/sysvinit-debian/docker @@ -50,20 +50,34 @@ fail_unless_root() { fi } +cgroupfs_mount() { + # see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount + if grep -v '^#' /etc/fstab | grep -q cgroup \ + || [ ! -e /proc/cgroups ] \ + || [ ! -d /sys/fs/cgroup ]; then + return + fi + if ! mountpoint -q /sys/fs/cgroup; then + mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup + fi + ( + cd /sys/fs/cgroup + for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do + mkdir -p $sys + if ! mountpoint -q $sys; then + if ! mount -n -t cgroup -o $sys cgroup $sys; then + rmdir $sys || true + fi + fi + done + ) +} + case "$1" in start) fail_unless_root - if ! grep -q cgroup /proc/mounts; then - # rough approximation of cgroupfs-mount - mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup - for sys in $(cut -d' ' -f1 /proc/cgroups); do - mkdir -p /sys/fs/cgroup/$sys - if ! mount -n -t cgroup -o $sys cgroup /sys/fs/cgroup/$sys 2>/dev/null; then - rmdir /sys/fs/cgroup/$sys 2>/dev/null || true - fi - done - fi + cgroupfs_mount touch /var/log/docker.log chgrp docker /var/log/docker.log diff --git a/contrib/init/upstart/docker.conf b/contrib/init/upstart/docker.conf index e2cc4536e..047f21c09 100644 --- a/contrib/init/upstart/docker.conf +++ b/contrib/init/upstart/docker.conf @@ -5,6 +5,29 @@ stop on runlevel [!2345] respawn +pre-start script + # see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount + if grep -v '^#' /etc/fstab | grep -q cgroup \ + || [ ! -e /proc/cgroups ] \ + || [ ! -d /sys/fs/cgroup ]; then + exit 0 + fi + if ! mountpoint -q /sys/fs/cgroup; then + mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup + fi + ( + cd /sys/fs/cgroup + for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do + mkdir -p $sys + if ! mountpoint -q $sys; then + if ! mount -n -t cgroup -o $sys cgroup $sys; then + rmdir $sys || true + fi + fi + done + ) +end script + script # modify these in /etc/default/$UPSTART_JOB (/etc/default/docker) DOCKER=/usr/bin/$UPSTART_JOB @@ -12,15 +35,5 @@ script if [ -f /etc/default/$UPSTART_JOB ]; then . /etc/default/$UPSTART_JOB fi - if ! grep -q cgroup /proc/mounts; then - # rough approximation of cgroupfs-mount - mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup - for sys in $(cut -d' ' -f1 /proc/cgroups); do - mkdir -p /sys/fs/cgroup/$sys - if ! mount -n -t cgroup -o $sys cgroup /sys/fs/cgroup/$sys 2>/dev/null; then - rmdir /sys/fs/cgroup/$sys 2>/dev/null || true - fi - done - fi "$DOCKER" -d $DOCKER_OPTS end script From 2741b82cf3c790adc4603376ec8187086de6f860 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 11 Mar 2014 01:40:31 -0600 Subject: [PATCH 04/35] Add variable for DOCKER_LOGFILE to sysvinit and use append instead of overwrite in opening the logfile Docker-DCO-1.1-Signed-off-by: Andrew Page (github: tianon) --- contrib/init/sysvinit-debian/docker | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contrib/init/sysvinit-debian/docker b/contrib/init/sysvinit-debian/docker index 62e8f5f0a..67f0d2807 100755 --- a/contrib/init/sysvinit-debian/docker +++ b/contrib/init/sysvinit-debian/docker @@ -21,6 +21,7 @@ BASE=$(basename $0) # modify these in /etc/default/$BASE (/etc/default/docker) DOCKER=/usr/bin/$BASE DOCKER_PIDFILE=/var/run/$BASE.pid +DOCKER_LOGFILE=/var/log/$BASE.log DOCKER_OPTS= DOCKER_DESC="Docker" @@ -79,8 +80,8 @@ case "$1" in cgroupfs_mount - touch /var/log/docker.log - chgrp docker /var/log/docker.log + touch "$DOCKER_LOGFILE" + chgrp docker "$DOCKER_LOGFILE" log_begin_msg "Starting $DOCKER_DESC: $BASE" start-stop-daemon --start --background \ @@ -90,7 +91,7 @@ case "$1" in -- \ -d -p "$DOCKER_PIDFILE" \ $DOCKER_OPTS \ - > /var/log/docker.log 2>&1 + >> "$DOCKER_LOGFILE" 2>&1 log_end_msg $? ;; From d70e20cddd99de9310d902fd5755633222ff74fc Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 6 Mar 2014 18:14:56 +0100 Subject: [PATCH 05/35] devmapper: Add per-device lock We currently use a global lock to protect global data (like the Devices map) as well as device data itself and access to (non-threadsafe) libdevmapper. This commit also adds a per-device lock, which will allow per-device operations to temporarily release the global lock while e.g. waiting. The per-device lock will make sure that nothing else accesses that device while we're operating on it. Docker-DCO-1.1-Signed-off-by: Alexander Larsson (github: alexlarsson) --- graphdriver/devmapper/deviceset.go | 39 +++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/graphdriver/devmapper/deviceset.go b/graphdriver/devmapper/deviceset.go index 303e363e9..f1a0e47d0 100644 --- a/graphdriver/devmapper/deviceset.go +++ b/graphdriver/devmapper/deviceset.go @@ -39,6 +39,13 @@ type DevInfo struct { // first get (since we need to mount to set up the device // a bit first). floating bool `json:"-"` + + // The global DeviceSet lock guarantees that we serialize all + // the calls to libdevmapper (which is not threadsafe), but we + // sometimes release that lock while sleeping. In that case + // this per-device lock is still held, protecting against + // other accesses to the device that we're doing the wait on. + lock sync.Mutex `json:"-"` } type MetaData struct { @@ -47,7 +54,7 @@ type MetaData struct { type DeviceSet struct { MetaData - sync.Mutex + sync.Mutex // Protects Devices map and serializes calls into libdevmapper root string devicePrefix string TransactionId uint64 @@ -569,6 +576,9 @@ func (devices *DeviceSet) AddDevice(hash, baseHash string) error { return fmt.Errorf("Error adding device for '%s': can't find device for parent '%s'", hash, baseHash) } + baseInfo.lock.Lock() + defer baseInfo.lock.Unlock() + deviceId := devices.allocateDeviceId() if err := devices.createSnapDevice(devices.getPoolDevName(), deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil { @@ -636,6 +646,14 @@ func (devices *DeviceSet) DeleteDevice(hash string) error { devices.Lock() defer devices.Unlock() + info := devices.Devices[hash] + if info == nil { + return fmt.Errorf("Unknown device %s", hash) + } + + info.lock.Lock() + defer info.lock.Unlock() + return devices.deleteDevice(hash) } @@ -773,20 +791,26 @@ func (devices *DeviceSet) Shutdown() error { defer utils.Debugf("[deviceset %s] shutdown END", devices.devicePrefix) for _, info := range devices.Devices { + info.lock.Lock() if info.mountCount > 0 { if err := sysUnmount(info.mountPath, 0); err != nil { utils.Debugf("Shutdown unmounting %s, error: %s\n", info.mountPath, err) } } + info.lock.Unlock() } for _, d := range devices.Devices { + d.lock.Lock() + if err := devices.waitClose(d.Hash); err != nil { utils.Errorf("Warning: error waiting for device %s to unmount: %s\n", d.Hash, err) } if err := devices.deactivateDevice(d.Hash); err != nil { utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err) } + + d.lock.Unlock() } if err := devices.deactivatePool(); err != nil { @@ -805,6 +829,9 @@ func (devices *DeviceSet) MountDevice(hash, path string) error { return fmt.Errorf("Unknown device %s", hash) } + info.lock.Lock() + defer info.lock.Unlock() + if info.mountCount > 0 { if path != info.mountPath { return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path) @@ -851,6 +878,9 @@ func (devices *DeviceSet) UnmountDevice(hash string, mode UnmountMode) error { return fmt.Errorf("UnmountDevice: no such device %s\n", hash) } + info.lock.Lock() + defer info.lock.Unlock() + if mode == UnmountFloat { if info.floating { return fmt.Errorf("UnmountDevice: can't float floating reference %s\n", hash) @@ -920,6 +950,10 @@ func (devices *DeviceSet) HasActivatedDevice(hash string) bool { if info == nil { return false } + + info.lock.Lock() + defer info.lock.Unlock() + devinfo, _ := getInfo(info.Name()) return devinfo != nil && devinfo.Exists != 0 } @@ -974,6 +1008,9 @@ func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) { return nil, fmt.Errorf("No device %s", hash) } + info.lock.Lock() + defer info.lock.Unlock() + status := &DevStatus{ DeviceId: info.DeviceId, Size: info.Size, From 39dbaa08dc3745cf02892ee32e3d9736b53a2aa5 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 6 Mar 2014 18:25:43 +0100 Subject: [PATCH 06/35] devmapper: Increase sleep times and unlock while sleeping We've seen some cases in the wild where waiting for unmount/deactivate of devmapper devices taking a long time (several seconds). So, we increase the sleeps to 10 seconds before we timeout. For instance: https://github.com/dotcloud/docker/issues/4389 But, in order to not keep other processes blocked we unlock the global dm lock while waiting to allow other devices to continue working. Docker-DCO-1.1-Signed-off-by: Alexander Larsson (github: alexlarsson) --- graphdriver/devmapper/deviceset.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/graphdriver/devmapper/deviceset.go b/graphdriver/devmapper/deviceset.go index f1a0e47d0..f6b26655a 100644 --- a/graphdriver/devmapper/deviceset.go +++ b/graphdriver/devmapper/deviceset.go @@ -701,7 +701,7 @@ func (devices *DeviceSet) deactivateDevice(hash string) error { func (devices *DeviceSet) removeDeviceAndWait(devname string) error { var err error - for i := 0; i < 10; i++ { + for i := 0; i < 1000; i++ { devices.sawBusy = false err = removeDevice(devname) if err == nil { @@ -713,7 +713,9 @@ func (devices *DeviceSet) removeDeviceAndWait(devname string) error { // If we see EBUSY it may be a transient error, // sleep a bit a retry a few times. - time.Sleep(5 * time.Millisecond) + devices.Unlock() + time.Sleep(10 * time.Millisecond) + devices.Lock() } if err != nil { return err @@ -746,7 +748,9 @@ func (devices *DeviceSet) waitRemove(devname string) error { break } - time.Sleep(1 * time.Millisecond) + devices.Unlock() + time.Sleep(10 * time.Millisecond) + devices.Lock() } if i == 1000 { return fmt.Errorf("Timeout while waiting for device %s to be removed", devname) From 6ce9daea0e3456ef95ff710dd5232fa682f5039a Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Tue, 11 Mar 2014 17:10:05 -0700 Subject: [PATCH 07/35] Fix attach exit on darwin Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- api/client.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/api/client.go b/api/client.go index 10075ae61..da05bb1d5 100644 --- a/api/client.go +++ b/api/client.go @@ -28,7 +28,7 @@ import ( "path" "reflect" "regexp" - "runtime" + goruntime "runtime" "strconv" "strings" "syscall" @@ -367,7 +367,7 @@ func (cli *DockerCli) CmdVersion(args ...string) error { if dockerversion.VERSION != "" { fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION) } - fmt.Fprintf(cli.out, "Go version (client): %s\n", runtime.Version()) + fmt.Fprintf(cli.out, "Go version (client): %s\n", goruntime.Version()) if dockerversion.GITCOMMIT != "" { fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT) } @@ -2239,7 +2239,12 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea if setRawTerminal && cli.isTerminal { term.RestoreTerminal(cli.terminalFd, oldState) } - in.Close() + // For some reason this Close call blocks on darwin.. + // As the client exists right after, simply discard the close + // until we find a better solution. + if goruntime.GOOS != "darwin" { + in.Close() + } } }() From 463cf287885060ed40441ae039901c460c36002b Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Wed, 12 Mar 2014 00:51:46 +0000 Subject: [PATCH 08/35] improve deprecation message Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- pkg/mflag/example/example.go | 3 ++- pkg/mflag/flag.go | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pkg/mflag/example/example.go b/pkg/mflag/example/example.go index ed940e8d7..ce9dd30e4 100644 --- a/pkg/mflag/example/example.go +++ b/pkg/mflag/example/example.go @@ -13,7 +13,8 @@ var ( func init() { flag.Bool([]string{"#hp", "#-halp"}, false, "display the halp") - flag.BoolVar(&b, []string{"b"}, false, "a simple bool") + flag.BoolVar(&b, []string{"b", "#bal", "#bol", "-bal"}, false, "a simple bool") + flag.BoolVar(&b, []string{"g", "#gil"}, false, "a simple bool") flag.BoolVar(&b2, []string{"#-bool"}, false, "a simple bool") flag.IntVar(&i, []string{"-integer", "-number"}, -1, "a simple integer") flag.StringVar(&str, []string{"s", "#hidden", "-string"}, "", "a simple string") //-s -hidden and --string will work, but -hidden won't be in the usage diff --git a/pkg/mflag/flag.go b/pkg/mflag/flag.go index 7125c030e..581041065 100644 --- a/pkg/mflag/flag.go +++ b/pkg/mflag/flag.go @@ -805,9 +805,20 @@ func (f *FlagSet) parseOne() (bool, string, error) { f.actual = make(map[string]*Flag) } f.actual[name] = flag - for _, n := range flag.Names { + for i, n := range flag.Names { if n == fmt.Sprintf("#%s", name) { - fmt.Fprintf(f.out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name) + replacement := "" + for j := i; j < len(flag.Names); j++ { + if flag.Names[j][0] != '#' { + replacement = flag.Names[j] + break + } + } + if replacement != "" { + fmt.Fprintf(f.out(), "Warning: '-%s' is deprecated, it will be replaced by '-%s' soon. See usage.\n", name, replacement) + } else { + fmt.Fprintf(f.out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name) + } } } return true, "", nil From d8448f27c69dbef6f03652cd63b07049a64f7bc1 Mon Sep 17 00:00:00 2001 From: unclejack Date: Wed, 12 Mar 2014 17:58:53 +0200 Subject: [PATCH 09/35] don't leave empty cidFile behind This makes `--cidfile` clean up empty container ID files. These are left behind when creating the container fails. Docker-DCO-1.1-Signed-off-by: Cristian Staretu (github: unclejack) --- api/client.go | 16 +++++++++++++++- integration/commands_test.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/api/client.go b/api/client.go index da05bb1d5..5f0633405 100644 --- a/api/client.go +++ b/api/client.go @@ -1753,7 +1753,21 @@ func (cli *DockerCli) CmdRun(args ...string) error { if containerIDFile, err = os.Create(hostConfig.ContainerIDFile); err != nil { return fmt.Errorf("Failed to create the container ID file: %s", err) } - defer containerIDFile.Close() + defer func() { + containerIDFile.Close() + var ( + cidFileInfo os.FileInfo + err error + ) + if cidFileInfo, err = os.Stat(hostConfig.ContainerIDFile); err != nil { + return + } + if cidFileInfo.Size() == 0 { + if err := os.Remove(hostConfig.ContainerIDFile); err != nil { + fmt.Printf("failed to remove CID file '%s': %s \n", hostConfig.ContainerIDFile, err) + } + } + }() } containerValues := url.Values{} diff --git a/integration/commands_test.go b/integration/commands_test.go index 9f7a41384..f254973b4 100644 --- a/integration/commands_test.go +++ b/integration/commands_test.go @@ -930,7 +930,7 @@ run [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ] // #2098 - Docker cidFiles only contain short version of the containerId //sudo docker run --cidfile /tmp/docker_test.cid ubuntu echo "test" // TestRunCidFile tests that run --cidfile returns the longid -func TestRunCidFile(t *testing.T) { +func TestRunCidFileCheckIDLength(t *testing.T) { stdout, stdoutPipe := io.Pipe() tmpDir, err := ioutil.TempDir("", "TestRunCidFile") @@ -979,6 +979,35 @@ func TestRunCidFile(t *testing.T) { } +// Ensure that CIDFile gets deleted if it's empty +// Perform this test by making `docker run` fail +func TestRunCidFileCleanupIfEmpty(t *testing.T) { + tmpDir, err := ioutil.TempDir("", "TestRunCidFile") + if err != nil { + t.Fatal(err) + } + tmpCidFile := path.Join(tmpDir, "cid") + + cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr) + defer cleanup(globalEngine, t) + + c := make(chan struct{}) + go func() { + defer close(c) + if err := cli.CmdRun("--cidfile", tmpCidFile, unitTestImageID); err == nil { + t.Fatal("running without a command should haveve failed") + } + if _, err := os.Stat(tmpCidFile); err == nil { + t.Fatalf("empty CIDFile '%s' should've been deleted", tmpCidFile) + } + }() + defer os.RemoveAll(tmpDir) + + setTimeout(t, "CmdRun timed out", 5*time.Second, func() { + <-c + }) +} + func TestContainerOrphaning(t *testing.T) { // setup a temporary directory From ab5b715964c34321bcbd70a41fefcefdcf1ead64 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 12 Mar 2014 11:13:24 -0700 Subject: [PATCH 10/35] Fix issue when /etc/apparmor.d does not exists Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- pkg/libcontainer/apparmor/setup.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/libcontainer/apparmor/setup.go b/pkg/libcontainer/apparmor/setup.go index e07759cc6..4e1c95143 100644 --- a/pkg/libcontainer/apparmor/setup.go +++ b/pkg/libcontainer/apparmor/setup.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "os/exec" + "path" ) const DefaultProfilePath = "/etc/apparmor.d/docker" @@ -85,6 +86,11 @@ func InstallDefaultProfile() error { return nil } + // Make sure /etc/apparmor.d exists + if err := os.MkdirAll(path.Dir(DefaultProfilePath), 0755); err != nil { + return err + } + if err := ioutil.WriteFile(DefaultProfilePath, []byte(DefaultProfile), 0644); err != nil { return err } From 78d66068a5d260bbfeadf2c21e74ad35383222c5 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Thu, 13 Mar 2014 14:31:09 -0700 Subject: [PATCH 11/35] Always symlink /dev/ptmx for libcontainer Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- pkg/libcontainer/nsinit/mount.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/libcontainer/nsinit/mount.go b/pkg/libcontainer/nsinit/mount.go index 83577cfa8..072188ecd 100644 --- a/pkg/libcontainer/nsinit/mount.go +++ b/pkg/libcontainer/nsinit/mount.go @@ -46,10 +46,8 @@ func setupNewMountNamespace(rootfs, console string, readonly, noPivotRoot bool) if err := setupDev(rootfs); err != nil { return err } - if console != "" { - if err := setupPtmx(rootfs, console); err != nil { - return err - } + if err := setupPtmx(rootfs, console); err != nil { + return err } if err := system.Chdir(rootfs); err != nil { return fmt.Errorf("chdir into %s %s", rootfs, err) @@ -245,8 +243,10 @@ func setupPtmx(rootfs, console string) error { if err := os.Symlink("pts/ptmx", ptmx); err != nil { return fmt.Errorf("symlink dev ptmx %s", err) } - if err := setupConsole(rootfs, console); err != nil { - return err + if console != "" { + if err := setupConsole(rootfs, console); err != nil { + return err + } } return nil } From 7c35bfd78e168e9027ec88bf6af7f550e76950bc Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Thu, 13 Mar 2014 22:26:42 +0000 Subject: [PATCH 12/35] as you could have multiple messages per line with streams, don't \r Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- utils/jsonmessage.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/jsonmessage.go b/utils/jsonmessage.go index 9050dda74..f84cc42c7 100644 --- a/utils/jsonmessage.go +++ b/utils/jsonmessage.go @@ -85,7 +85,7 @@ func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error { return jm.Error } var endl string - if isTerminal { + if isTerminal && jm.Stream == "" { // [2K = erase entire current line fmt.Fprintf(out, "%c[2K\r", 27) endl = "\r" From bcab23bbdc1a88c6255ef6e5211696cd6ef981cb Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 13 Mar 2014 16:19:28 -0700 Subject: [PATCH 13/35] Have the exec driver and kernel version in non-debug mode in `docker info` Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- api/client.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/api/client.go b/api/client.go index 5f0633405..d49915ff0 100644 --- a/api/client.go +++ b/api/client.go @@ -432,7 +432,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error { fmt.Fprintf(cli.out, "Containers: %d\n", remoteInfo.GetInt("Containers")) fmt.Fprintf(cli.out, "Images: %d\n", remoteInfo.GetInt("Images")) - fmt.Fprintf(cli.out, "Driver: %s\n", remoteInfo.Get("Driver")) + fmt.Fprintf(cli.out, "Storage Driver: %s\n", remoteInfo.Get("Driver")) var driverStatus [][2]string if err := remoteInfo.GetJson("DriverStatus", &driverStatus); err != nil { return err @@ -440,14 +440,15 @@ func (cli *DockerCli) CmdInfo(args ...string) error { for _, pair := range driverStatus { fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1]) } + fmt.Fprintf(cli.out, "Execution Driver: %s\n", remoteInfo.Get("ExecutionDriver")) + fmt.Fprintf(cli.out, "Kernel Version: %s\n", remoteInfo.Get("KernelVersion")) + if remoteInfo.GetBool("Debug") || os.Getenv("DEBUG") != "" { fmt.Fprintf(cli.out, "Debug mode (server): %v\n", remoteInfo.GetBool("Debug")) fmt.Fprintf(cli.out, "Debug mode (client): %v\n", os.Getenv("DEBUG") != "") fmt.Fprintf(cli.out, "Fds: %d\n", remoteInfo.GetInt("NFd")) fmt.Fprintf(cli.out, "Goroutines: %d\n", remoteInfo.GetInt("NGoroutines")) - fmt.Fprintf(cli.out, "Execution Driver: %s\n", remoteInfo.Get("ExecutionDriver")) fmt.Fprintf(cli.out, "EventsListeners: %d\n", remoteInfo.GetInt("NEventsListener")) - fmt.Fprintf(cli.out, "Kernel Version: %s\n", remoteInfo.Get("KernelVersion")) if initSha1 := remoteInfo.Get("InitSha1"); initSha1 != "" { fmt.Fprintf(cli.out, "Init SHA1: %s\n", initSha1) From b9a0e886fc39aca1b40af77ec9f0b6e7d748e44a Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Fri, 14 Mar 2014 11:42:01 -0700 Subject: [PATCH 14/35] Send sigterm to child instead of sigkill Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- pkg/libcontainer/nsinit/init.go | 4 +++- pkg/system/calls_linux.go | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/libcontainer/nsinit/init.go b/pkg/libcontainer/nsinit/init.go index 336fc1eaa..a51560c40 100644 --- a/pkg/libcontainer/nsinit/init.go +++ b/pkg/libcontainer/nsinit/init.go @@ -48,7 +48,9 @@ func (ns *linuxNs) Init(container *libcontainer.Container, uncleanRootfs, consol return fmt.Errorf("setctty %s", err) } } - if err := system.ParentDeathSignal(); err != nil { + // this is our best effort to let the process know that the parent has died and that it + // should it should act on it how it sees fit + if err := system.ParentDeathSignal(uintptr(syscall.SIGTERM)); err != nil { return fmt.Errorf("parent death signal %s", err) } if err := setupNewMountNamespace(rootfs, console, container.ReadonlyFs, container.NoPivotRoot); err != nil { diff --git a/pkg/system/calls_linux.go b/pkg/system/calls_linux.go index bf667c535..43c00ed55 100644 --- a/pkg/system/calls_linux.go +++ b/pkg/system/calls_linux.go @@ -115,8 +115,8 @@ func Mknod(path string, mode uint32, dev int) error { return syscall.Mknod(path, mode, dev) } -func ParentDeathSignal() error { - if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, uintptr(syscall.SIGKILL), 0); err != 0 { +func ParentDeathSignal(sig uintptr) error { + if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, sig, 0); err != 0 { return err } return nil From f020f1d31ef1e520fb4f73aab607f888477dbb18 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sat, 15 Mar 2014 23:04:36 +0100 Subject: [PATCH 15/35] Add failing test case for issue #4681 Add a failing test case for an issue where docker is not creating a loopback device if networking is dissabled. Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) --- integration/container_test.go | 69 ++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/integration/container_test.go b/integration/container_test.go index 4efb95a2a..980fb4419 100644 --- a/integration/container_test.go +++ b/integration/container_test.go @@ -434,28 +434,6 @@ func TestOutput(t *testing.T) { } } -func TestContainerNetwork(t *testing.T) { - runtime := mkRuntime(t) - defer nuke(runtime) - container, _, err := runtime.Create( - &runconfig.Config{ - Image: GetTestImage(runtime).ID, - Cmd: []string{"ping", "-c", "1", "127.0.0.1"}, - }, - "", - ) - if err != nil { - t.Fatal(err) - } - defer runtime.Destroy(container) - if err := container.Run(); err != nil { - t.Fatal(err) - } - if code := container.State.GetExitCode(); code != 0 { - t.Fatalf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", code) - } -} - func TestKillDifferentUser(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) @@ -1523,6 +1501,53 @@ func TestVolumesFromWithVolumes(t *testing.T) { } } +func TestContainerNetwork(t *testing.T) { + runtime := mkRuntime(t) + defer nuke(runtime) + container, _, err := runtime.Create( + &runconfig.Config{ + Image: GetTestImage(runtime).ID, + // If I change this to ping 8.8.8.8 it fails. Any idea why? - timthelion + Cmd: []string{"ping", "-c", "1", "127.0.0.1"}, + }, + "", + ) + if err != nil { + t.Fatal(err) + } + defer runtime.Destroy(container) + if err := container.Run(); err != nil { + t.Fatal(err) + } + if code := container.State.GetExitCode(); code != 0 { + t.Fatalf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", code) + } +} + +// Issue #4681 +func TestLoopbackFunctionsWhenNetworkingIsDissabled(t *testing.T) { + runtime := mkRuntime(t) + defer nuke(runtime) + container, _, err := runtime.Create( + &runconfig.Config{ + Image: GetTestImage(runtime).ID, + Cmd: []string{"ping", "-c", "1", "127.0.0.1"}, + NetworkDisabled: true, + }, + "", + ) + if err != nil { + t.Fatal(err) + } + defer runtime.Destroy(container) + if err := container.Run(); err != nil { + t.Fatal(err) + } + if code := container.State.GetExitCode(); code != 0 { + t.Fatalf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", code) + } +} + func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) { eng := NewTestEngine(t) runtime := mkRuntimeFromEngine(eng, t) From 899f06bf798cb5c6f8244645a7d952837ce8a9c1 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sun, 16 Mar 2014 01:01:31 +0100 Subject: [PATCH 16/35] Fix issue #4681 - No loopback interface within container when networking is disabled. Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) Remove loopback code from veth strategy Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) Looback strategy: Get rid of uneeded code in Create Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) Use append when building network strategy list Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) Swap loopback and veth strategies in Networks list Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) Revert "Swap loopback and veth strategies in Networks list" This reverts commit 3b8b2c8454171d79bed5e9a80165172617e92fc7. Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) When initializing networks, only return from the loop if there is an error Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) --- execdriver/native/default_template.go | 35 +++++++++++++++++++-------- pkg/libcontainer/network/loopback.go | 24 ++++++++++++++++++ pkg/libcontainer/network/strategy.go | 3 ++- pkg/libcontainer/network/veth.go | 6 ----- pkg/libcontainer/nsinit/init.go | 6 ++++- 5 files changed, 56 insertions(+), 18 deletions(-) create mode 100644 pkg/libcontainer/network/loopback.go diff --git a/execdriver/native/default_template.go b/execdriver/native/default_template.go index 6e7d597b7..9c5def25b 100644 --- a/execdriver/native/default_template.go +++ b/execdriver/native/default_template.go @@ -19,19 +19,34 @@ func createContainer(c *execdriver.Command) *libcontainer.Container { container.WorkingDir = c.WorkingDir container.Env = c.Env + loopbackNetwork := libcontainer.Network{ + // Using constants here because + // when networking is disabled + // These settings simply don't exist: + // https://github.com/dotcloud/docker/blob/c7ea6e5da80af3d9ba7558f876efbf0801d988d8/runtime/container.go#L367 + Mtu: 1500, + Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0), + Gateway: "localhost", + Type: "loopback", + Context: libcontainer.Context{}, + } + + container.Networks = []*libcontainer.Network{ + &loopbackNetwork, + } + if c.Network != nil { - container.Networks = []*libcontainer.Network{ - { - Mtu: c.Network.Mtu, - Address: fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen), - Gateway: c.Network.Gateway, - Type: "veth", - Context: libcontainer.Context{ - "prefix": "veth", - "bridge": c.Network.Bridge, - }, + vethNetwork := libcontainer.Network{ + Mtu: c.Network.Mtu, + Address: fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen), + Gateway: c.Network.Gateway, + Type: "veth", + Context: libcontainer.Context{ + "prefix": "veth", + "bridge": c.Network.Bridge, }, } + container.Networks = append(container.Networks, &vethNetwork) } container.Cgroups.Name = c.ID diff --git a/pkg/libcontainer/network/loopback.go b/pkg/libcontainer/network/loopback.go new file mode 100644 index 000000000..6215061dc --- /dev/null +++ b/pkg/libcontainer/network/loopback.go @@ -0,0 +1,24 @@ +package network + +import ( + "fmt" + "github.com/dotcloud/docker/pkg/libcontainer" +) + +// Loopback is a network strategy that provides a basic loopback device +type Loopback struct { +} + +func (l *Loopback) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error { + return nil +} + +func (l *Loopback) Initialize(config *libcontainer.Network, context libcontainer.Context) error { + if err := SetMtu("lo", config.Mtu); err != nil { + return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err) + } + if err := InterfaceUp("lo"); err != nil { + return fmt.Errorf("lo up %s", err) + } + return nil +} diff --git a/pkg/libcontainer/network/strategy.go b/pkg/libcontainer/network/strategy.go index 234fcc0aa..693790d28 100644 --- a/pkg/libcontainer/network/strategy.go +++ b/pkg/libcontainer/network/strategy.go @@ -10,7 +10,8 @@ var ( ) var strategies = map[string]NetworkStrategy{ - "veth": &Veth{}, + "veth": &Veth{}, + "loopback": &Loopback{}, } // NetworkStrategy represents a specific network configuration for diff --git a/pkg/libcontainer/network/veth.go b/pkg/libcontainer/network/veth.go index 3ab1b2393..3df0cd61e 100644 --- a/pkg/libcontainer/network/veth.go +++ b/pkg/libcontainer/network/veth.go @@ -68,12 +68,6 @@ func (v *Veth) Initialize(config *libcontainer.Network, context libcontainer.Con if err := InterfaceUp("eth0"); err != nil { return fmt.Errorf("eth0 up %s", err) } - if err := SetMtu("lo", config.Mtu); err != nil { - return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err) - } - if err := InterfaceUp("lo"); err != nil { - return fmt.Errorf("lo up %s", err) - } if config.Gateway != "" { if err := SetDefaultGateway(config.Gateway); err != nil { return fmt.Errorf("set gateway to %s %s", config.Gateway, err) diff --git a/pkg/libcontainer/nsinit/init.go b/pkg/libcontainer/nsinit/init.go index a51560c40..09f85e214 100644 --- a/pkg/libcontainer/nsinit/init.go +++ b/pkg/libcontainer/nsinit/init.go @@ -126,7 +126,11 @@ func setupNetwork(container *libcontainer.Container, context libcontainer.Contex if err != nil { return err } - return strategy.Initialize(config, context) + + err1 := strategy.Initialize(config, context) + if err1 != nil { + return err1 + } } return nil } From d1f7ebda1695b6e9c2e920e4dd8ae275d8e4545d Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Sun, 16 Mar 2014 20:52:27 +0100 Subject: [PATCH 17/35] Refactor out interface specific information from execdriver.Network Docker-DCO-1.1-Signed-off-by: Timothy Hobbs (github: https://github.com/timthelion) --- container.go | 8 ++++++-- execdriver/driver.go | 10 +++++++--- execdriver/lxc/driver.go | 10 ++++++---- execdriver/lxc/lxc_template.go | 6 +++--- execdriver/lxc/lxc_template_unit_test.go | 8 ++++++++ execdriver/native/default_template.go | 14 +++++--------- 6 files changed, 35 insertions(+), 21 deletions(-) diff --git a/container.go b/container.go index 50332f27d..d48b7da82 100644 --- a/container.go +++ b/container.go @@ -363,14 +363,18 @@ func populateCommand(c *Container) { driverConfig []string ) + en = &execdriver.Network{ + Mtu: c.runtime.config.Mtu, + Interface: nil, + } + if !c.Config.NetworkDisabled { network := c.NetworkSettings - en = &execdriver.Network{ + en.Interface = &execdriver.NetworkInterface{ Gateway: network.Gateway, Bridge: network.Bridge, IPAddress: network.IPAddress, IPPrefixLen: network.IPPrefixLen, - Mtu: c.runtime.config.Mtu, } } diff --git a/execdriver/driver.go b/execdriver/driver.go index ec8f48f52..bb7aad272 100644 --- a/execdriver/driver.go +++ b/execdriver/driver.go @@ -84,11 +84,15 @@ type Driver interface { // Network settings of the container type Network struct { + Interface *NetworkInterface `json:"interface"` // if interface is nil then networking is disabled + Mtu int `json:"mtu"` +} + +type NetworkInterface struct { Gateway string `json:"gateway"` IPAddress string `json:"ip"` Bridge string `json:"bridge"` IPPrefixLen int `json:"ip_prefix_len"` - Mtu int `json:"mtu"` } type Resources struct { @@ -111,8 +115,8 @@ type Command struct { WorkingDir string `json:"working_dir"` ConfigPath string `json:"config_path"` // this should be able to be removed when the lxc template is moved into the driver Tty bool `json:"tty"` - Network *Network `json:"network"` // if network is nil then networking is disabled - Config []string `json:"config"` // generic values that specific drivers can consume + Network *Network `json:"network"` + Config []string `json:"config"` // generic values that specific drivers can consume Resources *Resources `json:"resources"` Terminal Terminal `json:"-"` // standard or tty terminal diff --git a/execdriver/lxc/driver.go b/execdriver/lxc/driver.go index b398cb1a3..f24b3b51b 100644 --- a/execdriver/lxc/driver.go +++ b/execdriver/lxc/driver.go @@ -94,13 +94,15 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba DriverName, } - if c.Network != nil { + if c.Network.Interface != nil { params = append(params, - "-g", c.Network.Gateway, - "-i", fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen), - "-mtu", strconv.Itoa(c.Network.Mtu), + "-g", c.Network.Interface.Gateway, + "-i", fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen), ) } + params = append(params, + "-mtu", strconv.Itoa(c.Network.Mtu), + ) if c.User != "" { params = append(params, "-u", c.User) diff --git a/execdriver/lxc/lxc_template.go b/execdriver/lxc/lxc_template.go index 1181396a1..03d01e893 100644 --- a/execdriver/lxc/lxc_template.go +++ b/execdriver/lxc/lxc_template.go @@ -7,17 +7,17 @@ import ( ) const LxcTemplate = ` -{{if .Network}} +{{if .Network.Interface}} # network configuration lxc.network.type = veth -lxc.network.link = {{.Network.Bridge}} +lxc.network.link = {{.Network.Interface.Bridge}} lxc.network.name = eth0 -lxc.network.mtu = {{.Network.Mtu}} {{else}} # network is disabled (-n=false) lxc.network.type = empty lxc.network.flags = up {{end}} +lxc.network.mtu = {{.Network.Mtu}} # root filesystem {{$ROOTFS := .Rootfs}} diff --git a/execdriver/lxc/lxc_template_unit_test.go b/execdriver/lxc/lxc_template_unit_test.go index 99d6e636f..6fea86d29 100644 --- a/execdriver/lxc/lxc_template_unit_test.go +++ b/execdriver/lxc/lxc_template_unit_test.go @@ -43,6 +43,10 @@ func TestLXCConfig(t *testing.T) { Memory: int64(mem), CpuShares: int64(cpu), }, + Network: &execdriver.Network{ + Mtu: 1500, + Interface: nil, + }, } p, err := driver.generateLXCConfig(command) if err != nil { @@ -75,6 +79,10 @@ func TestCustomLxcConfig(t *testing.T) { "lxc.utsname = docker", "lxc.cgroup.cpuset.cpus = 0,1", }, + Network: &execdriver.Network{ + Mtu: 1500, + Interface: nil, + }, } p, err := driver.generateLXCConfig(command) diff --git a/execdriver/native/default_template.go b/execdriver/native/default_template.go index 9c5def25b..62d804016 100644 --- a/execdriver/native/default_template.go +++ b/execdriver/native/default_template.go @@ -20,11 +20,7 @@ func createContainer(c *execdriver.Command) *libcontainer.Container { container.Env = c.Env loopbackNetwork := libcontainer.Network{ - // Using constants here because - // when networking is disabled - // These settings simply don't exist: - // https://github.com/dotcloud/docker/blob/c7ea6e5da80af3d9ba7558f876efbf0801d988d8/runtime/container.go#L367 - Mtu: 1500, + Mtu: c.Network.Mtu, Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0), Gateway: "localhost", Type: "loopback", @@ -35,15 +31,15 @@ func createContainer(c *execdriver.Command) *libcontainer.Container { &loopbackNetwork, } - if c.Network != nil { + if c.Network.Interface != nil { vethNetwork := libcontainer.Network{ Mtu: c.Network.Mtu, - Address: fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen), - Gateway: c.Network.Gateway, + Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen), + Gateway: c.Network.Interface.Gateway, Type: "veth", Context: libcontainer.Context{ "prefix": "veth", - "bridge": c.Network.Bridge, + "bridge": c.Network.Interface.Bridge, }, } container.Networks = append(container.Networks, &vethNetwork) From 9e98ba72e1b0e35389b37ce8b35f5bd82610281f Mon Sep 17 00:00:00 2001 From: Isabel Jimenez Date: Mon, 17 Mar 2014 01:40:36 -0700 Subject: [PATCH 18/35] adding configuration for timeout and disable it by default Docker-DCO-1.1-Signed-off-by: Isabel Jimenez (github: jimenez) --- api/server.go | 5 ++--- pkg/listenbuffer/buffer.go | 27 ++++++--------------------- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/api/server.go b/api/server.go index 6fafe60f9..818394a8b 100644 --- a/api/server.go +++ b/api/server.go @@ -26,7 +26,6 @@ import ( "strconv" "strings" "syscall" - "time" ) var ( @@ -1130,7 +1129,7 @@ func changeGroup(addr string, nameOrGid string) error { // ListenAndServe sets up the required http.Server and gets it listening for // each addr passed in and does protocol specific checking. -func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors bool, dockerVersion string, socketGroup string) error { +func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors bool, dockerVersion, socketGroup string) error { r, err := createRouter(eng, logging, enableCors, dockerVersion) if err != nil { @@ -1147,7 +1146,7 @@ func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors } } - l, err := listenbuffer.NewListenBuffer(proto, addr, activationLock, 15*time.Minute) + l, err := listenbuffer.NewListenBuffer(proto, addr, activationLock) if err != nil { return err } diff --git a/pkg/listenbuffer/buffer.go b/pkg/listenbuffer/buffer.go index c350805a7..17572c8a0 100644 --- a/pkg/listenbuffer/buffer.go +++ b/pkg/listenbuffer/buffer.go @@ -5,15 +5,10 @@ */ package listenbuffer -import ( - "fmt" - "net" - "time" -) +import "net" -// NewListenBuffer returns a listener listening on addr with the protocol. It sets the -// timeout to wait on first connection before an error is returned -func NewListenBuffer(proto, addr string, activate chan struct{}, timeout time.Duration) (net.Listener, error) { +// NewListenBuffer returns a listener listening on addr with the protocol. +func NewListenBuffer(proto, addr string, activate chan struct{}) (net.Listener, error) { wrapped, err := net.Listen(proto, addr) if err != nil { return nil, err @@ -22,7 +17,6 @@ func NewListenBuffer(proto, addr string, activate chan struct{}, timeout time.Du return &defaultListener{ wrapped: wrapped, activate: activate, - timeout: timeout, }, nil } @@ -30,7 +24,6 @@ type defaultListener struct { wrapped net.Listener // the real listener to wrap ready bool // is the listner ready to start accpeting connections activate chan struct{} - timeout time.Duration // how long to wait before we consider this an error } func (l *defaultListener) Close() error { @@ -47,15 +40,7 @@ func (l *defaultListener) Accept() (net.Conn, error) { if l.ready { return l.wrapped.Accept() } - - select { - case <-time.After(l.timeout): - // close the connection so any clients are disconnected - l.Close() - return nil, fmt.Errorf("timeout (%s) reached waiting for listener to become ready", l.timeout.String()) - case <-l.activate: - l.ready = true - return l.Accept() - } - panic("unreachable") + <-l.activate + l.ready = true + return l.Accept() } From 2463be4dea6b0015485ea5c23d4ba060c228e904 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 17 Mar 2014 19:33:40 +0000 Subject: [PATCH 19/35] fix panic in monitor Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- container.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container.go b/container.go index d48b7da82..42b905a26 100644 --- a/container.go +++ b/container.go @@ -788,7 +788,7 @@ func (container *Container) monitor(callback execdriver.StartCallback) error { utils.Errorf("Error running container: %s", err) } - if container.runtime.srv.IsRunning() { + if container.runtime != nil && container.runtime.srv != nil && container.runtime.srv.IsRunning() { container.State.SetStopped(exitCode) // FIXME: there is a race condition here which causes this to fail during the unit tests. From 816d55342d9239ea57a1bb320e0fe6b5518a1c16 Mon Sep 17 00:00:00 2001 From: Wes Morgan Date: Thu, 30 Jan 2014 12:00:18 -0700 Subject: [PATCH 20/35] merge existing config when committing Fixes #1141 Docker-DCO-1.1-Signed-off-by: Wes Morgan (github: cap10morgan) --- docs/sources/reference/commandline/cli.rst | 61 ++++++++++++++++------ integration/server_test.go | 57 ++++++++++++++++++++ server.go | 11 ++-- 3 files changed, 110 insertions(+), 19 deletions(-) diff --git a/docs/sources/reference/commandline/cli.rst b/docs/sources/reference/commandline/cli.rst index 2e49cd5ca..9e99671ba 100644 --- a/docs/sources/reference/commandline/cli.rst +++ b/docs/sources/reference/commandline/cli.rst @@ -88,7 +88,7 @@ Commands -v, --version=false: Print version information and quit --mtu=0: Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if no default route is available -The Docker daemon is the persistent process that manages containers. Docker uses the same binary for both the +The Docker daemon is the persistent process that manages containers. Docker uses the same binary for both the daemon and client. To run the daemon you provide the ``-d`` flag. To force Docker to use devicemapper as the storage driver, use ``docker -d -s devicemapper``. @@ -100,10 +100,10 @@ To run the daemon with debug output, use ``docker -d -D``. To use lxc as the execution driver, use ``docker -d -e lxc``. The docker client will also honor the ``DOCKER_HOST`` environment variable to set -the ``-H`` flag for the client. +the ``-H`` flag for the client. :: - + docker -H tcp://0.0.0.0:4243 ps # or export DOCKER_HOST="tcp://0.0.0.0:4243" @@ -141,7 +141,7 @@ TMPDIR and the data directory can be set like this: You can detach from the container again (and leave it running) with ``CTRL-c`` (for a quiet exit) or ``CTRL-\`` to get a stacktrace of -the Docker client when it quits. When you detach from the container's +the Docker client when it quits. When you detach from the container's process the exit code will be returned to the client. To stop a container, use ``docker stop``. @@ -303,7 +303,7 @@ by using the ``git://`` schema. -m, --message="": Commit message -a, --author="": Author (eg. "John Hannibal Smith " - --run="": Configuration to be applied when the image is launched with `docker run`. + --run="": Configuration changes to be applied when the image is launched with `docker run`. (ex: -run='{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}') .. _cli_commit_examples: @@ -315,14 +315,14 @@ Commit an existing container $ sudo docker ps ID IMAGE COMMAND CREATED STATUS PORTS - c3f279d17e0a ubuntu:12.04 /bin/bash 7 days ago Up 25 hours - 197387f1b436 ubuntu:12.04 /bin/bash 7 days ago Up 25 hours + c3f279d17e0a ubuntu:12.04 /bin/bash 7 days ago Up 25 hours + 197387f1b436 ubuntu:12.04 /bin/bash 7 days ago Up 25 hours $ docker commit c3f279d17e0a SvenDowideit/testimage:version3 f5283438590d $ docker images | head REPOSITORY TAG ID CREATED VIRTUAL SIZE SvenDowideit/testimage version3 f5283438590d 16 seconds ago 335.7 MB - + Change the command that a container runs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -344,11 +344,40 @@ run ``ls /etc``. apt host.conf lsb-base rc2.d ... +Merged configs example +...................... + +Say you have a Dockerfile like so: + +.. code-block:: bash + + ENV MYVAR foobar + RUN apt-get install openssh + EXPOSE 22 + CMD ["/usr/sbin/sshd -D"] + ... + +If you run that, make some changes, and then commit, Docker will merge the environment variable and exposed port configuration settings with any that you specify in the -run= option. This is a change from Docker 0.8.0 and prior where no attempt was made to preserve any existing configuration on commit. + +.. code-block:: bash + + $ docker build -t me/foo . + $ docker run -t -i me/foo /bin/bash + foo-container$ [make changes in the container] + foo-container$ exit + $ docker commit -run='{"Cmd": ["ls"]}' [container-id] me/bar + ... + +The me/bar image will now have port 22 exposed, MYVAR env var set to 'foobar', and its default command will be ["ls"]. + +Note that this is currently a shallow merge. So, for example, if you had specified a new port spec in the -run= config above, that would have clobbered the 'EXPOSE 22' setting from the parent container. + Full -run example ................. The ``--run`` JSON hash changes the ``Config`` section when running ``docker inspect CONTAINERID`` -or ``config`` when running ``docker inspect IMAGEID``. +or ``config`` when running ``docker inspect IMAGEID``. Existing configuration key-values that are +not overridden in the JSON hash will be merged in. (Multiline is okay within a single quote ``'``) @@ -664,7 +693,7 @@ Displaying image hierarchy Usage: docker import URL|- [REPOSITORY[:TAG]] - Create an empty filesystem image and import the contents of the tarball + Create an empty filesystem image and import the contents of the tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then optionally tag it. At this time, the URL must start with ``http`` and point to a single @@ -942,7 +971,7 @@ Running ``docker ps`` showing 2 linked containers. $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 4c01db0b339c ubuntu:12.04 bash 17 seconds ago Up 16 seconds webapp + 4c01db0b339c ubuntu:12.04 bash 17 seconds ago Up 16 seconds webapp d7886598dbe2 crosbymichael/redis:latest /redis-server --dir 33 minutes ago Up 33 minutes 6379/tcp redis,webapp/db fd2645e2e2b5 busybox:latest top 10 days ago Ghost insane_ptolemy @@ -1047,7 +1076,7 @@ containers will not be deleted. Remove one or more images -f, --force=false: Force - + Removing tagged images ~~~~~~~~~~~~~~~~~~~~~~ @@ -1126,8 +1155,8 @@ Once the container is stopped it still exists and can be started back up. See ` The ``docker run`` command can be used in combination with ``docker commit`` to :ref:`change the command that a container runs `. -See :ref:`port_redirection` for more detailed information about the ``--expose``, -``-p``, ``-P`` and ``--link`` parameters, and :ref:`working_with_links_names` for +See :ref:`port_redirection` for more detailed information about the ``--expose``, +``-p``, ``-P`` and ``--link`` parameters, and :ref:`working_with_links_names` for specific examples using ``--link``. Known Issues (run -volumes-from) @@ -1207,8 +1236,8 @@ starting your container. $ sudo docker run -t -i -v /var/run/docker.sock:/var/run/docker.sock -v ./static-docker:/usr/bin/docker busybox sh -By bind-mounting the docker unix socket and statically linked docker binary -(such as that provided by https://get.docker.io), you give the container +By bind-mounting the docker unix socket and statically linked docker binary +(such as that provided by https://get.docker.io), you give the container the full access to create and manipulate the host's docker daemon. .. code-block:: bash diff --git a/integration/server_test.go b/integration/server_test.go index 69a90527b..e9781777e 100644 --- a/integration/server_test.go +++ b/integration/server_test.go @@ -281,6 +281,63 @@ func TestCommit(t *testing.T) { } } +func TestMergeConfigOnCommit(t *testing.T) { + eng := NewTestEngine(t) + runtime := mkRuntimeFromEngine(eng, t) + defer runtime.Nuke() + + container1, _, _ := mkContainer(runtime, []string{"-e", "FOO=bar", unitTestImageID, "echo test > /tmp/foo"}, t) + defer runtime.Destroy(container1) + + config, _, _, err := runconfig.Parse([]string{container1.ID, "cat /tmp/foo"}, nil) + if err != nil { + t.Error(err) + } + + job := eng.Job("commit", container1.ID) + job.Setenv("repo", "testrepo") + job.Setenv("tag", "testtag") + job.SetenvJson("config", config) + var newId string + job.Stdout.AddString(&newId) + if err := job.Run(); err != nil { + t.Error(err) + } + + container2, _, _ := mkContainer(runtime, []string{newId}, t) + defer runtime.Destroy(container2) + + job = eng.Job("inspect", container1.Name, "container") + baseContainer, _ := job.Stdout.AddEnv() + if err := job.Run(); err != nil { + t.Error(err) + } + + job = eng.Job("inspect", container2.Name, "container") + commitContainer, _ := job.Stdout.AddEnv() + if err := job.Run(); err != nil { + t.Error(err) + } + + baseConfig := baseContainer.GetSubEnv("Config") + commitConfig := commitContainer.GetSubEnv("Config") + + if commitConfig.Get("Env") != baseConfig.Get("Env") { + t.Fatalf("Env config in committed container should be %v, was %v", + baseConfig.Get("Env"), commitConfig.Get("Env")) + } + + if baseConfig.Get("Cmd") != "[\"echo test \\u003e /tmp/foo\"]" { + t.Fatalf("Cmd in base container should be [\"echo test \\u003e /tmp/foo\"], was %s", + baseConfig.Get("Cmd")) + } + + if commitConfig.Get("Cmd") != "[\"cat /tmp/foo\"]" { + t.Fatalf("Cmd in committed container should be [\"cat /tmp/foo\"], was %s", + commitConfig.Get("Cmd")) + } +} + func TestRestartKillWait(t *testing.T) { eng := NewTestEngine(t) srv := mkServerFromEngine(eng, t) diff --git a/server.go b/server.go index 7fb70bacc..2885d4a61 100644 --- a/server.go +++ b/server.go @@ -1039,12 +1039,17 @@ func (srv *Server) ContainerCommit(job *engine.Job) engine.Status { if container == nil { return job.Errorf("No such container: %s", name) } - var config runconfig.Config - if err := job.GetenvJson("config", &config); err != nil { + var config = container.Config + var newConfig runconfig.Config + if err := job.GetenvJson("config", &newConfig); err != nil { return job.Error(err) } - img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &config) + if err := runconfig.Merge(&newConfig, config); err != nil { + return job.Error(err) + } + + img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &newConfig) if err != nil { return job.Error(err) } From 6908e0ba1e5fe6ad128f6c859899fa14a1d60429 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 17 Mar 2014 17:56:21 +0000 Subject: [PATCH 21/35] fix content-type detection in docker cp Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- api/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/server.go b/api/server.go index 818394a8b..771f3c6cd 100644 --- a/api/server.go +++ b/api/server.go @@ -882,7 +882,7 @@ func postContainersCopy(eng *engine.Engine, version version.Version, w http.Resp var copyData engine.Env - if contentType := r.Header.Get("Content-Type"); contentType == "application/json" { + if contentType := r.Header.Get("Content-Type"); MatchesContentType(contentType, "application/json") { if err := copyData.Decode(r.Body); err != nil { return err } From 3c9e23c2975cae80552e27d76ae16aec960e0b26 Mon Sep 17 00:00:00 2001 From: Vladimir Rutsky Date: Sun, 16 Mar 2014 18:35:13 +0400 Subject: [PATCH 22/35] Fix external link on security of containers Docker-DCO-1.1-Signed-off-by: Vladimir Rutsky (github: rutsky) --- docs/sources/articles/security.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sources/articles/security.rst b/docs/sources/articles/security.rst index 3dc5780e8..e738e9a84 100644 --- a/docs/sources/articles/security.rst +++ b/docs/sources/articles/security.rst @@ -7,7 +7,7 @@ Docker Security =============== - *Adapted from* `Containers & Docker: How Secure are They? `_ + *Adapted from* `Containers & Docker: How Secure are They? `_ There are three major areas to consider when reviewing Docker security: @@ -261,7 +261,7 @@ with Docker, since everything is provided by the kernel anyway. For more context and especially for comparisons with VMs and other container systems, please also see the `original blog post -`_. +`_. .. _blogsecurity: http://blog.docker.io/2013/08/containers-docker-how-secure-are-they/ From 63596f8c5d5f1053f486c95d38be792b471c3da7 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 6 Mar 2014 15:12:09 +0100 Subject: [PATCH 23/35] DeviceMapper: Succeed immediately when removing non-existant devices We've seen situations where removal of "ID-init" failed during container deletion (EBUSY), after removal of "ID" has succeeded. This caused the container delete operation to fail, and on the next delete attempt the removal of "ID" failed immediately with "does not exist". Ideally we should not fail the ID-init removal, but its also non-ideal to allow a state where the container is half-removed and we cannot make progress deleting the container. So, we silently ignore not-exist errors on device removal. Docker-DCO-1.1-Signed-off-by: Alexander Larsson (github: alexlarsson) --- graphdriver/devmapper/driver.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/graphdriver/devmapper/driver.go b/graphdriver/devmapper/driver.go index 4d414f9a7..8c5a19eea 100644 --- a/graphdriver/devmapper/driver.go +++ b/graphdriver/devmapper/driver.go @@ -90,6 +90,13 @@ func (d *Driver) Create(id, parent string) error { } func (d *Driver) Remove(id string) error { + if !d.DeviceSet.HasDevice(id) { + // Consider removing a non-existing device a no-op + // This is useful to be able to progress on container removal + // if the underlying device has gone away due to earlier errors + return nil + } + // Sink the float from create in case no Get() call was made if err := d.DeviceSet.UnmountDevice(id, UnmountSink); err != nil { return err From 6fe06c6cc86f31aedd43831d0bf284dda7e53e7a Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 18 Mar 2014 15:52:00 +0100 Subject: [PATCH 24/35] devmapper: Increase timeout in waitClose to 10sec As reported in https://github.com/dotcloud/docker/issues/4389 we're currently seeing timeouts in waitClose on some systems. We already bumped the timeout in waitRemove() in https://github.com/dotcloud/docker/issues/4504. Docker-DCO-1.1-Signed-off-by: Alexander Larsson (github: alexlarsson) --- graphdriver/devmapper/deviceset.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/graphdriver/devmapper/deviceset.go b/graphdriver/devmapper/deviceset.go index f6b26655a..4d33e243e 100644 --- a/graphdriver/devmapper/deviceset.go +++ b/graphdriver/devmapper/deviceset.go @@ -729,7 +729,7 @@ func (devices *DeviceSet) removeDeviceAndWait(devname string) error { // waitRemove blocks until either: // a) the device registered at - is removed, -// or b) the 1 second timeout expires. +// or b) the 10 second timeout expires. func (devices *DeviceSet) waitRemove(devname string) error { utils.Debugf("[deviceset %s] waitRemove(%s)", devices.devicePrefix, devname) defer utils.Debugf("[deviceset %s] waitRemove(%s) END", devices.devicePrefix, devname) @@ -760,7 +760,7 @@ func (devices *DeviceSet) waitRemove(devname string) error { // waitClose blocks until either: // a) the device registered at - is closed, -// or b) the 1 second timeout expires. +// or b) the 10 second timeout expires. func (devices *DeviceSet) waitClose(hash string) error { info := devices.Devices[hash] if info == nil { @@ -778,7 +778,9 @@ func (devices *DeviceSet) waitClose(hash string) error { if devinfo.OpenCount == 0 { break } - time.Sleep(1 * time.Millisecond) + devices.Unlock() + time.Sleep(10 * time.Millisecond) + devices.Lock() } if i == 1000 { return fmt.Errorf("Timeout while waiting for device %s to close", hash) From fda2934b6d7778d84bba74950e79f780fe593de6 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 10 Mar 2014 13:38:17 -0700 Subject: [PATCH 25/35] Move signal to pkg Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- api/client.go | 13 +-- {utils => pkg/signal}/signal.go | 2 +- {utils => pkg/signal}/signal_darwin.go | 2 +- .../signal/signal_freebsd.go | 7 +- pkg/signal/signal_linux.go | 87 +++++++++++++++++++ 5 files changed, 97 insertions(+), 14 deletions(-) rename {utils => pkg/signal}/signal.go (87%) rename {utils => pkg/signal}/signal_darwin.go (97%) rename utils/signal_linux.go => pkg/signal/signal_freebsd.go (85%) create mode 100644 pkg/signal/signal_linux.go diff --git a/api/client.go b/api/client.go index d49915ff0..660c1662b 100644 --- a/api/client.go +++ b/api/client.go @@ -13,6 +13,7 @@ import ( "github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/nat" flag "github.com/dotcloud/docker/pkg/mflag" + "github.com/dotcloud/docker/pkg/signal" "github.com/dotcloud/docker/pkg/term" "github.com/dotcloud/docker/registry" "github.com/dotcloud/docker/runconfig" @@ -24,7 +25,7 @@ import ( "net/http/httputil" "net/url" "os" - "os/signal" + gosignal "os/signal" "path" "reflect" "regexp" @@ -534,7 +535,7 @@ func (cli *DockerCli) CmdRestart(args ...string) error { func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal { sigc := make(chan os.Signal, 1) - utils.CatchAll(sigc) + signal.CatchAll(sigc) go func() { for s := range sigc { if s == syscall.SIGCHLD { @@ -582,7 +583,7 @@ func (cli *DockerCli) CmdStart(args ...string) error { if !container.Config.Tty { sigc := cli.forwardAllSignals(cmd.Arg(0)) - defer utils.StopCatch(sigc) + defer signal.StopCatch(sigc) } var in io.ReadCloser @@ -1615,7 +1616,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error { if *proxy && !container.Config.Tty { sigc := cli.forwardAllSignals(cmd.Arg(0)) - defer utils.StopCatch(sigc) + defer signal.StopCatch(sigc) } if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, in, cli.out, cli.err, nil); err != nil { @@ -1833,7 +1834,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { if sigProxy { sigc := cli.forwardAllSignals(runResult.Get("Id")) - defer utils.StopCatch(sigc) + defer signal.StopCatch(sigc) } var ( @@ -2340,7 +2341,7 @@ func (cli *DockerCli) monitorTtySize(id string) error { cli.resizeTty(id) sigchan := make(chan os.Signal, 1) - signal.Notify(sigchan, syscall.SIGWINCH) + gosignal.Notify(sigchan, syscall.SIGWINCH) go func() { for _ = range sigchan { cli.resizeTty(id) diff --git a/utils/signal.go b/pkg/signal/signal.go similarity index 87% rename from utils/signal.go rename to pkg/signal/signal.go index 0cac7d113..6f9874bd0 100644 --- a/utils/signal.go +++ b/pkg/signal/signal.go @@ -1,4 +1,4 @@ -package utils +package signal import ( "os" diff --git a/utils/signal_darwin.go b/pkg/signal/signal_darwin.go similarity index 97% rename from utils/signal_darwin.go rename to pkg/signal/signal_darwin.go index 28730db8e..22a60ae18 100644 --- a/utils/signal_darwin.go +++ b/pkg/signal/signal_darwin.go @@ -1,4 +1,4 @@ -package utils +package signal import ( "os" diff --git a/utils/signal_linux.go b/pkg/signal/signal_freebsd.go similarity index 85% rename from utils/signal_linux.go rename to pkg/signal/signal_freebsd.go index 26cfd5696..d27782217 100644 --- a/utils/signal_linux.go +++ b/pkg/signal/signal_freebsd.go @@ -1,4 +1,4 @@ -package utils +package signal import ( "os" @@ -12,7 +12,6 @@ func CatchAll(sigc chan os.Signal) { syscall.SIGALRM, syscall.SIGBUS, syscall.SIGCHLD, - syscall.SIGCLD, syscall.SIGCONT, syscall.SIGFPE, syscall.SIGHUP, @@ -22,12 +21,9 @@ func CatchAll(sigc chan os.Signal) { syscall.SIGIOT, syscall.SIGKILL, syscall.SIGPIPE, - syscall.SIGPOLL, syscall.SIGPROF, - syscall.SIGPWR, syscall.SIGQUIT, syscall.SIGSEGV, - syscall.SIGSTKFLT, syscall.SIGSTOP, syscall.SIGSYS, syscall.SIGTERM, @@ -35,7 +31,6 @@ func CatchAll(sigc chan os.Signal) { syscall.SIGTSTP, syscall.SIGTTIN, syscall.SIGTTOU, - syscall.SIGUNUSED, syscall.SIGURG, syscall.SIGUSR1, syscall.SIGUSR2, diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go new file mode 100644 index 000000000..b6b25d518 --- /dev/null +++ b/pkg/signal/signal_linux.go @@ -0,0 +1,87 @@ +package signal + +import ( + "os" + "os/signal" + "syscall" +) + +var signalMap = map[string]syscall.Signal{} + +/* + syscall.SIGABRT, + syscall.SIGALRM, + syscall.SIGBUS, + syscall.SIGCHLD, + syscall.SIGCLD, + syscall.SIGCONT, + syscall.SIGFPE, + syscall.SIGHUP, + syscall.SIGILL, + syscall.SIGINT, + syscall.SIGIO, + syscall.SIGIOT, + syscall.SIGKILL, + syscall.SIGPIPE, + syscall.SIGPOLL, + syscall.SIGPROF, + syscall.SIGPWR, + syscall.SIGQUIT, + syscall.SIGSEGV, + syscall.SIGSTKFLT, + syscall.SIGSTOP, + syscall.SIGSYS, + syscall.SIGTERM, + syscall.SIGTRAP, + syscall.SIGTSTP, + syscall.SIGTTIN, + syscall.SIGTTOU, + syscall.SIGUNUSED, + syscall.SIGURG, + syscall.SIGUSR1, + syscall.SIGUSR2, + syscall.SIGVTALRM, + syscall.SIGWINCH, + syscall.SIGXCPU, + syscall.SIGXFSZ, +*/ + +func CatchAll(sigc chan os.Signal) { + signal.Notify(sigc, + syscall.SIGABRT, + syscall.SIGALRM, + syscall.SIGBUS, + syscall.SIGCHLD, + syscall.SIGCLD, + syscall.SIGCONT, + syscall.SIGFPE, + syscall.SIGHUP, + syscall.SIGILL, + syscall.SIGINT, + syscall.SIGIO, + syscall.SIGIOT, + syscall.SIGKILL, + syscall.SIGPIPE, + syscall.SIGPOLL, + syscall.SIGPROF, + syscall.SIGPWR, + syscall.SIGQUIT, + syscall.SIGSEGV, + syscall.SIGSTKFLT, + syscall.SIGSTOP, + syscall.SIGSYS, + syscall.SIGTERM, + syscall.SIGTRAP, + syscall.SIGTSTP, + syscall.SIGTTIN, + syscall.SIGTTOU, + syscall.SIGUNUSED, + syscall.SIGURG, + syscall.SIGUSR1, + syscall.SIGUSR2, + syscall.SIGVTALRM, + syscall.SIGWINCH, + syscall.SIGXCPU, + syscall.SIGXFSZ, + ) +} From d1e027291b2d29c15c6e9ca332b6cc8f79d24971 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 10 Mar 2014 13:50:16 -0700 Subject: [PATCH 26/35] Create portable signalMap Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- pkg/signal/signal.go | 8 +++ pkg/signal/signal_darwin.go | 70 +++++++++---------- pkg/signal/signal_freebsd.go | 68 +++++++++--------- pkg/signal/signal_linux.go | 116 ++++++++++--------------------- pkg/signal/signal_unsupported.go | 9 +++ 5 files changed, 121 insertions(+), 150 deletions(-) create mode 100644 pkg/signal/signal_unsupported.go diff --git a/pkg/signal/signal.go b/pkg/signal/signal.go index 6f9874bd0..a67322262 100644 --- a/pkg/signal/signal.go +++ b/pkg/signal/signal.go @@ -5,6 +5,14 @@ import ( "os/signal" ) +func CatchAll(sigc chan os.Signal) { + handledSigs := []os.Signal{} + for _, s := range signalMap { + handledSigs = append(handledSigs, s) + } + signal.Notify(sigc, handledSigs...) +} + func StopCatch(sigc chan os.Signal) { signal.Stop(sigc) close(sigc) diff --git a/pkg/signal/signal_darwin.go b/pkg/signal/signal_darwin.go index 22a60ae18..b290a8b53 100644 --- a/pkg/signal/signal_darwin.go +++ b/pkg/signal/signal_darwin.go @@ -1,44 +1,40 @@ package signal import ( - "os" - "os/signal" "syscall" ) -func CatchAll(sigc chan os.Signal) { - signal.Notify(sigc, - syscall.SIGABRT, - syscall.SIGALRM, - syscall.SIGBUS, - syscall.SIGCHLD, - syscall.SIGCONT, - syscall.SIGEMT, - syscall.SIGFPE, - syscall.SIGHUP, - syscall.SIGILL, - syscall.SIGINFO, - syscall.SIGINT, - syscall.SIGIO, - syscall.SIGIOT, - syscall.SIGKILL, - syscall.SIGPIPE, - syscall.SIGPROF, - syscall.SIGQUIT, - syscall.SIGSEGV, - syscall.SIGSTOP, - syscall.SIGSYS, - syscall.SIGTERM, - syscall.SIGTRAP, - syscall.SIGTSTP, - syscall.SIGTTIN, - syscall.SIGTTOU, - syscall.SIGURG, - syscall.SIGUSR1, - syscall.SIGUSR2, - syscall.SIGVTALRM, - syscall.SIGWINCH, - syscall.SIGXCPU, - syscall.SIGXFSZ, - ) +var signalMap = map[string]syscall.Signal{ + "ABRT": syscall.SIGABRT, + "ALRM": syscall.SIGALRM, + "BUG": syscall.SIGBUS, + "CHLD": syscall.SIGCHLD, + "CONT": syscall.SIGCONT, + "EMT": syscall.SIGEMT, + "FPE": syscall.SIGFPE, + "HUP": syscall.SIGHUP, + "ILL": syscall.SIGILL, + "INFO": syscall.SIGINFO, + "INT": syscall.SIGINT, + "IO": syscall.SIGIO, + "IOT": syscall.SIGIOT, + "KILL": syscall.SIGKILL, + "PIPE": syscall.SIGPIPE, + "PROF": syscall.SIGPROF, + "QUIT": syscall.SIGQUIT, + "SEGV": syscall.SIGSEGV, + "STOP": syscall.SIGSTOP, + "SYS": syscall.SIGSYS, + "TERM": syscall.SIGTERM, + "TRAP": syscall.SIGTRAP, + "TSTP": syscall.SIGTSTP, + "TTIN": syscall.SIGTTIN, + "TTOU": syscall.SIGTTOU, + "URG": syscall.SIGURG, + "USR1": syscall.SIGUSR1, + "USR2": syscall.SIGUSR2, + "VTALRM": syscall.SIGVTALRM, + "WINCH": syscall.SIGWINCH, + "XCPU": syscall.SIGXCPU, + "XFSZ": syscall.SIGXFSZ, } diff --git a/pkg/signal/signal_freebsd.go b/pkg/signal/signal_freebsd.go index d27782217..b7e3ff4f7 100644 --- a/pkg/signal/signal_freebsd.go +++ b/pkg/signal/signal_freebsd.go @@ -6,37 +6,39 @@ import ( "syscall" ) -func CatchAll(sigc chan os.Signal) { - signal.Notify(sigc, - syscall.SIGABRT, - syscall.SIGALRM, - syscall.SIGBUS, - syscall.SIGCHLD, - syscall.SIGCONT, - syscall.SIGFPE, - syscall.SIGHUP, - syscall.SIGILL, - syscall.SIGINT, - syscall.SIGIO, - syscall.SIGIOT, - syscall.SIGKILL, - syscall.SIGPIPE, - syscall.SIGPROF, - syscall.SIGQUIT, - syscall.SIGSEGV, - syscall.SIGSTOP, - syscall.SIGSYS, - syscall.SIGTERM, - syscall.SIGTRAP, - syscall.SIGTSTP, - syscall.SIGTTIN, - syscall.SIGTTOU, - syscall.SIGURG, - syscall.SIGUSR1, - syscall.SIGUSR2, - syscall.SIGVTALRM, - syscall.SIGWINCH, - syscall.SIGXCPU, - syscall.SIGXFSZ, - ) +var signalMap = map[string]syscall.Signal{ + "ABRT": syscall.SIGABRT, + "ALRM": syscall.SIGALRM, + "BUF": syscall.SIGBUS, + "CHLD": syscall.SIGCHLD, + "CONT": syscall.SIGCONT, + "EMT": syscall.SIGEMT, + "FPE": syscall.SIGFPE, + "HUP": syscall.SIGHUP, + "ILL": syscall.SIGILL, + "INFO": syscall.SIGINFO, + "INT": syscall.SIGINT, + "IO": syscall.SIGIO, + "IOT": syscall.SIGIOT, + "KILL": syscall.SIGKILL, + "LWP": syscall.SIGLWP, + "PIPE": syscall.SIGPIPE, + "PROF": syscall.SIGPROF, + "QUIT": syscall.SIGQUIT, + "SEGV": syscall.SIGSEGV, + "STOP": syscall.SIGSTOP, + "SYS": syscall.SIGSYS, + "TERM": syscall.SIGTERM, + "THR": syscall.SIGTHR, + "TRAP": syscall.SIGTRAP, + "TSTP": syscall.SIGTSTP, + "TTIN": syscall.SIGTTIN, + "TTOU": syscall.SIGTTOU, + "URG": syscall.SIGURG, + "USR1": syscall.SIGUSR1, + "USR2": syscall.SIGUSR2, + "VTALRM": syscall.SIGVTALRM, + "WINCH": syscall.SIGWINCH, + "XCPU": syscall.SIGXCPU, + "XFSZ": syscall.SIGXFSZ, } diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go index b6b25d518..cd8cb83e4 100644 --- a/pkg/signal/signal_linux.go +++ b/pkg/signal/signal_linux.go @@ -1,87 +1,43 @@ package signal import ( - "os" - "os/signal" "syscall" ) -var signalMap = map[string]syscall.Signal{} - -/* - syscall.SIGABRT, - syscall.SIGALRM, - syscall.SIGBUS, - syscall.SIGCHLD, - syscall.SIGCLD, - syscall.SIGCONT, - syscall.SIGFPE, - syscall.SIGHUP, - syscall.SIGILL, - syscall.SIGINT, - syscall.SIGIO, - syscall.SIGIOT, - syscall.SIGKILL, - syscall.SIGPIPE, - syscall.SIGPOLL, - syscall.SIGPROF, - syscall.SIGPWR, - syscall.SIGQUIT, - syscall.SIGSEGV, - syscall.SIGSTKFLT, - syscall.SIGSTOP, - syscall.SIGSYS, - syscall.SIGTERM, - syscall.SIGTRAP, - syscall.SIGTSTP, - syscall.SIGTTIN, - syscall.SIGTTOU, - syscall.SIGUNUSED, - syscall.SIGURG, - syscall.SIGUSR1, - syscall.SIGUSR2, - syscall.SIGVTALRM, - syscall.SIGWINCH, - syscall.SIGXCPU, - syscall.SIGXFSZ, -*/ - -func CatchAll(sigc chan os.Signal) { - signal.Notify(sigc, - syscall.SIGABRT, - syscall.SIGALRM, - syscall.SIGBUS, - syscall.SIGCHLD, - syscall.SIGCLD, - syscall.SIGCONT, - syscall.SIGFPE, - syscall.SIGHUP, - syscall.SIGILL, - syscall.SIGINT, - syscall.SIGIO, - syscall.SIGIOT, - syscall.SIGKILL, - syscall.SIGPIPE, - syscall.SIGPOLL, - syscall.SIGPROF, - syscall.SIGPWR, - syscall.SIGQUIT, - syscall.SIGSEGV, - syscall.SIGSTKFLT, - syscall.SIGSTOP, - syscall.SIGSYS, - syscall.SIGTERM, - syscall.SIGTRAP, - syscall.SIGTSTP, - syscall.SIGTTIN, - syscall.SIGTTOU, - syscall.SIGUNUSED, - syscall.SIGURG, - syscall.SIGUSR1, - syscall.SIGUSR2, - syscall.SIGVTALRM, - syscall.SIGWINCH, - syscall.SIGXCPU, - syscall.SIGXFSZ, - ) +var signalMap = map[string]syscall.Signal{ + "ABRT": syscall.SIGABRT, + "ALRM": syscall.SIGALRM, + "BUS": syscall.SIGBUS, + "CHLD": syscall.SIGCHLD, + "CLD": syscall.SIGCLD, + "CONT": syscall.SIGCONT, + "FPE": syscall.SIGFPE, + "HUP": syscall.SIGHUP, + "ILL": syscall.SIGILL, + "INT": syscall.SIGINT, + "IO": syscall.SIGIO, + "IOT": syscall.SIGIOT, + "KILL": syscall.SIGKILL, + "PIPE": syscall.SIGPIPE, + "POLL": syscall.SIGPOLL, + "PROF": syscall.SIGPROF, + "PWR": syscall.SIGPWR, + "QUIT": syscall.SIGQUIT, + "SEGV": syscall.SIGSEGV, + "STKFLT": syscall.SIGSTKFLT, + "STOP": syscall.SIGSTOP, + "SYS": syscall.SIGSYS, + "TERM": syscall.SIGTERM, + "TRAP": syscall.SIGTRAP, + "TSTP": syscall.SIGTSTP, + "TTIN": syscall.SIGTTIN, + "TTOU": syscall.SIGTTOU, + "UNUSED": syscall.SIGUNUSED, + "URG": syscall.SIGURG, + "USR1": syscall.SIGUSR1, + "USR2": syscall.SIGUSR2, + "VTALRM": syscall.SIGVTALRM, + "WINCH": syscall.SIGWINCH, + "XCPU": syscall.SIGXCPU, + "XFSZ": syscall.SIGXFSZ, } diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go new file mode 100644 index 000000000..2c49a0b0f --- /dev/null +++ b/pkg/signal/signal_unsupported.go @@ -0,0 +1,9 @@ +// +build !linux,!darwin,!freebsd + +package signal + +import ( + "syscall" +) + +var signalMap = map[string]syscall.Signal{} From cec512ccbb5ae71776645d51ac73f5e0b391f16a Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 10 Mar 2014 14:22:27 -0700 Subject: [PATCH 27/35] Make docker use the signal pkg with strings Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) --- api/client.go | 12 +++++- pkg/signal/signal.go | 2 +- pkg/signal/signal_darwin.go | 64 ++++++++++++++++---------------- pkg/signal/signal_freebsd.go | 2 +- pkg/signal/signal_linux.go | 2 +- pkg/signal/signal_unsupported.go | 2 +- server.go | 63 ++++++++++--------------------- 7 files changed, 66 insertions(+), 81 deletions(-) diff --git a/api/client.go b/api/client.go index 660c1662b..d7d126ec7 100644 --- a/api/client.go +++ b/api/client.go @@ -541,7 +541,17 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal { if s == syscall.SIGCHLD { continue } - if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%d", cid, s), nil, false)); err != nil { + var sig string + for sigStr, sigN := range signal.SignalMap { + if sigN == s { + sig = sigStr + break + } + } + if sig == "" { + utils.Errorf("Unsupported signal: %d. Discarding.", s) + } + if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, false)); err != nil { utils.Debugf("Error sending signal: %s", err) } } diff --git a/pkg/signal/signal.go b/pkg/signal/signal.go index a67322262..63337542d 100644 --- a/pkg/signal/signal.go +++ b/pkg/signal/signal.go @@ -7,7 +7,7 @@ import ( func CatchAll(sigc chan os.Signal) { handledSigs := []os.Signal{} - for _, s := range signalMap { + for _, s := range SignalMap { handledSigs = append(handledSigs, s) } signal.Notify(sigc, handledSigs...) diff --git a/pkg/signal/signal_darwin.go b/pkg/signal/signal_darwin.go index b290a8b53..fcd3a8f2c 100644 --- a/pkg/signal/signal_darwin.go +++ b/pkg/signal/signal_darwin.go @@ -4,37 +4,37 @@ import ( "syscall" ) -var signalMap = map[string]syscall.Signal{ - "ABRT": syscall.SIGABRT, - "ALRM": syscall.SIGALRM, - "BUG": syscall.SIGBUS, - "CHLD": syscall.SIGCHLD, - "CONT": syscall.SIGCONT, - "EMT": syscall.SIGEMT, - "FPE": syscall.SIGFPE, - "HUP": syscall.SIGHUP, - "ILL": syscall.SIGILL, - "INFO": syscall.SIGINFO, - "INT": syscall.SIGINT, - "IO": syscall.SIGIO, - "IOT": syscall.SIGIOT, - "KILL": syscall.SIGKILL, - "PIPE": syscall.SIGPIPE, - "PROF": syscall.SIGPROF, - "QUIT": syscall.SIGQUIT, - "SEGV": syscall.SIGSEGV, - "STOP": syscall.SIGSTOP, - "SYS": syscall.SIGSYS, - "TERM": syscall.SIGTERM, - "TRAP": syscall.SIGTRAP, - "TSTP": syscall.SIGTSTP, - "TTIN": syscall.SIGTTIN, - "TTOU": syscall.SIGTTOU, - "URG": syscall.SIGURG, - "USR1": syscall.SIGUSR1, - "USR2": syscall.SIGUSR2, +var SignalMap = map[string]syscall.Signal{ + "ABRT": syscall.SIGABRT, + "ALRM": syscall.SIGALRM, + "BUG": syscall.SIGBUS, + "CHLD": syscall.SIGCHLD, + "CONT": syscall.SIGCONT, + "EMT": syscall.SIGEMT, + "FPE": syscall.SIGFPE, + "HUP": syscall.SIGHUP, + "ILL": syscall.SIGILL, + "INFO": syscall.SIGINFO, + "INT": syscall.SIGINT, + "IO": syscall.SIGIO, + "IOT": syscall.SIGIOT, + "KILL": syscall.SIGKILL, + "PIPE": syscall.SIGPIPE, + "PROF": syscall.SIGPROF, + "QUIT": syscall.SIGQUIT, + "SEGV": syscall.SIGSEGV, + "STOP": syscall.SIGSTOP, + "SYS": syscall.SIGSYS, + "TERM": syscall.SIGTERM, + "TRAP": syscall.SIGTRAP, + "TSTP": syscall.SIGTSTP, + "TTIN": syscall.SIGTTIN, + "TTOU": syscall.SIGTTOU, + "URG": syscall.SIGURG, + "USR1": syscall.SIGUSR1, + "USR2": syscall.SIGUSR2, "VTALRM": syscall.SIGVTALRM, - "WINCH": syscall.SIGWINCH, - "XCPU": syscall.SIGXCPU, - "XFSZ": syscall.SIGXFSZ, + "WINCH": syscall.SIGWINCH, + "XCPU": syscall.SIGXCPU, + "XFSZ": syscall.SIGXFSZ, } diff --git a/pkg/signal/signal_freebsd.go b/pkg/signal/signal_freebsd.go index b7e3ff4f7..da042d7e7 100644 --- a/pkg/signal/signal_freebsd.go +++ b/pkg/signal/signal_freebsd.go @@ -6,7 +6,7 @@ import ( "syscall" ) -var signalMap = map[string]syscall.Signal{ +var SignalMap = map[string]syscall.Signal{ "ABRT": syscall.SIGABRT, "ALRM": syscall.SIGALRM, "BUF": syscall.SIGBUS, diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go index cd8cb83e4..a62f79d4a 100644 --- a/pkg/signal/signal_linux.go +++ b/pkg/signal/signal_linux.go @@ -4,7 +4,7 @@ import ( "syscall" ) -var signalMap = map[string]syscall.Signal{ +var SignalMap = map[string]syscall.Signal{ "ABRT": syscall.SIGABRT, "ALRM": syscall.SIGALRM, "BUS": syscall.SIGBUS, diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go index 2c49a0b0f..99f946597 100644 --- a/pkg/signal/signal_unsupported.go +++ b/pkg/signal/signal_unsupported.go @@ -6,4 +6,4 @@ import ( "syscall" ) -var signalMap = map[string]syscall.Signal{} +var SignalMap = map[string]syscall.Signal{} diff --git a/server.go b/server.go index 2885d4a61..c5ad24c4b 100644 --- a/server.go +++ b/server.go @@ -8,6 +8,7 @@ import ( "github.com/dotcloud/docker/dockerversion" "github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/pkg/graphdb" + "github.com/dotcloud/docker/pkg/signal" "github.com/dotcloud/docker/registry" "github.com/dotcloud/docker/runconfig" "github.com/dotcloud/docker/utils" @@ -18,7 +19,7 @@ import ( "net/url" "os" "os/exec" - "os/signal" + gosignal "os/signal" "path" "path/filepath" "runtime" @@ -47,7 +48,7 @@ func InitServer(job *engine.Job) engine.Status { } job.Logf("Setting up signal traps") c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) + gosignal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) go func() { sig := <-c log.Printf("Received signal '%v', exiting\n", sig) @@ -122,56 +123,30 @@ func (v *simpleVersionInfo) Version() string { // for the container to exit. // If a signal is given, then just send it to the container and return. func (srv *Server) ContainerKill(job *engine.Job) engine.Status { - signalMap := map[string]syscall.Signal{ - "HUP": syscall.SIGHUP, - "INT": syscall.SIGINT, - "QUIT": syscall.SIGQUIT, - "ILL": syscall.SIGILL, - "TRAP": syscall.SIGTRAP, - "ABRT": syscall.SIGABRT, - "BUS": syscall.SIGBUS, - "FPE": syscall.SIGFPE, - "KILL": syscall.SIGKILL, - "USR1": syscall.SIGUSR1, - "SEGV": syscall.SIGSEGV, - "USR2": syscall.SIGUSR2, - "PIPE": syscall.SIGPIPE, - "ALRM": syscall.SIGALRM, - "TERM": syscall.SIGTERM, - //"STKFLT": syscall.SIGSTKFLT, - "CHLD": syscall.SIGCHLD, - "CONT": syscall.SIGCONT, - "STOP": syscall.SIGSTOP, - "TSTP": syscall.SIGTSTP, - "TTIN": syscall.SIGTTIN, - "TTOU": syscall.SIGTTOU, - "URG": syscall.SIGURG, - "XCPU": syscall.SIGXCPU, - "XFSZ": syscall.SIGXFSZ, - "VTALRM": syscall.SIGVTALRM, - "PROF": syscall.SIGPROF, - "WINCH": syscall.SIGWINCH, - "IO": syscall.SIGIO, - //"PWR": syscall.SIGPWR, - "SYS": syscall.SIGSYS, - } - if n := len(job.Args); n < 1 || n > 2 { return job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name) } - name := job.Args[0] - var sig uint64 + var ( + name = job.Args[0] + sig uint64 + err error + ) + + // If we have a signal, look at it. Otherwise, do nothing if len(job.Args) == 2 && job.Args[1] != "" { - sig = uint64(signalMap[job.Args[1]]) - if sig == 0 { - var err error - // The largest legal signal is 31, so let's parse on 5 bits - sig, err = strconv.ParseUint(job.Args[1], 10, 5) - if err != nil { + // Check if we passed the singal as a number: + // The largest legal signal is 31, so let's parse on 5 bits + sig, err = strconv.ParseUint(job.Args[1], 10, 5) + if err != nil { + // The signal is not a number, treat it as a string + sig = uint64(signal.SignalMap[job.Args[1]]) + if sig == 0 { return job.Errorf("Invalid signal: %s", job.Args[1]) } + } } + if container := srv.runtime.Get(name); container != nil { // If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait()) if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL { From 9cad4c2a1bdf5c81c69343a3ec5b7034d4b21ec9 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Sun, 16 Mar 2014 21:10:59 +0000 Subject: [PATCH 28/35] Generate md5 and sha265 hashes when building, and upload them in hack/release.sh Docker-DCO-1.1-Signed-off-by: Sven Dowideit (github: SvenDowideit) Docker-DCO-1.1-Signed-off-by: Andrew Page (github: tianon) --- hack/make/binary | 8 ++++ hack/release.sh | 122 +++++++++++++++++++++++++++++------------------ 2 files changed, 84 insertions(+), 46 deletions(-) mode change 100644 => 100755 hack/make/binary diff --git a/hack/make/binary b/hack/make/binary old mode 100644 new mode 100755 index 7272b1ede..dee7d98dc --- a/hack/make/binary +++ b/hack/make/binary @@ -11,3 +11,11 @@ go build \ " \ ./docker echo "Created binary: $DEST/docker-$VERSION" + +if command -v md5sum &> /dev/null; then + md5sum "$DEST/docker-$VERSION" > "$DEST/docker-$VERSION.md5" +fi +if command -v sha256sum &> /dev/null; then + sha256sum "$DEST/docker-$VERSION" > "$DEST/docker-$VERSION.sha256" +fi + diff --git a/hack/release.sh b/hack/release.sh index 50913dd39..e7f892399 100755 --- a/hack/release.sh +++ b/hack/release.sh @@ -55,33 +55,16 @@ RELEASE_BUNDLES=( if [ "$1" != '--release-regardless-of-test-failure' ]; then RELEASE_BUNDLES=( test "${RELEASE_BUNDLES[@]}" ) fi - -if ! ./hack/make.sh "${RELEASE_BUNDLES[@]}"; then - echo >&2 - echo >&2 'The build or tests appear to have failed.' - echo >&2 - echo >&2 'You, as the release maintainer, now have a couple options:' - echo >&2 '- delay release and fix issues' - echo >&2 '- delay release and fix issues' - echo >&2 '- did we mention how important this is? issues need fixing :)' - echo >&2 - echo >&2 'As a final LAST RESORT, you (because only you, the release maintainer,' - echo >&2 ' really knows all the hairy problems at hand with the current release' - echo >&2 ' issues) may bypass this checking by running this script again with the' - echo >&2 ' single argument of "--release-regardless-of-test-failure", which will skip' - echo >&2 ' running the test suite, and will only build the binaries and packages. Please' - echo >&2 ' avoid using this if at all possible.' - echo >&2 - echo >&2 'Regardless, we cannot stress enough the scarcity with which this bypass' - echo >&2 ' should be used. If there are release issues, we should always err on the' - echo >&2 ' side of caution.' - echo >&2 - exit 1 -fi - + VERSION=$(cat VERSION) BUCKET=$AWS_S3_BUCKET +# These are the 2 keys we've used to sign the deb's +# release (get.docker.io +# GPG_KEY="36A1D7869245C8950F966E92D8576A8BA88D21E9" +# test (test.docker.io) +# GPG_KEY="740B314AE3941731B942C66ADF4FD13717AAD7D6" + setup_s3() { # Try creating the bucket. Ignore errors (it might already exist). s3cmd mb s3://$BUCKET 2>/dev/null || true @@ -114,12 +97,40 @@ s3_url() { esac } +build_all() { + if ! ./hack/make.sh "${RELEASE_BUNDLES[@]}"; then + echo >&2 + echo >&2 'The build or tests appear to have failed.' + echo >&2 + echo >&2 'You, as the release maintainer, now have a couple options:' + echo >&2 '- delay release and fix issues' + echo >&2 '- delay release and fix issues' + echo >&2 '- did we mention how important this is? issues need fixing :)' + echo >&2 + echo >&2 'As a final LAST RESORT, you (because only you, the release maintainer,' + echo >&2 ' really knows all the hairy problems at hand with the current release' + echo >&2 ' issues) may bypass this checking by running this script again with the' + echo >&2 ' single argument of "--release-regardless-of-test-failure", which will skip' + echo >&2 ' running the test suite, and will only build the binaries and packages. Please' + echo >&2 ' avoid using this if at all possible.' + echo >&2 + echo >&2 'Regardless, we cannot stress enough the scarcity with which this bypass' + echo >&2 ' should be used. If there are release issues, we should always err on the' + echo >&2 ' side of caution.' + echo >&2 + exit 1 + fi +} + release_build() { GOOS=$1 GOARCH=$2 - BINARY=bundles/$VERSION/cross/$GOOS/$GOARCH/docker-$VERSION - TGZ=bundles/$VERSION/tgz/$GOOS/$GOARCH/docker-$VERSION.tgz + SOURCE_DIR=bundles/$VERSION/cross/$GOOS/$GOARCH + BINARY=docker-$VERSION + BINARY_MD5=docker-$VERSION.md5 + BINARY_SHA256=docker-$VERSION.sha256 + TGZ=docker-$VERSION.tgz # we need to map our GOOS and GOARCH to uname values # see https://en.wikipedia.org/wiki/Uname @@ -172,17 +183,29 @@ release_build() { fi echo "Uploading $BINARY to $S3OS/$S3ARCH/docker-$VERSION" - s3cmd --follow-symlinks --preserve --acl-public put $BINARY $S3DIR/docker-$VERSION + s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$BINARY $S3DIR/$BINARY + + echo "Uploading $BINARY_MD5 to $S3OS/$S3ARCH/docker-$VERSION.md5" + s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$BINARY_MD5 $S3DIR/$BINARY_MD5 + + echo "Uploading $BINARY_BINARY_SHA256 to $S3OS/$S3ARCH/docker-$VERSION.sha256" + s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$BINARY_SHA256 $S3DIR/$BINARY_SHA256 echo "Uploading $TGZ to $S3OS/$S3ARCH/docker-$VERSION.tgz" - s3cmd --follow-symlinks --preserve --acl-public put $TGZ $S3DIR/docker-$VERSION.tgz + s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$TGZ $S3DIR/$TGZ if [ -z "$NOLATEST" ]; then - echo "Copying $S3OS/$S3ARCH/docker-$VERSION to $S3OS/$S3ARCH/docker-latest" - s3cmd --acl-public cp $S3DIR/docker-$VERSION $S3DIR/docker-latest + echo "Copying $S3DIR/$BINARY to $S3DIR/docker-latest" + s3cmd --acl-public cp $S3DIR/$BINARY $S3DIR/docker-latest - echo "Copying $S3OS/$S3ARCH/docker-$VERSION.tgz to $S3OS/$S3ARCH/docker-latest.tgz" - s3cmd --acl-public cp $S3DIR/docker-$VERSION.tgz $S3DIR/docker-latest.tgz + echo "Copying $S3DIR/$BINARY_MD5 to $S3DIR/docker-latest.md5" + s3cmd --acl-public cp $S3DIR/$BINARY_MD5 $S3DIR/docker-latest.md5 + + echo "Copying $S3DIR/$BINARY_SHA256 to $S3DIR/docker-latest.sha256" + s3cmd --acl-public cp $S3DIR/$BINARY_SHA256 $S3DIR/docker-latest.sha256 + + echo "Copying $S3DIR/$TGZ $S3DIR/docker-latest.tgz" + s3cmd --acl-public cp $S3DIR/$TGZ $S3DIR/docker-latest.tgz fi } @@ -194,21 +217,8 @@ release_ubuntu() { echo >&2 './hack/make.sh must be run before release_ubuntu' exit 1 } - # Make sure that we have our keys - mkdir -p /.gnupg/ + s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ /.gnupg/ || true - gpg --list-keys releasedocker >/dev/null || { - gpg --gen-key --batch </dev/null || { + gpg --gen-key --batch < Date: Thu, 20 Mar 2014 09:35:58 +1000 Subject: [PATCH 29/35] whitespace-blind Docker-DCO-1.1-Signed-off-by: Sven Dowideit (github: SvenDowideit) Docker-DCO-1.1-Signed-off-by: Andrew Page (github: tianon) --- hack/make/binary | 1 - hack/release.sh | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/hack/make/binary b/hack/make/binary index dee7d98dc..f220d2dae 100755 --- a/hack/make/binary +++ b/hack/make/binary @@ -18,4 +18,3 @@ fi if command -v sha256sum &> /dev/null; then sha256sum "$DEST/docker-$VERSION" > "$DEST/docker-$VERSION.sha256" fi - diff --git a/hack/release.sh b/hack/release.sh index e7f892399..d267acb1a 100755 --- a/hack/release.sh +++ b/hack/release.sh @@ -60,7 +60,7 @@ VERSION=$(cat VERSION) BUCKET=$AWS_S3_BUCKET # These are the 2 keys we've used to sign the deb's -# release (get.docker.io +# release (get.docker.io) # GPG_KEY="36A1D7869245C8950F966E92D8576A8BA88D21E9" # test (test.docker.io) # GPG_KEY="740B314AE3941731B942C66ADF4FD13717AAD7D6" @@ -342,7 +342,6 @@ main() { release_test } - main echo From e5974ae0ff49824edb38d3f69abf33ffc1a09852 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Thu, 20 Mar 2014 10:18:08 +1000 Subject: [PATCH 30/35] missed a bug Docker-DCO-1.1-Signed-off-by: Sven Dowideit (github: SvenDowideit) --- hack/release.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hack/release.sh b/hack/release.sh index d267acb1a..0132bccb4 100755 --- a/hack/release.sh +++ b/hack/release.sh @@ -173,8 +173,8 @@ release_build() { S3DIR=s3://$BUCKET/builds/$S3OS/$S3ARCH - if [ ! -x "$BINARY" ]; then - echo >&2 "error: can't find $BINARY - was it compiled properly?" + if [ ! -x "$SOURCE_DIR/$BINARY" ]; then + echo >&2 "error: can't find $SOURCE_DIR/$BINARY - was it compiled properly?" exit 1 fi if [ ! -f "$TGZ" ]; then @@ -188,7 +188,7 @@ release_build() { echo "Uploading $BINARY_MD5 to $S3OS/$S3ARCH/docker-$VERSION.md5" s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$BINARY_MD5 $S3DIR/$BINARY_MD5 - echo "Uploading $BINARY_BINARY_SHA256 to $S3OS/$S3ARCH/docker-$VERSION.sha256" + echo "Uploading $BINARY_SHA256 to $S3OS/$S3ARCH/docker-$VERSION.sha256" s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$BINARY_SHA256 $S3DIR/$BINARY_SHA256 echo "Uploading $TGZ to $S3OS/$S3ARCH/docker-$VERSION.tgz" From 3f47f23fecfe59a2aa9c11adbf112c03b29a6978 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 19 Mar 2014 19:58:39 -0600 Subject: [PATCH 31/35] Fix a lot of the sha256 and md5 stuff to be more DRY and extendible, and on more things (specifically, the tgz files too) Docker-DCO-1.1-Signed-off-by: Andrew Page (github: tianon) --- hack/make.sh | 21 ++++++++ hack/make/binary | 9 +--- hack/make/dynbinary | 6 ++- hack/make/tgz | 2 + hack/release.sh | 121 ++++++++++++++++++++++++++------------------ 5 files changed, 100 insertions(+), 59 deletions(-) diff --git a/hack/make.sh b/hack/make.sh index 63edca4d4..50886eb9d 100755 --- a/hack/make.sh +++ b/hack/make.sh @@ -141,6 +141,27 @@ find_dirs() { \) -name "$1" -print0 | xargs -0n1 dirname | sort -u } +hash_files() { + while [ $# -gt 0 ]; do + f="$1" + shift + dir="$(dirname "$f")" + base="$(basename "$f")" + for hashAlgo in md5 sha256; do + if command -v "${hashAlgo}sum" &> /dev/null; then + ( + # subshell and cd so that we get output files like: + # $HASH docker-$VERSION + # instead of: + # $HASH /go/src/github.com/.../$VERSION/binary/docker-$VERSION + cd "$dir" + "${hashAlgo}sum" "$base" > "$base.$hashAlgo" + ) + fi + done + done +} + bundle() { bundlescript=$1 bundle=$(basename $bundlescript) diff --git a/hack/make/binary b/hack/make/binary index f220d2dae..7b4d7b5b5 100755 --- a/hack/make/binary +++ b/hack/make/binary @@ -3,7 +3,7 @@ DEST=$1 go build \ - -o $DEST/docker-$VERSION \ + -o "$DEST/docker-$VERSION" \ "${BUILDFLAGS[@]}" \ -ldflags " $LDFLAGS @@ -12,9 +12,4 @@ go build \ ./docker echo "Created binary: $DEST/docker-$VERSION" -if command -v md5sum &> /dev/null; then - md5sum "$DEST/docker-$VERSION" > "$DEST/docker-$VERSION.md5" -fi -if command -v sha256sum &> /dev/null; then - sha256sum "$DEST/docker-$VERSION" > "$DEST/docker-$VERSION.sha256" -fi +hash_files "$DEST/docker-$VERSION" diff --git a/hack/make/dynbinary b/hack/make/dynbinary index d4f583fb6..75cffe3dc 100644 --- a/hack/make/dynbinary +++ b/hack/make/dynbinary @@ -5,7 +5,7 @@ DEST=$1 if [ -z "$DOCKER_CLIENTONLY" ]; then # dockerinit still needs to be a static binary, even if docker is dynamic go build \ - -o $DEST/dockerinit-$VERSION \ + -o "$DEST/dockerinit-$VERSION" \ "${BUILDFLAGS[@]}" \ -ldflags " $LDFLAGS @@ -14,7 +14,9 @@ if [ -z "$DOCKER_CLIENTONLY" ]; then " \ ./dockerinit echo "Created binary: $DEST/dockerinit-$VERSION" - ln -sf dockerinit-$VERSION $DEST/dockerinit + ln -sf "dockerinit-$VERSION" "$DEST/dockerinit" + + hash_files "$DEST/dockerinit-$VERSION" sha1sum= if command -v sha1sum &> /dev/null; then diff --git a/hack/make/tgz b/hack/make/tgz index 5d0330632..120339976 100644 --- a/hack/make/tgz +++ b/hack/make/tgz @@ -23,6 +23,8 @@ for d in "$CROSS/"*/*; do tar --numeric-owner --owner 0 -C "$DEST/build" -czf "$TGZ" usr + hash_files "$TGZ" + rm -rf "$DEST/build" echo "Created tgz: $TGZ" diff --git a/hack/release.sh b/hack/release.sh index 0132bccb4..c771fb7a9 100755 --- a/hack/release.sh +++ b/hack/release.sh @@ -122,91 +122,113 @@ build_all() { fi } +upload_release_build() { + src="$1" + dst="$2" + latest="$3" + + echo + echo "Uploading $src" + echo " to $dst" + echo + s3cmd --follow-symlinks --preserve --acl-public put "$src" "$dst" + if [ "$latest" ]; then + echo + echo "Copying to $latest" + echo + s3cmd --acl-public cp "$dst" "$latest" + fi + + # get hash files too (see hash_files() in hack/make.sh) + for hashAlgo in md5 sha256; do + if [ -e "$src.$hashAlgo" ]; then + echo + echo "Uploading $src.$hashAlgo" + echo " to $dst.$hashAlgo" + echo + s3cmd --follow-symlinks --preserve --acl-public --mime-type='text/plain' put "$src.$hashAlgo" "$dst.$hashAlgo" + if [ "$latest" ]; then + echo + echo "Copying to $latest.$hashAlgo" + echo + s3cmd --acl-public cp "$dst.$hashAlgo" "$latest.$hashAlgo" + fi + fi + done +} + release_build() { GOOS=$1 GOARCH=$2 - SOURCE_DIR=bundles/$VERSION/cross/$GOOS/$GOARCH - BINARY=docker-$VERSION - BINARY_MD5=docker-$VERSION.md5 - BINARY_SHA256=docker-$VERSION.sha256 - TGZ=docker-$VERSION.tgz + binDir=bundles/$VERSION/cross/$GOOS/$GOARCH + tgzDir=bundles/$VERSION/tgz/$GOOS/$GOARCH + binary=docker-$VERSION + tgz=docker-$VERSION.tgz + + latestBase= + if [ -z "$NOLATEST" ]; then + latestBase=docker-latest + fi # we need to map our GOOS and GOARCH to uname values # see https://en.wikipedia.org/wiki/Uname # ie, GOOS=linux -> "uname -s"=Linux - S3OS=$GOOS - case "$S3OS" in + s3Os=$GOOS + case "$s3Os" in darwin) - S3OS=Darwin + s3Os=Darwin ;; freebsd) - S3OS=FreeBSD + s3Os=FreeBSD ;; linux) - S3OS=Linux + s3Os=Linux ;; *) - echo >&2 "error: can't convert $S3OS to an appropriate value for 'uname -s'" + echo >&2 "error: can't convert $s3Os to an appropriate value for 'uname -s'" exit 1 ;; esac - S3ARCH=$GOARCH - case "$S3ARCH" in + s3Arch=$GOARCH + case "$s3Arch" in amd64) - S3ARCH=x86_64 + s3Arch=x86_64 ;; 386) - S3ARCH=i386 + s3Arch=i386 ;; arm) - S3ARCH=armel + s3Arch=armel # someday, we might potentially support mutliple GOARM values, in which case we might get armhf here too ;; *) - echo >&2 "error: can't convert $S3ARCH to an appropriate value for 'uname -m'" + echo >&2 "error: can't convert $s3Arch to an appropriate value for 'uname -m'" exit 1 ;; esac - S3DIR=s3://$BUCKET/builds/$S3OS/$S3ARCH + s3Dir=s3://$BUCKET/builds/$s3Os/$s3Arch + latest= + latestTgz= + if [ "$latestBase" ]; then + latest="$s3Dir/$latestBase" + latestTgz="$s3Dir/$latestBase.tgz" + fi - if [ ! -x "$SOURCE_DIR/$BINARY" ]; then - echo >&2 "error: can't find $SOURCE_DIR/$BINARY - was it compiled properly?" + if [ ! -x "$binDir/$binary" ]; then + echo >&2 "error: can't find $binDir/$binary - was it compiled properly?" exit 1 fi - if [ ! -f "$TGZ" ]; then - echo >&2 "error: can't find $TGZ - was it packaged properly?" + if [ ! -f "$tgzDir/$tgz" ]; then + echo >&2 "error: can't find $tgzDir/$tgz - was it packaged properly?" exit 1 fi - echo "Uploading $BINARY to $S3OS/$S3ARCH/docker-$VERSION" - s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$BINARY $S3DIR/$BINARY - - echo "Uploading $BINARY_MD5 to $S3OS/$S3ARCH/docker-$VERSION.md5" - s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$BINARY_MD5 $S3DIR/$BINARY_MD5 - - echo "Uploading $BINARY_SHA256 to $S3OS/$S3ARCH/docker-$VERSION.sha256" - s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$BINARY_SHA256 $S3DIR/$BINARY_SHA256 - - echo "Uploading $TGZ to $S3OS/$S3ARCH/docker-$VERSION.tgz" - s3cmd --follow-symlinks --preserve --acl-public put $SOURCE_DIR/$TGZ $S3DIR/$TGZ - - if [ -z "$NOLATEST" ]; then - echo "Copying $S3DIR/$BINARY to $S3DIR/docker-latest" - s3cmd --acl-public cp $S3DIR/$BINARY $S3DIR/docker-latest - - echo "Copying $S3DIR/$BINARY_MD5 to $S3DIR/docker-latest.md5" - s3cmd --acl-public cp $S3DIR/$BINARY_MD5 $S3DIR/docker-latest.md5 - - echo "Copying $S3DIR/$BINARY_SHA256 to $S3DIR/docker-latest.sha256" - s3cmd --acl-public cp $S3DIR/$BINARY_SHA256 $S3DIR/docker-latest.sha256 - - echo "Copying $S3DIR/$TGZ $S3DIR/docker-latest.tgz" - s3cmd --acl-public cp $S3DIR/$TGZ $S3DIR/docker-latest.tgz - fi + upload_release_build "$binDir/$binary" "$s3Dir/$binary" "$latest" + upload_release_build "$tgzDir/$tgz" "$s3Dir/$tgz" "$latestTgz" } # Upload the 'ubuntu' bundle to S3: @@ -217,8 +239,6 @@ release_ubuntu() { echo >&2 './hack/make.sh must be run before release_ubuntu' exit 1 } - - s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ /.gnupg/ || true # Sign our packages dpkg-sig -g "--passphrase $GPG_PASSPHRASE" -k releasedocker \ @@ -318,10 +338,11 @@ release_test() { setup_gpg() { # Make sure that we have our keys mkdir -p /.gnupg/ + s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ /.gnupg/ || true gpg --list-keys releasedocker >/dev/null || { gpg --gen-key --batch < Date: Wed, 19 Mar 2014 20:37:36 +0200 Subject: [PATCH 32/35] retry to retrieve metadata on failure during pull This makes Docker retry to retrieve the JSON metadata for the layers. Docker will make 5 attempts to retrieve the metadata before failing and it will increase the delay between attempts after each failed attempt. This is a backport of PR #4387. The following changes had to be made: - img *image.Image + img *Image - img, err = image.NewImgJSON(imgJSON) + img, err = NewImgJSON(imgJSON) Docker-DCO-1.1-Signed-off-by: Cristian Staretu (github: unclejack) --- server.go | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/server.go b/server.go index c5ad24c4b..d6513d874 100644 --- a/server.go +++ b/server.go @@ -1067,16 +1067,32 @@ func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgID, endpoin if !srv.runtime.graph.Exists(id) { out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling metadata", nil)) - imgJSON, imgSize, err := r.GetRemoteImageJSON(id, endpoint, token) - if err != nil { - out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil)) - // FIXME: Keep going in case of error? - return err - } - img, err := NewImgJSON(imgJSON) - if err != nil { - out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil)) - return fmt.Errorf("Failed to parse json: %s", err) + var ( + imgJSON []byte + imgSize int + err error + img *Image + ) + retries := 5 + for j := 1; j <= retries; j++ { + imgJSON, imgSize, err = r.GetRemoteImageJSON(id, endpoint, token) + if err != nil && j == retries { + out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil)) + return err + } else if err != nil { + time.Sleep(time.Duration(j) * 500 * time.Millisecond) + continue + } + img, err = NewImgJSON(imgJSON) + if err != nil && j == retries { + out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil)) + return fmt.Errorf("Failed to parse json: %s", err) + } else if err != nil { + time.Sleep(time.Duration(j) * 500 * time.Millisecond) + continue + } else { + break + } } // Get the layer From b60e316b67b5d1b6cff72de26d55ac430d15134c Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Mon, 17 Mar 2014 17:42:16 -0700 Subject: [PATCH 33/35] Only unshare the mount namespace for execin Fixes #4728 Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) Conflicts: pkg/libcontainer/nsinit/execin.go: ns.logger.Println("unshare namespaces")' was removed already --- pkg/libcontainer/nsinit/execin.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/libcontainer/nsinit/execin.go b/pkg/libcontainer/nsinit/execin.go index 488fe0e24..628854ff3 100644 --- a/pkg/libcontainer/nsinit/execin.go +++ b/pkg/libcontainer/nsinit/execin.go @@ -14,9 +14,12 @@ import ( // ExecIn uses an existing pid and joins the pid's namespaces with the new command. func (ns *linuxNs) ExecIn(container *libcontainer.Container, nspid int, args []string) (int, error) { - for _, ns := range container.Namespaces { - if err := system.Unshare(ns.Value); err != nil { - return -1, err + for _, nsv := range container.Namespaces { + // skip the PID namespace on unshare because it it not supported + if nsv.Key != "NEWPID" { + if err := system.Unshare(nsv.Value); err != nil { + return -1, err + } } } fds, err := ns.getNsFds(nspid, container) From 8e681c34af7a539c152e224c0ff5091b092478f8 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 13 Mar 2014 11:11:02 -0700 Subject: [PATCH 34/35] Use BSD raw mode on darwin. Fixes nano, tmux and others Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes (github: creack) Conflicts: pkg/term/termios_freebsd.go: removed changes for this file because it's not present --- pkg/term/termios_darwin.go | 39 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/pkg/term/termios_darwin.go b/pkg/term/termios_darwin.go index 24e79de4b..11cd70d10 100644 --- a/pkg/term/termios_darwin.go +++ b/pkg/term/termios_darwin.go @@ -9,16 +9,24 @@ const ( getTermios = syscall.TIOCGETA setTermios = syscall.TIOCSETA - ECHO = 0x00000008 - ONLCR = 0x2 - ISTRIP = 0x20 - INLCR = 0x40 - ISIG = 0x80 - IGNCR = 0x80 - ICANON = 0x100 - ICRNL = 0x100 - IXOFF = 0x400 - IXON = 0x200 + IGNBRK = syscall.IGNBRK + PARMRK = syscall.PARMRK + INLCR = syscall.INLCR + IGNCR = syscall.IGNCR + ECHONL = syscall.ECHONL + CSIZE = syscall.CSIZE + ICRNL = syscall.ICRNL + ISTRIP = syscall.ISTRIP + PARENB = syscall.PARENB + ECHO = syscall.ECHO + ICANON = syscall.ICANON + ISIG = syscall.ISIG + IXON = syscall.IXON + BRKINT = syscall.BRKINT + INPCK = syscall.INPCK + OPOST = syscall.OPOST + CS8 = syscall.CS8 + IEXTEN = syscall.IEXTEN ) type Termios struct { @@ -41,10 +49,13 @@ func MakeRaw(fd uintptr) (*State, error) { } newState := oldState.termios - newState.Iflag &^= (ISTRIP | INLCR | IGNCR | IXON | IXOFF) - newState.Iflag |= ICRNL - newState.Oflag |= ONLCR - newState.Lflag &^= (ECHO | ICANON | ISIG) + newState.Iflag &^= (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON) + newState.Oflag &^= OPOST + newState.Lflag &^= (ECHO | ECHONL | ICANON | ISIG | IEXTEN) + newState.Cflag &^= (CSIZE | PARENB) + newState.Cflag |= CS8 + newState.Cc[syscall.VMIN] = 1 + newState.Cc[syscall.VTIME] = 0 if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&newState))); err != 0 { return nil, err From 3600720a36929b1a51a227699a337cc593e2534d Mon Sep 17 00:00:00 2001 From: unclejack Date: Mon, 24 Mar 2014 19:43:40 +0200 Subject: [PATCH 35/35] Bump to version v0.9.1 Docker-DCO-1.1-Signed-off-by: Cristian Staretu (github: unclejack) --- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++++++++++++ VERSION | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40ba3d32a..c8ea94361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,45 @@ # Changelog +## 0.9.1 (2014-03-24) + +#### Builder +- Fix printing multiple messages on a single line. Fixes broken output during builds. + +#### Documentation +- Fix external link on security of containers. + +#### Contrib +- Fix init script cgroup mounting workarounds to be more similar to cgroupfs-mount and thus work properly. +- Add variable for DOCKER_LOGFILE to sysvinit and use append instead of overwrite in opening the logfile. + +#### Hack +- Generate md5 and sha256 hashes when building, and upload them via hack/release.sh. + +#### Remote API +- Fix content-type detection in `docker cp`. + +#### Runtime +- Use BSD raw mode on Darwin. Fixes nano, tmux and others. +- Only unshare the mount namespace for execin. +- Retry to retrieve the layer metadata up to 5 times for `docker pull`. +- Merge existing config when committing. +- Fix panic in monitor. +- Disable daemon startup timeout. +- Fix issue #4681: add loopback interface when networking is disabled. +- Add failing test case for issue #4681. +- Send SIGTERM to child, instead of SIGKILL. +- Show the driver and the kernel version in `docker info` even when not in debug mode. +- Always symlink /dev/ptmx for libcontainer. This fixes console related problems. +- Fix issue caused by the absence of /etc/apparmor.d. +- Don't leave empty cidFile behind when failing to create the container. +- Improve deprecation message. +- Fix attach exit on darwin. +- devicemapper: improve handling of devicemapper devices (add per device lock, increase sleep time, unlock while sleeping). +- devicemapper: succeed immediately when removing non-existing devices. +- devicemapper: increase timeout in waitClose to 10 seconds. +- Remove goroutine leak on error. +- Update parseLxcInfo to comply with new lxc1.0 format. + ## 0.9.0 (2014-03-10) #### Builder diff --git a/VERSION b/VERSION index ac39a106c..f374f6662 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.0 +0.9.1