From 0bf56a21bc6393d3e965df68c86e18e8398b5ec1 Mon Sep 17 00:00:00 2001 From: Roger Peppe Date: Mon, 23 Sep 2013 01:06:31 +0100 Subject: [PATCH 001/112] use less reflection in command line method invocation Upstream-commit: 181b9badddf3571da395509d152eb244d87b6883 Component: engine --- components/engine/api_params.go | 14 +++++++------- components/engine/api_test.go | 1 - components/engine/commands.go | 22 ++++++++-------------- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/components/engine/api_params.go b/components/engine/api_params.go index 6403bc6a26..5f1a338057 100644 --- a/components/engine/api_params.go +++ b/components/engine/api_params.go @@ -56,13 +56,13 @@ type APIContainers struct { func (self *APIContainers) ToLegacy() APIContainersOld { return APIContainersOld{ - ID: self.ID, - Image: self.Image, - Command: self.Command, - Created: self.Created, - Status: self.Status, - Ports: displayablePorts(self.Ports), - SizeRw: self.SizeRw, + ID: self.ID, + Image: self.Image, + Command: self.Command, + Created: self.Created, + Status: self.Status, + Ports: displayablePorts(self.Ports), + SizeRw: self.SizeRw, SizeRootFs: self.SizeRootFs, } } diff --git a/components/engine/api_test.go b/components/engine/api_test.go index d24cf7cfda..0144513c05 100644 --- a/components/engine/api_test.go +++ b/components/engine/api_test.go @@ -566,7 +566,6 @@ func TestPostCommit(t *testing.T) { srv := &Server{runtime: runtime} - // Create a container and remove a file container, err := runtime.Create( &Config{ diff --git a/components/engine/commands.go b/components/engine/commands.go index df33dfc306..5ce21b4e28 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -36,9 +36,13 @@ var ( VERSION string ) -func (cli *DockerCli) getMethod(name string) (reflect.Method, bool) { +func (cli *DockerCli) getMethod(name string) (func(...string) error, bool) { methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:]) - return reflect.TypeOf(cli).MethodByName(methodName) + method := reflect.ValueOf(cli).MethodByName(methodName) + if !method.IsValid() { + return nil, false + } + return method.Interface().(func(...string) error), true } func ParseCommands(proto, addr string, args ...string) error { @@ -50,14 +54,7 @@ func ParseCommands(proto, addr string, args ...string) error { fmt.Println("Error: Command not found:", args[0]) return cli.CmdHelp(args[1:]...) } - ret := method.Func.CallSlice([]reflect.Value{ - reflect.ValueOf(cli), - reflect.ValueOf(args[1:]), - })[0].Interface() - if ret == nil { - return nil - } - return ret.(error) + return method(args[1:]...) } return cli.CmdHelp(args...) } @@ -68,10 +65,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error { if !exists { fmt.Fprintf(cli.err, "Error: Command not found: %s\n", args[0]) } else { - method.Func.CallSlice([]reflect.Value{ - reflect.ValueOf(cli), - reflect.ValueOf([]string{"--help"}), - })[0].Interface() + method("--help") return nil } } From 58ded672edfe9d72bc8f31304a136cd3105876c5 Mon Sep 17 00:00:00 2001 From: Paul Nasrat Date: Wed, 9 Oct 2013 16:40:46 -0400 Subject: [PATCH 002/112] Fixes issues with mounting subdirectories of /mnt in container. Tested with mkdir /mnt/data docker run -v /mnt/data:/mnt/data -t ubuntu:12.10 touch /mnt/data/bar Expected /mnt/data/bar on host. Upstream-commit: aa3697520a916ce2de525e020d2afa0bbd102df2 Component: engine --- components/engine/lxc_template.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/engine/lxc_template.go b/components/engine/lxc_template.go index 0e2dfafd47..37232a89d3 100644 --- a/components/engine/lxc_template.go +++ b/components/engine/lxc_template.go @@ -81,6 +81,8 @@ lxc.cgroup.devices.allow = c 10:200 rwm {{end}} # standard mount point +# Use mnt.putold as per https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/986385 +lxc.pivotdir = lxc_putold # WARNING: procfs is a known attack vector and should probably be disabled # if your userspace allows it. eg. see http://blog.zx2c4.com/749 lxc.mount.entry = proc {{$ROOTFS}}/proc proc nosuid,nodev,noexec 0 0 From 9c63bb13cc7e78336e03ae80ca4cc9d7da470233 Mon Sep 17 00:00:00 2001 From: Yang Bai Date: Mon, 14 Oct 2013 15:27:38 +0800 Subject: [PATCH 003/112] check return value of syscall.Chdir when changing working directory Upstream-commit: 1043055b10443c3b8d6b7c67c3e858a6b3ca9e00 Component: engine --- components/engine/AUTHORS | 1 + components/engine/sysinit.go | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/components/engine/AUTHORS b/components/engine/AUTHORS index 9a22e88de7..7b1bba49e7 100644 --- a/components/engine/AUTHORS +++ b/components/engine/AUTHORS @@ -185,4 +185,5 @@ Vladimir Kirillov Walter Stanish Wes Morgan Will Dietz +Yang Bai Zaiste! diff --git a/components/engine/sysinit.go b/components/engine/sysinit.go index 34f1cbdac6..c569d57264 100644 --- a/components/engine/sysinit.go +++ b/components/engine/sysinit.go @@ -27,7 +27,9 @@ func setupWorkingDirectory(workdir string) { if workdir == "" { return } - syscall.Chdir(workdir) + if err := syscall.Chdir(workdir); err != nil { + log.Fatalf("Unable to change dir to %v: %v", workdir, err) + } } // Takes care of dropping privileges to the desired user From 6d8f5d1b1a72c76142a0eea8773db10a39eb9251 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 15 Oct 2013 02:26:10 -0600 Subject: [PATCH 004/112] Rename mkimage-debian.sh to mkimage-debootstrap.sh to more clearly reflect its true function Upstream-commit: 4967f9f19ca9ead375f7d0b3252f543082806c36 Component: engine --- .../contrib/{mkimage-debian.sh => mkimage-debootstrap.sh} | 0 components/engine/docs/sources/use/baseimages.rst | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename components/engine/contrib/{mkimage-debian.sh => mkimage-debootstrap.sh} (100%) diff --git a/components/engine/contrib/mkimage-debian.sh b/components/engine/contrib/mkimage-debootstrap.sh similarity index 100% rename from components/engine/contrib/mkimage-debian.sh rename to components/engine/contrib/mkimage-debootstrap.sh diff --git a/components/engine/docs/sources/use/baseimages.rst b/components/engine/docs/sources/use/baseimages.rst index fa5c47b621..4785cc5298 100644 --- a/components/engine/docs/sources/use/baseimages.rst +++ b/components/engine/docs/sources/use/baseimages.rst @@ -40,4 +40,4 @@ Docker Github Repo: * `CentOS `_ * `Debian/Ubuntu - `_ + `_ From ef800becac31a50e4f58109fe43ad235a2a8e268 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 15 Oct 2013 02:26:52 -0600 Subject: [PATCH 005/112] Refactor mkimage-debootstrap.sh to be much more full-featured This includes the following: - options to control certain parameters - an option specifically for creating tarballs directly, esp. for dockerbrew - the addition of the updates and security repositories for Debian images - the addition of the universe, updates, and security repositories for Ubuntu images - more correct tagging of Debian images - tagging of Ubuntu image versions (12.04, 12.10, etc) and latest tag for LTS Upstream-commit: 095aab9d975a149c33729a0b4981d5b2649167d2 Component: engine --- .../engine/contrib/mkimage-debootstrap.sh | 250 ++++++++++++++---- 1 file changed, 198 insertions(+), 52 deletions(-) diff --git a/components/engine/contrib/mkimage-debootstrap.sh b/components/engine/contrib/mkimage-debootstrap.sh index c1abd4f7ac..e4c6b1c514 100755 --- a/components/engine/contrib/mkimage-debootstrap.sh +++ b/components/engine/contrib/mkimage-debootstrap.sh @@ -1,31 +1,114 @@ #!/bin/bash set -e -# these should match the names found at http://www.debian.org/releases/ -stableSuite='wheezy' -testingSuite='jessie' -unstableSuite='sid' - variant='minbase' include='iproute,iputils-ping' +arch='amd64' # intentionally undocumented for now +skipDetection= +strictDebootstrap= +justTar= + +usage() { + echo >&2 + + echo >&2 "usage: $0 [options] repo suite [mirror]" + + echo >&2 + echo >&2 'options: (not recommended)' + echo >&2 " -v $variant # change default debootstrap variant" + echo >&2 " -i $include # change default package includes" + echo >&2 " -d # strict debootstrap (do not apply any docker-specific tweaks)" + echo >&2 " -s # skip version detection and tagging (ie, precise also tagged as 12.04)" + echo >&2 " # note that this will also skip adding universe and/or security/updates to sources.list" + echo >&2 " -t # just create a tarball, especially for dockerbrew (uses repo as tarball name)" + + echo >&2 + echo >&2 " ie: $0 username/debian squeeze" + echo >&2 " $0 username/debian squeeze http://ftp.uk.debian.org/debian/" + + echo >&2 + echo >&2 " ie: $0 username/ubuntu precise" + echo >&2 " $0 username/ubuntu precise http://mirrors.melbourne.co.uk/ubuntu/" + + echo >&2 + echo >&2 " ie: $0 -t precise.tar.bz2 precise" + echo >&2 " $0 -t wheezy.tgz wheezy" + echo >&2 " $0 -t wheezy-uk.tar.xz wheezy http://ftp.uk.debian.org/debian/" + + echo >&2 +} + +# these should match the names found at http://www.debian.org/releases/ +debianStable=wheezy +debianUnstable=sid +# this should match the name found at http://releases.ubuntu.com/ +ubuntuLatestLTS=precise + +while getopts v:i:a:dst name; do + case "$name" in + v) + variant="$OPTARG" + ;; + i) + include="$OPTARG" + ;; + a) + arch="$OPTARG" + ;; + d) + strictDebootstrap=1 + ;; + s) + skipDetection=1 + ;; + t) + justTar=1 + ;; + ?) + usage + exit 0 + ;; + esac +done +shift $(($OPTIND - 1)) repo="$1" suite="$2" mirror="${3:-}" # stick to the default debootstrap mirror if one is not provided if [ ! "$repo" ] || [ ! "$suite" ]; then - echo >&2 "usage: $0 repo suite [mirror]" - echo >&2 - echo >&2 " ie: $0 tianon/debian squeeze" - echo >&2 " $0 tianon/debian squeeze http://ftp.uk.debian.org/debian/" - echo >&2 - echo >&2 " ie: $0 tianon/ubuntu precise" - echo >&2 " $0 tianon/ubuntu precise http://mirrors.melbourne.co.uk/ubuntu/" - echo >&2 + usage exit 1 fi -target="/tmp/docker-rootfs-debian-$suite-$$-$RANDOM" +# some rudimentary detection for whether we need to "sudo" our docker calls +docker='' +if docker version > /dev/null 2>&1; then + docker='docker' +elif sudo docker version > /dev/null 2>&1; then + docker='sudo docker' +elif command -v docker > /dev/null 2>&1; then + docker='docker' +else + echo >&2 "warning: either docker isn't installed, or your current user cannot run it;" + echo >&2 " this script is not likely to work as expected" + sleep 3 + docker='docker' # give us a command-not-found later +fi + +# make sure we have an absolute path to our final tarball so we can still reference it properly after we change directory +if [ "$justTar" ]; then + if [ ! -d "$(dirname "$repo")" ]; then + echo >&2 "error: $(dirname "$repo") does not exist" + exit 1 + fi + repo="$(cd "$(dirname "$repo")" && pwd -P)/$(basename "$repo")" +fi + +# will be filled in later, if [ -z "$skipDetection" ] +lsbDist='' + +target="/tmp/docker-rootfs-debootstrap-$suite-$$-$RANDOM" cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" returnTo="$(pwd -P)" @@ -34,48 +117,111 @@ set -x # bootstrap mkdir -p "$target" -sudo debootstrap --verbose --variant="$variant" --include="$include" "$suite" "$target" "$mirror" +sudo debootstrap --verbose --variant="$variant" --include="$include" --arch="$arch" "$suite" "$target" "$mirror" cd "$target" -# prevent init scripts from running during install/update -# policy-rc.d (for most scripts) -echo $'#!/bin/sh\nexit 101' | sudo tee usr/sbin/policy-rc.d > /dev/null -sudo chmod +x usr/sbin/policy-rc.d -# initctl (for some pesky upstart scripts) -sudo chroot . dpkg-divert --local --rename --add /sbin/initctl -sudo ln -sf /bin/true sbin/initctl -# see https://github.com/dotcloud/docker/issues/446#issuecomment-16953173 - -# shrink the image, since apt makes us fat (wheezy: ~157.5MB vs ~120MB) -sudo chroot . apt-get clean - -# while we're at it, apt is unnecessarily slow inside containers -# this forces dpkg not to call sync() after package extraction and speeds up install -# the benefit is huge on spinning disks, and the penalty is nonexistent on SSD or decent server virtualization -echo 'force-unsafe-io' | sudo tee etc/dpkg/dpkg.cfg.d/02apt-speedup > /dev/null -# we want to effectively run "apt-get clean" after every install to keep images small -echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' | sudo tee etc/apt/apt.conf.d/no-cache > /dev/null - -# helpful undo lines for each the above tweaks (for lack of a better home to keep track of them): -# rm /usr/sbin/policy-rc.d -# rm /sbin/initctl; dpkg-divert --rename --remove /sbin/initctl -# rm /etc/dpkg/dpkg.cfg.d/02apt-speedup -# rm /etc/apt/apt.conf.d/no-cache - -# create the image (and tag $repo:$suite) -sudo tar -c . | docker import - $repo $suite - -# test the image -docker run -i -t $repo:$suite echo success - -if [ "$suite" = "$stableSuite" -o "$suite" = 'stable' ]; then - # tag latest - docker tag $repo:$suite $repo latest +if [ -z "$strictDebootstrap" ]; then + # prevent init scripts from running during install/update + # policy-rc.d (for most scripts) + echo $'#!/bin/sh\nexit 101' | sudo tee usr/sbin/policy-rc.d > /dev/null + sudo chmod +x usr/sbin/policy-rc.d + # initctl (for some pesky upstart scripts) + sudo chroot . dpkg-divert --local --rename --add /sbin/initctl + sudo ln -sf /bin/true sbin/initctl + # see https://github.com/dotcloud/docker/issues/446#issuecomment-16953173 - # tag the specific debian release version - ver=$(docker run $repo:$suite cat /etc/debian_version) - docker tag $repo:$suite $repo $ver + # shrink the image, since apt makes us fat (wheezy: ~157.5MB vs ~120MB) + sudo chroot . apt-get clean + + # while we're at it, apt is unnecessarily slow inside containers + # this forces dpkg not to call sync() after package extraction and speeds up install + # the benefit is huge on spinning disks, and the penalty is nonexistent on SSD or decent server virtualization + echo 'force-unsafe-io' | sudo tee etc/dpkg/dpkg.cfg.d/02apt-speedup > /dev/null + # we want to effectively run "apt-get clean" after every install to keep images small + echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' | sudo tee etc/apt/apt.conf.d/no-cache > /dev/null + + # helpful undo lines for each the above tweaks (for lack of a better home to keep track of them): + # rm /usr/sbin/policy-rc.d + # rm /sbin/initctl; dpkg-divert --rename --remove /sbin/initctl + # rm /etc/dpkg/dpkg.cfg.d/02apt-speedup + # rm /etc/apt/apt.conf.d/no-cache + + if [ -z "$skipDetection" ]; then + # see also rudimentary platform detection in hack/install.sh + lsbDist='' + if [ -r etc/lsb-release ]; then + lsbDist="$(. etc/lsb-release && echo "$DISTRIB_ID")" + fi + if [ -z "$lsbDist" ] && [ -r etc/debian_version ]; then + lsbDist='Debian' + fi + + case "$lsbDist" in + Debian) + # add the updates and security repositories + if [ "$suite" != "$debianUnstable" -a "$suite" != 'unstable' ]; then + # ${suite}-updates only applies to non-unstable + sudo sed -i "p; s/ $suite main$/ ${suite}-updates main/" etc/apt/sources.list + + # same for security updates + echo "deb http://security.debian.org/ $suite/updates main" | sudo tee -a etc/apt/sources.list > /dev/null + fi + ;; + Ubuntu) + # add the universe, updates, and security repositories + sudo sed -i " + s/ $suite main$/ $suite main universe/; p; + s/ $suite main/ ${suite}-updates main/; p; + s/ $suite-updates main/ ${suite}-security main/ + " etc/apt/sources.list + ;; + esac + fi +fi + +if [ "$justTar" ]; then + # create the tarball file so it has the right permissions (ie, not root) + touch "$repo" + + # fill the tarball + sudo tar -caf "$repo" . +else + # create the image (and tag $repo:$suite) + sudo tar -c . | $docker import - $repo $suite + + # test the image + $docker run -i -t $repo:$suite echo success + + if [ -z "$skipDetection" ]; then + case "$lsbDist" in + Debian) + if [ "$suite" = "$debianStable" -o "$suite" = 'stable' ] && [ -r etc/debian_version ]; then + # tag latest + $docker tag $repo:$suite $repo latest + + if [ -r etc/debian_version ]; then + # tag the specific debian release version (which is only reasonable to tag on debian stable) + ver=$(cat etc/debian_version) + $docker tag $repo:$suite $repo $ver + fi + fi + ;; + Ubuntu) + if [ "$suite" = "$ubuntuLatestLTS" ]; then + # tag latest + $docker tag $repo:$suite $repo latest + fi + if [ -r etc/lsb-release ]; then + lsbRelease="$(. etc/lsb-release && echo "$DISTRIB_RELEASE")" + if [ "$lsbRelease" ]; then + # tag specific Ubuntu version number, if available (12.04, etc.) + $docker tag $repo:$suite $repo $lsbRelease + fi + fi + ;; + esac + fi fi # cleanup From 04a26ac7f0d9fdd69190de38e2c9a2b1ce14c499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Petazzoni?= Date: Thu, 10 Oct 2013 18:22:23 -0700 Subject: [PATCH 006/112] Try a different presentation of infrastructure documentation. Upstream-commit: 7b1c6ccabd1c1276c80abc1e818b45804a5d05ed Component: engine --- .../engine/hack/infrastructure/README.md | 80 +++++++++++++- .../engine/hack/infrastructure/overview.md | 103 ------------------ 2 files changed, 78 insertions(+), 105 deletions(-) delete mode 100644 components/engine/hack/infrastructure/overview.md diff --git a/components/engine/hack/infrastructure/README.md b/components/engine/hack/infrastructure/README.md index 126792a6b0..a3641f6dc8 100644 --- a/components/engine/hack/infrastructure/README.md +++ b/components/engine/hack/infrastructure/README.md @@ -1,5 +1,81 @@ # Docker project infrastructure -This directory holds all information about the technical infrastructure of the docker project; servers, dns, email, and all the corresponding tools and configuration. +This is an overview of the Docker infrastructure. -Obviously credentials should not be stored in this repo, but how to obtain and use them should be documented here. +**Note: obviously, credentials should not be stored in this repository.** +However, when there are credentials, we should list how to obtain them +(e.g. who has them). + + +## Providers + +This should be the list of all the entities providing some kind of +infrastructure service to the Docker project (either for free, +or paid by dotCloud). + + +Provider | Service +--------------|------------------------------------------------- +AWS | packages (S3 bucket), dotCloud PAAS, dev-env, ci +CloudFlare | cdn +Digital Ocean | ci +dotCloud PAAS | website, index, registry, ssl, blog +DynECT | dns (docker.io) +GitHub | repository +Linode | dev-env +Mailgun | outgoing e-mail +ReadTheDocs | docs + +*Ordered-by: lexicographic* + + +## URLs + +This should be the list of all the infrastructure-related URLs +and which service is handling them. + +URL | Service +--------------------------------------------|--------------------------------- + http://blog.docker.io/ | blog +*http://cdn-registry-1.docker.io/ | registry (pull) + http://debug.docker.io/ | debug tool + http://docs.docker.io/ | docsproxy (proxy to readthedocs) + http://docker-ci.dotcloud.com/ | ci + http://docker.io/ | redirect to www.docker.io (dynect) + http://docker.readthedocs.org/ | docs +*http://get.docker.io/ | packages + https://github.com/dotcloud/docker | repository +*https://index.docker.io/ | index + http://registry-1.docker.io/ | registry (push) + http://staging-docker-ci.dotcloud.com/ | ci +*http://test.docker.io/ | packages +*http://www.docker.io/ | website + +*Ordered-by: lexicographic* + +**Note:** an asterisk in front of the URL means that it is cached by CloudFlare. + + +## Services + +This should be the list of all services referenced above. + +Service | Maintainer(s) | How to update | Source +--------------------|--------------------|------------------|------- +blog | @jbarbier | dotcloud push | https://github.com/dotcloud/blog.docker.io +cdn | @jpetazzo @samalba | cloudflare panel | N/A +ci | @mzdaniel | See [docker-ci] | See [docker-ci] +docs | @metalivedev | github webhook | docker repo +docsproxy | @dhrp | dotcloud push | https://github.com/dotcloud/docker-docs-dotcloud-proxy +index | @kencochrane | dotcloud push | private +packages | @jpetazzo | hack/release | docker repo +registry | @samalba | dotcloud push | https://github.com/dotcloud/docker-registry +repository (github) | N/A | N/A | N/A +ssl (dotcloud) | @jpetazzo | dotcloud ops | N/A +ssl (cloudflare) | @jpetazzo | cloudflare panel | N/A +website | @dhrp | dotcloud push | https://github.com/dotcloud/www.docker.io + +*Ordered-by: lexicographic* + + +[docker-ci]: docker-ci.rst diff --git a/components/engine/hack/infrastructure/overview.md b/components/engine/hack/infrastructure/overview.md deleted file mode 100644 index 592c9b0b22..0000000000 --- a/components/engine/hack/infrastructure/overview.md +++ /dev/null @@ -1,103 +0,0 @@ -# Docker Server Overview -This is an overview of the Docker infrastructure - -## Docker Git Repo -The Docker source code lives on github.com under the dotCloud account. -https://github.com/dotcloud/docker - -## DNS -We are using dyn.com for our DNS server for the docker.io domain. -It is using the dotCloud account. - -### DNS Redirect -We have a DNS redirect in dyn.com that will automatically redirect -docker.io to www.docker.io - -## email -Email is sent via dotCloud account on MailGun.com - -## CDN -We are using a CDN in front of some of the docker.io domains to help improve -proformance. The CDN is Cloudflare, using a Pro account. - -*This is currently disabled due to an issue with slow performance during pull -in some regions of the world.* - -### CDN Domains -- www.docker.io -- test.docker.io -- registry-1.docker.io -- debug.docker.io -- cdn-registry-1.docker.io - -## edge-docker.dotcloud.com -All of the Docker applications that live on dotCloud go through their own -load balancer, and this is where SSL is terminated as well. - -## www.docker.io -This is hosted under the docker account on dotCloud's PaaS. - -### Source Code -The source code for the website lives here: -https://github.com/dotcloud/www.docker.io - -## Docker Registry -The registry is where the image data is store. - -### URL: -- registry-1.docker.io -- cdn-registry-1.docker.io - -There are two urls, one is behind a CDN the other isn't this is because when -you pull, you pull from the CDN url, to help with pull speeds. We don't push -through the CDN as well, because it doesn't help us, so we bypass it. - -### Data Store: -The data store for the registry is using Amazon S3 in a bucket under the docker -aws account. - -### Source Code -The source code for the registry lives here: https://github.com/dotcloud/docker-registry - -### Hosted: -Hosted on the Docker account on dotCloud's PaaS - -## index.docker.io -This is the docker index, it stores all of the meta information about the -docker images, but all data is stored in the registry. - -### Source Code: -Not available - -### Hosted: -Hosted on the Docker account on dotCloud's PaaS - -## blog.docker.io -This is a wordpress based Docker blog. - -### URL: -http://blog.docker.io - -### Source Code: -https://github.com/dotcloud/blog.docker.io - -## docs.docker.io -This is where all of the documentation for docker lives. - -### Hosted: -This website is hosted on ReadTheDocs.org. - -### Updates -These docs get automatically updated when the Docker repo on github has -new commits. It does this via a webhook. - -### Proxy: -This is a simple dotcloud app, with its main and only purpose to forward -http (and https) requests to docker.readthedocs.org. - -https://github.com/dotcloud/docker-docs-dotcloud-proxy - -## get.docker.io -This is the docker repository where we store images - -TODO: need more here. jerome? From e2a6017ff61f68b74925a73171168d7f621629bd Mon Sep 17 00:00:00 2001 From: Edmund Wagner Date: Thu, 17 Oct 2013 09:31:35 +0200 Subject: [PATCH 007/112] make copy paste user friendly copying only the first line killed my sources.list file Upstream-commit: 2110b3cca80da253d2fd7443480509a3b58a19e2 Component: engine --- components/engine/docs/sources/installation/ubuntulinux.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/engine/docs/sources/installation/ubuntulinux.rst b/components/engine/docs/sources/installation/ubuntulinux.rst index e653f704a8..f3406c5b4b 100644 --- a/components/engine/docs/sources/installation/ubuntulinux.rst +++ b/components/engine/docs/sources/installation/ubuntulinux.rst @@ -78,7 +78,8 @@ Docker is available as a Debian package, which makes installation easy. sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -" # Add the Docker repository to your apt sources list. - sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list" + sudo sh -c "echo deb http://get.docker.io/ubuntu docker main\ + > /etc/apt/sources.list.d/docker.list" # Update your sources sudo apt-get update From 438bef94302854cf2beb69cf075f55c9b95d62f8 Mon Sep 17 00:00:00 2001 From: Edmund Wagner Date: Thu, 17 Oct 2013 10:07:12 +0200 Subject: [PATCH 008/112] c&p improvement for 13.04 first line killed sources list Upstream-commit: bc39ac71e66327aa73c44633b374ef75630909dc Component: engine --- components/engine/docs/sources/installation/ubuntulinux.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/engine/docs/sources/installation/ubuntulinux.rst b/components/engine/docs/sources/installation/ubuntulinux.rst index f3406c5b4b..fd869fbe9c 100644 --- a/components/engine/docs/sources/installation/ubuntulinux.rst +++ b/components/engine/docs/sources/installation/ubuntulinux.rst @@ -133,7 +133,8 @@ to follow them again.* sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -" # Add the Docker repository to your apt sources list. - sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list" + sudo sh -c "echo deb http://get.docker.io/ubuntu docker main\ + > /etc/apt/sources.list.d/docker.list" # update sudo apt-get update From 82851ecb8f04d415bbd5fbcc7c3843b4acb6f63a Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 15 Oct 2013 09:37:18 -0600 Subject: [PATCH 009/112] Add initial init scripts library, including systemd, sysvinit, upstart, and openrc Upstream-commit: c405d53b6e6658b1cbe9ad7ba52ea6dc9330f546 Component: engine --- .../engine/contrib/init/openrc/docker.confd | 13 +++ .../engine/contrib/init/openrc/docker.initd | 31 +++++++ .../contrib/init/systemd/docker.service | 13 +++ .../engine/contrib/init/sysvinit/docker | 85 +++++++++++++++++++ .../engine/contrib/init/upstart/docker.conf | 10 +++ 5 files changed, 152 insertions(+) create mode 100644 components/engine/contrib/init/openrc/docker.confd create mode 100755 components/engine/contrib/init/openrc/docker.initd create mode 100644 components/engine/contrib/init/systemd/docker.service create mode 100755 components/engine/contrib/init/sysvinit/docker create mode 100644 components/engine/contrib/init/upstart/docker.conf diff --git a/components/engine/contrib/init/openrc/docker.confd b/components/engine/contrib/init/openrc/docker.confd new file mode 100644 index 0000000000..ae247c007e --- /dev/null +++ b/components/engine/contrib/init/openrc/docker.confd @@ -0,0 +1,13 @@ +# /etc/conf.d/docker: config file for /etc/init.d/docker + +# where the docker daemon output gets piped +#DOCKER_LOGFILE="/var/log/docker.log" + +# where docker's pid get stored +#DOCKER_PIDFILE="/run/docker.pid" + +# where the docker daemon itself is run from +#DOCKER_BINARY="/usr/bin/docker" + +# any other random options you want to pass to docker +DOCKER_OPTS="" diff --git a/components/engine/contrib/init/openrc/docker.initd b/components/engine/contrib/init/openrc/docker.initd new file mode 100755 index 0000000000..2d79a73973 --- /dev/null +++ b/components/engine/contrib/init/openrc/docker.initd @@ -0,0 +1,31 @@ +#!/sbin/runscript +# Copyright 1999-2013 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DOCKER_LOGFILE=${DOCKER_LOGFILE:-/var/log/${SVCNAME}.log} +DOCKER_PIDFILE=${DOCKER_PIDFILE:-/run/${SVCNAME}.pid} +DOCKER_BINARY=${DOCKER_BINARY:-/usr/bin/docker} +DOCKER_OPTS=${DOCKER_OPTS:-} + +start() { + checkpath -f -m 0644 -o root:docker "$DOCKER_LOGFILE" + + ebegin "Starting docker daemon" + start-stop-daemon --start --background \ + --exec "$DOCKER_BINARY" \ + --pidfile "$DOCKER_PIDFILE" \ + --stdout "$DOCKER_LOGFILE" \ + --stderr "$DOCKER_LOGFILE" \ + -- -d -p "$DOCKER_PIDFILE" \ + $DOCKER_OPTS + eend $? +} + +stop() { + ebegin "Stopping docker daemon" + start-stop-daemon --stop \ + --exec "$DOCKER_BINARY" \ + --pidfile "$DOCKER_PIDFILE" + eend $? +} diff --git a/components/engine/contrib/init/systemd/docker.service b/components/engine/contrib/init/systemd/docker.service new file mode 100644 index 0000000000..dacb0b74f5 --- /dev/null +++ b/components/engine/contrib/init/systemd/docker.service @@ -0,0 +1,13 @@ +[Unit] +Description=Easily create lightweight, portable, self-sufficient containers from any application! +Documentation=http://docs.docker.io +Requires=network.target +After=multi-user.target + +[Service] +Type=simple +ExecStartPre=/bin/mount --make-rprivate / +ExecStart=/usr/bin/docker -d + +[Install] +WantedBy=multi-user.target diff --git a/components/engine/contrib/init/sysvinit/docker b/components/engine/contrib/init/sysvinit/docker new file mode 100755 index 0000000000..5a457db785 --- /dev/null +++ b/components/engine/contrib/init/sysvinit/docker @@ -0,0 +1,85 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: docker +# Required-Start: $syslog $remote_fs +# Required-Stop: $syslog $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Linux container runtime +# Description: Linux container runtime +### END INIT INFO + +DOCKER=/usr/bin/docker +DOCKER_PIDFILE=/var/run/docker.pid +DOCKER_OPTS= + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin + +# Check lxc-docker is present +[ -x $DOCKER ] || (log_failure_msg "docker not present"; exit 1) + +# Get lsb functions +. /lib/lsb/init-functions + +if [ -f /etc/default/lxc ]; then + . /etc/default/lxc +fi + +if [ "$1" = start ] && which initctl >/dev/null && initctl version | grep -q upstart; then + exit 1 +fi + +check_root_id () +{ + if [ "$(id -u)" != "0" ]; then + log_failure_msg "Docker must be run as root"; exit 1 + fi +} + +case "$1" in + start) + check_root_id || exit 1 + log_begin_msg "Starting Docker" + mount | grep cgroup >/dev/null || mount -t cgroup none /sys/fs/cgroup 2>/dev/null + start-stop-daemon --start --background $NO_CLOSE \ + --exec "$DOCKER" \ + --pidfile "$DOCKER_PIDFILE" \ + -- -d -p "$DOCKER_PIDFILE" \ + $DOCKER_OPTS + log_end_msg $? + ;; + + stop) + check_root_id || exit 1 + log_begin_msg "Stopping Docker" + start-stop-daemon --stop \ + --pidfile "$DOCKER_PIDFILE" + log_end_msg $? + ;; + + restart) + check_root_id || exit 1 + docker_pid=`cat "$DOCKER_PIDFILE" 2>/dev/null` + [ -n "$docker_pid" ] \ + && ps -p $docker_pid > /dev/null 2>&1 \ + && $0 stop + $0 start + ;; + + force-reload) + check_root_id || exit 1 + $0 restart + ;; + + status) + status_of_proc -p "$DOCKER_PIDFILE" "$DOCKER" docker + ;; + + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/components/engine/contrib/init/upstart/docker.conf b/components/engine/contrib/init/upstart/docker.conf new file mode 100644 index 0000000000..72c132c860 --- /dev/null +++ b/components/engine/contrib/init/upstart/docker.conf @@ -0,0 +1,10 @@ +description "Docker daemon" + +start on filesystem and started lxc-net +stop on runlevel [!2345] + +respawn + +script + /usr/bin/docker -d +end script From fe7c7ab66657cbeeb675a22920506ce96a200ca6 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Thu, 17 Oct 2013 11:26:17 -0700 Subject: [PATCH 010/112] Update CHANGELOG.md Upstream-commit: 47cc6c808161057f3a04f090dc01f32da2132b47 Component: engine --- components/engine/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/CHANGELOG.md b/components/engine/CHANGELOG.md index ddd8580a10..b81e0d7706 100644 --- a/components/engine/CHANGELOG.md +++ b/components/engine/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.6.4 (2013-10-15) +## 0.6.4 (2013-10-16) - Runtime: Add cleanup of container when Start() fails - Testing: Catch errClosing error when TCP and UDP proxies are terminated - Testing: Add aggregated docker-ci email report From 427dad8458d6457d7034db227487b06873837c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Petazzoni?= Date: Thu, 17 Oct 2013 14:11:10 -0700 Subject: [PATCH 011/112] Add Stackbrew. Upstream-commit: d401e9d3ace06d3291ddd96a8ab8aa690d5935dc Component: engine --- .../engine/hack/infrastructure/README.md | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/components/engine/hack/infrastructure/README.md b/components/engine/hack/infrastructure/README.md index a3641f6dc8..a74f1f4095 100644 --- a/components/engine/hack/infrastructure/README.md +++ b/components/engine/hack/infrastructure/README.md @@ -22,7 +22,7 @@ Digital Ocean | ci dotCloud PAAS | website, index, registry, ssl, blog DynECT | dns (docker.io) GitHub | repository -Linode | dev-env +Linode | stackbrew Mailgun | outgoing e-mail ReadTheDocs | docs @@ -34,22 +34,23 @@ ReadTheDocs | docs This should be the list of all the infrastructure-related URLs and which service is handling them. -URL | Service ---------------------------------------------|--------------------------------- - http://blog.docker.io/ | blog -*http://cdn-registry-1.docker.io/ | registry (pull) - http://debug.docker.io/ | debug tool - http://docs.docker.io/ | docsproxy (proxy to readthedocs) - http://docker-ci.dotcloud.com/ | ci - http://docker.io/ | redirect to www.docker.io (dynect) - http://docker.readthedocs.org/ | docs -*http://get.docker.io/ | packages - https://github.com/dotcloud/docker | repository -*https://index.docker.io/ | index - http://registry-1.docker.io/ | registry (push) - http://staging-docker-ci.dotcloud.com/ | ci -*http://test.docker.io/ | packages -*http://www.docker.io/ | website +URL | Service +---------------------------------------------|--------------------------------- + http://blog.docker.io/ | blog +*http://cdn-registry-1.docker.io/ | registry (pull) + http://debug.docker.io/ | debug tool + http://docs.docker.io/ | docsproxy (proxy to readthedocs) + http://docker-ci.dotcloud.com/ | ci + http://docker.io/ | redirect to www.docker.io (dynect) + http://docker.readthedocs.org/ | docs +*http://get.docker.io/ | packages + https://github.com/dotcloud/docker | repository +*https://index.docker.io/ | index + http://registry-1.docker.io/ | registry (push) + http://staging-docker-ci.dotcloud.com/ | ci +*http://test.docker.io/ | packages +*http://www.docker.io/ | website + http://? (internal URL, not for public use) | stackbrew *Ordered-by: lexicographic* @@ -73,6 +74,7 @@ registry | @samalba | dotcloud push | https://github.com repository (github) | N/A | N/A | N/A ssl (dotcloud) | @jpetazzo | dotcloud ops | N/A ssl (cloudflare) | @jpetazzo | cloudflare panel | N/A +stackbrew | @shin- | manual | https://github.com/dotcloud/stackbrew/stackbrew website | @dhrp | dotcloud push | https://github.com/dotcloud/www.docker.io *Ordered-by: lexicographic* From b73b1d5688aedc4e2a519ae8f0d17a52b0eb1506 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Thu, 17 Oct 2013 02:08:14 -0600 Subject: [PATCH 012/112] Update hack/release.sh process to automatically invoke hack/make.sh and bail on building/testing issues Upstream-commit: 83a2e92d47bc1d78a44b9508656725a043f08b6b Component: engine --- components/engine/hack/make.sh | 3 +- components/engine/hack/release.sh | 75 ++++++++++++++++++++++++------- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/components/engine/hack/make.sh b/components/engine/hack/make.sh index 98b62ea6ae..f911c035f2 100755 --- a/components/engine/hack/make.sh +++ b/components/engine/hack/make.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -e # This script builds various binary artifacts from a checkout of the docker # source code. @@ -19,7 +20,7 @@ # "docker run hack/make.sh" in the resulting container image. # -set -e +set -o pipefail # We're a nice, sexy, little shell script, and people might try to run us; # but really, they shouldn't. We want to be in a container! diff --git a/components/engine/hack/release.sh b/components/engine/hack/release.sh index 12ad27dce3..56538ea70a 100755 --- a/components/engine/hack/release.sh +++ b/components/engine/hack/release.sh @@ -1,4 +1,5 @@ -#!/bin/sh +#!/bin/bash +set -e # This script looks for bundles built by make.sh, and releases them on a # public S3 bucket. @@ -9,11 +10,11 @@ # official Dockerfile at the root of the Docker source code. The Dockerfile, # make.sh and release.sh should all be from the same source code revision. -set -e +set -o pipefail # Print a usage message and exit. usage() { - cat <&2 <<'EOF' To run, I need: - to be in a container generated by the Dockerfile at the top of the Docker repository; @@ -26,11 +27,12 @@ To run, I need: - a generous amount of good will and nice manners. The canonical way to run me is to run the image produced by the Dockerfile: e.g.:" -docker run -e AWS_S3_BUCKET=get-staging.docker.io \\ - AWS_ACCESS_KEY=AKI1234... \\ - AWS_SECRET_KEY=sEs4mE... \\ - GPG_PASSPHRASE=m0resEs4mE... \\ - f0058411 +docker run -e AWS_S3_BUCKET=get-staging.docker.io \ + -e AWS_ACCESS_KEY=AKI1234... \ + -e AWS_SECRET_KEY=sEs4mE... \ + -e GPG_PASSPHRASE=m0resEs4mE... \ + -i -t -privileged \ + docker ./hack/release.sh EOF exit 1 } @@ -39,8 +41,41 @@ EOF [ "$AWS_ACCESS_KEY" ] || usage [ "$AWS_SECRET_KEY" ] || usage [ "$GPG_PASSPHRASE" ] || usage -[ -d /go/src/github.com/dotcloud/docker/ ] || usage -cd /go/src/github.com/dotcloud/docker/ +[ -d /go/src/github.com/dotcloud/docker ] || usage +cd /go/src/github.com/dotcloud/docker +[ -x hack/make.sh ] || usage + +RELEASE_BUNDLES=( + binary + ubuntu +) + +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 @@ -81,11 +116,15 @@ s3_url() { # 1. A full APT repository is published at $BUCKET/ubuntu/ # 2. Instructions for using the APT repository are uploaded at $BUCKET/ubuntu/info release_ubuntu() { + [ -e bundles/$VERSION/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 < /etc/apt/sources.list.d/docker.list curl $(s3_url)/gpg | apt-key add - # Install docker apt-get update ; apt-get install -y lxc-docker + +# +# Alternatively, just use the curl-able install.sh script provided at $(s3_url) +# EOF echo "APT repository uploaded. Instructions available at $(s3_url)/ubuntu/info" } # Upload a static binary to S3 release_binary() { - [ -e bundles/$VERSION ] + [ -e bundles/$VERSION/binary/docker-$VERSION ] || { + echo >&2 './hack/make.sh must be run before release_binary' + exit 1 + } S3DIR=s3://$BUCKET/builds/Linux/x86_64 s3cmd --acl-public put bundles/$VERSION/binary/docker-$VERSION $S3DIR/docker-$VERSION cat < Date: Thu, 17 Oct 2013 23:40:43 +0000 Subject: [PATCH 013/112] clean split between errors and output. JSON output always valid Upstream-commit: 8bce284496e60231ac2e82fc023ff1faadff6aa5 Component: engine --- components/engine/commands.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/components/engine/commands.go b/components/engine/commands.go index 7d33b81d0a..18661d83a9 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -577,11 +577,10 @@ func (cli *DockerCli) CmdInspect(args ...string) error { cmd.Usage() return nil } - fmt.Fprintf(cli.out, "[") - for i, name := range args { - if i > 0 { - fmt.Fprintf(cli.out, ",") - } + + indented := new(bytes.Buffer) + + for _, name := range args { obj, _, err := cli.call("GET", "/containers/"+name+"/json", nil) if err != nil { obj, _, err = cli.call("GET", "/images/"+name+"/json", nil) @@ -591,14 +590,18 @@ func (cli *DockerCli) CmdInspect(args ...string) error { } } - indented := new(bytes.Buffer) if err = json.Indent(indented, obj, "", " "); err != nil { fmt.Fprintf(cli.err, "%s\n", err) continue } - if _, err := io.Copy(cli.out, indented); err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - } + indented.WriteString(",") + } + // Remove trailling ',' + indented.Truncate(indented.Len() - 1) + + fmt.Fprintf(cli.out, "[") + if _, err := io.Copy(cli.out, indented); err != nil { + fmt.Fprintf(cli.err, "%s\n", err) } fmt.Fprintf(cli.out, "]") return nil From ce87496ba9eb908e5b4a3e001382449952769ec2 Mon Sep 17 00:00:00 2001 From: Andy Rothfusz Date: Thu, 17 Oct 2013 17:57:01 -0700 Subject: [PATCH 014/112] Clean up build warnings. Remove redundant files. Upstream-commit: 689bcd1dc3afdcae5bd45e32541b464fcf3ecbd0 Component: engine --- components/engine/docs/sources/api/index.rst | 2 +- .../engine/docs/sources/commandline/cli.rst | 702 ++++++++++++++++-- .../sources/commandline/command/attach.rst | 59 -- .../sources/commandline/command/build.rst | 65 -- .../sources/commandline/command/commit.rst | 52 -- .../docs/sources/commandline/command/cp.rst | 14 - .../docs/sources/commandline/command/diff.rst | 13 - .../sources/commandline/command/events.rst | 34 - .../sources/commandline/command/export.rst | 13 - .../sources/commandline/command/history.rst | 13 - .../sources/commandline/command/images.rst | 26 - .../sources/commandline/command/import.rst | 44 -- .../docs/sources/commandline/command/info.rst | 13 - .../sources/commandline/command/insert.rst | 23 - .../sources/commandline/command/inspect.rst | 13 - .../docs/sources/commandline/command/kill.rst | 13 - .../sources/commandline/command/login.rst | 24 - .../docs/sources/commandline/command/logs.rst | 13 - .../docs/sources/commandline/command/port.rst | 13 - .../docs/sources/commandline/command/ps.rst | 17 - .../docs/sources/commandline/command/pull.rst | 13 - .../docs/sources/commandline/command/push.rst | 13 - .../sources/commandline/command/restart.rst | 13 - .../docs/sources/commandline/command/rm.rst | 13 - .../docs/sources/commandline/command/rmi.rst | 13 - .../docs/sources/commandline/command/run.rst | 85 --- .../sources/commandline/command/search.rst | 14 - .../sources/commandline/command/start.rst | 13 - .../docs/sources/commandline/command/stop.rst | 15 - .../docs/sources/commandline/command/tag.rst | 15 - .../docs/sources/commandline/command/top.rst | 13 - .../sources/commandline/command/version.rst | 7 - .../docs/sources/commandline/command/wait.rst | 13 - .../docker_images.gif | Bin .../engine/docs/sources/commandline/index.rst | 35 +- .../docs/sources/examples/hello_world.rst | 2 +- components/engine/docs/sources/index.rst | 2 - 37 files changed, 651 insertions(+), 794 deletions(-) delete mode 100644 components/engine/docs/sources/commandline/command/attach.rst delete mode 100644 components/engine/docs/sources/commandline/command/build.rst delete mode 100644 components/engine/docs/sources/commandline/command/commit.rst delete mode 100644 components/engine/docs/sources/commandline/command/cp.rst delete mode 100644 components/engine/docs/sources/commandline/command/diff.rst delete mode 100644 components/engine/docs/sources/commandline/command/events.rst delete mode 100644 components/engine/docs/sources/commandline/command/export.rst delete mode 100644 components/engine/docs/sources/commandline/command/history.rst delete mode 100644 components/engine/docs/sources/commandline/command/images.rst delete mode 100644 components/engine/docs/sources/commandline/command/import.rst delete mode 100644 components/engine/docs/sources/commandline/command/info.rst delete mode 100644 components/engine/docs/sources/commandline/command/insert.rst delete mode 100644 components/engine/docs/sources/commandline/command/inspect.rst delete mode 100644 components/engine/docs/sources/commandline/command/kill.rst delete mode 100644 components/engine/docs/sources/commandline/command/login.rst delete mode 100644 components/engine/docs/sources/commandline/command/logs.rst delete mode 100644 components/engine/docs/sources/commandline/command/port.rst delete mode 100644 components/engine/docs/sources/commandline/command/ps.rst delete mode 100644 components/engine/docs/sources/commandline/command/pull.rst delete mode 100644 components/engine/docs/sources/commandline/command/push.rst delete mode 100644 components/engine/docs/sources/commandline/command/restart.rst delete mode 100644 components/engine/docs/sources/commandline/command/rm.rst delete mode 100644 components/engine/docs/sources/commandline/command/rmi.rst delete mode 100644 components/engine/docs/sources/commandline/command/run.rst delete mode 100644 components/engine/docs/sources/commandline/command/search.rst delete mode 100644 components/engine/docs/sources/commandline/command/start.rst delete mode 100644 components/engine/docs/sources/commandline/command/stop.rst delete mode 100644 components/engine/docs/sources/commandline/command/tag.rst delete mode 100644 components/engine/docs/sources/commandline/command/top.rst delete mode 100644 components/engine/docs/sources/commandline/command/version.rst delete mode 100644 components/engine/docs/sources/commandline/command/wait.rst rename components/engine/docs/sources/{static_files => commandline}/docker_images.gif (100%) diff --git a/components/engine/docs/sources/api/index.rst b/components/engine/docs/sources/api/index.rst index d7345e8746..017369143c 100644 --- a/components/engine/docs/sources/api/index.rst +++ b/components/engine/docs/sources/api/index.rst @@ -14,5 +14,5 @@ Your programs and scripts can access Docker's functionality via these interfaces registry_api index_api docker_remote_api - + remote_api_client_libraries diff --git a/components/engine/docs/sources/commandline/cli.rst b/components/engine/docs/sources/commandline/cli.rst index 62dd3707a1..71a902d46f 100644 --- a/components/engine/docs/sources/commandline/cli.rst +++ b/components/engine/docs/sources/commandline/cli.rst @@ -4,11 +4,8 @@ .. _cli: -Overview -====================== - -Docker Usage -~~~~~~~~~~~~~~~~~~ +Command Line Help +----------------- To list available commands, either run ``docker`` with no parameters or execute ``docker help``:: @@ -21,71 +18,666 @@ To list available commands, either run ``docker`` with no parameters or execute ... +.. _cli_attach: + +``attach`` +---------- + +:: + + Usage: docker attach CONTAINER + + Attach to a running container. + +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. + +To stop a container, use ``docker stop`` + +To kill the container, use ``docker kill`` + +.. _cli_attach_examples: + +Examples: +~~~~~~~~~ + +.. code-block:: bash + + $ ID=$(sudo docker run -d ubuntu /usr/bin/top -b) + $ sudo docker attach $ID + top - 02:05:52 up 3:05, 0 users, load average: 0.01, 0.02, 0.05 + Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie + Cpu(s): 0.1%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st + Mem: 373572k total, 355560k used, 18012k free, 27872k buffers + Swap: 786428k total, 0k used, 786428k free, 221740k cached + + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 17200 1116 912 R 0 0.3 0:00.03 top + + top - 02:05:55 up 3:05, 0 users, load average: 0.01, 0.02, 0.05 + Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie + Cpu(s): 0.0%us, 0.2%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st + Mem: 373572k total, 355244k used, 18328k free, 27872k buffers + Swap: 786428k total, 0k used, 786428k free, 221776k cached + + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top -Available Commands -~~~~~~~~~~~~~~~~~~ + top - 02:05:58 up 3:06, 0 users, load average: 0.01, 0.02, 0.05 + Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie + Cpu(s): 0.2%us, 0.3%sy, 0.0%ni, 99.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st + Mem: 373572k total, 355780k used, 17792k free, 27880k buffers + Swap: 786428k total, 0k used, 786428k free, 221776k cached -.. include:: command/attach.rst + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top + ^C$ + $ sudo docker stop $ID -.. include:: command/build.rst +.. _cli_build: -.. include:: command/commit.rst +``build`` +--------- -.. include:: command/cp.rst +:: -.. include:: command/diff.rst + Usage: docker build [OPTIONS] PATH | URL | - + Build a new container image from the source code at PATH + -t="": Repository name (and optionally a tag) to be applied to the resulting image in case of success. + -q=false: Suppress verbose build output. + -no-cache: Do not use the cache when building the image. + -rm: Remove intermediate containers after a successful build + When a single Dockerfile is given as URL, then no context is set. When a git repository is set as URL, the repository is used as context -.. include:: command/events.rst +.. _cli_build_examples: -.. include:: command/export.rst +Examples +~~~~~~~~ -.. include:: command/history.rst +.. code-block:: bash -.. include:: command/images.rst + sudo docker build . -.. include:: command/import.rst +This will read the ``Dockerfile`` from the current directory. It will +also send any other files and directories found in the current +directory to the ``docker`` daemon. -.. include:: command/info.rst +The contents of this directory would be used by ``ADD`` commands found +within the ``Dockerfile``. This will send a lot of data to the +``docker`` daemon if the current directory contains a lot of data. If +the absolute path is provided instead of ``.`` then only the files and +directories required by the ADD commands from the ``Dockerfile`` will be +added to the context and transferred to the ``docker`` daemon. -.. include:: command/insert.rst +.. code-block:: bash -.. include:: command/inspect.rst + sudo docker build -t vieux/apache:2.0 . + +This will build like the previous example, but it will then tag the +resulting image. The repository name will be ``vieux/apache`` and the +tag will be ``2.0`` + + +.. code-block:: bash + + sudo docker build - < Dockerfile + +This will read a ``Dockerfile`` from *stdin* without context. Due to +the lack of a context, no contents of any local directory will be sent +to the ``docker`` daemon. ``ADD`` doesn't work when running in this +mode because the absence of the context provides no source files to +copy to the container. + + +.. code-block:: bash + + sudo docker build github.com/creack/docker-firefox + +This will clone the Github repository and use it as context. The +``Dockerfile`` at the root of the repository is used as +``Dockerfile``. Note that you can specify an arbitrary git repository +by using the ``git://`` schema. + + +.. _cli_commit: + +``commit`` +---------- + +:: + + Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY [TAG]] + + Create a new image from a container's changes + + -m="": Commit message + -author="": Author (eg. "John Hannibal Smith " + -run="": Configuration to be applied when the image is launched with `docker run`. + (ex: '{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}') + +Full -run example (multiline is ok within a single quote ``'``) + +:: + + $ sudo docker commit -run=' + { + "Entrypoint" : null, + "Privileged" : false, + "User" : "", + "VolumesFrom" : "", + "Cmd" : ["cat", "-e", "/etc/resolv.conf"], + "Dns" : ["8.8.8.8", "8.8.4.4"], + "MemorySwap" : 0, + "AttachStdin" : false, + "AttachStderr" : false, + "CpuShares" : 0, + "OpenStdin" : false, + "Volumes" : null, + "Hostname" : "122612f45831", + "PortSpecs" : ["22", "80", "443"], + "Image" : "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc", + "Tty" : false, + "Env" : [ + "HOME=/", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "StdinOnce" : false, + "Domainname" : "", + "WorkingDir" : "/", + "NetworkDisabled" : false, + "Memory" : 0, + "AttachStdout" : false + }' $CONTAINER_ID + +.. _cli_cp: + +``cp`` +------ + +:: + + Usage: docker cp CONTAINER:RESOURCE HOSTPATH + + Copy files/folders from the containers filesystem to the host + path. Paths are relative to the root of the filesystem. + +.. _cli_diff: + +``diff`` +-------- + +:: + + Usage: docker diff CONTAINER [OPTIONS] + + Inspect changes on a container's filesystem + +.. _cli_events: + +``events`` +---------- + +:: + + Usage: docker events + + Get real time events from the server + +.. _cli_events_example: + +Examples +~~~~~~~~ + +You'll need two shells for this example. + +Shell 1: Listening for events +............................. + +.. code-block:: bash + + $ sudo docker events + +Shell 2: Start and Stop a Container +................................... + +.. code-block:: bash + + $ sudo docker start 4386fb97867d + $ sudo docker stop 4386fb97867d + +Shell 1: (Again .. now showing events) +...................................... + +.. code-block:: bash + + [2013-09-03 15:49:26 +0200 CEST] 4386fb97867d: (from 12de384bfb10) start + [2013-09-03 15:49:29 +0200 CEST] 4386fb97867d: (from 12de384bfb10) die + [2013-09-03 15:49:29 +0200 CEST] 4386fb97867d: (from 12de384bfb10) stop + + +.. _cli_export: + +``export`` +---------- + +:: + + Usage: docker export CONTAINER + + Export the contents of a filesystem as a tar archive + +.. _cli_history: + +``history`` +----------- + +:: + + Usage: docker history [OPTIONS] IMAGE + + Show the history of an image + +.. _cli_images: + +``images`` +---------- + +:: + + Usage: docker images [OPTIONS] [NAME] + + List images + + -a=false: show all images + -q=false: only show numeric IDs + -viz=false: output in graphviz format + +Displaying images visually +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + sudo docker images -viz | dot -Tpng -o docker.png + +.. image:: docker_images.gif + :alt: Example inheritance graph of Docker images. + +.. _cli_import: + +``import`` +---------- + +:: + + Usage: docker import URL|- [REPOSITORY [TAG]] + + Create a new filesystem image from the contents of a tarball + +At this time, the URL must start with ``http`` and point to a single +file archive (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) containing a +root filesystem. If you would like to import from a local directory or +archive, you can use the ``-`` parameter to take the data from +standard in. + +Examples +~~~~~~~~ + +Import from a remote location +............................. + +``$ sudo docker import http://example.com/exampleimage.tgz exampleimagerepo`` + +Import from a local file +........................ + +Import to docker via pipe and standard in + +``$ cat exampleimage.tgz | sudo docker import - exampleimagelocal`` + +Import from a local directory +............................. + +``$ sudo tar -c . | docker import - exampleimagedir`` + +Note the ``sudo`` in this example -- you must preserve the ownership +of the files (especially root ownership) during the archiving with +tar. If you are not root (or sudo) when you tar, then the ownerships +might not get preserved. + +.. _cli_info: + +``info`` +-------- + +:: + + Usage: docker info + + Display system-wide information. + +.. _cli_insert: + +``insert`` +---------- + +:: + + Usage: docker insert IMAGE URL PATH + + Insert a file from URL in the IMAGE at PATH + +Examples +~~~~~~~~ + +Insert file from github +....................... + +.. code-block:: bash + + $ sudo docker insert 8283e18b24bc https://raw.github.com/metalivedev/django/master/postinstall /tmp/postinstall.sh + +.. _cli_inspect: + +``inspect`` +----------- + +:: + + Usage: docker inspect [OPTIONS] CONTAINER + + Return low-level information on a container + +.. _cli_kill: + +``kill`` +-------- + +:: + + Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...] + + Kill a running container + +.. _cli_login: + +``login`` +--------- + +:: + + Usage: docker login [OPTIONS] [SERVER] + + Register or Login to the docker registry server + + -e="": email + -p="": password + -u="": username + + If you want to login to a private registry you can + specify this by adding the server name. + + example: + docker login localhost:8080 + + +.. _cli_logs: + +``logs`` +-------- + + +:: + + Usage: docker logs [OPTIONS] CONTAINER + + Fetch the logs of a container + + +.. _cli_port: + +``port`` +-------- + +:: + + Usage: docker port [OPTIONS] CONTAINER PRIVATE_PORT + + Lookup the public-facing port which is NAT-ed to PRIVATE_PORT + + +.. _cli_ps: + +``ps`` +------ + +:: + + Usage: docker ps [OPTIONS] + + List containers + + -a=false: Show all containers. Only running containers are shown by default. + -notrunc=false: Don't truncate output + -q=false: Only display numeric IDs + +.. _cli_pull: + +``pull`` +-------- + +:: + + Usage: docker pull NAME + + Pull an image or a repository from the registry + + +.. _cli_push: + +``push`` +-------- + +:: + + Usage: docker push NAME + + Push an image or a repository to the registry + + +.. _cli_restart: + +``restart`` +----------- + +:: + + Usage: docker restart [OPTIONS] NAME + + Restart a running container + +.. _cli_rm: + +``rm`` +------ + +:: + + Usage: docker rm [OPTIONS] CONTAINER + + Remove one or more containers + +.. _cli_rmi: + +``rmi`` +------- + +:: + + Usage: docker rmi IMAGE [IMAGE...] + + Remove one or more images + +.. _cli_run: + +``run`` +------- + +:: + + Usage: docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...] + + Run a command in a new container + + -a=map[]: Attach to stdin, stdout or stderr. + -c=0: CPU shares (relative weight) + -cidfile="": Write the container ID to the file + -d=false: Detached mode: Run container in the background, print new container id + -e=[]: Set environment variables + -h="": Container host name + -i=false: Keep stdin open even if not attached + -privileged=false: Give extended privileges to this container + -m=0: Memory limit (in bytes) + -n=true: Enable networking for this container + -p=[]: Map a network port to the container + -rm=false: Automatically remove the container when it exits (incompatible with -d) + -t=false: Allocate a pseudo-tty + -u="": Username or UID + -dns=[]: Set custom dns servers for the container + -v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]. If "container-dir" is missing, then docker creates a new volume. + -volumes-from="": Mount all volumes from the given container. + -entrypoint="": Overwrite the default entrypoint set by the image. + -w="": Working directory inside the container + -lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" + +Examples +~~~~~~~~ + +.. code-block:: bash + + sudo docker run -cidfile /tmp/docker_test.cid ubuntu echo "test" + +This will create a container and print "test" to the console. The +``cidfile`` flag makes docker attempt to create a new file and write the +container ID to it. If the file exists already, docker will return an +error. Docker will close this file when docker run exits. + +.. code-block:: bash + + docker run mount -t tmpfs none /var/spool/squid + +This will *not* work, because by default, most potentially dangerous +kernel capabilities are dropped; including ``cap_sys_admin`` (which is +required to mount filesystems). However, the ``-privileged`` flag will +allow it to run: + +.. code-block:: bash + + docker run -privileged mount -t tmpfs none /var/spool/squid + +The ``-privileged`` flag gives *all* capabilities to the container, +and it also lifts all the limitations enforced by the ``device`` +cgroup controller. In other words, the container can then do almost +everything that the host can do. This flag exists to allow special +use-cases, like running Docker within Docker. + +.. code-block:: bash + + docker run -w /path/to/dir/ -i -t ubuntu pwd + +The ``-w`` lets the command being executed inside directory given, +here /path/to/dir/. If the path does not exists it is created inside the +container. + +.. code-block:: bash + + docker run -v `pwd`:`pwd` -w `pwd` -i -t ubuntu pwd + +The ``-v`` flag mounts the current working directory into the container. +The ``-w`` lets the command being executed inside the current +working directory, by changing into the directory to the value +returned by ``pwd``. So this combination executes the command +using the container, but inside the current working directory. + +.. _cli_search: + +``search`` +---------- + +:: + + Usage: docker search TERM + + Searches for the TERM parameter on the Docker index and prints out + a list of repositories that match. + +.. _cli_start: + +``start`` +--------- + +:: + + Usage: docker start [OPTIONS] NAME + + Start a stopped container + +.. _cli_stop: + +``stop`` +-------- + +:: + + Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] + + Stop a running container + + -t=10: Number of seconds to wait for the container to stop before killing it. + +.. _cli_tag: + +``tag`` +------- + +:: + + Usage: docker tag [OPTIONS] IMAGE REPOSITORY [TAG] + + Tag an image into a repository + + -f=false: Force + +.. _cli_top: + +``top`` +------- + +:: + + Usage: docker top CONTAINER + + Lookup the running processes of a container + +.. _cli_version: + +``version`` +----------- + +Show the version of the docker client, daemon, and latest released version. + + +.. _cli_wait: + +``wait`` +-------- + +:: + + Usage: docker wait [OPTIONS] NAME + + Block until a container stops, then print its exit code. -.. include:: command/kill.rst - -.. include:: command/login.rst - -.. include:: command/logs.rst - -.. include:: command/port.rst - -.. include:: command/ps.rst - -.. include:: command/pull.rst - -.. include:: command/push.rst - -.. include:: command/restart.rst - -.. include:: command/rm.rst - -.. include:: command/rmi.rst - -.. include:: command/run.rst - -.. include:: command/search.rst - -.. include:: command/start.rst - -.. include:: command/stop.rst - -.. include:: command/tag.rst - -.. include:: command/top.rst - -.. include:: command/version.rst - -.. include:: command/wait.rst diff --git a/components/engine/docs/sources/commandline/command/attach.rst b/components/engine/docs/sources/commandline/command/attach.rst deleted file mode 100644 index 12ed802a02..0000000000 --- a/components/engine/docs/sources/commandline/command/attach.rst +++ /dev/null @@ -1,59 +0,0 @@ -:title: Attach Command -:description: Attach to a running container -:keywords: attach, container, docker, documentation - -=========================================== -``attach`` -- Attach to a running container -=========================================== - -:: - - Usage: docker attach CONTAINER - - Attach to a running container. - -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. - -To stop a container, use ``docker stop`` - -To kill the container, use ``docker kill`` - -Examples: ---------- - -.. code-block:: bash - - $ ID=$(sudo docker run -d ubuntu /usr/bin/top -b) - $ sudo docker attach $ID - top - 02:05:52 up 3:05, 0 users, load average: 0.01, 0.02, 0.05 - Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie - Cpu(s): 0.1%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st - Mem: 373572k total, 355560k used, 18012k free, 27872k buffers - Swap: 786428k total, 0k used, 786428k free, 221740k cached - - PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND - 1 root 20 0 17200 1116 912 R 0 0.3 0:00.03 top - - top - 02:05:55 up 3:05, 0 users, load average: 0.01, 0.02, 0.05 - Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie - Cpu(s): 0.0%us, 0.2%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st - Mem: 373572k total, 355244k used, 18328k free, 27872k buffers - Swap: 786428k total, 0k used, 786428k free, 221776k cached - - PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND - 1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top - - - top - 02:05:58 up 3:06, 0 users, load average: 0.01, 0.02, 0.05 - Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie - Cpu(s): 0.2%us, 0.3%sy, 0.0%ni, 99.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st - Mem: 373572k total, 355780k used, 17792k free, 27880k buffers - Swap: 786428k total, 0k used, 786428k free, 221776k cached - - PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND - 1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top - ^C$ - $ sudo docker stop $ID - diff --git a/components/engine/docs/sources/commandline/command/build.rst b/components/engine/docs/sources/commandline/command/build.rst deleted file mode 100644 index 5ce70d85d9..0000000000 --- a/components/engine/docs/sources/commandline/command/build.rst +++ /dev/null @@ -1,65 +0,0 @@ -:title: Build Command -:description: Build a new image from the Dockerfile passed via stdin -:keywords: build, docker, container, documentation - -================================================ -``build`` -- Build a container from a Dockerfile -================================================ - -:: - - Usage: docker build [OPTIONS] PATH | URL | - - Build a new container image from the source code at PATH - -t="": Repository name (and optionally a tag) to be applied to the resulting image in case of success. - -q=false: Suppress verbose build output. - -no-cache: Do not use the cache when building the image. - -rm: Remove intermediate containers after a successful build - When a single Dockerfile is given as URL, then no context is set. When a git repository is set as URL, the repository is used as context - - -Examples --------- - -.. code-block:: bash - - sudo docker build . - -This will read the ``Dockerfile`` from the current directory. It will -also send any other files and directories found in the current -directory to the ``docker`` daemon. - -The contents of this directory would be used by ``ADD`` commands found -within the ``Dockerfile``. This will send a lot of data to the -``docker`` daemon if the current directory contains a lot of data. If -the absolute path is provided instead of ``.`` then only the files and -directories required by the ADD commands from the ``Dockerfile`` will be -added to the context and transferred to the ``docker`` daemon. - -.. code-block:: bash - - sudo docker build -t vieux/apache:2.0 . - -This will build like the previous example, but it will then tag the -resulting image. The repository name will be ``vieux/apache`` and the -tag will be ``2.0`` - - -.. code-block:: bash - - sudo docker build - < Dockerfile - -This will read a ``Dockerfile`` from *stdin* without context. Due to -the lack of a context, no contents of any local directory will be sent -to the ``docker`` daemon. ``ADD`` doesn't work when running in this -mode because the absence of the context provides no source files to -copy to the container. - - -.. code-block:: bash - - sudo docker build github.com/creack/docker-firefox - -This will clone the Github repository and use it as context. The -``Dockerfile`` at the root of the repository is used as -``Dockerfile``. Note that you can specify an arbitrary git repository -by using the ``git://`` schema. diff --git a/components/engine/docs/sources/commandline/command/commit.rst b/components/engine/docs/sources/commandline/command/commit.rst deleted file mode 100644 index ef0d863688..0000000000 --- a/components/engine/docs/sources/commandline/command/commit.rst +++ /dev/null @@ -1,52 +0,0 @@ -:title: Commit Command -:description: Create a new image from a container's changes -:keywords: commit, docker, container, documentation - -=========================================================== -``commit`` -- Create a new image from a container's changes -=========================================================== - -:: - - Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY [TAG]] - - Create a new image from a container's changes - - -m="": Commit message - -author="": Author (eg. "John Hannibal Smith " - -run="": Configuration to be applied when the image is launched with `docker run`. - (ex: '{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}') - -Full -run example (multiline is ok within a single quote ``'``) - -:: - - $ sudo docker commit -run=' - { - "Entrypoint" : null, - "Privileged" : false, - "User" : "", - "VolumesFrom" : "", - "Cmd" : ["cat", "-e", "/etc/resolv.conf"], - "Dns" : ["8.8.8.8", "8.8.4.4"], - "MemorySwap" : 0, - "AttachStdin" : false, - "AttachStderr" : false, - "CpuShares" : 0, - "OpenStdin" : false, - "Volumes" : null, - "Hostname" : "122612f45831", - "PortSpecs" : ["22", "80", "443"], - "Image" : "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc", - "Tty" : false, - "Env" : [ - "HOME=/", - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - ], - "StdinOnce" : false, - "Domainname" : "", - "WorkingDir" : "/", - "NetworkDisabled" : false, - "Memory" : 0, - "AttachStdout" : false - }' $CONTAINER_ID diff --git a/components/engine/docs/sources/commandline/command/cp.rst b/components/engine/docs/sources/commandline/command/cp.rst deleted file mode 100644 index ea84fa1f90..0000000000 --- a/components/engine/docs/sources/commandline/command/cp.rst +++ /dev/null @@ -1,14 +0,0 @@ -:title: Cp Command -:description: Copy files/folders from the containers filesystem to the host path -:keywords: cp, docker, container, documentation, copy - -============================================================================ -``cp`` -- Copy files/folders from the containers filesystem to the host path -============================================================================ - -:: - - Usage: docker cp CONTAINER:RESOURCE HOSTPATH - - Copy files/folders from the containers filesystem to the host - path. Paths are relative to the root of the filesystem. diff --git a/components/engine/docs/sources/commandline/command/diff.rst b/components/engine/docs/sources/commandline/command/diff.rst deleted file mode 100644 index 2901a7f215..0000000000 --- a/components/engine/docs/sources/commandline/command/diff.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Diff Command -:description: Inspect changes on a container's filesystem -:keywords: diff, docker, container, documentation - -======================================================= -``diff`` -- Inspect changes on a container's filesystem -======================================================= - -:: - - Usage: docker diff CONTAINER [OPTIONS] - - Inspect changes on a container's filesystem diff --git a/components/engine/docs/sources/commandline/command/events.rst b/components/engine/docs/sources/commandline/command/events.rst deleted file mode 100644 index b8dd591fb1..0000000000 --- a/components/engine/docs/sources/commandline/command/events.rst +++ /dev/null @@ -1,34 +0,0 @@ -:title: Events Command -:description: Get real time events from the server -:keywords: events, docker, documentation - -================================================================= -``events`` -- Get real time events from the server -================================================================= - -:: - - Usage: docker events - - Get real time events from the server - -Examples --------- - -Starting and stopping a container -................................. - -.. code-block:: bash - - $ sudo docker start 4386fb97867d - $ sudo docker stop 4386fb97867d - -In another shell - -.. code-block:: bash - - $ sudo docker events - [2013-09-03 15:49:26 +0200 CEST] 4386fb97867d: (from 12de384bfb10) start - [2013-09-03 15:49:29 +0200 CEST] 4386fb97867d: (from 12de384bfb10) die - [2013-09-03 15:49:29 +0200 CEST] 4386fb97867d: (from 12de384bfb10) stop - diff --git a/components/engine/docs/sources/commandline/command/export.rst b/components/engine/docs/sources/commandline/command/export.rst deleted file mode 100644 index 9d7e6b369c..0000000000 --- a/components/engine/docs/sources/commandline/command/export.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Export Command -:description: Export the contents of a filesystem as a tar archive -:keywords: export, docker, container, documentation - -================================================================= -``export`` -- Stream the contents of a container as a tar archive -================================================================= - -:: - - Usage: docker export CONTAINER - - Export the contents of a filesystem as a tar archive diff --git a/components/engine/docs/sources/commandline/command/history.rst b/components/engine/docs/sources/commandline/command/history.rst deleted file mode 100644 index 2f9d3f2814..0000000000 --- a/components/engine/docs/sources/commandline/command/history.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: History Command -:description: Show the history of an image -:keywords: history, docker, container, documentation - -=========================================== -``history`` -- Show the history of an image -=========================================== - -:: - - Usage: docker history [OPTIONS] IMAGE - - Show the history of an image diff --git a/components/engine/docs/sources/commandline/command/images.rst b/components/engine/docs/sources/commandline/command/images.rst deleted file mode 100644 index 279bf240c9..0000000000 --- a/components/engine/docs/sources/commandline/command/images.rst +++ /dev/null @@ -1,26 +0,0 @@ -:title: Images Command -:description: List images -:keywords: images, docker, container, documentation - -========================= -``images`` -- List images -========================= - -:: - - Usage: docker images [OPTIONS] [NAME] - - List images - - -a=false: show all images - -q=false: only show numeric IDs - -viz=false: output in graphviz format - -Displaying images visually --------------------------- - -:: - - sudo docker images -viz | dot -Tpng -o docker.png - -.. image:: https://docs.docker.io/en/latest/_static/docker_images.gif diff --git a/components/engine/docs/sources/commandline/command/import.rst b/components/engine/docs/sources/commandline/command/import.rst deleted file mode 100644 index e236c5bc2b..0000000000 --- a/components/engine/docs/sources/commandline/command/import.rst +++ /dev/null @@ -1,44 +0,0 @@ -:title: Import Command -:description: Create a new filesystem image from the contents of a tarball -:keywords: import, tarball, docker, url, documentation - -========================================================================== -``import`` -- Create a new filesystem image from the contents of a tarball -========================================================================== - -:: - - Usage: docker import URL|- [REPOSITORY [TAG]] - - Create a new filesystem image from the contents of a tarball - -At this time, the URL must start with ``http`` and point to a single -file archive (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) containing a -root filesystem. If you would like to import from a local directory or -archive, you can use the ``-`` parameter to take the data from -standard in. - -Examples --------- - -Import from a remote location -............................. - -``$ sudo docker import http://example.com/exampleimage.tgz exampleimagerepo`` - -Import from a local file -........................ - -Import to docker via pipe and standard in - -``$ cat exampleimage.tgz | sudo docker import - exampleimagelocal`` - -Import from a local directory -............................. - -``$ sudo tar -c . | docker import - exampleimagedir`` - -Note the ``sudo`` in this example -- you must preserve the ownership -of the files (especially root ownership) during the archiving with -tar. If you are not root (or sudo) when you tar, then the ownerships -might not get preserved. diff --git a/components/engine/docs/sources/commandline/command/info.rst b/components/engine/docs/sources/commandline/command/info.rst deleted file mode 100644 index 6df3486c53..0000000000 --- a/components/engine/docs/sources/commandline/command/info.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Info Command -:description: Display system-wide information. -:keywords: info, docker, information, documentation - -=========================================== -``info`` -- Display system-wide information -=========================================== - -:: - - Usage: docker info - - Display system-wide information. diff --git a/components/engine/docs/sources/commandline/command/insert.rst b/components/engine/docs/sources/commandline/command/insert.rst deleted file mode 100644 index 0f2612c9af..0000000000 --- a/components/engine/docs/sources/commandline/command/insert.rst +++ /dev/null @@ -1,23 +0,0 @@ -:title: Insert Command -:description: Insert a file in an image -:keywords: insert, image, docker, documentation - -========================================================================== -``insert`` -- Insert a file in an image -========================================================================== - -:: - - Usage: docker insert IMAGE URL PATH - - Insert a file from URL in the IMAGE at PATH - -Examples --------- - -Insert file from github -....................... - -.. code-block:: bash - - $ sudo docker insert 8283e18b24bc https://raw.github.com/metalivedev/django/master/postinstall /tmp/postinstall.sh diff --git a/components/engine/docs/sources/commandline/command/inspect.rst b/components/engine/docs/sources/commandline/command/inspect.rst deleted file mode 100644 index 90dbe959eb..0000000000 --- a/components/engine/docs/sources/commandline/command/inspect.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Inspect Command -:description: Return low-level information on a container -:keywords: inspect, container, docker, documentation - -========================================================== -``inspect`` -- Return low-level information on a container -========================================================== - -:: - - Usage: docker inspect [OPTIONS] CONTAINER - - Return low-level information on a container diff --git a/components/engine/docs/sources/commandline/command/kill.rst b/components/engine/docs/sources/commandline/command/kill.rst deleted file mode 100644 index f53d3883b0..0000000000 --- a/components/engine/docs/sources/commandline/command/kill.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Kill Command -:description: Kill a running container -:keywords: kill, container, docker, documentation - -==================================== -``kill`` -- Kill a running container -==================================== - -:: - - Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...] - - Kill a running container diff --git a/components/engine/docs/sources/commandline/command/login.rst b/components/engine/docs/sources/commandline/command/login.rst deleted file mode 100644 index 46f354d6be..0000000000 --- a/components/engine/docs/sources/commandline/command/login.rst +++ /dev/null @@ -1,24 +0,0 @@ -:title: Login Command -:description: Register or Login to the docker registry server -:keywords: login, docker, documentation - -============================================================ -``login`` -- Register or Login to the docker registry server -============================================================ - -:: - - Usage: docker login [OPTIONS] [SERVER] - - Register or Login to the docker registry server - - -e="": email - -p="": password - -u="": username - - If you want to login to a private registry you can - specify this by adding the server name. - - example: - docker login localhost:8080 - diff --git a/components/engine/docs/sources/commandline/command/logs.rst b/components/engine/docs/sources/commandline/command/logs.rst deleted file mode 100644 index a3423f6e0c..0000000000 --- a/components/engine/docs/sources/commandline/command/logs.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Logs Command -:description: Fetch the logs of a container -:keywords: logs, container, docker, documentation - -========================================= -``logs`` -- Fetch the logs of a container -========================================= - -:: - - Usage: docker logs [OPTIONS] CONTAINER - - Fetch the logs of a container diff --git a/components/engine/docs/sources/commandline/command/port.rst b/components/engine/docs/sources/commandline/command/port.rst deleted file mode 100644 index 8d59fedab6..0000000000 --- a/components/engine/docs/sources/commandline/command/port.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Port Command -:description: Lookup the public-facing port which is NAT-ed to PRIVATE_PORT -:keywords: port, docker, container, documentation - -========================================================================= -``port`` -- Lookup the public-facing port which is NAT-ed to PRIVATE_PORT -========================================================================= - -:: - - Usage: docker port [OPTIONS] CONTAINER PRIVATE_PORT - - Lookup the public-facing port which is NAT-ed to PRIVATE_PORT diff --git a/components/engine/docs/sources/commandline/command/ps.rst b/components/engine/docs/sources/commandline/command/ps.rst deleted file mode 100644 index 597dbd9ae7..0000000000 --- a/components/engine/docs/sources/commandline/command/ps.rst +++ /dev/null @@ -1,17 +0,0 @@ -:title: Ps Command -:description: List containers -:keywords: ps, docker, documentation, container - -========================= -``ps`` -- List containers -========================= - -:: - - Usage: docker ps [OPTIONS] - - List containers - - -a=false: Show all containers. Only running containers are shown by default. - -notrunc=false: Don't truncate output - -q=false: Only display numeric IDs diff --git a/components/engine/docs/sources/commandline/command/pull.rst b/components/engine/docs/sources/commandline/command/pull.rst deleted file mode 100644 index 4348f28d0f..0000000000 --- a/components/engine/docs/sources/commandline/command/pull.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Pull Command -:description: Pull an image or a repository from the registry -:keywords: pull, image, repo, repository, documentation, docker - -========================================================================= -``pull`` -- Pull an image or a repository from the docker registry server -========================================================================= - -:: - - Usage: docker pull NAME - - Pull an image or a repository from the registry diff --git a/components/engine/docs/sources/commandline/command/push.rst b/components/engine/docs/sources/commandline/command/push.rst deleted file mode 100644 index 9304f9acc5..0000000000 --- a/components/engine/docs/sources/commandline/command/push.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Push Command -:description: Push an image or a repository to the registry -:keywords: push, docker, image, repository, documentation, repo - -======================================================================= -``push`` -- Push an image or a repository to the docker registry server -======================================================================= - -:: - - Usage: docker push NAME - - Push an image or a repository to the registry diff --git a/components/engine/docs/sources/commandline/command/restart.rst b/components/engine/docs/sources/commandline/command/restart.rst deleted file mode 100644 index dfc0dfea6e..0000000000 --- a/components/engine/docs/sources/commandline/command/restart.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Restart Command -:description: Restart a running container -:keywords: restart, container, docker, documentation - -========================================== -``restart`` -- Restart a running container -========================================== - -:: - - Usage: docker restart [OPTIONS] NAME - - Restart a running container diff --git a/components/engine/docs/sources/commandline/command/rm.rst b/components/engine/docs/sources/commandline/command/rm.rst deleted file mode 100644 index 8a2309ce79..0000000000 --- a/components/engine/docs/sources/commandline/command/rm.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Rm Command -:description: Remove a container -:keywords: remove, container, docker, documentation, rm - -============================ -``rm`` -- Remove a container -============================ - -:: - - Usage: docker rm [OPTIONS] CONTAINER - - Remove one or more containers diff --git a/components/engine/docs/sources/commandline/command/rmi.rst b/components/engine/docs/sources/commandline/command/rmi.rst deleted file mode 100644 index 954e5222c6..0000000000 --- a/components/engine/docs/sources/commandline/command/rmi.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Rmi Command -:description: Remove an image -:keywords: rmi, remove, image, docker, documentation - -========================== -``rmi`` -- Remove an image -========================== - -:: - - Usage: docker rmi IMAGE [IMAGE...] - - Remove one or more images diff --git a/components/engine/docs/sources/commandline/command/run.rst b/components/engine/docs/sources/commandline/command/run.rst deleted file mode 100644 index b68e08303f..0000000000 --- a/components/engine/docs/sources/commandline/command/run.rst +++ /dev/null @@ -1,85 +0,0 @@ -:title: Run Command -:description: Run a command in a new container -:keywords: run, container, docker, documentation - -=========================================== -``run`` -- Run a command in a new container -=========================================== - -:: - - Usage: docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...] - - Run a command in a new container - - -a=map[]: Attach to stdin, stdout or stderr. - -c=0: CPU shares (relative weight) - -cidfile="": Write the container ID to the file - -d=false: Detached mode: Run container in the background, print new container id - -e=[]: Set environment variables - -h="": Container host name - -i=false: Keep stdin open even if not attached - -privileged=false: Give extended privileges to this container - -m=0: Memory limit (in bytes) - -n=true: Enable networking for this container - -p=[]: Map a network port to the container - -rm=false: Automatically remove the container when it exits (incompatible with -d) - -t=false: Allocate a pseudo-tty - -u="": Username or UID - -dns=[]: Set custom dns servers for the container - -v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]. If "container-dir" is missing, then docker creates a new volume. - -volumes-from="": Mount all volumes from the given container. - -entrypoint="": Overwrite the default entrypoint set by the image. - -w="": Working directory inside the container - -lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" - -Examples --------- - -.. code-block:: bash - - sudo docker run -cidfile /tmp/docker_test.cid ubuntu echo "test" - -This will create a container and print "test" to the console. The -``cidfile`` flag makes docker attempt to create a new file and write the -container ID to it. If the file exists already, docker will return an -error. Docker will close this file when docker run exits. - -.. code-block:: bash - - docker run mount -t tmpfs none /var/spool/squid - -This will *not* work, because by default, most potentially dangerous -kernel capabilities are dropped; including ``cap_sys_admin`` (which is -required to mount filesystems). However, the ``-privileged`` flag will -allow it to run: - -.. code-block:: bash - - docker run -privileged mount -t tmpfs none /var/spool/squid - -The ``-privileged`` flag gives *all* capabilities to the container, -and it also lifts all the limitations enforced by the ``device`` -cgroup controller. In other words, the container can then do almost -everything that the host can do. This flag exists to allow special -use-cases, like running Docker within Docker. - -.. code-block:: bash - - docker run -w /path/to/dir/ -i -t ubuntu pwd - -The ``-w`` lets the command being executed inside directory given, -here /path/to/dir/. If the path does not exists it is created inside the -container. - -.. code-block:: bash - - docker run -v `pwd`:`pwd` -w `pwd` -i -t ubuntu pwd - -The ``-v`` flag mounts the current working directory into the container. -The ``-w`` lets the command being executed inside the current -working directory, by changing into the directory to the value -returned by ``pwd``. So this combination executes the command -using the container, but inside the current working directory. - - diff --git a/components/engine/docs/sources/commandline/command/search.rst b/components/engine/docs/sources/commandline/command/search.rst deleted file mode 100644 index 8107016a41..0000000000 --- a/components/engine/docs/sources/commandline/command/search.rst +++ /dev/null @@ -1,14 +0,0 @@ -:title: Search Command -:description: Searches for the TERM parameter on the Docker index and prints out a list of repositories that match. -:keywords: search, docker, image, documentation - -=================================================================== -``search`` -- Search for an image in the docker index -=================================================================== - -:: - - Usage: docker search TERM - - Searches for the TERM parameter on the Docker index and prints out - a list of repositories that match. diff --git a/components/engine/docs/sources/commandline/command/start.rst b/components/engine/docs/sources/commandline/command/start.rst deleted file mode 100644 index b70ad21cfd..0000000000 --- a/components/engine/docs/sources/commandline/command/start.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Start Command -:description: Start a stopped container -:keywords: start, docker, container, documentation - -====================================== -``start`` -- Start a stopped container -====================================== - -:: - - Usage: docker start [OPTIONS] NAME - - Start a stopped container diff --git a/components/engine/docs/sources/commandline/command/stop.rst b/components/engine/docs/sources/commandline/command/stop.rst deleted file mode 100644 index 6a64908eae..0000000000 --- a/components/engine/docs/sources/commandline/command/stop.rst +++ /dev/null @@ -1,15 +0,0 @@ -:title: Stop Command -:description: Stop a running container -:keywords: stop, container, docker, documentation - -==================================== -``stop`` -- Stop a running container -==================================== - -:: - - Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] - - Stop a running container - - -t=10: Number of seconds to wait for the container to stop before killing it. diff --git a/components/engine/docs/sources/commandline/command/tag.rst b/components/engine/docs/sources/commandline/command/tag.rst deleted file mode 100644 index a9e831aae9..0000000000 --- a/components/engine/docs/sources/commandline/command/tag.rst +++ /dev/null @@ -1,15 +0,0 @@ -:title: Tag Command -:description: Tag an image into a repository -:keywords: tag, docker, image, repository, documentation, repo - -========================================= -``tag`` -- Tag an image into a repository -========================================= - -:: - - Usage: docker tag [OPTIONS] IMAGE REPOSITORY [TAG] - - Tag an image into a repository - - -f=false: Force diff --git a/components/engine/docs/sources/commandline/command/top.rst b/components/engine/docs/sources/commandline/command/top.rst deleted file mode 100644 index bdd35adcfa..0000000000 --- a/components/engine/docs/sources/commandline/command/top.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Top Command -:description: Lookup the running processes of a container -:keywords: top, docker, container, documentation - -======================================================= -``top`` -- Lookup the running processes of a container -======================================================= - -:: - - Usage: docker top CONTAINER - - Lookup the running processes of a container diff --git a/components/engine/docs/sources/commandline/command/version.rst b/components/engine/docs/sources/commandline/command/version.rst deleted file mode 100644 index fb3d3b450e..0000000000 --- a/components/engine/docs/sources/commandline/command/version.rst +++ /dev/null @@ -1,7 +0,0 @@ -:title: Version Command -:description: -:keywords: version, docker, documentation - -================================================== -``version`` -- Show the docker version information -================================================== diff --git a/components/engine/docs/sources/commandline/command/wait.rst b/components/engine/docs/sources/commandline/command/wait.rst deleted file mode 100644 index 23bd54513c..0000000000 --- a/components/engine/docs/sources/commandline/command/wait.rst +++ /dev/null @@ -1,13 +0,0 @@ -:title: Wait Command -:description: Block until a container stops, then print its exit code. -:keywords: wait, docker, container, documentation - -=================================================================== -``wait`` -- Block until a container stops, then print its exit code -=================================================================== - -:: - - Usage: docker wait [OPTIONS] NAME - - Block until a container stops, then print its exit code. diff --git a/components/engine/docs/sources/static_files/docker_images.gif b/components/engine/docs/sources/commandline/docker_images.gif similarity index 100% rename from components/engine/docs/sources/static_files/docker_images.gif rename to components/engine/docs/sources/commandline/docker_images.gif diff --git a/components/engine/docs/sources/commandline/index.rst b/components/engine/docs/sources/commandline/index.rst index 0e7c8738b3..5536e1012e 100644 --- a/components/engine/docs/sources/commandline/index.rst +++ b/components/engine/docs/sources/commandline/index.rst @@ -1,6 +1,6 @@ :title: Commands -:description: -- todo: change me -:keywords: todo, commands, command line, help, docker, documentation +:description: docker command line interface +:keywords: commands, command line, help, docker Commands @@ -12,34 +12,3 @@ Contents: :maxdepth: 1 cli - attach - build - commit - cp - diff - events - export - history - images - import - info - insert - inspect - kill - login - logs - port - ps - pull - push - restart - rm - rmi - run - search - start - stop - tag - top - version - wait diff --git a/components/engine/docs/sources/examples/hello_world.rst b/components/engine/docs/sources/examples/hello_world.rst index 647a34aa1f..54ebdacc6a 100644 --- a/components/engine/docs/sources/examples/hello_world.rst +++ b/components/engine/docs/sources/examples/hello_world.rst @@ -178,4 +178,4 @@ you could skip to any of the other examples: * :ref:`running_ssh_service` * :ref:`running_couchdb_service` * :ref:`postgresql_service` -* :ref:`mongodb` +* :ref:`mongodb_image` diff --git a/components/engine/docs/sources/index.rst b/components/engine/docs/sources/index.rst index 99d2159aa7..88752ac3bf 100644 --- a/components/engine/docs/sources/index.rst +++ b/components/engine/docs/sources/index.rst @@ -2,8 +2,6 @@ :description: An overview of the Docker Documentation :keywords: containers, lxc, concepts, explanation -.. image:: https://www.docker.io/static/img/linked/dockerlogo-horizontal.png - Introduction ------------ From 06ac81c4b1d43ae9039ff1d732131ec730251d98 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Wed, 16 Oct 2013 20:10:20 +0000 Subject: [PATCH 015/112] Hack: don't run integration tests in /var/lib/docker/unit-tests; add missing cleanups in a few tests Upstream-commit: 240d5b3fa1b66f099b71c20ff8dc4ed1ecffc1d3 Component: engine --- components/engine/api_test.go | 1 + components/engine/runtime_test.go | 60 ++++++++++++++++++++----------- components/engine/server_test.go | 1 + components/engine/z_final_test.go | 2 +- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/components/engine/api_test.go b/components/engine/api_test.go index fcb3bc8593..e047aba9e5 100644 --- a/components/engine/api_test.go +++ b/components/engine/api_test.go @@ -112,6 +112,7 @@ func TestGetInfo(t *testing.T) { func TestGetEvents(t *testing.T) { runtime := mkRuntime(t) + defer nuke(runtime) srv := &Server{ runtime: runtime, events: make([]utils.JSONMessage, 0, 64), diff --git a/components/engine/runtime_test.go b/components/engine/runtime_test.go index 1abbcc51e6..75081fff1e 100644 --- a/components/engine/runtime_test.go +++ b/components/engine/runtime_test.go @@ -87,45 +87,63 @@ func init() { NetworkBridgeIface = unitTestNetworkBridge - // Make it our Store root - if runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false); err != nil { - log.Fatalf("Unable to create a runtime for tests:", err) - } else { - globalRuntime = runtime - } + // Setup the base runtime, which will be duplicated for each test. + // (no tests are run directly in the base) + setupBaseImage() - // Cleanup any leftover container - for _, container := range globalRuntime.List() { - if err := globalRuntime.Destroy(container); err != nil { - log.Fatalf("Error destroying leftover container: %s", err) - } + // Create the "global runtime" with a long-running daemon for integration tests + spawnGlobalDaemon() + startFds, startGoroutines = utils.GetTotalUsedFds(), runtime.NumGoroutine() +} + + +func setupBaseImage() { + runtime, err := NewRuntimeFromDirectory(unitTestStoreBase, false) + if err != nil { + log.Fatalf("Unable to create a runtime for tests:", err) } // Create the "Server" + srv := &Server{ + runtime: runtime, + enableCors: false, + pullingPool: make(map[string]struct{}), + pushingPool: make(map[string]struct{}), + } + + // If the unit test is not found, try to download it. + if img, err := runtime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID { + // Retrieve the Image + if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil, nil, true); err != nil { + log.Fatalf("Unable to pull the test image:", err) + } + } +} + + +func spawnGlobalDaemon() { + if globalRuntime != nil { + utils.Debugf("Global runtime already exists. Skipping.") + return + } + globalRuntime = mkRuntime(log.New(os.Stderr, "", 0)) srv := &Server{ runtime: globalRuntime, enableCors: false, pullingPool: make(map[string]struct{}), pushingPool: make(map[string]struct{}), } - // If the unit test is not found, try to download it. - if img, err := globalRuntime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID { - // Retrieve the Image - if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil, nil, true); err != nil { - log.Fatalf("Unable to pull the test image:", err) - } - } + // Spawn a Daemon go func() { + utils.Debugf("Spawning global daemon for integration tests") if err := ListenAndServe(testDaemonProto, testDaemonAddr, srv, os.Getenv("DEBUG") != ""); err != nil { log.Fatalf("Unable to spawn the test daemon:", err) } }() - // Give some time to ListenAndServer to actually start + // FIXME: use inmem transports instead of tcp time.Sleep(time.Second) - - startFds, startGoroutines = utils.GetTotalUsedFds(), runtime.NumGoroutine() } // FIXME: test that ImagePull(json=true) send correct json output diff --git a/components/engine/server_test.go b/components/engine/server_test.go index ee9549d7b7..c13754b5ea 100644 --- a/components/engine/server_test.go +++ b/components/engine/server_test.go @@ -351,6 +351,7 @@ func TestPools(t *testing.T) { func TestLogEvent(t *testing.T) { runtime := mkRuntime(t) + defer nuke(runtime) srv := &Server{ runtime: runtime, events: make([]utils.JSONMessage, 0, 64), diff --git a/components/engine/z_final_test.go b/components/engine/z_final_test.go index 08a180baaf..837b5d13e6 100644 --- a/components/engine/z_final_test.go +++ b/components/engine/z_final_test.go @@ -11,7 +11,7 @@ func displayFdGoroutines(t *testing.T) { } func TestFinal(t *testing.T) { - cleanup(globalRuntime) + nuke(globalRuntime) t.Logf("Start Fds: %d, Start Goroutines: %d", startFds, startGoroutines) displayFdGoroutines(t) } From c53c4a96f0df8431c9d4e7d7db16a22f581803f0 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Wed, 16 Oct 2013 20:44:15 +0000 Subject: [PATCH 016/112] Hack: fix tests which didn't cleanup properly Upstream-commit: 5c175357aaa7e011e3535eeb1ee162450f390b9e Component: engine --- components/engine/auth/auth_test.go | 5 ++++- components/engine/container_test.go | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/components/engine/auth/auth_test.go b/components/engine/auth/auth_test.go index 01aecae3da..5dc634a719 100644 --- a/components/engine/auth/auth_test.go +++ b/components/engine/auth/auth_test.go @@ -76,7 +76,7 @@ func TestCreateAccount(t *testing.T) { } func setupTempConfigFile() (*ConfigFile, error) { - root, err := ioutil.TempDir("", "docker-test") + root, err := ioutil.TempDir("", "docker-test-auth") if err != nil { return nil, err } @@ -101,6 +101,7 @@ func TestSameAuthDataPostSave(t *testing.T) { if err != nil { t.Fatal(err) } + defer os.RemoveAll(configFile.rootPath) err = SaveConfig(configFile) if err != nil { @@ -127,6 +128,7 @@ func TestResolveAuthConfigIndexServer(t *testing.T) { if err != nil { t.Fatal(err) } + defer os.RemoveAll(configFile.rootPath) for _, registry := range []string{"", IndexServerAddress()} { resolved := configFile.ResolveAuthConfig(registry) @@ -141,6 +143,7 @@ func TestResolveAuthConfigFullURL(t *testing.T) { if err != nil { t.Fatal(err) } + defer os.RemoveAll(configFile.rootPath) registryAuth := AuthConfig{ Username: "foo-user", diff --git a/components/engine/container_test.go b/components/engine/container_test.go index e678c98898..9fdddc9044 100644 --- a/components/engine/container_test.go +++ b/components/engine/container_test.go @@ -1189,7 +1189,7 @@ func BenchmarkRunParallel(b *testing.B) { } func tempDir(t *testing.T) string { - tmpDir, err := ioutil.TempDir("", "docker-test") + tmpDir, err := ioutil.TempDir("", "docker-test-container") if err != nil { t.Fatal(err) } From 40ae0bfbb268cb5381767358d8a61152cc2ea864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Petazzoni?= Date: Thu, 17 Oct 2013 20:32:23 -0700 Subject: [PATCH 017/112] Work around an exotic bug affecting Docker-in-Docker + systemd. Upstream-commit: 255b6aadfacfd346ef413a1ffd945360276cbcf6 Component: engine --- components/engine/hack/dind | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/components/engine/hack/dind b/components/engine/hack/dind index 7810715675..e8b715cc9c 100755 --- a/components/engine/hack/dind +++ b/components/engine/hack/dind @@ -27,6 +27,31 @@ do [ -d $CGROUP/$SUBSYS ] || mkdir $CGROUP/$SUBSYS mountpoint -q $CGROUP/$SUBSYS || mount -n -t cgroup -o $SUBSYS cgroup $CGROUP/$SUBSYS + + # The two following sections address a bug which manifests itself + # by a cryptic "lxc-start: no ns_cgroup option specified" when + # trying to start containers withina container. + # The bug seems to appear when the cgroup hierarchies are not + # mounted on the exact same directories in the host, and in the + # container. + + # Named, control-less cgroups are mounted with "-o name=foo" + # (and appear as such under /proc//cgroup) but are usually + # mounted on a directory named "foo" (without the "name=" prefix). + # Systemd and OpenRC (and possibly others) both create such a + # cgroup. To avoid the aforementioned bug, we symlink "foo" to + # "name=foo". This shouldn't have any adverse effect. + echo $SUBSYS | grep -q ^name= && { + NAME=$(echo $SUBSYS | sed s/^name=//) + ln -s $SUBSYS $CGROUP/$NAME + } + + # Likewise, on at least one system, it has been reported that + # systemd would mount the CPU and CPU accounting controllers + # (respectively "cpu" and "cpuacct") with "-o cpuacct,cpu" + # but on a directory called "cpu,cpuacct" (note the inversion + # in the order of the groups). This tries to work around it. + [ $SUBSYS = cpuacct,cpu ] && ln -s $SUBSYS $CGROUP/cpu,cpuacct done # Note: as I write those lines, the LXC userland tools cannot setup From b7d138e4ad7a7eaccfe1b468318d65a98081ffcf Mon Sep 17 00:00:00 2001 From: Travis Cline Date: Fri, 18 Oct 2013 00:34:29 -0500 Subject: [PATCH 018/112] Use heredoc to make expect script more clear Upstream-commit: f34a62ea19b477bbaa74a09c04d5e8faf67c44a2 Component: engine --- components/engine/contrib/mkimage-arch.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/components/engine/contrib/mkimage-arch.sh b/components/engine/contrib/mkimage-arch.sh index cdc3c273d8..3b86022206 100755 --- a/components/engine/contrib/mkimage-arch.sh +++ b/components/engine/contrib/mkimage-arch.sh @@ -21,18 +21,20 @@ mkdir $ROOTFS #packages to ignore for space savings PKGIGNORE=linux,jfsutils,lvm2,cryptsetup,groff,man-db,man-pages,mdadm,pciutils,pcmciautils,reiserfsprogs,s-nail,xfsprogs -expect -c " +expect < Date: Thu, 17 Oct 2013 20:33:14 -0700 Subject: [PATCH 019/112] Remove spurious messages, and use proper args expansion. Also, display some (hopefully helpful) message when no command was given. Upstream-commit: 8c38c309851c2a44b9c12bac8f29bc011ea4040f Component: engine --- components/engine/hack/dind | 7 ++++--- components/engine/hack/make/test | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/engine/hack/dind b/components/engine/hack/dind index e8b715cc9c..17e7dfa709 100755 --- a/components/engine/hack/dind +++ b/components/engine/hack/dind @@ -63,7 +63,7 @@ grep -qw devices /proc/1/cgroup || echo "WARNING: it looks like the 'devices' cgroup is not mounted." # Now, close extraneous file descriptors. -pushd /proc/self/fd +pushd /proc/self/fd >/dev/null for FD in * do case "$FD" in @@ -76,9 +76,10 @@ do ;; esac done -popd +popd >/dev/null # Mount /tmp mount -t tmpfs none /tmp -exec $* +[ "$1" ] && exec "$@" +echo "You probably want to run hack/make.sh, or maybe a shell?" diff --git a/components/engine/hack/make/test b/components/engine/hack/make/test index c09727702d..9554f2946b 100644 --- a/components/engine/hack/make/test +++ b/components/engine/hack/make/test @@ -14,6 +14,7 @@ bundle_test() { for test_dir in $(find_test_dirs); do ( set -x cd $test_dir + go test -i go test -v -ldflags "$LDFLAGS" $TESTFLAGS ) done } 2>&1 | tee $DEST/test.log From b75aa9ace92fc8978513f1a9ca80effd490a7d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Petazzoni?= Date: Thu, 17 Oct 2013 20:33:34 -0700 Subject: [PATCH 020/112] Change bundle order, and fix shell array expansion. I believe that it is helpful to build the binary first. That way, if you interrupt the tests, you still get a binary to play with. If you run the tests first and interrupt them, no binary for you! Also, the second part of this commit is an undeniable proof that Bash array syntax is nothing else than an elaborate troll by Bash authors. Upstream-commit: 85956c70b5613439d9f239550c5c4ec360339cb6 Component: engine --- components/engine/hack/make.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/engine/hack/make.sh b/components/engine/hack/make.sh index f911c035f2..4eecfd0484 100755 --- a/components/engine/hack/make.sh +++ b/components/engine/hack/make.sh @@ -33,8 +33,8 @@ grep -q "$RESOLVCONF" /proc/mounts || { # List of bundles to create when no argument is passed DEFAULT_BUNDLES=( - test binary + test ubuntu ) @@ -67,7 +67,7 @@ main() { fi SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" if [ $# -lt 1 ]; then - bundles=($DEFAULT_BUNDLES) + bundles=(${DEFAULT_BUNDLES[@]}) else bundles=($@) fi From 21aae43f3a253ac3cb54e6522e63353beb73ee91 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 18 Oct 2013 06:44:30 +0000 Subject: [PATCH 021/112] Increase readbility of unit tests by using mkRuntime everywhere Upstream-commit: 07d9e4353bc199db7abb52b4b4bba1c2feb75c1a Component: engine --- components/engine/api_test.go | 5 +---- components/engine/buildfile_test.go | 30 ++++++----------------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/components/engine/api_test.go b/components/engine/api_test.go index e047aba9e5..479b9e1e57 100644 --- a/components/engine/api_test.go +++ b/components/engine/api_test.go @@ -472,10 +472,7 @@ func TestGetContainersChanges(t *testing.T) { func TestGetContainersTop(t *testing.T) { t.Skip("Fixme. Skipping test for now. Reported error when testing using dind: 'api_test.go:527: Expected 2 processes, found 0.'") - runtime, err := newTestRuntime() - if err != nil { - t.Fatal(err) - } + runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{runtime: runtime} diff --git a/components/engine/buildfile_test.go b/components/engine/buildfile_test.go index c3881a214f..1af457158a 100644 --- a/components/engine/buildfile_test.go +++ b/components/engine/buildfile_test.go @@ -229,10 +229,7 @@ func TestBuild(t *testing.T) { func buildImage(context testContextTemplate, t *testing.T, srv *Server, useCache bool) *Image { if srv == nil { - runtime, err := newTestRuntime() - if err != nil { - t.Fatal(err) - } + runtime := mkRuntime(t) defer nuke(runtime) srv = &Server{ @@ -370,10 +367,7 @@ func TestBuildEntrypoint(t *testing.T) { // testing #1405 - config.Cmd does not get cleaned up if // utilizing cache func TestBuildEntrypointRunCleanup(t *testing.T) { - runtime, err := newTestRuntime() - if err != nil { - t.Fatal(err) - } + runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{ @@ -402,10 +396,7 @@ func TestBuildEntrypointRunCleanup(t *testing.T) { } func TestBuildImageWithCache(t *testing.T) { - runtime, err := newTestRuntime() - if err != nil { - t.Fatal(err) - } + runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{ @@ -433,10 +424,7 @@ func TestBuildImageWithCache(t *testing.T) { } func TestBuildImageWithoutCache(t *testing.T) { - runtime, err := newTestRuntime() - if err != nil { - t.Fatal(err) - } + runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{ @@ -464,10 +452,7 @@ func TestBuildImageWithoutCache(t *testing.T) { } func TestForbiddenContextPath(t *testing.T) { - runtime, err := newTestRuntime() - if err != nil { - t.Fatal(err) - } + runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{ @@ -513,10 +498,7 @@ func TestForbiddenContextPath(t *testing.T) { } func TestBuildADDFileNotFound(t *testing.T) { - runtime, err := newTestRuntime() - if err != nil { - t.Fatal(err) - } + runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{ From d53bf7553c66f7de037340ae363ff53a993c6ab4 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 18 Oct 2013 06:47:08 +0000 Subject: [PATCH 022/112] hack: encode the name of the current test in temporary directories, for easier tracking Conflicts: utils_test.go Upstream-commit: b629810fe08dc864674a6e64a7f1b418096bc448 Component: engine --- components/engine/utils_test.go | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/components/engine/utils_test.go b/components/engine/utils_test.go index 740a5fc1bc..3f99de570b 100644 --- a/components/engine/utils_test.go +++ b/components/engine/utils_test.go @@ -2,22 +2,38 @@ package docker import ( "github.com/dotcloud/docker/utils" + "fmt" "io" "io/ioutil" "os" "path" "strings" "testing" + "runtime" ) // This file contains utility functions for docker's unit test suite. // It has to be named XXX_test.go, apparently, in other to access private functions // from other XXX_test.go functions. +var globalTestID string + // Create a temporary runtime suitable for unit testing. // Call t.Fatal() at the first error. func mkRuntime(f Fataler) *Runtime { - runtime, err := newTestRuntime() + // Use the caller function name as a prefix. + // This helps trace temp directories back to their test. + pc, _, _, _ := runtime.Caller(1) + callerLongName := runtime.FuncForPC(pc).Name() + parts := strings.Split(callerLongName, ".") + callerShortName := parts[len(parts) - 1] + if globalTestID == "" { + globalTestID = GenerateID()[:4] + } + prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, callerShortName) + utils.Debugf("prefix = '%s'", prefix) + + runtime, err := newTestRuntime(prefix) if err != nil { f.Fatal(err) } @@ -30,8 +46,16 @@ type Fataler interface { Fatal(args ...interface{}) } -func newTestRuntime() (*Runtime, error) { - root, err := ioutil.TempDir("", "docker-test") +func newTestRuntime(prefix string) (runtime *Runtime, err error) { + if prefix == "" { + prefix = "docker-test-" + } + utils.Debugf("prefix = %s", prefix) + utils.Debugf("newTestRuntime start") + root, err := ioutil.TempDir("", prefix) + defer func() { + utils.Debugf("newTestRuntime: %s", root) + }() if err != nil { return nil, err } @@ -42,7 +66,7 @@ func newTestRuntime() (*Runtime, error) { return nil, err } - runtime, err := NewRuntimeFromDirectory(root, false) + runtime, err = NewRuntimeFromDirectory(root, false) if err != nil { return nil, err } From 6bdd999b912c488d4a0dff7b06c9b06f7be51aee Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Fri, 18 Oct 2013 12:18:13 -0600 Subject: [PATCH 023/112] Add "vendor/pkg/" to .gitignore now that we "go test -i" Upstream-commit: 4870265a9f07b443fa06df07c50ddd6f13c9f13f Component: engine --- components/engine/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/components/engine/.gitignore b/components/engine/.gitignore index 5843eaf9cc..8cf66168eb 100644 --- a/components/engine/.gitignore +++ b/components/engine/.gitignore @@ -17,3 +17,4 @@ docs/_templates bundles/ .hg/ .git/ +vendor/pkg/ From 02bbabf14d5fce10f282fea8ea5e3e76963309e7 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 11 Sep 2013 23:50:26 -0700 Subject: [PATCH 024/112] Add -nostdin and -proxy to docker attach, allow arbirary signal to be sent via docker kill api endpoint Allow attach from `docker start` Add host integration script generation Update doc with host integration Upstream-commit: 4918769b1ac2d38f23087b766140e6a7f8979310 Component: engine --- components/engine/api.go | 15 +- components/engine/commands.go | 92 ++++++++++++- components/engine/container.go | 14 +- .../contrib/host_integration/Dockerfile.dev | 27 ++++ .../contrib/host_integration/Dockerfile.min | 4 + .../contrib/host_integration/manager.go | 130 ++++++++++++++++++ .../docs/sources/use/host_integration.rst | 68 +++++++++ components/engine/docs/sources/use/index.rst | 1 + components/engine/server.go | 4 +- components/engine/utils/signal_darwin.go | 44 ++++++ components/engine/utils/signal_linux.go | 47 +++++++ 11 files changed, 430 insertions(+), 16 deletions(-) create mode 100644 components/engine/contrib/host_integration/Dockerfile.dev create mode 100644 components/engine/contrib/host_integration/Dockerfile.min create mode 100644 components/engine/contrib/host_integration/manager.go create mode 100644 components/engine/docs/sources/use/host_integration.rst create mode 100644 components/engine/utils/signal_darwin.go create mode 100644 components/engine/utils/signal_linux.go diff --git a/components/engine/api.go b/components/engine/api.go index ad308335cc..a656414062 100644 --- a/components/engine/api.go +++ b/components/engine/api.go @@ -135,8 +135,21 @@ func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r * if vars == nil { return fmt.Errorf("Missing parameter") } + if err := parseForm(r); err != nil { + return err + } name := vars["name"] - if err := srv.ContainerKill(name); err != nil { + s := r.Form.Get("signal") + signal := 9 + if s != "" { + if s, err := strconv.Atoi(s); err != nil { + return err + } else { + signal = s + } + } + + if err := srv.ContainerKill(name, signal); err != nil { return err } w.WriteHeader(http.StatusNoContent) diff --git a/components/engine/commands.go b/components/engine/commands.go index 7d33b81d0a..5bf4437b90 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -547,6 +547,8 @@ func (cli *DockerCli) CmdRestart(args ...string) error { func (cli *DockerCli) CmdStart(args ...string) error { cmd := Subcmd("start", "CONTAINER [CONTAINER...]", "Restart a stopped container") + attach := cmd.Bool("a", false, "Attach container's stdout/stderr and forward all signals to the process") + openStdin := cmd.Bool("i", false, "Attach container's stdin") if err := cmd.Parse(args); err != nil { return nil } @@ -555,17 +557,79 @@ func (cli *DockerCli) CmdStart(args ...string) error { return nil } + var cErr chan error + if *attach || *openStdin { + if cmd.NArg() > 1 { + return fmt.Errorf("Impossible to start and attach multiple containers at once.") + } + + body, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil) + if err != nil { + return err + } + + container := &Container{} + err = json.Unmarshal(body, container) + if err != nil { + return err + } + + if !container.Config.Tty { + sigc := make(chan os.Signal, 1) + utils.CatchAll(sigc) + go func() { + for s := range sigc { + if _, _, err := cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%d", cmd.Arg(0), s), nil); err != nil { + utils.Debugf("Error sending signal: %s", err) + } + } + }() + } + + if container.Config.Tty { + if err := cli.monitorTtySize(cmd.Arg(0)); err != nil { + return err + } + } + + v := url.Values{} + v.Set("stream", "1") + if *openStdin && container.Config.OpenStdin { + v.Set("stdin", "1") + } + v.Set("stdout", "1") + v.Set("stderr", "1") + + cErr = utils.Go(func() error { + return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out) + }) + } + var encounteredError error - for _, name := range args { + for _, name := range cmd.Args() { _, _, err := cli.call("POST", "/containers/"+name+"/start", nil) if err != nil { - fmt.Fprintf(cli.err, "%s\n", err) - encounteredError = fmt.Errorf("Error: failed to start one or more containers") + if !*attach || !*openStdin { + fmt.Fprintf(cli.err, "%s\n", err) + encounteredError = fmt.Errorf("Error: failed to start one or more containers") + } } else { - fmt.Fprintf(cli.out, "%s\n", name) + if !*attach || !*openStdin { + fmt.Fprintf(cli.out, "%s\n", name) + } } } - return encounteredError + if encounteredError != nil { + if *openStdin || *attach { + cli.in.Close() + <-cErr + } + return encounteredError + } + if *openStdin || *attach { + return <-cErr + } + return nil } func (cli *DockerCli) CmdInspect(args ...string) error { @@ -1238,6 +1302,8 @@ func (cli *DockerCli) CmdLogs(args ...string) error { func (cli *DockerCli) CmdAttach(args ...string) error { cmd := Subcmd("attach", "CONTAINER", "Attach to a running container") + noStdin := cmd.Bool("nostdin", false, "Do not attach stdin") + proxy := cmd.Bool("proxy", false, "Proxify all received signal to the process (even in non-tty mode)") if err := cmd.Parse(args); err != nil { return nil } @@ -1269,10 +1335,24 @@ func (cli *DockerCli) CmdAttach(args ...string) error { v := url.Values{} v.Set("stream", "1") - v.Set("stdin", "1") + if !*noStdin && container.Config.OpenStdin { + v.Set("stdin", "1") + } v.Set("stdout", "1") v.Set("stderr", "1") + if *proxy && !container.Config.Tty { + sigc := make(chan os.Signal, 1) + utils.CatchAll(sigc) + go func() { + for s := range sigc { + if _, _, err := cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%d", cmd.Arg(0), s), nil); err != nil { + utils.Debugf("Error sending signal: %s", err) + } + } + }() + } + if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out, cli.err); err != nil { return err } diff --git a/components/engine/container.go b/components/engine/container.go index 7d85aef0a1..cf92461f2c 100644 --- a/components/engine/container.go +++ b/components/engine/container.go @@ -1044,13 +1044,13 @@ func (container *Container) cleanup() { } } -func (container *Container) kill() error { +func (container *Container) kill(sig int) error { if !container.State.Running { return nil } // Sending SIGKILL to the process via lxc - output, err := exec.Command("lxc-kill", "-n", container.ID, "9").CombinedOutput() + output, err := exec.Command("lxc-kill", "-n", container.ID, strconv.Itoa(sig)).CombinedOutput() if err != nil { log.Printf("error killing container %s (%s, %s)", container.ID, output, err) } @@ -1060,7 +1060,7 @@ func (container *Container) kill() error { if container.cmd == nil { return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", container.ID) } - log.Printf("Container %s failed to exit within 10 seconds of lxc SIGKILL - trying direct SIGKILL", container.ID) + log.Printf("Container %s failed to exit within 10 seconds of lxc-kill %d - trying direct SIGKILL", sig, container.ID) if err := container.cmd.Process.Kill(); err != nil { return err } @@ -1071,13 +1071,13 @@ func (container *Container) kill() error { return nil } -func (container *Container) Kill() error { +func (container *Container) Kill(sig int) error { container.State.Lock() defer container.State.Unlock() if !container.State.Running { return nil } - return container.kill() + return container.kill(sig) } func (container *Container) Stop(seconds int) error { @@ -1091,7 +1091,7 @@ func (container *Container) Stop(seconds int) error { if output, err := exec.Command("lxc-kill", "-n", container.ID, "15").CombinedOutput(); err != nil { log.Print(string(output)) log.Print("Failed to send SIGTERM to the process, force killing") - if err := container.kill(); err != nil { + if err := container.kill(9); err != nil { return err } } @@ -1099,7 +1099,7 @@ func (container *Container) Stop(seconds int) error { // 2. Wait for the process to exit on its own if err := container.WaitTimeout(time.Duration(seconds) * time.Second); err != nil { log.Printf("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds) - if err := container.kill(); err != nil { + if err := container.kill(9); err != nil { return err } } diff --git a/components/engine/contrib/host_integration/Dockerfile.dev b/components/engine/contrib/host_integration/Dockerfile.dev new file mode 100644 index 0000000000..161416e750 --- /dev/null +++ b/components/engine/contrib/host_integration/Dockerfile.dev @@ -0,0 +1,27 @@ +# +# This Dockerfile will create an image that allows to generate upstart and +# systemd scripts (more to come) +# +# docker-version 0.6.2 +# + +FROM ubuntu:12.10 +MAINTAINER Guillaume J. Charmes + +RUN apt-get update && apt-get install -y wget git mercurial + +# Install Go +RUN wget --no-check-certificate https://go.googlecode.com/files/go1.1.2.linux-amd64.tar.gz -O go-1.1.2.tar.gz +RUN tar -xzvf go-1.1.2.tar.gz && mv /go /goroot +RUN mkdir /go + +ENV GOROOT /goroot +ENV GOPATH /go +ENV PATH $GOROOT/bin:$PATH + +RUN go get github.com/dotcloud/docker && cd /go/src/github.com/dotcloud/docker && git checkout v0.6.3 +ADD manager.go /manager/ +RUN cd /manager && go build -o /usr/bin/manager + +ENTRYPOINT ["/usr/bin/manager"] + diff --git a/components/engine/contrib/host_integration/Dockerfile.min b/components/engine/contrib/host_integration/Dockerfile.min new file mode 100644 index 0000000000..1a7b3a9d82 --- /dev/null +++ b/components/engine/contrib/host_integration/Dockerfile.min @@ -0,0 +1,4 @@ +FROM busybox +MAINTAINER Guillaume J. Charmes +ADD manager /usr/bin/ +ENTRYPOINT ["/usr/bin/manager"] diff --git a/components/engine/contrib/host_integration/manager.go b/components/engine/contrib/host_integration/manager.go new file mode 100644 index 0000000000..98ff90aa1b --- /dev/null +++ b/components/engine/contrib/host_integration/manager.go @@ -0,0 +1,130 @@ +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "github.com/dotcloud/docker" + "os" + "strings" + "text/template" +) + +var templates = map[string]string{ + + "upstart": `description "{{.description}}" +author "{{.author}}" +start on filesystem and started lxc-net and started docker +stop on runlevel [!2345] +respawn +exec /home/vagrant/goroot/bin/docker start -a {{.container_id}} +`, + + "systemd": `[Unit] + Description={{.description}} + Author={{.author}} + After=docker.service + +[Service] + Restart=always + ExecStart=/usr/bin/docker start -a {{.container_id}} + ExecStop=/usr/bin/docker stop -t 2 {{.container_id}} + +[Install] + WantedBy=local.target +`, +} + +func main() { + // Parse command line for custom options + kind := flag.String("t", "upstart", "Type of manager requested") + author := flag.String("a", "", "Author of the image") + description := flag.String("d", "", "Description of the image") + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "\nUsage: manager \n\n") + flag.PrintDefaults() + } + flag.Parse() + + // We require at least the container ID + if flag.NArg() != 1 { + println(flag.NArg()) + flag.Usage() + return + } + + // Check that the requested process manager is supported + if _, exists := templates[*kind]; !exists { + panic("Unkown script template") + } + + // Load the requested template + tpl, err := template.New("processManager").Parse(templates[*kind]) + if err != nil { + panic(err) + } + + // Create stdout/stderr buffers + bufOut := bytes.NewBuffer(nil) + bufErr := bytes.NewBuffer(nil) + + // Instanciate the Docker CLI + cli := docker.NewDockerCli(nil, bufOut, bufErr, "unix", "/var/run/docker.sock") + // Retrieve the container info + if err := cli.CmdInspect(flag.Arg(0)); err != nil { + // As of docker v0.6.3, CmdInspect always returns nil + panic(err) + } + + // If there is nothing in the error buffer, then the Docker daemon is there and the container has been found + if bufErr.Len() == 0 { + // Unmarshall the resulting container data + c := []*docker.Container{{}} + if err := json.Unmarshal(bufOut.Bytes(), &c); err != nil { + panic(err) + } + // Reset the buffers + bufOut.Reset() + bufErr.Reset() + // Retrieve the info of the linked image + if err := cli.CmdInspect(c[0].Image); err != nil { + panic(err) + } + // If there is nothing in the error buffer, then the image has been found. + if bufErr.Len() == 0 { + // Unmarshall the resulting image data + img := []*docker.Image{{}} + if err := json.Unmarshal(bufOut.Bytes(), &img); err != nil { + panic(err) + } + // If no author has been set, use the one from the image + if *author == "" && img[0].Author != "" { + *author = strings.Replace(img[0].Author, "\"", "", -1) + } + // If no description has been set, use the comment from the image + if *description == "" && img[0].Comment != "" { + *description = strings.Replace(img[0].Comment, "\"", "", -1) + } + } + } + + /// Old version: Wrtie the resulting script to file + // f, err := os.OpenFile(kind, os.O_CREATE|os.O_WRONLY, 0755) + // if err != nil { + // panic(err) + // } + // defer f.Close() + + // Create a map with needed data + data := map[string]string{ + "author": *author, + "description": *description, + "container_id": flag.Arg(0), + } + + // Process the template and output it on Stdout + if err := tpl.Execute(os.Stdout, data); err != nil { + panic(err) + } +} diff --git a/components/engine/docs/sources/use/host_integration.rst b/components/engine/docs/sources/use/host_integration.rst new file mode 100644 index 0000000000..cc2f56a5c7 --- /dev/null +++ b/components/engine/docs/sources/use/host_integration.rst @@ -0,0 +1,68 @@ +:title: Host Integration +:description: How to generate scripts for upstart, systemd, etc. +:keywords: systemd, upstart, supervisor, docker, documentation, host integration + +Introduction +============ + +When you have finished setting up your image and are happy with your running +container, you may want to use a process manager like `upstart` or `systemd`. + +In order to do so, we provide a simple image: creack/manger:min. + +This image takes the container ID as parameter. We also can specify the kind of +process manager and meta datas like Author and Description. + +If no process manager is specified, then `upstart` is assumed. + +Note: The result will be an output to stdout. + +Usage +===== +Usage: docker run creack/manager:min [OPTIONS] + + -a="": Author of the image + -d="": Description of the image + -t="upstart": Type of manager requested + +Development +=========== + +The image creack/manager:min is a `busybox` base with the binary as entrypoint. +It is meant to be light and fast to download. + +Now, if you want/need to change or add things, you can download the full +creack/manager repository that contains creack/manager:min and +creack/manager:dev. + +The Dockerfiles and the sources are available in `/contrib/host_integration`. + + +Upstart +======= + +Upstart is the default process manager. The generated script will start the +container after docker daemon. If the container dies, it will respawn. +Start/Restart/Stop/Reload are supported. Reload will send a SIGHUP to the container. + +Example: +`CID=$(docker run -d creack/firefo-vnc)` +`docker run creack/manager:min -a 'Guillaume J. Charmes ' -d 'Awesome Firefox in VLC' $CID > /etc/init/firefoxvnc.conf` + +You can now do `start firefoxvnc` or `stop firefoxvnc` and if the container +dies for some reason, upstart will restart it. + +Systemd +======= + +In order to generate a systemd script, we need to -t option. The generated +script will start the container after docker daemon. If the container dies, it +will respawn. +Start/Restart/Reload/Stop are supported. + +Example (fedora): +`CID=$(docker run -d creack/firefo-vnc)` +`docker run creack/manager:min -t systemd -a 'Guillaume J. Charmes ' -d 'Awesome Firefox in VLC' $CID > /usr/lib/systemd/system/firefoxvnc.service` + +You can now do `systemctl start firefoxvnc` or `systemctl stop firefoxvnc` +and if the container dies for some reason, systemd will restart it. diff --git a/components/engine/docs/sources/use/index.rst b/components/engine/docs/sources/use/index.rst index d0a40159e9..7d0b3c5a31 100644 --- a/components/engine/docs/sources/use/index.rst +++ b/components/engine/docs/sources/use/index.rst @@ -18,3 +18,4 @@ Contents: baseimages port_redirection puppet + host_integration diff --git a/components/engine/server.go b/components/engine/server.go index 27d1968dc8..65040ba7fd 100644 --- a/components/engine/server.go +++ b/components/engine/server.go @@ -72,9 +72,9 @@ func (srv *Server) versionInfos() []utils.VersionInfo { return ret } -func (srv *Server) ContainerKill(name string) error { +func (srv *Server) ContainerKill(name string, sig int) error { if container := srv.runtime.Get(name); container != nil { - if err := container.Kill(); err != nil { + if err := container.Kill(sig); err != nil { return fmt.Errorf("Error killing container %s: %s", name, err) } srv.LogEvent("kill", container.ShortID(), srv.runtime.repositories.ImageName(container.Image)) diff --git a/components/engine/utils/signal_darwin.go b/components/engine/utils/signal_darwin.go new file mode 100644 index 0000000000..28730db8e5 --- /dev/null +++ b/components/engine/utils/signal_darwin.go @@ -0,0 +1,44 @@ +package utils + +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, + ) +} diff --git a/components/engine/utils/signal_linux.go b/components/engine/utils/signal_linux.go new file mode 100644 index 0000000000..26cfd56967 --- /dev/null +++ b/components/engine/utils/signal_linux.go @@ -0,0 +1,47 @@ +package utils + +import ( + "os" + "os/signal" + "syscall" +) + +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 9e4d782d8f1bb51bcd7e5196fa6bec3b335a744a Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Fri, 4 Oct 2013 07:59:06 -0600 Subject: [PATCH 025/112] Add POSIX shell version of host_integration/manager.go in the style of hack/make.sh Rename host_integration to host-integration for consistency Upstream-commit: 7cf1877098edb7d4874509a338f663d550ef0ede Component: engine --- .../Dockerfile.dev | 0 .../Dockerfile.min | 0 .../manager.go | 0 .../contrib/host-integration/manager.sh | 53 +++++++++++++++++++ .../contrib/host-integration/manager/systemd | 20 +++++++ .../contrib/host-integration/manager/upstart | 15 ++++++ 6 files changed, 88 insertions(+) rename components/engine/contrib/{host_integration => host-integration}/Dockerfile.dev (100%) rename components/engine/contrib/{host_integration => host-integration}/Dockerfile.min (100%) rename components/engine/contrib/{host_integration => host-integration}/manager.go (100%) create mode 100755 components/engine/contrib/host-integration/manager.sh create mode 100755 components/engine/contrib/host-integration/manager/systemd create mode 100755 components/engine/contrib/host-integration/manager/upstart diff --git a/components/engine/contrib/host_integration/Dockerfile.dev b/components/engine/contrib/host-integration/Dockerfile.dev similarity index 100% rename from components/engine/contrib/host_integration/Dockerfile.dev rename to components/engine/contrib/host-integration/Dockerfile.dev diff --git a/components/engine/contrib/host_integration/Dockerfile.min b/components/engine/contrib/host-integration/Dockerfile.min similarity index 100% rename from components/engine/contrib/host_integration/Dockerfile.min rename to components/engine/contrib/host-integration/Dockerfile.min diff --git a/components/engine/contrib/host_integration/manager.go b/components/engine/contrib/host-integration/manager.go similarity index 100% rename from components/engine/contrib/host_integration/manager.go rename to components/engine/contrib/host-integration/manager.go diff --git a/components/engine/contrib/host-integration/manager.sh b/components/engine/contrib/host-integration/manager.sh new file mode 100755 index 0000000000..fecf4bf64b --- /dev/null +++ b/components/engine/contrib/host-integration/manager.sh @@ -0,0 +1,53 @@ +#!/bin/sh +set -e + +usage() { + echo >&2 "usage: $0 [-a author] [-d description] container [manager]" + echo >&2 " ie: $0 -a 'John Smith' 4ec9612a37cd systemd" + echo >&2 " ie: $0 -d 'Super Cool System' 4ec9612a37cd # defaults to upstart" + exit 1 +} + +auth='' +desc='' +have_auth= +have_desc= +while getopts a:d: opt; do + case "$opt" in + a) + auth="$OPTARG" + have_auth=1 + ;; + d) + desc="$OPTARG" + have_desc=1 + ;; + esac +done +shift $(($OPTIND - 1)) + +[ $# -ge 1 -a $# -le 2 ] || usage + +cid="$1" +script="${2:-upstart}" +if [ ! -e "manager/$script" ]; then + echo >&2 "Error: manager type '$script' is unknown (PRs always welcome!)." + echo >&2 'The currently supported types are:' + echo >&2 " $(cd manager && echo *)" + exit 1 +fi + +# TODO https://github.com/dotcloud/docker/issues/734 (docker inspect formatting) +#if command -v docker > /dev/null 2>&1; then +# image="$(docker inspect -f '{{.Image}}' "$cid")" +# if [ "$image" ]; then +# if [ -z "$have_auth" ]; then +# auth="$(docker inspect -f '{{.Author}}' "$image")" +# fi +# if [ -z "$have_desc" ]; then +# desc="$(docker inspect -f '{{.Comment}}' "$image")" +# fi +# fi +#fi + +exec "manager/$script" "$cid" "$auth" "$desc" diff --git a/components/engine/contrib/host-integration/manager/systemd b/components/engine/contrib/host-integration/manager/systemd new file mode 100755 index 0000000000..0431b3ced4 --- /dev/null +++ b/components/engine/contrib/host-integration/manager/systemd @@ -0,0 +1,20 @@ +#!/bin/sh +set -e + +cid="$1" +auth="$2" +desc="$3" + +cat <<-EOF + [Unit] + Description=$desc + Author=$auth + After=docker.service + + [Service] + ExecStart=/usr/bin/docker start -a $cid + ExecStop=/usr/bin/docker stop -t 2 $cid + + [Install] + WantedBy=local.target +EOF diff --git a/components/engine/contrib/host-integration/manager/upstart b/components/engine/contrib/host-integration/manager/upstart new file mode 100755 index 0000000000..af90f1fddd --- /dev/null +++ b/components/engine/contrib/host-integration/manager/upstart @@ -0,0 +1,15 @@ +#!/bin/sh +set -e + +cid="$1" +auth="$2" +desc="$3" + +cat <<-EOF + description "$(echo "$desc" | sed 's/"/\\"/g')" + author "$(echo "$auth" | sed 's/"/\\"/g')" + start on filesystem and started lxc-net and started docker + stop on runlevel [!2345] + respawn + exec /usr/bin/docker start -a "$cid" +EOF From b3613b29c94275f22e5fe1e3c26ad3ddc4ec2c9c Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Tue, 8 Oct 2013 19:15:29 +0000 Subject: [PATCH 026/112] Fix issue killing container while sending signal Fix rebase issue Update docs Upstream-commit: 333bc23f21e8423d3085632db99a6d1df227c5f1 Component: engine --- components/engine/api.go | 20 ++++-- components/engine/api_test.go | 4 +- components/engine/commands.go | 45 +++++++------ components/engine/commands_test.go | 6 +- components/engine/container.go | 67 +++++++++++-------- .../sources/api/docker_remote_api_v1.6.rst | 3 +- .../engine/docs/sources/commandline/cli.rst | 9 ++- components/engine/server.go | 25 +++++-- components/engine/server_test.go | 29 ++++---- 9 files changed, 121 insertions(+), 87 deletions(-) diff --git a/components/engine/api.go b/components/engine/api.go index a656414062..6c1c47a001 100644 --- a/components/engine/api.go +++ b/components/engine/api.go @@ -42,6 +42,9 @@ func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) { //If we don't do this, POST method without Content-type (even with empty body) will fail func parseForm(r *http.Request) error { + if r == nil { + return nil + } if err := r.ParseForm(); err != nil && !strings.HasPrefix(err.Error(), "mime:") { return err } @@ -139,13 +142,16 @@ func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r * return err } name := vars["name"] - s := r.Form.Get("signal") - signal := 9 - if s != "" { - if s, err := strconv.Atoi(s); err != nil { - return err - } else { - signal = s + + signal := 0 + if r != nil { + s := r.Form.Get("signal") + if s != "" { + if s, err := strconv.Atoi(s); err != nil { + return err + } else { + signal = s + } } } diff --git a/components/engine/api_test.go b/components/engine/api_test.go index 479b9e1e57..35667c74f1 100644 --- a/components/engine/api_test.go +++ b/components/engine/api_test.go @@ -347,6 +347,8 @@ func TestGetContainersJSON(t *testing.T) { srv := &Server{runtime: runtime} + beginLen := runtime.containers.Len() + container, err := runtime.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "test"}, @@ -370,7 +372,7 @@ func TestGetContainersJSON(t *testing.T) { t.Fatal(err) } if len(containers) != 1 { - t.Fatalf("Expected %d container, %d found", 1, len(containers)) + t.Fatalf("Expected %d container, %d found (started with: %d)", 1, len(containers), beginLen) } if containers[0].ID != container.ID { t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", container.ID, containers[0].ID) diff --git a/components/engine/commands.go b/components/engine/commands.go index 5bf4437b90..befe8a6bcf 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -545,6 +545,18 @@ func (cli *DockerCli) CmdRestart(args ...string) error { return nil } +func (cli *DockerCli) forwardAllSignals(cid string) { + sigc := make(chan os.Signal, 1) + utils.CatchAll(sigc) + go func() { + for s := range sigc { + if _, _, err := cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%d", cid, s), nil); err != nil { + utils.Debugf("Error sending signal: %s", err) + } + } + }() +} + func (cli *DockerCli) CmdStart(args ...string) error { cmd := Subcmd("start", "CONTAINER [CONTAINER...]", "Restart a stopped container") attach := cmd.Bool("a", false, "Attach container's stdout/stderr and forward all signals to the process") @@ -575,15 +587,7 @@ func (cli *DockerCli) CmdStart(args ...string) error { } if !container.Config.Tty { - sigc := make(chan os.Signal, 1) - utils.CatchAll(sigc) - go func() { - for s := range sigc { - if _, _, err := cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%d", cmd.Arg(0), s), nil); err != nil { - utils.Debugf("Error sending signal: %s", err) - } - } - }() + cli.forwardAllSignals(cmd.Arg(0)) } if container.Config.Tty { @@ -601,7 +605,7 @@ func (cli *DockerCli) CmdStart(args ...string) error { v.Set("stderr", "1") cErr = utils.Go(func() error { - return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out) + return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out, cli.err) }) } @@ -1301,9 +1305,9 @@ func (cli *DockerCli) CmdLogs(args ...string) error { } func (cli *DockerCli) CmdAttach(args ...string) error { - cmd := Subcmd("attach", "CONTAINER", "Attach to a running container") + cmd := Subcmd("attach", "[OPTIONS] CONTAINER", "Attach to a running container") noStdin := cmd.Bool("nostdin", false, "Do not attach stdin") - proxy := cmd.Bool("proxy", false, "Proxify all received signal to the process (even in non-tty mode)") + proxy := cmd.Bool("sig-proxy", false, "Proxify all received signal to the process (even in non-tty mode)") if err := cmd.Parse(args); err != nil { return nil } @@ -1342,15 +1346,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error { v.Set("stderr", "1") if *proxy && !container.Config.Tty { - sigc := make(chan os.Signal, 1) - utils.CatchAll(sigc) - go func() { - for s := range sigc { - if _, _, err := cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%d", cmd.Arg(0), s), nil); err != nil { - utils.Debugf("Error sending signal: %s", err) - } - } - }() + cli.forwardAllSignals(cmd.Arg(0)) } if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out, cli.err); err != nil { @@ -1516,6 +1512,9 @@ func (cli *DockerCli) CmdRun(args ...string) error { flRm := cmd.Lookup("rm") autoRemove, _ := strconv.ParseBool(flRm.Value.String()) + flSigProxy := cmd.Lookup("sig-proxy") + sigProxy, _ := strconv.ParseBool(flSigProxy.Value.String()) + var containerIDFile *os.File if len(hostConfig.ContainerIDFile) > 0 { if _, err := ioutil.ReadFile(hostConfig.ContainerIDFile); err == nil { @@ -1594,6 +1593,10 @@ func (cli *DockerCli) CmdRun(args ...string) error { } } + if sigProxy { + cli.forwardAllSignals(runResult.ID) + } + //start the container if _, _, err = cli.call("POST", "/containers/"+runResult.ID+"/start", hostConfig); err != nil { return err diff --git a/components/engine/commands_test.go b/components/engine/commands_test.go index aceb7a6577..c5fa83d3e4 100644 --- a/components/engine/commands_test.go +++ b/components/engine/commands_test.go @@ -393,7 +393,7 @@ func TestRunDetach(t *testing.T) { container := globalRuntime.List()[0] setTimeout(t, "Escape sequence timeout", 5*time.Second, func() { - stdinPipe.Write([]byte{'', ''}) + stdinPipe.Write([]byte{16, 17}) if err := stdinPipe.Close(); err != nil { t.Fatal(err) } @@ -411,7 +411,6 @@ func TestRunDetach(t *testing.T) { setTimeout(t, "Waiting for container to die timed out", 20*time.Second, func() { container.Kill() - container.Wait() }) } @@ -451,7 +450,7 @@ func TestAttachDetach(t *testing.T) { }) setTimeout(t, "Escape sequence timeout", 5*time.Second, func() { - stdinPipe.Write([]byte{'', ''}) + stdinPipe.Write([]byte{16, 17}) if err := stdinPipe.Close(); err != nil { t.Fatal(err) } @@ -469,7 +468,6 @@ func TestAttachDetach(t *testing.T) { setTimeout(t, "Waiting for container to die timedout", 5*time.Second, func() { container.Kill() - container.Wait() }) } diff --git a/components/engine/container.go b/components/engine/container.go index cf92461f2c..f17cabbce4 100644 --- a/components/engine/container.go +++ b/components/engine/container.go @@ -99,7 +99,10 @@ type BindMap struct { } var ( - ErrInvaidWorikingDirectory = errors.New("The working directory is invalid. It needs to be an absolute path.") + ErrInvalidWorikingDirectory = errors.New("The working directory is invalid. It needs to be an absolute path.") + ErrConflictTtySigProxy = errors.New("TTY mode (-t) already imply signal proxying (-sig-proxy)") + ErrConflictAttachDetach = errors.New("Conflicting options: -a and -d") + ErrConflictDetachAutoRemove = errors.New("Conflicting options: -rm and -d") ) type KeyValuePair struct { @@ -127,6 +130,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig, flNetwork := cmd.Bool("n", true, "Enable networking for this container") flPrivileged := cmd.Bool("privileged", false, "Give extended privileges to this container") flAutoRemove := cmd.Bool("rm", false, "Automatically remove the container when it exits (incompatible with -d)") + flSigProxy := cmd.Bool("sig-proxy", false, "Proxify all received signal to the process (even in non-tty mode)") if capabilities != nil && *flMemory > 0 && !capabilities.MemoryLimit { //fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n") @@ -159,11 +163,18 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig, return nil, nil, cmd, err } if *flDetach && len(flAttach) > 0 { - return nil, nil, cmd, fmt.Errorf("Conflicting options: -a and -d") + return nil, nil, cmd, ErrConflictAttachDetach } if *flWorkingDir != "" && !path.IsAbs(*flWorkingDir) { - return nil, nil, cmd, ErrInvaidWorikingDirectory + return nil, nil, cmd, ErrInvalidWorikingDirectory } + if *flTty && *flSigProxy { + return nil, nil, cmd, ErrConflictTtySigProxy + } + if *flDetach && *flAutoRemove { + return nil, nil, cmd, ErrConflictDetachAutoRemove + } + // If neither -d or -a are set, attach to everything by default if len(flAttach) == 0 && !*flDetach { if !*flDetach { @@ -175,10 +186,6 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig, } } - if *flDetach && *flAutoRemove { - return nil, nil, cmd, fmt.Errorf("Conflicting options: -rm and -d") - } - var binds []string // add any bind targets to the list of container volumes @@ -1045,51 +1052,54 @@ func (container *Container) cleanup() { } func (container *Container) kill(sig int) error { + container.State.Lock() + defer container.State.Unlock() + if !container.State.Running { return nil } - // Sending SIGKILL to the process via lxc - output, err := exec.Command("lxc-kill", "-n", container.ID, strconv.Itoa(sig)).CombinedOutput() - if err != nil { - log.Printf("error killing container %s (%s, %s)", container.ID, output, err) + if output, err := exec.Command("lxc-kill", "-n", container.ID, strconv.Itoa(sig)).CombinedOutput(); err != nil { + log.Printf("error killing container %s (%s, %s)", container.ShortID(), output, err) + return err + } + + return nil +} + +func (container *Container) Kill() error { + if !container.State.Running { + return nil + } + + // 1. Send SIGKILL + if err := container.kill(9); err != nil { + return err } // 2. Wait for the process to die, in last resort, try to kill the process directly if err := container.WaitTimeout(10 * time.Second); err != nil { if container.cmd == nil { - return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", container.ID) + return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", container.ShortID()) } - log.Printf("Container %s failed to exit within 10 seconds of lxc-kill %d - trying direct SIGKILL", sig, container.ID) + log.Printf("Container %s failed to exit within 10 seconds of lxc-kill %s - trying direct SIGKILL", "SIGKILL", container.ShortID()) if err := container.cmd.Process.Kill(); err != nil { return err } } - // Wait for the container to be actually stopped container.Wait() return nil } -func (container *Container) Kill(sig int) error { - container.State.Lock() - defer container.State.Unlock() - if !container.State.Running { - return nil - } - return container.kill(sig) -} - func (container *Container) Stop(seconds int) error { - container.State.Lock() - defer container.State.Unlock() if !container.State.Running { return nil } // 1. Send a SIGTERM - if output, err := exec.Command("lxc-kill", "-n", container.ID, "15").CombinedOutput(); err != nil { - log.Print(string(output)) + if err := container.kill(15); err != nil { + utils.Debugf("Error sending kill SIGTERM: %s", err) log.Print("Failed to send SIGTERM to the process, force killing") if err := container.kill(9); err != nil { return err @@ -1099,7 +1109,8 @@ func (container *Container) Stop(seconds int) error { // 2. Wait for the process to exit on its own if err := container.WaitTimeout(time.Duration(seconds) * time.Second); err != nil { log.Printf("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds) - if err := container.kill(9); err != nil { + // 3. If it doesn't, then send SIGKILL + if err := container.Kill(); err != nil { return err } } diff --git a/components/engine/docs/sources/api/docker_remote_api_v1.6.rst b/components/engine/docs/sources/api/docker_remote_api_v1.6.rst index d84d5e85d0..1734f81c07 100644 --- a/components/engine/docs/sources/api/docker_remote_api_v1.6.rst +++ b/components/engine/docs/sources/api/docker_remote_api_v1.6.rst @@ -442,7 +442,8 @@ Kill a container .. sourcecode:: http HTTP/1.1 204 OK - + + :query signal: Signal to send to the container (integer). When not set, SIGKILL is assumed and the call will waits for the container to exit. :statuscode 204: no error :statuscode 404: no such container :statuscode 500: server error diff --git a/components/engine/docs/sources/commandline/cli.rst b/components/engine/docs/sources/commandline/cli.rst index 71a902d46f..cc0e46c14c 100644 --- a/components/engine/docs/sources/commandline/cli.rst +++ b/components/engine/docs/sources/commandline/cli.rst @@ -29,6 +29,9 @@ To list available commands, either run ``docker`` with no parameters or execute Attach to a running container. + -nostdin=false: Do not attach stdin + -sig-proxy=false: Proxify all received signal to the process (even in non-tty mode) + 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. @@ -396,7 +399,7 @@ Insert file from github :: - Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...] + Usage: docker kill CONTAINER [CONTAINER...] Kill a running container @@ -550,6 +553,7 @@ Insert file from github -entrypoint="": Overwrite the default entrypoint set by the image. -w="": Working directory inside the container -lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" + -sig-proxy=false: Proxify all received signal to the process (even in non-tty mode) Examples ~~~~~~~~ @@ -623,6 +627,9 @@ using the container, but inside the current working directory. Start a stopped container + -a=false: Attach container's stdout/stderr and forward all signals to the process + -i=false: Attach container's stdin + .. _cli_stop: ``stop`` diff --git a/components/engine/server.go b/components/engine/server.go index 65040ba7fd..0adf8aa6cd 100644 --- a/components/engine/server.go +++ b/components/engine/server.go @@ -55,8 +55,7 @@ func (v *simpleVersionInfo) Version() string { // Such information will be used on call to NewRegistry(). func (srv *Server) versionInfos() []utils.VersionInfo { v := srv.DockerVersion() - ret := make([]utils.VersionInfo, 0, 4) - ret = append(ret, &simpleVersionInfo{"docker", v.Version}) + ret := append(make([]utils.VersionInfo, 0, 4), &simpleVersionInfo{"docker", v.Version}) if len(v.GoVersion) > 0 { ret = append(ret, &simpleVersionInfo{"go", v.GoVersion}) @@ -64,20 +63,32 @@ func (srv *Server) versionInfos() []utils.VersionInfo { if len(v.GitCommit) > 0 { ret = append(ret, &simpleVersionInfo{"git-commit", v.GitCommit}) } - kernelVersion, err := utils.GetKernelVersion() - if err == nil { + if kernelVersion, err := utils.GetKernelVersion(); err == nil { ret = append(ret, &simpleVersionInfo{"kernel", kernelVersion.String()}) } return ret } +// ContainerKill send signal to the container +// If no signal is given (sig 0), then Kill with SIGKILL and wait +// for the container to exit. +// If a signal is given, then just send it to the container and return. func (srv *Server) ContainerKill(name string, sig int) error { if container := srv.runtime.Get(name); container != nil { - if err := container.Kill(sig); err != nil { - return fmt.Errorf("Error killing container %s: %s", name, err) + // If no signal is passed, perform regular Kill (SIGKILL + wait()) + if sig == 0 { + if err := container.Kill(); err != nil { + return fmt.Errorf("Error killing container %s: %s", name, err) + } + srv.LogEvent("kill", container.ShortID(), srv.runtime.repositories.ImageName(container.Image)) + } else { + // Otherwise, just send the requested signal + if err := container.kill(sig); err != nil { + return fmt.Errorf("Error killing container %s: %s", name, err) + } + // FIXME: Add event for signals } - srv.LogEvent("kill", container.ShortID(), srv.runtime.repositories.ImageName(container.Image)) } else { return fmt.Errorf("No such container: %s", name) } diff --git a/components/engine/server_test.go b/components/engine/server_test.go index c13754b5ea..0dae862071 100644 --- a/components/engine/server_test.go +++ b/components/engine/server_test.go @@ -188,33 +188,28 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) { t.Errorf("Expected 1 container, %v found", len(runtime.List())) } - err = srv.ContainerStart(id, hostConfig) - if err != nil { + if err := srv.ContainerStart(id, hostConfig); err != nil { t.Fatal(err) } - err = srv.ContainerRestart(id, 1) - if err != nil { + if err := srv.ContainerRestart(id, 1); err != nil { t.Fatal(err) } - err = srv.ContainerStop(id, 1) - if err != nil { + if err := srv.ContainerStop(id, 1); err != nil { t.Fatal(err) } - err = srv.ContainerStart(id, hostConfig) - if err != nil { + if err := srv.ContainerStart(id, hostConfig); err != nil { t.Fatal(err) } - err = srv.ContainerKill(id) - if err != nil { + if err := srv.ContainerKill(id, 0); err != nil { t.Fatal(err) } // FIXME: this failed once with a race condition ("Unable to remove filesystem for xxx: directory not empty") - if err = srv.ContainerDestroy(id, true); err != nil { + if err := srv.ContainerDestroy(id, true); err != nil { t.Fatal(err) } @@ -225,20 +220,18 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) { } func TestRunWithTooLowMemoryLimit(t *testing.T) { - var err error runtime := mkRuntime(t) - srv := &Server{runtime: runtime} defer nuke(runtime) + // Try to create a container with a memory limit of 1 byte less than the minimum allowed limit. - _, err = srv.ContainerCreate( + if _, err := (*Server).ContainerCreate(&Server{runtime: runtime}, &Config{ Image: GetTestImage(runtime).ID, Memory: 524287, CpuShares: 1000, Cmd: []string{"/bin/cat"}, }, - ) - if err == nil { + ); err == nil { t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!") } @@ -246,10 +239,12 @@ func TestRunWithTooLowMemoryLimit(t *testing.T) { func TestContainerTop(t *testing.T) { t.Skip("Fixme. Skipping test for now. Reported error: 'server_test.go:236: Expected 2 processes, found 1.'") + runtime := mkRuntime(t) - srv := &Server{runtime: runtime} defer nuke(runtime) + srv := &Server{runtime: runtime} + c, hostConfig, _ := mkContainer(runtime, []string{"_", "/bin/sh", "-c", "sleep 2"}, t) c, hostConfig, err := mkContainer(runtime, []string{"_", "/bin/sh", "-c", "sleep 2"}, t) if err != nil { From fbbaaa37c7c188ccdf1b56028120c4c4f37fe987 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Tue, 8 Oct 2013 18:42:53 -0700 Subject: [PATCH 027/112] Fix attach race condition, improve unit tests, make sure the container is started before unblocking Start Upstream-commit: 3e014aa6624bdc3411bb6f5bc2c297e45a47ad68 Component: engine --- components/engine/api_test.go | 4 +-- components/engine/commands.go | 37 +++++++++++------------- components/engine/commands_test.go | 45 +++++++++++++++++++++++------- components/engine/container.go | 39 ++++++++++++++++++++++++-- components/engine/runtime_test.go | 32 ++++++++++----------- components/engine/server_test.go | 4 +-- 6 files changed, 106 insertions(+), 55 deletions(-) diff --git a/components/engine/api_test.go b/components/engine/api_test.go index 35667c74f1..4af9c78058 100644 --- a/components/engine/api_test.go +++ b/components/engine/api_test.go @@ -371,8 +371,8 @@ func TestGetContainersJSON(t *testing.T) { if err := json.Unmarshal(r.Body.Bytes(), &containers); err != nil { t.Fatal(err) } - if len(containers) != 1 { - t.Fatalf("Expected %d container, %d found (started with: %d)", 1, len(containers), beginLen) + if len(containers) != beginLen+1 { + t.Fatalf("Expected %d container, %d found (started with: %d)", beginLen+1, len(containers), beginLen) } if containers[0].ID != container.ID { t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", container.ID, containers[0].ID) diff --git a/components/engine/commands.go b/components/engine/commands.go index befe8a6bcf..aab705cc43 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -1597,12 +1597,10 @@ func (cli *DockerCli) CmdRun(args ...string) error { cli.forwardAllSignals(runResult.ID) } - //start the container - if _, _, err = cli.call("POST", "/containers/"+runResult.ID+"/start", hostConfig); err != nil { - return err - } - - var wait chan struct{} + var ( + wait chan struct{} + errCh chan error + ) if !config.AttachStdout && !config.AttachStderr { // Make this asynchrone in order to let the client write to stdin before having to read the ID @@ -1621,7 +1619,6 @@ func (cli *DockerCli) CmdRun(args ...string) error { } v := url.Values{} - v.Set("logs", "1") v.Set("stream", "1") var out, stderr io.Writer @@ -1641,18 +1638,18 @@ func (cli *DockerCli) CmdRun(args ...string) error { } } - signals := make(chan os.Signal, 1) - signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) - go func() { - for sig := range signals { - fmt.Printf("\nReceived signal: %s; cleaning up\n", sig) - if err := cli.CmdStop("-t", "4", runResult.ID); err != nil { - fmt.Printf("failed to stop container: %v", err) - } - } - }() + errCh = utils.Go(func() error { + return cli.hijack("POST", "/containers/"+runResult.ID+"/attach?"+v.Encode(), config.Tty, cli.in, out, stderr) + }) + } - if err := cli.hijack("POST", "/containers/"+runResult.ID+"/attach?"+v.Encode(), config.Tty, cli.in, out, stderr); err != nil { + //start the container + if _, _, err = cli.call("POST", "/containers/"+runResult.ID+"/start", hostConfig); err != nil { + return err + } + + if errCh != nil { + if err := <-errCh; err != nil { utils.Debugf("Error hijack: %s", err) return err } @@ -1667,8 +1664,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { return err } if autoRemove { - _, _, err = cli.call("DELETE", "/containers/"+runResult.ID, nil) - if err != nil { + if _, _, err = cli.call("DELETE", "/containers/"+runResult.ID, nil); err != nil { return err } } @@ -1753,6 +1749,7 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int, return nil, -1, err } defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, -1, err diff --git a/components/engine/commands_test.go b/components/engine/commands_test.go index c5fa83d3e4..2034269eaf 100644 --- a/components/engine/commands_test.go +++ b/components/engine/commands_test.go @@ -84,7 +84,7 @@ func TestRunHostname(t *testing.T) { } }) - setTimeout(t, "CmdRun timed out", 5*time.Second, func() { + setTimeout(t, "CmdRun timed out", 10*time.Second, func() { <-c }) @@ -115,7 +115,7 @@ func TestRunWorkdir(t *testing.T) { } }) - setTimeout(t, "CmdRun timed out", 5*time.Second, func() { + setTimeout(t, "CmdRun timed out", 10*time.Second, func() { <-c }) @@ -399,6 +399,8 @@ func TestRunDetach(t *testing.T) { } }) + closeWrap(stdin, stdinPipe, stdout, stdoutPipe) + // wait for CmdRun to return setTimeout(t, "Waiting for CmdRun timed out", 15*time.Second, func() { <-ch @@ -422,30 +424,52 @@ func TestAttachDetach(t *testing.T) { cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) defer cleanup(globalRuntime) - go stdout.Read(make([]byte, 1024)) - setTimeout(t, "Starting container timed out", 2*time.Second, func() { + ch := make(chan struct{}) + go func() { + defer close(ch) if err := cli.CmdRun("-i", "-t", "-d", unitTestImageID, "cat"); err != nil { t.Fatal(err) } - }) + }() - container := globalRuntime.List()[0] + var container *Container + + setTimeout(t, "Reading container's id timed out", 10*time.Second, func() { + buf := make([]byte, 1024) + n, err := stdout.Read(buf) + if err != nil { + t.Fatal(err) + } + + container = globalRuntime.List()[0] + + if strings.Trim(string(buf[:n]), " \r\n") != container.ShortID() { + t.Fatalf("Wrong ID received. Expect %s, received %s", container.ShortID(), buf[:n]) + } + }) + setTimeout(t, "Starting container timed out", 10*time.Second, func() { + <-ch + }) stdin, stdinPipe = io.Pipe() stdout, stdoutPipe = io.Pipe() cli = NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) - ch := make(chan struct{}) + ch = make(chan struct{}) go func() { defer close(ch) if err := cli.CmdAttach(container.ShortID()); err != nil { - t.Fatal(err) + if err != io.ErrClosedPipe { + t.Fatal(err) + } } }() setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() { if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil { - t.Fatal(err) + if err != io.ErrClosedPipe { + t.Fatal(err) + } } }) @@ -455,6 +479,7 @@ func TestAttachDetach(t *testing.T) { t.Fatal(err) } }) + closeWrap(stdin, stdinPipe, stdout, stdoutPipe) // wait for CmdRun to return setTimeout(t, "Waiting for CmdAttach timed out", 15*time.Second, func() { @@ -568,7 +593,7 @@ func TestRunAutoRemove(t *testing.T) { } }) - setTimeout(t, "CmdRun timed out", 5*time.Second, func() { + setTimeout(t, "CmdRun timed out", 10*time.Second, func() { <-c }) diff --git a/components/engine/container.go b/components/engine/container.go index f17cabbce4..c2188be625 100644 --- a/components/engine/container.go +++ b/components/engine/container.go @@ -99,6 +99,8 @@ type BindMap struct { } var ( + ErrContainerStart = errors.New("The container failed to start. Unkown error") + ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.") ErrInvalidWorikingDirectory = errors.New("The working directory is invalid. It needs to be an absolute path.") ErrConflictTtySigProxy = errors.New("TTY mode (-t) already imply signal proxying (-sig-proxy)") ErrConflictAttachDetach = errors.New("Conflicting options: -a and -d") @@ -838,12 +840,43 @@ func (container *Container) Start(hostConfig *HostConfig) (err error) { container.ToDisk() container.SaveHostConfig(hostConfig) go container.monitor(hostConfig) - return nil + + defer utils.Debugf("Container running: %v", container.State.Running) + // We wait for the container to be fully running. + // Timeout after 5 seconds. In case of broken pipe, just retry. + // Note: The container can run and finish correctly before + // the end of this loop + for now := time.Now(); time.Since(now) < 5*time.Second; { + // If the container dies while waiting for it, just reutrn + if !container.State.Running { + return nil + } + output, err := exec.Command("lxc-info", "-n", container.ID).CombinedOutput() + if err != nil { + utils.Debugf("Error with lxc-info: %s (%s)", err, output) + + output, err = exec.Command("lxc-info", "-n", container.ID).CombinedOutput() + if err != nil { + utils.Debugf("Second Error with lxc-info: %s (%s)", err, output) + return err + } + + } + if strings.Contains(string(output), "RUNNING") { + return nil + } + utils.Debugf("Waiting for the container to start (running: %v): %s\n", container.State.Running, output) + time.Sleep(50 * time.Millisecond) + } + + if container.State.Running { + return ErrContainerStartTimeout + } + return ErrContainerStart } func (container *Container) Run() error { - hostConfig := &HostConfig{} - if err := container.Start(hostConfig); err != nil { + if err := container.Start(&HostConfig{}); err != nil { return err } container.Wait() diff --git a/components/engine/runtime_test.go b/components/engine/runtime_test.go index 75081fff1e..74feb02976 100644 --- a/components/engine/runtime_test.go +++ b/components/engine/runtime_test.go @@ -212,22 +212,16 @@ func TestRuntimeCreate(t *testing.T) { } // Make sure crete with bad parameters returns an error - _, err = runtime.Create( - &Config{ - Image: GetTestImage(runtime).ID, - }, - ) - if err == nil { + if _, err = runtime.Create(&Config{Image: GetTestImage(runtime).ID}); err == nil { t.Fatal("Builder.Create should throw an error when Cmd is missing") } - _, err = runtime.Create( + if _, err := runtime.Create( &Config{ Image: GetTestImage(runtime).ID, Cmd: []string{}, }, - ) - if err == nil { + ); err == nil { t.Fatal("Builder.Create should throw an error when Cmd is empty") } @@ -258,11 +252,11 @@ func TestRuntimeCreate(t *testing.T) { func TestDestroy(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) + container, err := runtime.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, - }, - ) + }) if err != nil { t.Fatal(err) } @@ -327,11 +321,14 @@ func TestGet(t *testing.T) { } func startEchoServerContainer(t *testing.T, proto string) (*Runtime, *Container, string) { - var err error - runtime := mkRuntime(t) - port := 5554 - var container *Container - var strPort string + var ( + err error + container *Container + strPort string + runtime = mkRuntime(t) + port = 5554 + ) + for { port += 1 strPort = strconv.Itoa(port) @@ -359,8 +356,7 @@ func startEchoServerContainer(t *testing.T, proto string) (*Runtime, *Container, t.Logf("Port %v already in use", strPort) } - hostConfig := &HostConfig{} - if err := container.Start(hostConfig); err != nil { + if err := container.Start(&HostConfig{}); err != nil { nuke(runtime) t.Fatal(err) } diff --git a/components/engine/server_test.go b/components/engine/server_test.go index 0dae862071..c7bfa415db 100644 --- a/components/engine/server_test.go +++ b/components/engine/server_test.go @@ -192,11 +192,11 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) { t.Fatal(err) } - if err := srv.ContainerRestart(id, 1); err != nil { + if err := srv.ContainerRestart(id, 15); err != nil { t.Fatal(err) } - if err := srv.ContainerStop(id, 1); err != nil { + if err := srv.ContainerStop(id, 15); err != nil { t.Fatal(err) } From 295b7a4df782d04d2e4bd2ad789c3b85121d0d50 Mon Sep 17 00:00:00 2001 From: Andy Rothfusz Date: Wed, 9 Oct 2013 12:31:40 -0700 Subject: [PATCH 028/112] Update documentation Upstream-commit: 8cf0f2dbe54e5ff5175a830af30ba428f8b1f526 Component: engine --- .../docs/sources/use/host_integration.rst | 139 ++++++++++++------ 1 file changed, 98 insertions(+), 41 deletions(-) diff --git a/components/engine/docs/sources/use/host_integration.rst b/components/engine/docs/sources/use/host_integration.rst index cc2f56a5c7..47d9ea7528 100644 --- a/components/engine/docs/sources/use/host_integration.rst +++ b/components/engine/docs/sources/use/host_integration.rst @@ -2,67 +2,124 @@ :description: How to generate scripts for upstart, systemd, etc. :keywords: systemd, upstart, supervisor, docker, documentation, host integration + + +Host Integration +================ + +You can use your Docker containers with process managers like ``upstart``, +``systemd`` and ``supervisor``. + Introduction -============ +------------ -When you have finished setting up your image and are happy with your running -container, you may want to use a process manager like `upstart` or `systemd`. +When you have finished setting up your image and are happy with your +running container, you may want to use a process manager to manage +it. To help with this, we provide a simple image: ``creack/manger:min`` -In order to do so, we provide a simple image: creack/manger:min. - -This image takes the container ID as parameter. We also can specify the kind of -process manager and meta datas like Author and Description. - -If no process manager is specified, then `upstart` is assumed. - -Note: The result will be an output to stdout. +This image takes the container ID as parameter. We also can specify +the kind of process manager and metadata like *Author* and +*Description*. The output will will be text suitable for a +configuration file, echoed to stdout. It is up to you to create the +.conf file (for `upstart +`_) or +.service file (for `systemd +`_) and +put it in the right place for your system. Usage -===== -Usage: docker run creack/manager:min [OPTIONS] +----- + +.. code-block:: bash + + docker run creack/manager:min [OPTIONS] + +.. program:: docker run creack/manager:min + +.. cmdoption:: -a="" + + Author of the image + +.. cmdoption:: -d="" + + Description of the image + +.. cmdoption:: -t="upstart" + + Type of manager requested: ``upstart`` or ``systemd`` + +Example Output +.............. + +.. code-block:: bash + + docker run creack/manager:min -t="systemd" b28605f2f9a4 + [Unit] + Description= + Author= + After=docker.service + + [Service] + Restart=always + ExecStart=/usr/bin/docker start -a b28605f2f9a4 + ExecStop=/usr/bin/docker stop -t 2 b28605f2f9a4 + + [Install] + WantedBy=local.target + - -a="": Author of the image - -d="": Description of the image - -t="upstart": Type of manager requested Development -=========== +----------- -The image creack/manager:min is a `busybox` base with the binary as entrypoint. -It is meant to be light and fast to download. +The image ``creack/manager:min`` is a ``busybox`` base with the +compiled binary of ``manager.go`` as the :ref:`Entrypoint +`. It is meant to be light and fast to download. -Now, if you want/need to change or add things, you can download the full -creack/manager repository that contains creack/manager:min and -creack/manager:dev. +If you would like to change or add things, you can download the full +``creack/manager`` repository that contains ``creack/manager:min`` and +``creack/manager:dev``. -The Dockerfiles and the sources are available in `/contrib/host_integration`. +The Dockerfiles and the sources are available in +`/contrib/host_integration +`_. Upstart -======= +------- -Upstart is the default process manager. The generated script will start the -container after docker daemon. If the container dies, it will respawn. -Start/Restart/Stop/Reload are supported. Reload will send a SIGHUP to the container. +Upstart is the default process manager. The generated script will +start the container after the ``docker`` daemon. If the container +dies, it will respawn. Start/Restart/Stop/Reload are +supported. Reload will send a SIGHUP to the container. -Example: -`CID=$(docker run -d creack/firefo-vnc)` -`docker run creack/manager:min -a 'Guillaume J. Charmes ' -d 'Awesome Firefox in VLC' $CID > /etc/init/firefoxvnc.conf` +Example (``upstart`` on Debian) +............................... -You can now do `start firefoxvnc` or `stop firefoxvnc` and if the container +.. code-block:: bash + + CID=$(docker run -d creack/firefo-vnc) + docker run creack/manager:min -a 'Guillaume J. Charmes ' -d 'Awesome Firefox in VLC' $CID > /etc/init/firefoxvnc.conf + +You can now ``start firefoxvnc`` or ``stop firefoxvnc`` and if the container dies for some reason, upstart will restart it. Systemd -======= +------- -In order to generate a systemd script, we need to -t option. The generated -script will start the container after docker daemon. If the container dies, it -will respawn. -Start/Restart/Reload/Stop are supported. +In order to generate a systemd script, we need to use the ``-t`` +option. The generated script will start the container after docker +daemon. If the container dies, it will respawn. +``Start/Restart/Reload/Stop`` are supported. -Example (fedora): -`CID=$(docker run -d creack/firefo-vnc)` -`docker run creack/manager:min -t systemd -a 'Guillaume J. Charmes ' -d 'Awesome Firefox in VLC' $CID > /usr/lib/systemd/system/firefoxvnc.service` +Example (``systemd`` on Fedora) +............................... -You can now do `systemctl start firefoxvnc` or `systemctl stop firefoxvnc` -and if the container dies for some reason, systemd will restart it. +.. code-block:: bash + + CID=$(docker run -d creack/firefo-vnc) + docker run creack/manager:min -t systemd -a 'Guillaume J. Charmes ' -d 'Awesome Firefox in VLC' $CID > /usr/lib/systemd/system/firefoxvnc.service + +You can now run ``systemctl start firefoxvnc`` or ``systemctl stop +firefoxvnc`` and if the container dies for some reason, ``systemd`` +will restart it. From d6470d0bf35f64c06049380e2a977013cd97a6e3 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 9 Oct 2013 14:38:52 -0700 Subject: [PATCH 029/112] Fix issue with autoremove Upstream-commit: e7269b98416e8228930dde9461bfcad38eeb2c56 Component: engine --- components/engine/commands.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/components/engine/commands.go b/components/engine/commands.go index aab705cc43..19712f2223 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -1659,12 +1659,19 @@ func (cli *DockerCli) CmdRun(args ...string) error { // Detached mode <-wait } else { - status, err := getExitCode(cli, runResult.ID) + running, status, err := getExitCode(cli, runResult.ID) if err != nil { return err } if autoRemove { - if _, _, err = cli.call("DELETE", "/containers/"+runResult.ID, nil); err != nil { + if running { + return fmt.Errorf("Impossible to auto-remove a detached container") + } + // Wait for the process to + if _, _, err := cli.call("POST", "/containers/"+runResult.ID+"/wait", nil); err != nil { + return err + } + if _, _, err := cli.call("DELETE", "/containers/"+runResult.ID, nil); err != nil { return err } } @@ -1984,20 +1991,22 @@ func waitForExit(cli *DockerCli, containerId string) (int, error) { return out.StatusCode, nil } -func getExitCode(cli *DockerCli, containerId string) (int, error) { +// getExitCode perform an inspect on the container. It returns +// the running state and the exit code. +func getExitCode(cli *DockerCli, containerId string) (bool, int, error) { body, _, err := cli.call("GET", "/containers/"+containerId+"/json", nil) if err != nil { // If we can't connect, then the daemon probably died. if err != ErrConnectionRefused { - return -1, err + return false, -1, err } - return -1, nil + return false, -1, nil } c := &Container{} if err := json.Unmarshal(body, c); err != nil { - return -1, err + return false, -1, err } - return c.State.ExitCode, nil + return c.State.Running, c.State.ExitCode, nil } func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string) *DockerCli { From cc12d3d32e89a4f5bc1e923ad3d8072e94172204 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 10 Oct 2013 11:20:50 -0700 Subject: [PATCH 030/112] Add a chan to hijack() to block until the hijack is completed Upstream-commit: 9bceae244044435647e843ffdd040322507d182b Component: engine --- components/engine/commands.go | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/components/engine/commands.go b/components/engine/commands.go index 19712f2223..48bf4fe83d 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -605,7 +605,7 @@ func (cli *DockerCli) CmdStart(args ...string) error { v.Set("stderr", "1") cErr = utils.Go(func() error { - return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out, cli.err) + return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out, cli.err, nil) }) } @@ -1298,7 +1298,7 @@ func (cli *DockerCli) CmdLogs(args ...string) error { return nil } - if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?logs=1&stdout=1&stderr=1", false, nil, cli.out, cli.err); err != nil { + if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?logs=1&stdout=1&stderr=1", false, nil, cli.out, cli.err, nil); err != nil { return err } return nil @@ -1349,7 +1349,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error { cli.forwardAllSignals(cmd.Arg(0)) } - if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out, cli.err); err != nil { + if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out, cli.err, nil); err != nil { return err } return nil @@ -1611,6 +1611,8 @@ func (cli *DockerCli) CmdRun(args ...string) error { }() } + hijacked := make(chan bool) + if config.AttachStdin || config.AttachStdout || config.AttachStderr { if config.Tty { if err := cli.monitorTtySize(runResult.ID); err != nil { @@ -1639,8 +1641,20 @@ func (cli *DockerCli) CmdRun(args ...string) error { } errCh = utils.Go(func() error { - return cli.hijack("POST", "/containers/"+runResult.ID+"/attach?"+v.Encode(), config.Tty, cli.in, out, stderr) + return cli.hijack("POST", "/containers/"+runResult.ID+"/attach?"+v.Encode(), config.Tty, cli.in, out, stderr, hijacked) }) + } else { + close(hijacked) + } + + // Acknowledge the hijack before starting + select { + case <-hijacked: + case err := <-errCh: + if err != nil { + utils.Debugf("Error hijack: %s", err) + return err + } } //start the container @@ -1829,7 +1843,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, h return nil } -func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer) error { +func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer, started chan bool) error { req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), nil) if err != nil { @@ -1855,6 +1869,10 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea rwc, br := clientconn.Hijack() defer rwc.Close() + if started != nil { + started <- true + } + var receiveStdout chan error if stdout != nil { From 8f6b16d850472961b0e8ff454cc40b1b817bf44d Mon Sep 17 00:00:00 2001 From: Andy Rothfusz Date: Fri, 18 Oct 2013 18:00:44 -0700 Subject: [PATCH 031/112] Fix #2302 Upstream-commit: bba5fd455567f831270ff60bd6991481d5340958 Component: engine --- .../engine/docs/sources/api/docker_remote_api_v1.6.rst | 9 ++++++--- components/engine/docs/sources/use/basics.rst | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/components/engine/docs/sources/api/docker_remote_api_v1.6.rst b/components/engine/docs/sources/api/docker_remote_api_v1.6.rst index 1734f81c07..4a743a75ac 100644 --- a/components/engine/docs/sources/api/docker_remote_api_v1.6.rst +++ b/components/engine/docs/sources/api/docker_remote_api_v1.6.rst @@ -13,9 +13,12 @@ Docker Remote API v1.6 1. Brief introduction ===================== -- The Remote API is replacing rcli -- Default port in the docker daemon is 4243 -- The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr +- The Remote API has replaced rcli +- The daemon listens on ``unix:///var/run/docker.sock``, but you can + :ref:`bind_docker`. +- The API tends to be REST, but for some complex commands, like + ``attach`` or ``pull``, the HTTP connection is hijacked to transport + ``stdout, stdin`` and ``stderr`` 2. Endpoints ============ diff --git a/components/engine/docs/sources/use/basics.rst b/components/engine/docs/sources/use/basics.rst index 8b4676f6ee..d66d5a8bd9 100644 --- a/components/engine/docs/sources/use/basics.rst +++ b/components/engine/docs/sources/use/basics.rst @@ -67,6 +67,8 @@ you don't need to add ``sudo`` to all the client commands. # Restart the docker daemon sudo service docker restart +.. _bind_docker: + Bind Docker to another host/port or a Unix socket ------------------------------------------------- From 5cdd5ff8f0406d0d69ffaf89db69785955723f61 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Sat, 19 Oct 2013 23:40:28 -0600 Subject: [PATCH 032/112] Update hack/install.sh with some more Ubuntu-specific installation stuff while we're still on AUFS (installing linux-image-extra-$(uname -r) when we can't find AUFS to try to find AUFS) Upstream-commit: 3b0cbc59ea4da94cd9013fe60e83919d1a5859aa Component: engine --- components/engine/hack/install.sh | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/components/engine/hack/install.sh b/components/engine/hack/install.sh index e184a87361..179a643946 100755 --- a/components/engine/hack/install.sh +++ b/components/engine/hack/install.sh @@ -75,16 +75,35 @@ case "$lsb_dist" in Ubuntu|Debian) export DEBIAN_FRONTEND=noninteractive - # TODO remove this comment/section once device-mapper lands - echo 'Warning: Docker currently requires AUFS support in the kernel.' - echo 'Please ensure that your kernel includes such support.' - ( set -x; sleep 10 ) + did_apt_get_update= + apt_get_update() { + if [ -z "$did_apt_get_update" ]; then + ( set -x; $sh_c 'sleep 3; apt-get update' ) + did_apt_get_update=1 + fi + } + + # TODO remove this section once device-mapper lands + if ! grep -q aufs /proc/filesystems && ! modprobe aufs; then + kern_extras="linux-image-extra-$(uname -r)" + + apt_get_update + ( set -x; $sh_c 'sleep 3; apt-get install -y -q '"$kern_extras" ) || true + + if ! grep -q aufs /proc/filesystems && ! modprobe aufs; then + echo >&2 'Warning: tried to install '"$kern_extras"' (for AUFS)' + echo >&2 ' but we still have no AUFS. Docker may not work. Proceeding anyways!' + ( set -x; sleep 10 ) + fi + fi if [ ! -e /usr/lib/apt/methods/https ]; then - ( set -x; $sh_c 'sleep 3; apt-get update; apt-get install -y -q apt-transport-https' ) + apt_get_update + ( set -x; $sh_c 'sleep 3; apt-get install -y -q apt-transport-https' ) fi if [ -z "$curl" ]; then - ( set -x; $sh_c 'sleep 3; apt-get update; apt-get install -y -q curl' ) + apt_get_update + ( set -x; $sh_c 'sleep 3; apt-get install -y -q curl' ) curl='curl -sL' fi ( From b3abc383b4b1f71bd586165c4cd058cb3f809e2b Mon Sep 17 00:00:00 2001 From: Gurjeet Singh Date: Sun, 20 Oct 2013 02:15:36 -0400 Subject: [PATCH 033/112] Place 'top' subcommand's help in proper order. Upstream-commit: 7e09c6332de11538e170b4d25ccd5bfa068ffd1e Component: engine --- components/engine/commands.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/engine/commands.go b/components/engine/commands.go index 48bf4fe83d..eb70dc2db5 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -99,7 +99,6 @@ func (cli *DockerCli) CmdHelp(args ...string) error { {"login", "Register or Login to the docker registry server"}, {"logs", "Fetch the logs of a container"}, {"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"}, - {"top", "Lookup the running processes of a container"}, {"ps", "List containers"}, {"pull", "Pull an image or a repository from the docker registry server"}, {"push", "Push an image or a repository to the docker registry server"}, @@ -111,6 +110,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error { {"start", "Start a stopped container"}, {"stop", "Stop a running container"}, {"tag", "Tag an image into a repository"}, + {"top", "Lookup the running processes of a container"}, {"version", "Show the docker version information"}, {"wait", "Block until a container stops, then print its exit code"}, } { From 4785dd092143683212fa8fa3a0d0d2f0e4ed9993 Mon Sep 17 00:00:00 2001 From: Ole Reifschneider Date: Mon, 21 Oct 2013 11:30:18 +0200 Subject: [PATCH 034/112] Fix github link in docs Upstream-commit: f903feee03d4df4361c79a44b6f5d78d4718b350 Component: engine --- components/engine/docs/theme/docker/layout.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/engine/docs/theme/docker/layout.html b/components/engine/docs/theme/docker/layout.html index e415e97235..193df7447f 100755 --- a/components/engine/docs/theme/docker/layout.html +++ b/components/engine/docs/theme/docker/layout.html @@ -13,6 +13,12 @@ {%- set url_root = pathto('', 1) %} {%- if url_root == '#' %}{% set url_root = '' %}{% endif %} + {%- if current_version == 'latest' %} + {% set github_tag = 'master' %} + {% else %} + {% set github_tag = current_version %} + {% endif %} +