Browse Source

Merge branch 'master' into add-libcontainer

Conflicts:
	runtime.go

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
Michael Crosby 11 years ago
parent
commit
27a43692c2

+ 1 - 0
.gitignore

@@ -22,3 +22,4 @@ bundles/
 .git/
 vendor/pkg/
 pyenv
+Vagrantfile

+ 0 - 1
MAINTAINERS

@@ -6,4 +6,3 @@ Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
 api.go: Victor Vieux <victor@dotcloud.com> (@vieux)
 Dockerfile: Tianon Gravi <admwiggin@gmail.com> (@tianon)
 Makefile: Tianon Gravi <admwiggin@gmail.com> (@tianon)
-Vagrantfile: Cristian Staretu <cristian.staretu@gmail.com> (@unclejack)

+ 0 - 206
Vagrantfile

@@ -1,206 +0,0 @@
-# -*- mode: ruby -*-
-# vi: set ft=ruby :
-
-BOX_NAME = ENV['BOX_NAME'] || "ubuntu"
-BOX_URI = ENV['BOX_URI'] || "http://files.vagrantup.com/precise64.box"
-VF_BOX_URI = ENV['BOX_URI'] || "http://files.vagrantup.com/precise64_vmware_fusion.box"
-AWS_BOX_URI = ENV['BOX_URI'] || "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
-AWS_REGION = ENV['AWS_REGION'] || "us-east-1"
-AWS_AMI = ENV['AWS_AMI'] || "ami-69f5a900"
-AWS_INSTANCE_TYPE = ENV['AWS_INSTANCE_TYPE'] || 't1.micro'
-SSH_PRIVKEY_PATH = ENV['SSH_PRIVKEY_PATH']
-PRIVATE_NETWORK = ENV['PRIVATE_NETWORK']
-
-# Boolean that forwards the Docker dynamic ports 49000-49900
-# See http://docs.docker.io/en/latest/use/port_redirection/ for more
-# $ FORWARD_DOCKER_PORTS=1 vagrant [up|reload]
-FORWARD_DOCKER_PORTS = ENV['FORWARD_DOCKER_PORTS']
-VAGRANT_RAM = ENV['VAGRANT_RAM'] || 512
-VAGRANT_CORES = ENV['VAGRANT_CORES'] || 1
-
-# You may also provide a comma-separated list of ports
-# for Vagrant to forward. For example:
-# $ FORWARD_PORTS=8080,27017 vagrant [up|reload]
-FORWARD_PORTS = ENV['FORWARD_PORTS']
-
-# A script to upgrade from the 12.04 kernel to the raring backport kernel (3.8)
-# and install docker.
-$script = <<SCRIPT
-# The username to add to the docker group will be passed as the first argument
-# to the script.  If nothing is passed, default to "vagrant".
-user="$1"
-if [ -z "$user" ]; then
-    user=vagrant
-fi
-
-# Enable memory cgroup and swap accounting
-sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"/g' /etc/default/grub
-update-grub
-
-# Adding an apt gpg key is idempotent.
-apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
-
-# Creating the docker.list file is idempotent, but it may overwrite desired
-# settings if it already exists.  This could be solved with md5sum but it
-# doesn't seem worth it.
-echo 'deb http://get.docker.io/ubuntu docker main' > \
-    /etc/apt/sources.list.d/docker.list
-
-# Update remote package metadata.  'apt-get update' is idempotent.
-apt-get update -q
-
-# Install docker.  'apt-get install' is idempotent.
-apt-get install -q -y lxc-docker
-
-usermod -a -G docker "$user"
-
-tmp=`mktemp -q` && {
-    # Only install the backport kernel, don't bother upgrading if the backport is
-    # already installed.  We want parse the output of apt so we need to save it
-    # with 'tee'.  NOTE: The installation of the kernel will trigger dkms to
-    # install vboxguest if needed.
-    apt-get install -q -y --no-upgrade linux-image-generic-lts-raring | \
-        tee "$tmp"
-
-    # Parse the number of installed packages from the output
-    NUM_INST=`awk '$2 == "upgraded," && $4 == "newly" { print $3 }' "$tmp"`
-    rm "$tmp"
-}
-
-# If the number of installed packages is greater than 0, we want to reboot (the
-# backport kernel was installed but is not running).
-if [ "$NUM_INST" -gt 0 ];
-then
-    echo "Rebooting down to activate new kernel."
-    echo "/vagrant will not be mounted.  Use 'vagrant halt' followed by"
-    echo "'vagrant up' to ensure /vagrant is mounted."
-    shutdown -r now
-fi
-SCRIPT
-
-# We need to install the virtualbox guest additions *before* we do the normal
-# docker installation.  As such this script is prepended to the common docker
-# install script above.  This allows the install of the backport kernel to
-# trigger dkms to build the virtualbox guest module install.
-$vbox_script = <<VBOX_SCRIPT + $script
-# Install the VirtualBox guest additions if they aren't already installed.
-if [ ! -d /opt/VBoxGuestAdditions-4.3.6/ ]; then
-    # Update remote package metadata.  'apt-get update' is idempotent.
-    apt-get update -q
-
-    # Kernel Headers and dkms are required to build the vbox guest kernel
-    # modules.
-    apt-get install -q -y linux-headers-generic-lts-raring dkms
-
-    echo 'Downloading VBox Guest Additions...'
-    wget -cq http://dlc.sun.com.edgesuite.net/virtualbox/4.3.6/VBoxGuestAdditions_4.3.6.iso
-    echo "95648fcdb5d028e64145a2fe2f2f28c946d219da366389295a61fed296ca79f0  VBoxGuestAdditions_4.3.6.iso" | sha256sum --check || exit 1
-
-    mount -o loop,ro /home/vagrant/VBoxGuestAdditions_4.3.6.iso /mnt
-    /mnt/VBoxLinuxAdditions.run --nox11
-    umount /mnt
-fi
-VBOX_SCRIPT
-
-Vagrant::Config.run do |config|
-  # Setup virtual machine box. This VM configuration code is always executed.
-  config.vm.box = BOX_NAME
-  config.vm.box_url = BOX_URI
-
-  # Use the specified private key path if it is specified and not empty.
-  if SSH_PRIVKEY_PATH
-      config.ssh.private_key_path = SSH_PRIVKEY_PATH
-  end
-
-  config.ssh.forward_agent = true
-end
-
-# Providers were added on Vagrant >= 1.1.0
-#
-# NOTE: The vagrant "vm.provision" appends its arguments to a list and executes
-# them in order.  If you invoke "vm.provision :shell, :inline => $script"
-# twice then vagrant will run the script two times.  Unfortunately when you use
-# providers and the override argument to set up provisioners (like the vbox
-# guest extensions) they 1) don't replace the other provisioners (they append
-# to the end of the list) and 2) you can't control the order the provisioners
-# are executed (you can only append to the list).  If you want the virtualbox
-# only script to run before the other script, you have to jump through a lot of
-# hoops.
-#
-# Here is my only repeatable solution: make one script that is common ($script)
-# and another script that is the virtual box guest *prepended* to the common
-# script.  Only ever use "vm.provision" *one time* per provider.  That means
-# every single provider has an override, and every single one configures
-# "vm.provision".  Much saddness, but such is life.
-Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
-  config.vm.provider :aws do |aws, override|
-    username = "ubuntu"
-    override.vm.box_url = AWS_BOX_URI
-    override.vm.provision :shell, :inline => $script, :args => username
-    aws.access_key_id = ENV["AWS_ACCESS_KEY"]
-    aws.secret_access_key = ENV["AWS_SECRET_KEY"]
-    aws.keypair_name = ENV["AWS_KEYPAIR_NAME"]
-    override.ssh.username = username
-    aws.region = AWS_REGION
-    aws.ami    = AWS_AMI
-    aws.instance_type = AWS_INSTANCE_TYPE
-  end
-
-  config.vm.provider :rackspace do |rs, override|
-    override.vm.provision :shell, :inline => $script
-    rs.username = ENV["RS_USERNAME"]
-    rs.api_key  = ENV["RS_API_KEY"]
-    rs.public_key_path = ENV["RS_PUBLIC_KEY"]
-    rs.flavor   = /512MB/
-    rs.image    = /Ubuntu/
-  end
-
-  config.vm.provider :vmware_fusion do |f, override|
-    override.vm.box_url = VF_BOX_URI
-    override.vm.synced_folder ".", "/vagrant", disabled: true
-    override.vm.provision :shell, :inline => $script
-    f.vmx["displayName"] = "docker"
-  end
-
-  config.vm.provider :virtualbox do |vb, override|
-    override.vm.provision :shell, :inline => $vbox_script
-    vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
-    vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
-    vb.customize ["modifyvm", :id, "--memory", VAGRANT_RAM]
-    vb.customize ["modifyvm", :id, "--cpus", VAGRANT_CORES]
-  end
-end
-
-# If this is a version 1 config, virtualbox is the only option.  A version 2
-# config would have already been set in the above provider section.
-Vagrant::VERSION < "1.1.0" and Vagrant::Config.run do |config|
-  config.vm.provision :shell, :inline => $vbox_script
-end
-
-# Setup port forwarding per loaded environment variables
-forward_ports = FORWARD_DOCKER_PORTS.nil? ? [] : [*49153..49900]
-forward_ports += FORWARD_PORTS.split(',').map{|i| i.to_i } if FORWARD_PORTS
-if forward_ports.any?
-  Vagrant::VERSION < "1.1.0" and Vagrant::Config.run do |config|
-    forward_ports.each do |port|
-      config.vm.forward_port port, port
-    end
-  end
-
-  Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
-    forward_ports.each do |port|
-      config.vm.network :forwarded_port, :host => port, :guest => port, auto_correct: true
-    end
-  end
-end
-
-if !PRIVATE_NETWORK.nil?
-  Vagrant::VERSION < "1.1.0" and Vagrant::Config.run do |config|
-    config.vm.network :hostonly, PRIVATE_NETWORK
-  end
-
-  Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
-    config.vm.network "private_network", ip: PRIVATE_NETWORK
-  end
-end
-

+ 44 - 0
api/common.go

@@ -0,0 +1,44 @@
+package api
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/engine"
+	"github.com/dotcloud/docker/utils"
+	"mime"
+	"strings"
+)
+
+const (
+	APIVERSION        = 1.9
+	DEFAULTHTTPHOST   = "127.0.0.1"
+	DEFAULTUNIXSOCKET = "/var/run/docker.sock"
+)
+
+func ValidateHost(val string) (string, error) {
+	host, err := utils.ParseHost(DEFAULTHTTPHOST, DEFAULTUNIXSOCKET, val)
+	if err != nil {
+		return val, err
+	}
+	return host, nil
+}
+
+//TODO remove, used on < 1.5 in getContainersJSON
+func displayablePorts(ports *engine.Table) string {
+	result := []string{}
+	for _, port := range ports.Data {
+		if port.Get("IP") == "" {
+			result = append(result, fmt.Sprintf("%d/%s", port.GetInt("PublicPort"), port.Get("Type")))
+		} else {
+			result = append(result, fmt.Sprintf("%s:%d->%d/%s", port.Get("IP"), port.GetInt("PublicPort"), port.GetInt("PrivatePort"), port.Get("Type")))
+		}
+	}
+	return strings.Join(result, ", ")
+}
+
+func MatchesContentType(contentType, expectedType string) bool {
+	mimetype, _, err := mime.ParseMediaType(contentType)
+	if err != nil {
+		utils.Errorf("Error parsing media type: %s error: %s", contentType, err.Error())
+	}
+	return err == nil && mimetype == expectedType
+}

+ 0 - 41
api/api.go → api/server.go

@@ -17,7 +17,6 @@ import (
 	"io"
 	"io/ioutil"
 	"log"
-	"mime"
 	"net"
 	"net/http"
 	"net/http/pprof"
@@ -29,31 +28,12 @@ import (
 	"time"
 )
 
-// FIXME: move code common to client and server to common.go
-const (
-	APIVERSION        = 1.9
-	DEFAULTHTTPHOST   = "127.0.0.1"
-	DEFAULTUNIXSOCKET = "/var/run/docker.sock"
-)
-
 var (
 	activationLock chan struct{}
 )
 
-func ValidateHost(val string) (string, error) {
-	host, err := utils.ParseHost(DEFAULTHTTPHOST, DEFAULTUNIXSOCKET, val)
-	if err != nil {
-		return val, err
-	}
-	return host, nil
-}
-
 type HttpApiFunc func(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error
 
-func init() {
-	engine.Register("serveapi", ServeApi)
-}
-
 func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
 	conn, _, err := w.(http.Hijacker).Hijack()
 	if err != nil {
@@ -133,27 +113,6 @@ func getBoolParam(value string) (bool, error) {
 	return ret, nil
 }
 
-//TODO remove, used on < 1.5 in getContainersJSON
-func displayablePorts(ports *engine.Table) string {
-	result := []string{}
-	for _, port := range ports.Data {
-		if port.Get("IP") == "" {
-			result = append(result, fmt.Sprintf("%d/%s", port.GetInt("PublicPort"), port.Get("Type")))
-		} else {
-			result = append(result, fmt.Sprintf("%s:%d->%d/%s", port.Get("IP"), port.GetInt("PublicPort"), port.GetInt("PrivatePort"), port.Get("Type")))
-		}
-	}
-	return strings.Join(result, ", ")
-}
-
-func MatchesContentType(contentType, expectedType string) bool {
-	mimetype, _, err := mime.ParseMediaType(contentType)
-	if err != nil {
-		utils.Errorf("Error parsing media type: %s error: %s", contentType, err.Error())
-	}
-	return err == nil && mimetype == expectedType
-}
-
 func postAuth(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	var (
 		authConfig, err = ioutil.ReadAll(r.Body)

+ 1 - 1
buildfile.go

@@ -110,7 +110,7 @@ func (b *buildFile) CmdFrom(name string) error {
 		b.config = image.Config
 	}
 	if b.config.Env == nil || len(b.config.Env) == 0 {
-		b.config.Env = append(b.config.Env, "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
+		b.config.Env = append(b.config.Env, "HOME=/", "PATH="+defaultPathEnv)
 	}
 	// Process ONBUILD triggers if they exist
 	if nTriggers := len(b.config.OnBuild); nTriggers != 0 {

+ 40 - 0
builtins/builtins.go

@@ -0,0 +1,40 @@
+package builtins
+
+import (
+	"github.com/dotcloud/docker/engine"
+
+	"github.com/dotcloud/docker"
+	"github.com/dotcloud/docker/api"
+	"github.com/dotcloud/docker/networkdriver/lxc"
+)
+
+func Register(eng *engine.Engine) {
+	daemon(eng)
+	remote(eng)
+}
+
+// remote: a RESTful api for cross-docker communication
+func remote(eng *engine.Engine) {
+	eng.Register("serveapi", api.ServeApi)
+}
+
+// daemon: a default execution and storage backend for Docker on Linux,
+// with the following underlying components:
+//
+// * Pluggable storage drivers including aufs, vfs, lvm and btrfs.
+// * Pluggable execution drivers including lxc and chroot.
+//
+// In practice `daemon` still includes most core Docker components, including:
+//
+// * The reference registry client implementation
+// * Image management
+// * The build facility
+// * Logging
+//
+// These components should be broken off into plugins of their own.
+//
+func daemon(eng *engine.Engine) {
+	eng.Register("initserver", docker.InitServer)
+	eng.Register("init_networkdriver", lxc.InitDriver)
+	eng.Register("version", docker.GetVersion)
+}

+ 2 - 0
config.go

@@ -25,6 +25,7 @@ type DaemonConfig struct {
 	BridgeIP                    string
 	InterContainerCommunication bool
 	GraphDriver                 string
+	ExecDriver                  string
 	Mtu                         int
 	DisableNetwork              bool
 }
@@ -43,6 +44,7 @@ func DaemonConfigFromJob(job *engine.Job) *DaemonConfig {
 		DefaultIp:                   net.ParseIP(job.Getenv("DefaultIp")),
 		InterContainerCommunication: job.GetenvBool("InterContainerCommunication"),
 		GraphDriver:                 job.Getenv("GraphDriver"),
+		ExecDriver:                  job.Getenv("ExecDriver"),
 	}
 	if dns := job.GetenvList("Dns"); dns != nil {
 		config.Dns = dns

+ 3 - 1
container.go

@@ -23,6 +23,8 @@ import (
 	"time"
 )
 
+const defaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
 var (
 	ErrNotATTY               = errors.New("The PTY is not a file")
 	ErrNoTTY                 = errors.New("No PTY found")
@@ -447,7 +449,7 @@ func (container *Container) Start() (err error) {
 	// Setup environment
 	env := []string{
 		"HOME=/",
-		"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+		"PATH=" + defaultPathEnv,
 		"HOSTNAME=" + container.Config.Hostname,
 	}
 

+ 35 - 0
contrib/mkimage-debootstrap.sh

@@ -44,6 +44,8 @@ debianStable=wheezy
 debianUnstable=sid
 # this should match the name found at http://releases.ubuntu.com/
 ubuntuLatestLTS=precise
+# this should match the name found at http://releases.tanglu.org/
+tangluLatest=aequorea
 
 while getopts v:i:a:p:dst name; do
 	case "$name" in
@@ -201,6 +203,17 @@ if [ -z "$strictDebootstrap" ]; then
 					s/ $suite-updates main/ ${suite}-security main/
 				" etc/apt/sources.list
 				;;
+			Tanglu)
+				# add the updates repository
+				if [ "$suite" = "$tangluLatest" ]; then
+					# ${suite}-updates only applies to stable Tanglu versions
+					sudo sed -i "p; s/ $suite main$/ ${suite}-updates main/" etc/apt/sources.list
+				fi
+				;;
+			SteamOS)
+				# add contrib and non-free
+				sudo sed -i "s/ $suite main$/ $suite main contrib non-free/" etc/apt/sources.list
+				;;
 		esac
 	fi
 	
@@ -248,6 +261,28 @@ else
 					fi
 				fi
 				;;
+			Tanglu)
+				if [ "$suite" = "$tangluLatest" ]; 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 Tanglu version number, if available (1.0, 2.0, etc.)
+						$docker tag $repo:$suite $repo:$lsbRelease
+					fi
+				fi
+				;;
+			SteamOS)
+				if [ -r etc/lsb-release ]; then
+					lsbRelease="$(. etc/lsb-release && echo "$DISTRIB_RELEASE")"
+					if [ "$lsbRelease" ]; then
+						# tag specific SteamOS version number, if available (1.0, 2.0, etc.)
+						$docker tag $repo:$suite $repo:$lsbRelease
+					fi
+				fi
+				;;
 		esac
 	fi
 fi

+ 1 - 1
contrib/vagrant-docker/README.md

@@ -31,7 +31,7 @@ stop on runlevel [!2345]
 respawn
 
 script
-    /usr/bin/docker -d -H=tcp://0.0.0.0:4243/
+    /usr/bin/docker -d -H=tcp://0.0.0.0:4243
 end script
 ```
 

+ 5 - 1
docker/docker.go

@@ -6,8 +6,8 @@ import (
 	"os"
 	"strings"
 
-	_ "github.com/dotcloud/docker"
 	"github.com/dotcloud/docker/api"
+	"github.com/dotcloud/docker/builtins"
 	"github.com/dotcloud/docker/dockerversion"
 	"github.com/dotcloud/docker/engine"
 	flag "github.com/dotcloud/docker/pkg/mflag"
@@ -39,6 +39,7 @@ func main() {
 		flDefaultIp          = flag.String([]string{"#ip", "-ip"}, "0.0.0.0", "Default IP address to use when binding container ports")
 		flInterContainerComm = flag.Bool([]string{"#icc", "-icc"}, true, "Enable inter-container communication")
 		flGraphDriver        = flag.String([]string{"s", "-storage-driver"}, "", "Force the docker runtime to use a specific storage driver")
+		flExecDriver         = flag.String([]string{"e", "-exec-driver"}, "", "Force the docker runtime to use a specific exec driver")
 		flHosts              = opts.NewListOpts(api.ValidateHost)
 		flMtu                = flag.Int([]string{"#mtu", "-mtu"}, 0, "Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if no default route is available")
 	)
@@ -81,6 +82,8 @@ func main() {
 		if err != nil {
 			log.Fatal(err)
 		}
+		// Load builtins
+		builtins.Register(eng)
 		// load the daemon in the background so we can immediately start
 		// the http api so that connections don't fail while the daemon
 		// is booting
@@ -98,6 +101,7 @@ func main() {
 			job.Setenv("DefaultIp", *flDefaultIp)
 			job.SetenvBool("InterContainerCommunication", *flInterContainerComm)
 			job.Setenv("GraphDriver", *flGraphDriver)
+			job.Setenv("ExecDriver", *flExecDriver)
 			job.SetenvInt("Mtu", *flMtu)
 			if err := job.Run(); err != nil {
 				log.Fatal(err)

+ 0 - 8
docs/sources/contributing/devenvironment.rst

@@ -92,14 +92,6 @@ To execute the test cases, run this command:
 
 	sudo make test
 
-
-Note: if you're running the tests in vagrant, you need to specify a dns entry in 
-the command (either edit the Makefile, or run the step manually): 
-
-.. code-block:: bash
-
-	sudo docker run -dns 8.8.8.8 -privileged -v `pwd`:/go/src/github.com/dotcloud/docker docker hack/make.sh test
-
 If the test are successful then the tail of the output should look something like this
 
 .. code-block:: bash

+ 3 - 3
docs/sources/faq.rst

@@ -25,9 +25,9 @@ Does Docker run on Mac OS X or Windows?
 
    Not at this time, Docker currently only runs on Linux, but you can
    use VirtualBox to run Docker in a virtual machine on your box, and
-   get the best of both worlds. Check out the
-   :ref:`macosx` and :ref:`windows` installation
-   guides.
+   get the best of both worlds. Check out the :ref:`macosx` and
+   :ref:`windows` installation guides. The small Linux distribution boot2docker
+   can be run inside virtual machines on these two operating systems.
 
 How do containers compare to virtual machines?
 ..............................................

+ 1 - 1
docs/sources/index.rst

@@ -24,6 +24,6 @@ For a high-level overview of Docker, please see the `Introduction
 Docker, we have a `quick start <http://www.docker.io/gettingstarted>`_
 and a more in-depth guide to :ref:`ubuntu_linux` and other
 :ref:`installation_list` paths including prebuilt binaries,
-Vagrant-created VMs, Rackspace and Amazon instances.
+Rackspace and Amazon instances.
 
 Enough reading! :ref:`Try it out! <running_examples>`

+ 1 - 110
docs/sources/installation/amazon.rst

@@ -10,8 +10,7 @@ Amazon EC2
 There are several ways to install Docker on AWS EC2:
 
 * :ref:`amazonquickstart` or
-* :ref:`amazonstandard` or
-* :ref:`amazonvagrant`
+* :ref:`amazonstandard`
 
 **You'll need an** `AWS account <http://aws.amazon.com/>`_ **first, of course.**
 
@@ -73,112 +72,4 @@ running Ubuntu. Just follow Step 1 from :ref:`amazonquickstart` to
 pick an image (or use one of your own) and skip the step with the
 *User Data*. Then continue with the :ref:`ubuntu_linux` instructions.
 
-.. _amazonvagrant:
-
-Use Vagrant
------------
-
-.. include:: install_unofficial.inc
-  
-And finally, if you prefer to work through Vagrant, you can install
-Docker that way too. Vagrant 1.1 or higher is required.
-
-1. Install vagrant from http://www.vagrantup.com/ (or use your package manager)
-2. Install the vagrant aws plugin
-
-   ::
-
-       vagrant plugin install vagrant-aws
-
-
-3. Get the docker sources, this will give you the latest Vagrantfile.
-
-   ::
-
-      git clone https://github.com/dotcloud/docker.git
-
-
-4. Check your AWS environment.
-
-   Create a keypair specifically for EC2, give it a name and save it
-   to your disk. *I usually store these in my ~/.ssh/ folder*.
-
-   Check that your default security group has an inbound rule to
-   accept SSH (port 22) connections.
-
-5. Inform Vagrant of your settings
-
-   Vagrant will read your access credentials from your environment, so
-   we need to set them there first. Make sure you have everything on
-   amazon aws setup so you can (manually) deploy a new image to EC2.
-
-   Note that where possible these variables are the same as those honored by
-   the ec2 api tools.
-   ::
-
-       export AWS_ACCESS_KEY=xxx
-       export AWS_SECRET_KEY=xxx
-       export AWS_KEYPAIR_NAME=xxx
-       export SSH_PRIVKEY_PATH=xxx
-
-       export BOX_NAME=xxx
-       export AWS_REGION=xxx
-       export AWS_AMI=xxx
-       export AWS_INSTANCE_TYPE=xxx
-
-   The required environment variables are:
-
-   * ``AWS_ACCESS_KEY`` - The API key used to make requests to AWS
-   * ``AWS_SECRET_KEY`` - The secret key to make AWS API requests
-   * ``AWS_KEYPAIR_NAME`` - The name of the keypair used for this EC2 instance
-   * ``SSH_PRIVKEY_PATH`` - The path to the private key for the named
-     keypair, for example ``~/.ssh/docker.pem``
-
-   There are a number of optional environment variables:
-
-   * ``BOX_NAME`` - The name of the vagrant box to use.  Defaults to
-     ``ubuntu``.
-   * ``AWS_REGION`` - The aws region to spawn the vm in.  Defaults to
-     ``us-east-1``.
-   * ``AWS_AMI`` - The aws AMI to start with as a base.  This must be
-     be an ubuntu 12.04 precise image.  You must change this value if
-     ``AWS_REGION`` is set to a value other than ``us-east-1``.
-     This is because AMIs are region specific.  Defaults to ``ami-69f5a900``.
-   * ``AWS_INSTANCE_TYPE`` - The aws instance type.  Defaults to ``t1.micro``.
-
-   You can check if they are set correctly by doing something like
-
-   ::
-
-      echo $AWS_ACCESS_KEY
-
-6. Do the magic!
-
-   ::
-
-      vagrant up --provider=aws
-
-
-   If it stalls indefinitely on ``[default] Waiting for SSH to become
-   available...``, Double check your default security zone on AWS
-   includes rights to SSH (port 22) to your container.
-
-   If you have an advanced AWS setup, you might want to have a look at
-   `vagrant-aws <https://github.com/mitchellh/vagrant-aws>`_.
-
-7. Connect to your machine
-
-   .. code-block:: bash
-
-      vagrant ssh
-
-8. Your first command
-
-   Now you are in the VM, run docker
-
-   .. code-block:: bash
-
-      sudo docker
-
-
 Continue with the :ref:`hello_world` example.

+ 31 - 182
docs/sources/installation/windows.rst

@@ -1,223 +1,72 @@
 :title: Installation on Windows
 :description: Please note this project is currently under heavy development. It should not be used in production.
-:keywords: Docker, Docker documentation, Windows, requirements, virtualbox, vagrant, git, ssh, putty, cygwin
+:keywords: Docker, Docker documentation, Windows, requirements, virtualbox, boot2docker
 
 .. _windows:
 
 Windows
 =======
 
-Docker can run on Windows using a VM like VirtualBox. You then run
-Linux within the VM.
+Docker can run on Windows using a virtualization platform like VirtualBox. A Linux
+distribution is run inside a virtual machine and that's where Docker will run. 
 
 Installation
 ------------
 
 .. include:: install_header.inc
 
-.. include:: install_unofficial.inc
+1. Install virtualbox from https://www.virtualbox.org - or follow this `tutorial <http://www.slideshare.net/julienbarbier42/install-virtualbox-on-windows-7>`_.
 
-1. Install virtualbox from https://www.virtualbox.org - or follow this tutorial__
+2. Download the latest boot2docker.iso from https://github.com/boot2docker/boot2docker/releases.
 
-.. __: http://www.slideshare.net/julienbarbier42/install-virtualbox-on-windows-7
+3. Start VirtualBox.
 
-2. Install vagrant from http://www.vagrantup.com - or follow this tutorial__
+4. Create a new Virtual machine with the following settings:
 
-.. __: http://www.slideshare.net/julienbarbier42/install-vagrant-on-windows-7
+ - `Name: boot2docker`
+ - `Type: Linux`
+ - `Version: Linux 2.6 (64 bit)`
+ - `Memory size: 1024 MB`
+ - `Hard drive: Do not add a virtual hard drive`
 
-3. Install git with ssh from http://git-scm.com/downloads - or follow this tutorial__
+5. Open the settings of the virtual machine:
 
-.. __: http://www.slideshare.net/julienbarbier42/install-git-with-ssh-on-windows-7
+   5.1. go to Storage
 
+   5.2. click the empty slot below `Controller: IDE`
 
-We recommend having at least 2Gb of free disk space and 2Gb of RAM (or more).
+   5.3. click the disc icon on the right of `IDE Secondary Master`
 
-Opening a command prompt
-------------------------
+   5.4. click `Choose a virtual CD/DVD disk file`
 
-First open a cmd prompt. Press Windows key and then press “R”
-key. This will open the RUN dialog box for you. Type “cmd” and press
-Enter. Or you can click on Start, type “cmd” in the “Search programs
-and files” field, and click on cmd.exe.
+6. Browse to the path where you've saved the `boot2docker.iso`, select the `boot2docker.iso` and click open.
 
-.. image:: images/win/_01.gif
-   :alt: Git install
-   :align: center
+7. Click OK on the Settings dialog to save the changes and close the window.
 
-This should open a cmd prompt window.
+8. Start the virtual machine by clicking the green start button.
 
-.. image:: images/win/_02.gif
-   :alt: run docker
-   :align: center
-
-Alternatively, you can also use a Cygwin terminal, or Git Bash (or any
-other command line program you are usually using). The next steps
-would be the same.
-
-.. _launch_ubuntu:
-
-Launch an Ubuntu virtual server
--------------------------------
-
-Let’s download and run an Ubuntu image with docker binaries already
-installed.
-
-.. code-block:: bash
-
-	git clone https://github.com/dotcloud/docker.git 
-	cd docker
-	vagrant up
-
-.. image:: images/win/run_02_.gif
-   :alt: run docker
-   :align: center
-
-Congratulations! You are running an Ubuntu server with docker
-installed on it. You do not see it though, because it is running in
-the background.
-
-Log onto your Ubuntu server
----------------------------
-
-Let’s log into your Ubuntu server now. To do so you have two choices:
-
-- Use Vagrant on Windows command prompt OR
-- Use SSH
-
-Using Vagrant on Windows Command Prompt
-```````````````````````````````````````
-
-Run the following command
-
-.. code-block:: bash
-
-	vagrant ssh
-
-You may see an error message starting with “`ssh` executable not
-found”. In this case it means that you do not have SSH in your
-PATH. If you do not have SSH in your PATH you can set it up with the
-“set” command. For instance, if your ssh.exe is in the folder named
-“C:\Program Files (x86)\Git\bin”, then you can run the following
-command:
-
-.. code-block:: bash
-
-	set PATH=%PATH%;C:\Program Files (x86)\Git\bin
-
-.. image:: images/win/run_03.gif
-   :alt: run docker
-   :align: center
-
-Using SSH
-`````````
-
-First step is to get the IP and port of your Ubuntu server. Simply run:
-
-.. code-block:: bash
-
-	vagrant ssh-config 
-
-You should see an output with HostName and Port information. In this
-example, HostName is 127.0.0.1 and port is 2222. And the User is
-“vagrant”. The password is not shown, but it is also “vagrant”.
-
-.. image:: images/win/ssh-config.gif
-   :alt: run docker
-   :align: center
-
-You can now use this information for connecting via SSH to your
-server. To do so you can:
-
-- Use putty.exe OR
-- Use SSH from a terminal
-
-Use putty.exe
-'''''''''''''
-
-You can download putty.exe from this page
-http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html Launch
-putty.exe and simply enter the information you got from last step.
-
-.. image:: images/win/putty.gif
-   :alt: run docker
-   :align: center
-
-Open, and enter user = vagrant and password = vagrant.
-
-.. image:: images/win/putty_2.gif
-   :alt: run docker
-   :align: center
-
-SSH from a terminal
-'''''''''''''''''''
-
-You can also run this command on your favorite terminal (windows
-prompt, cygwin, git-bash, …). Make sure to adapt the IP and port from
-what you got from the vagrant ssh-config command.
-
-.. code-block:: bash
-
-	ssh vagrant@127.0.0.1 –p 2222
-
-Enter user = vagrant and password = vagrant.
-
-.. image:: images/win/cygwin.gif
-   :alt: run docker
-   :align: center
-
-Congratulations, you are now logged onto your Ubuntu Server, running
-on top of your Windows machine !
+9. The boot2docker virtual machine should boot now.
 
 Running Docker
 --------------
 
-First you have to be root in order to run docker. Simply run the
-following command:
-
-.. code-block:: bash
+boot2docker will log you in automatically so you can start using Docker right
+away.
 
-	sudo su
-
-You are now ready for the docker’s “hello world” example. Run
+Let's try the “hello world” example. Run
 
 .. code-block:: bash
 
 	docker run busybox echo hello world
 
-.. image:: images/win/run_04.gif
-   :alt: run docker
-   :align: center
-
-All done!
-
-Now you can continue with the :ref:`hello_world` example.
+This will download the small busybox image and print hello world.
 
-Troubleshooting
----------------
 
-VM does not boot
-````````````````
-
-.. image:: images/win/ts_go_bios.JPG
-
-If you run into this error message "The VM failed to remain in the
-'running' state while attempting to boot", please check that your
-computer has virtualization technology available and activated by
-going to the BIOS. Here's an example for an HP computer (System
-configuration / Device configuration)
-
-.. image:: images/win/hp_bios_vm.JPG
-
-On some machines the BIOS menu can only be accessed before startup.
-To access BIOS in this scenario you should restart your computer and 
-press ESC/Enter when prompted to access the boot and BIOS controls. Typically
-the option to allow virtualization is contained within the BIOS/Security menu.
-
-Docker is not installed
-```````````````````````
+Observations
+------------
 
-.. image:: images/win/ts_no_docker.JPG
+Persistent storage
+``````````````````
 
-If you run into this error message "The program 'docker' is currently
-not installed", try deleting the docker folder and restart from
-:ref:`launch_ubuntu`
+The virtual machine created above lacks any persistent data storage. All images
+and containers will be lost when shutting down or rebooting the VM.

+ 15 - 2
docs/sources/reference/api/docker_remote_api_v1.8.rst

@@ -118,6 +118,7 @@ Create a container
                 "User":"",
                 "Memory":0,
                 "MemorySwap":0,
+                "CpuShares":0,
                 "AttachStdin":false,
                 "AttachStdout":true,
                 "AttachStderr":true,
@@ -153,7 +154,15 @@ Create a container
                 "Warnings":[]
            }
 
-        :jsonparam config: the container's configuration
+        :jsonparam Hostname: Container host name
+        :jsonparam User: Username or UID
+        :jsonparam Memory: Memory Limit in bytes
+        :jsonparam CpuShares: CPU shares (relative weight)
+        :jsonparam AttachStdin: 1/True/true or 0/False/false, attach to standard input. Default false
+        :jsonparam AttachStdout: 1/True/true or 0/False/false, attach to standard output. Default false
+        :jsonparam AttachStderr: 1/True/true or 0/False/false, attach to standard error. Default false
+        :jsonparam Tty: 1/True/true or 0/False/false, allocate a pseudo-tty. Default false
+        :jsonparam OpenStdin: 1/True/true or 0/False/false, keep stdin open even if not attached. Default false
         :query name: Assign the specified name to the container. Must match ``/?[a-zA-Z0-9_-]+``.
         :statuscode 201: no error
         :statuscode 404: no such container
@@ -394,7 +403,11 @@ Start a container
            HTTP/1.1 204 No Content
            Content-Type: text/plain
 
-        :jsonparam hostConfig: the container's host configuration (optional)
+        :jsonparam Binds: Create a bind mount to a directory or file with [host-path]:[container-path]:[rw|ro]. If a directory "container-path" is missing, then docker creates a new volume.
+        :jsonparam LxcConf: Map of custom lxc options
+        :jsonparam PortBindings: Expose ports from the container, optionally publishing them via the HostPort flag
+        :jsonparam PublishAllPorts: 1/True/true or 0/False/false, publish all exposed ports to the host interfaces. Default false
+        :jsonparam Privileged: 1/True/true or 0/False/false, give extended privileges to this container. Default false
         :statuscode 204: no error
         :statuscode 404: no such container
         :statuscode 500: server error

+ 15 - 2
docs/sources/reference/api/docker_remote_api_v1.9.rst

@@ -118,6 +118,7 @@ Create a container
                 "User":"",
                 "Memory":0,
                 "MemorySwap":0,
+                "CpuShares":0,
                 "AttachStdin":false,
                 "AttachStdout":true,
                 "AttachStderr":true,
@@ -153,7 +154,15 @@ Create a container
                 "Warnings":[]
            }
 
-        :jsonparam config: the container's configuration
+        :jsonparam Hostname: Container host name
+        :jsonparam User: Username or UID
+        :jsonparam Memory: Memory Limit in bytes
+        :jsonparam CpuShares: CPU shares (relative weight)
+        :jsonparam AttachStdin: 1/True/true or 0/False/false, attach to standard input. Default false
+        :jsonparam AttachStdout: 1/True/true or 0/False/false, attach to standard output. Default false
+        :jsonparam AttachStderr: 1/True/true or 0/False/false, attach to standard error. Default false
+        :jsonparam Tty: 1/True/true or 0/False/false, allocate a pseudo-tty. Default false
+        :jsonparam OpenStdin: 1/True/true or 0/False/false, keep stdin open even if not attached. Default false
         :query name: Assign the specified name to the container. Must match ``/?[a-zA-Z0-9_-]+``.
         :statuscode 201: no error
         :statuscode 404: no such container
@@ -394,7 +403,11 @@ Start a container
            HTTP/1.1 204 No Content
            Content-Type: text/plain
 
-        :jsonparam hostConfig: the container's host configuration (optional)
+        :jsonparam Binds: Create a bind mount to a directory or file with [host-path]:[container-path]:[rw|ro]. If a directory "container-path" is missing, then docker creates a new volume.
+        :jsonparam LxcConf: Map of custom lxc options
+        :jsonparam PortBindings: Expose ports from the container, optionally publishing them via the HostPort flag
+        :jsonparam PublishAllPorts: 1/True/true or 0/False/false, publish all exposed ports to the host interfaces. Default false
+        :jsonparam Privileged: 1/True/true or 0/False/false, give extended privileges to this container. Default false
         :statuscode 204: no error
         :statuscode 404: no such container
         :statuscode 500: server error

+ 1 - 1
docs/sources/reference/builder.rst

@@ -74,7 +74,7 @@ When you're done with your build, you're ready to look into
 2. Format
 =========
 
-The Dockerfile format is quite simple:
+Here is the format of the Dockerfile:
 
 ::
 

+ 1 - 0
docs/sources/reference/commandline/cli.rst

@@ -79,6 +79,7 @@ Commands
       -p, --pidfile="/var/run/docker.pid": Path to use for daemon PID file
       -r, --restart=true: Restart previously running containers
       -s, --storage-driver="": Force the docker runtime to use a specific storage driver
+      -e, --exec-driver="": Force the docker runtime to use a specific exec driver
       -v, --version=false: Print version information and quit
       --mtu=0: Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if no default route is available
 

+ 43 - 0
engine/engine.go

@@ -1,6 +1,7 @@
 package engine
 
 import (
+	"bufio"
 	"fmt"
 	"github.com/dotcloud/docker/utils"
 	"io"
@@ -136,6 +137,48 @@ func (eng *Engine) Job(name string, args ...string) *Job {
 	return job
 }
 
+// ParseJob creates a new job from a text description using a shell-like syntax.
+//
+// The following syntax is used to parse `input`:
+//
+// * Words are separated using standard whitespaces as separators.
+// * Quotes and backslashes are not interpreted.
+// * Words of the form 'KEY=[VALUE]' are added to the job environment.
+// * All other words are added to the job arguments.
+//
+// For example:
+//
+// job, _ := eng.ParseJob("VERBOSE=1 echo hello TEST=true world")
+//
+// The resulting job will have:
+//	job.Args={"echo", "hello", "world"}
+//	job.Env={"VERBOSE":"1", "TEST":"true"}
+//
+func (eng *Engine) ParseJob(input string) (*Job, error) {
+	// FIXME: use a full-featured command parser
+	scanner := bufio.NewScanner(strings.NewReader(input))
+	scanner.Split(bufio.ScanWords)
+	var (
+		cmd []string
+		env Env
+	)
+	for scanner.Scan() {
+		word := scanner.Text()
+		kv := strings.SplitN(word, "=", 2)
+		if len(kv) == 2 {
+			env.Set(kv[0], kv[1])
+		} else {
+			cmd = append(cmd, word)
+		}
+	}
+	if len(cmd) == 0 {
+		return nil, fmt.Errorf("empty command: '%s'", input)
+	}
+	job := eng.Job(cmd[0], cmd[1:]...)
+	job.Env().Init(&env)
+	return job, nil
+}
+
 func (eng *Engine) Logf(format string, args ...interface{}) (n int, err error) {
 	if os.Getenv("TEST") == "" {
 		prefixedFormat := fmt.Sprintf("[%s] %s\n", eng, strings.TrimRight(format, "\n"))

+ 38 - 0
engine/engine_test.go

@@ -5,6 +5,7 @@ import (
 	"os"
 	"path"
 	"path/filepath"
+	"strings"
 	"testing"
 )
 
@@ -114,3 +115,40 @@ func TestEngineLogf(t *testing.T) {
 		t.Fatalf("Test: Logf() should print at least as much as the input\ninput=%d\nprinted=%d", len(input), n)
 	}
 }
+
+func TestParseJob(t *testing.T) {
+	eng := newTestEngine(t)
+	defer os.RemoveAll(eng.Root())
+	// Verify that the resulting job calls to the right place
+	var called bool
+	eng.Register("echo", func(job *Job) Status {
+		called = true
+		return StatusOK
+	})
+	input := "echo DEBUG=1 hello world VERBOSITY=42"
+	job, err := eng.ParseJob(input)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if job.Name != "echo" {
+		t.Fatalf("Invalid job name: %v", job.Name)
+	}
+	if strings.Join(job.Args, ":::") != "hello:::world" {
+		t.Fatalf("Invalid job args: %v", job.Args)
+	}
+	if job.Env().Get("DEBUG") != "1" {
+		t.Fatalf("Invalid job env: %v", job.Env)
+	}
+	if job.Env().Get("VERBOSITY") != "42" {
+		t.Fatalf("Invalid job env: %v", job.Env)
+	}
+	if len(job.Env().Map()) != 2 {
+		t.Fatalf("Invalid job env: %v", job.Env)
+	}
+	if err := job.Run(); err != nil {
+		t.Fatal(err)
+	}
+	if !called {
+		t.Fatalf("Job was not called")
+	}
+}

+ 7 - 0
engine/env.go

@@ -36,6 +36,13 @@ func (env *Env) Exists(key string) bool {
 	return exists
 }
 
+func (env *Env) Init(src *Env) {
+	(*env) = make([]string, 0, len(*src))
+	for _, val := range *src {
+		(*env) = append((*env), val)
+	}
+}
+
 func (env *Env) GetBool(key string) (value bool) {
 	s := strings.ToLower(strings.Trim(env.Get(key), " \t"))
 	if s == "" || s == "0" || s == "no" || s == "false" || s == "none" {

+ 9 - 2
engine/job.go

@@ -74,7 +74,7 @@ func (job *Job) Run() error {
 		return err
 	}
 	if job.status != 0 {
-		return fmt.Errorf("%s: %s", job.Name, errorMessage)
+		return fmt.Errorf("%s", errorMessage)
 	}
 	return nil
 }
@@ -102,6 +102,10 @@ func (job *Job) String() string {
 	return fmt.Sprintf("%s.%s%s", job.Eng, job.CallString(), job.StatusString())
 }
 
+func (job *Job) Env() *Env {
+	return job.env
+}
+
 func (job *Job) EnvExists(key string) (value bool) {
 	return job.env.Exists(key)
 }
@@ -197,11 +201,14 @@ func (job *Job) Printf(format string, args ...interface{}) (n int, err error) {
 }
 
 func (job *Job) Errorf(format string, args ...interface{}) Status {
+	if format[len(format)-1] != '\n' {
+		format = format + "\n"
+	}
 	fmt.Fprintf(job.Stderr, format, args...)
 	return StatusErr
 }
 
 func (job *Job) Error(err error) Status {
-	fmt.Fprintf(job.Stderr, "%s", err)
+	fmt.Fprintf(job.Stderr, "%s\n", err)
 	return StatusErr
 }

+ 2 - 3
execdriver/lxc/driver.go

@@ -301,9 +301,8 @@ func (d *driver) Info(id string) execdriver.Info {
 func (d *driver) GetPidsForContainer(id string) ([]int, error) {
 	pids := []int{}
 
-	// memory is chosen randomly, any cgroup used by docker works
-	subsystem := "memory"
-
+	// cpu is chosen because it is the only non optional subsystem in cgroups
+	subsystem := "cpu"
 	cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem)
 	if err != nil {
 		return pids, err

+ 1 - 1
hack/make/test-integration

@@ -12,5 +12,5 @@ bundle_test_integration() {
 # this "grep" hides some really irritating warnings that "go test -coverpkg"
 # spews when it is given packages that aren't used
 bundle_test_integration 2>&1 \
-	| grep -v '^warning: no packages being tested depend on ' \
+	| grep --line-buffered -v '^warning: no packages being tested depend on ' \
 	| tee $DEST/test.log

+ 8 - 48
integration/runtime_test.go

@@ -123,19 +123,8 @@ func init() {
 }
 
 func setupBaseImage() {
-	eng, err := engine.New(unitTestStoreBase)
-	if err != nil {
-		log.Fatalf("Can't initialize engine at %s: %s", unitTestStoreBase, err)
-	}
-	job := eng.Job("initserver")
-	job.Setenv("Root", unitTestStoreBase)
-	job.SetenvBool("Autorestart", false)
-	job.Setenv("BridgeIface", unitTestNetworkBridge)
-	if err := job.Run(); err != nil {
-		log.Fatalf("Unable to create a runtime for tests: %s", err)
-	}
-
-	job = eng.Job("inspect", unitTestImageName, "image")
+	eng := newTestEngine(log.New(os.Stderr, "", 0), false, unitTestStoreBase)
+	job := eng.Job("inspect", unitTestImageName, "image")
 	img, _ := job.Stdout.AddEnv()
 	// If the unit test is not found, try to download it.
 	if err := job.Run(); err != nil || img.Get("id") != unitTestImageID {
@@ -575,18 +564,7 @@ func TestRestore(t *testing.T) {
 
 	// Here are are simulating a docker restart - that is, reloading all containers
 	// from scratch
-	root := eng.Root()
-	eng, err := engine.New(root)
-	if err != nil {
-		t.Fatal(err)
-	}
-	job := eng.Job("initserver")
-	job.Setenv("Root", eng.Root())
-	job.SetenvBool("Autorestart", false)
-	if err := job.Run(); err != nil {
-		t.Fatal(err)
-	}
-
+	eng = newTestEngine(t, false, eng.Root())
 	runtime2 := mkRuntimeFromEngine(eng, t)
 	if len(runtime2.List()) != 2 {
 		t.Errorf("Expected 2 container, %v found", len(runtime2.List()))
@@ -612,22 +590,14 @@ func TestRestore(t *testing.T) {
 }
 
 func TestReloadContainerLinks(t *testing.T) {
-	// FIXME: here we don't use NewTestEngine because it calls initserver with Autorestart=false,
-	// and we want to set it to true.
 	root, err := newTestDirectory(unitTestStoreBase)
 	if err != nil {
 		t.Fatal(err)
 	}
-	eng, err := engine.New(root)
-	if err != nil {
-		t.Fatal(err)
-	}
-	job := eng.Job("initserver")
-	job.Setenv("Root", eng.Root())
-	job.SetenvBool("Autorestart", true)
-	if err := job.Run(); err != nil {
-		t.Fatal(err)
-	}
+	// FIXME: here we don't use NewTestEngine because it calls initserver with Autorestart=false,
+	// and we want to set it to true.
+
+	eng := newTestEngine(t, true, root)
 
 	runtime1 := mkRuntimeFromEngine(eng, t)
 	defer nuke(runtime1)
@@ -668,17 +638,7 @@ func TestReloadContainerLinks(t *testing.T) {
 
 	// Here are are simulating a docker restart - that is, reloading all containers
 	// from scratch
-	eng, err = engine.New(root)
-	if err != nil {
-		t.Fatal(err)
-	}
-	job = eng.Job("initserver")
-	job.Setenv("Root", eng.Root())
-	job.SetenvBool("Autorestart", false)
-	if err := job.Run(); err != nil {
-		t.Fatal(err)
-	}
-
+	eng = newTestEngine(t, false, root)
 	runtime2 := mkRuntimeFromEngine(eng, t)
 	if len(runtime2.List()) != 2 {
 		t.Errorf("Expected 2 container, %v found", len(runtime2.List()))

+ 1 - 15
integration/server_test.go

@@ -2,7 +2,6 @@ package docker
 
 import (
 	"github.com/dotcloud/docker"
-	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/runconfig"
 	"strings"
 	"testing"
@@ -258,20 +257,7 @@ func TestRestartKillWait(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	eng, err = engine.New(eng.Root())
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	job = eng.Job("initserver")
-	job.Setenv("Root", eng.Root())
-	job.SetenvBool("AutoRestart", false)
-	// TestGetEnabledCors and TestOptionsRoute require EnableCors=true
-	job.SetenvBool("EnableCors", true)
-	if err := job.Run(); err != nil {
-		t.Fatal(err)
-	}
-
+	eng = newTestEngine(t, false, eng.Root())
 	srv = mkServerFromEngine(eng, t)
 
 	job = srv.Eng.Job("containers")

+ 20 - 25
integration/utils_test.go

@@ -15,6 +15,7 @@ import (
 	"time"
 
 	"github.com/dotcloud/docker"
+	"github.com/dotcloud/docker/builtins"
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/runconfig"
 	"github.com/dotcloud/docker/utils"
@@ -27,26 +28,12 @@ import (
 // Create a temporary runtime suitable for unit testing.
 // Call t.Fatal() at the first error.
 func mkRuntime(f utils.Fataler) *docker.Runtime {
-	root, err := newTestDirectory(unitTestStoreBase)
-	if err != nil {
-		f.Fatal(err)
-	}
-	config := &docker.DaemonConfig{
-		Root:        root,
-		AutoRestart: false,
-		Mtu:         docker.GetDefaultNetworkMtu(),
-	}
-
-	eng, err := engine.New(root)
-	if err != nil {
-		f.Fatal(err)
-	}
-
-	r, err := docker.NewRuntimeFromDirectory(config, eng)
-	if err != nil {
-		f.Fatal(err)
-	}
-	return r
+	eng := newTestEngine(f, false, "")
+	return mkRuntimeFromEngine(eng, f)
+	// FIXME:
+	// [...]
+	// Mtu:         docker.GetDefaultNetworkMtu(),
+	// [...]
 }
 
 func createNamedTestContainer(eng *engine.Engine, config *runconfig.Config, f utils.Fataler, name string) (shortId string) {
@@ -185,20 +172,24 @@ func mkRuntimeFromEngine(eng *engine.Engine, t utils.Fataler) *docker.Runtime {
 	return runtime
 }
 
-func NewTestEngine(t utils.Fataler) *engine.Engine {
-	root, err := newTestDirectory(unitTestStoreBase)
-	if err != nil {
-		t.Fatal(err)
+func newTestEngine(t utils.Fataler, autorestart bool, root string) *engine.Engine {
+	if root == "" {
+		if dir, err := newTestDirectory(unitTestStoreBase); err != nil {
+			t.Fatal(err)
+		} else {
+			root = dir
+		}
 	}
 	eng, err := engine.New(root)
 	if err != nil {
 		t.Fatal(err)
 	}
 	// Load default plugins
+	builtins.Register(eng)
 	// (This is manually copied and modified from main() until we have a more generic plugin system)
 	job := eng.Job("initserver")
 	job.Setenv("Root", root)
-	job.SetenvBool("AutoRestart", false)
+	job.SetenvBool("AutoRestart", autorestart)
 	// TestGetEnabledCors and TestOptionsRoute require EnableCors=true
 	job.SetenvBool("EnableCors", true)
 	if err := job.Run(); err != nil {
@@ -207,6 +198,10 @@ func NewTestEngine(t utils.Fataler) *engine.Engine {
 	return eng
 }
 
+func NewTestEngine(t utils.Fataler) *engine.Engine {
+	return newTestEngine(t, false, "")
+}
+
 func newTestDirectory(templateDir string) (dir string, err error) {
 	return utils.TestDirectory(templateDir)
 }

+ 1 - 1
links/links.go

@@ -72,7 +72,7 @@ func (l *Link) ToEnv() []string {
 			if len(parts) != 2 {
 				continue
 			}
-			// Ignore a few variables that are added during docker build
+			// Ignore a few variables that are added during docker build (and not really relevant to linked containers)
 			if parts[0] == "HOME" || parts[0] == "PATH" {
 				continue
 			}

+ 0 - 6
networkdriver/lxc/driver.go

@@ -57,12 +57,6 @@ var (
 	currentInterfaces = make(map[string]*networkInterface)
 )
 
-func init() {
-	if err := engine.Register("init_networkdriver", InitDriver); err != nil {
-		panic(err)
-	}
-}
-
 func InitDriver(job *engine.Job) engine.Status {
 	var (
 		network        *net.IPNet

+ 11 - 2
runtime.go

@@ -8,7 +8,7 @@ import (
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/execdriver"
 	"github.com/dotcloud/docker/execdriver/docker"
-	_ "github.com/dotcloud/docker/execdriver/lxc"
+	"github.com/dotcloud/docker/execdriver/lxc"
 	"github.com/dotcloud/docker/graphdriver"
 	"github.com/dotcloud/docker/graphdriver/aufs"
 	_ "github.com/dotcloud/docker/graphdriver/btrfs"
@@ -704,7 +704,16 @@ func NewRuntimeFromDirectory(config *DaemonConfig, eng *engine.Engine) (*Runtime
 
 	sysInfo := sysinfo.New(false)
 
-	ed, err := docker.NewDriver(config.Root)
+	var ed execdriver.Driver
+	utils.Debugf("execDriver: provided %s", config.ExecDriver)
+	if config.ExecDriver == "chroot" && false {
+		// chroot is presently a noop driver https://github.com/dotcloud/docker/pull/4189#issuecomment-35330655
+		ed, err = chroot.NewDriver()
+		utils.Debugf("execDriver: using chroot")
+	} else {
+		ed, err = lxc.NewDriver(config.Root, sysInfo.AppArmor)
+		utils.Debugf("execDriver: using lxc")
+	}
 	if err != nil {
 		return nil, err
 	}

+ 1 - 5
server.go

@@ -34,14 +34,10 @@ func (srv *Server) Close() error {
 	return srv.runtime.Close()
 }
 
-func init() {
-	engine.Register("initserver", jobInitServer)
-}
-
 // jobInitApi runs the remote api server `srv` as a daemon,
 // Only one api server can run at the same time - this is enforced by a pidfile.
 // The signals SIGINT, SIGQUIT and SIGTERM are intercepted for cleanup.
-func jobInitServer(job *engine.Job) engine.Status {
+func InitServer(job *engine.Job) engine.Status {
 	job.Logf("Creating server")
 	srv, err := NewServer(job.Eng, DaemonConfigFromJob(job))
 	if err != nil {

+ 1 - 5
version.go

@@ -7,11 +7,7 @@ import (
 	"runtime"
 )
 
-func init() {
-	engine.Register("version", jobVersion)
-}
-
-func jobVersion(job *engine.Job) engine.Status {
+func GetVersion(job *engine.Job) engine.Status {
 	if _, err := dockerVersion().WriteTo(job.Stdout); err != nil {
 		job.Errorf("%s", err)
 		return engine.StatusErr