Merge branch 'master' into add-libcontainer
Conflicts: runtime.go Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
commit
27a43692c2
|
@ -22,3 +22,4 @@ bundles/
|
|||
.git/
|
||||
vendor/pkg/
|
||||
pyenv
|
||||
Vagrantfile
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
|
@ -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)
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
..............................................
|
||||
|
|
|
@ -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>`
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
boot2docker will log you in automatically so you can start using Docker right
|
||||
away.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
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
|
||||
This will download the small busybox image and print hello world.
|
||||
|
||||
All done!
|
||||
|
||||
Now you can continue with the :ref:`hello_world` example.
|
||||
Observations
|
||||
------------
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
Persistent storage
|
||||
``````````````````
|
||||
|
||||
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
|
||||
```````````````````````
|
||||
|
||||
.. image:: images/win/ts_no_docker.JPG
|
||||
|
||||
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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
::
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
13
runtime.go
13
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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue