Compare commits

..

76 Commits

Author SHA1 Message Date
Guillaume J. Charmes 30d327d37e Add TestCommitAutoRun 2013-04-25 17:03:13 -07:00
Guillaume J. Charmes 724e2d6b0a Update unit test in order to comply with new api 2013-04-25 17:02:38 -07:00
Guillaume J. Charmes 51d6228261 Implement -config and -command in CmdCommit in order to allow autorun 2013-04-25 16:48:31 -07:00
Guillaume J. Charmes ee298d1420 Specify a different bridge for tests than for regular runtime 2013-04-24 17:43:41 -07:00
Solomon Hykes 03855b0027 Merge pull request #466 from dotcloud/441-vagrant-improve
* Packaging: simplify Vagrantfile
2013-04-24 17:25:20 -07:00
Daniel Mizyrycki 2726e3649a vagrant; issue #441: Improve main config including aws ubuntu lts dependency 2013-04-24 11:30:15 -07:00
Solomon Hykes 90668a8a99 Bumped version to 0.2.0 2013-04-23 23:15:09 -07:00
Solomon Hykes c7fd84b8a0 Merge branch 'master' of ssh://github.com/dotcloud/docker 2013-04-23 23:05:38 -07:00
Solomon Hykes 874a40ed3a - Dev: dockerbuilder requires a fake initctl because 'apt-get install devscripts' insists on installing a stupid daemon I never asked for in the first place. 2013-04-23 23:04:54 -07:00
Solomon Hykes 370fafacbf Merge branch 'master' of ssh://github.com/dotcloud/docker 2013-04-23 22:57:50 -07:00
Solomon Hykes a0478f726d dockerbuilder: upload most recent Ubuntu package (note version FOO might not yet be packaged at tag vFOO) 2013-04-23 22:57:34 -07:00
Solomon Hykes e5bc5a2e31 Merge pull request #427 from dhrp/docs
- Packaging: Fixed Vagrantfile
* Documentation: Updated install instructions
2013-04-23 19:49:28 -07:00
Solomon Hykes 25fc3a7e76 Merge pull request #470 from dotcloud/packaging-ubuntu
* Packaging: Add 0.1.8 to Ubuntu packaging changelog
* Packaging: Update the Ubuntu maintainer manual
2013-04-23 19:46:56 -07:00
Solomon Hykes b3ab0b561e Makefile improvements
+ Convenience rules: srcrelease, deps
	- Separate dependency vendoring from building the binary
	  (re-download dependencies with 'make deps')
2013-04-23 19:41:38 -07:00
Solomon Hykes 8b8c8bf7cb Fix 'make release RELEASE_VERSION=master' 2013-04-23 18:50:53 -07:00
Solomon Hykes a8651a23b2 make release: build a binary release of the most recent version tag 2013-04-23 18:32:59 -07:00
Daniel Mizyrycki f744cfd5a7 packaging-ubuntu: update maintainer documentation for changelog file 2013-04-23 13:51:03 -07:00
Solomon Hykes e03b241fb1 dockerbuilder: build with 'make; cp -R ./bin' 2013-04-23 12:07:54 -07:00
Thatcher Peskens 1ddca1948b Fixed remaining issues and conflicts created by last merge. 2013-04-23 12:04:53 -07:00
Solomon Hykes 2485bb2cd2 dockerbuilder: use a pristine GOPATH, with the fresh checkout registered at the right path (for internal submodules) 2013-04-23 11:45:47 -07:00
Solomon Hykes 7577f48dc4 dockerbuilder: build in current directory instead /go and /tmp 2013-04-23 10:53:02 -07:00
Solomon Hykes 0512cf9c83 dockerbuilder: /usr/local/bin is already set by docker 2013-04-23 10:49:58 -07:00
Solomon Hykes 73da7a12e7 Increased timeout in TCP port allocation test to pass on slower machines 2013-04-23 10:12:46 -07:00
Solomon Hykes 50f5723f1d Merge pull request #465 from shamrin/patch-2
- Documentation: fixed typo in "Building blocks"
2013-04-23 09:02:19 -07:00
Alexey Shamrin cbc4eccd50 fixed typo in buildingblocks.rst 2013-04-23 12:52:55 +04:00
Solomon Hykes cff26b3a6c Merge pull request #464 from tianon/patch-1
- Runtime: adapt cgroup capability detection to work on Gentoo
2013-04-23 00:36:10 -07:00
Solomon Hykes 329c3e0ffd Merge pull request #462 from dotcloud/initial_changelog
+ Add initial Changelog
2013-04-23 00:32:25 -07:00
Solomon Hykes 4f6cc5c733 Completed Changelog for all past versions 2013-04-23 00:30:18 -07:00
Tianon Gravi e413340723 Update FindCgroupMountpoint to be more forgiving
On Gentoo, the memory cgroup is mounted at /sys/fs/cgroup/memory, but the mount line looks like the following:
memory on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)

(note that the first word on the line is "memory", not "cgroup", but the other essentials are there, namely the type of cgroup and the memory mount option)
2013-04-23 01:09:29 -06:00
Solomon Hykes 95e066d24f - Runtime: ghost containers can be killed. 2013-04-22 22:30:33 -07:00
Solomon Hykes 82b8f7a565 hack/dockerbuilder: a standard build environment for building and uploading official binary builds of docker... inside docker 2013-04-22 22:29:12 -07:00
Solomon Hykes 97badbd29e Bumped version to 0.1.8 2013-04-22 22:04:57 -07:00
Thatcher Peskens 5a5e417d46 Merge remote-tracking branch 'dotcloud/master' into dhrp/docs
Conflicts:
	docker/docker.go
	docs/sources/installation/archlinux.rst
	docs/sources/installation/index.rst
	docs/sources/installation/ubuntulinux.rst
	runtime.go
	utils.go
2013-04-22 18:44:50 -07:00
Thatcher Peskens 4031a01af1 Merged changes 2013-04-22 18:38:42 -07:00
Guillaume J. Charmes 0b0d958b88 Merge pull request #463 from dotcloud/improve_pid_file_feature
Check that the pid in pidfile exists before preventing docker to start
2013-04-22 18:24:03 -07:00
Guillaume J. Charmes 03e4704ae5 Merge pull request #442 from dotcloud/fix_deleted_file_diff
Use aufs to handle parents whiteouts instead of doing it manually
2013-04-22 18:23:46 -07:00
Guillaume J. Charmes 7a8ac76299 Merge pull request #456 from dotcloud/453-generic_kernel_detection-fix
453 generic kernel detection fix
2013-04-22 18:20:17 -07:00
Guillaume J. Charmes c05c91ca3b Make kernel detection work without suffix 2013-04-22 18:15:33 -07:00
Guillaume J. Charmes b76d63cb0c Forbid attach to ghost 2013-04-22 17:53:32 -07:00
Guillaume J. Charmes f926ed182f Allow to kill/stop ghosts 2013-04-22 17:53:32 -07:00
Guillaume J. Charmes d440782e17 Allow to kill container after docker server restarts 2013-04-22 17:52:38 -07:00
Guillaume J. Charmes 82848d4158 Allow to wait on container even after docker server restarts using lxc-info 2013-04-22 17:52:38 -07:00
Guillaume J. Charmes 97535e5a64 Add unit test for file deletion 2013-04-22 17:51:09 -07:00
Guillaume J. Charmes f079fbe3fa Check that the pid in pidfile exists before preventing docker to start 2013-04-22 15:57:31 -07:00
Guillaume J. Charmes 90d144b612 Merge pull request #457 from shamrin/patch-1
README.md: `docker port` instead of just `port`
2013-04-22 15:40:03 -07:00
Guillaume J. Charmes d3db94696d Merge pull request #461 from neomantra/master
Fix typo (ghot -> ghost)
2013-04-22 15:39:34 -07:00
Evan Wies ffe16e3224 Fix typo (ghot -> ghost) 2013-04-22 18:37:06 -04:00
Guillaume J. Charmes 0b60829df7 Add initial changelog 2013-04-22 15:26:06 -07:00
Thatcher Peskens 690e118670 Updated gettingstarted with quicker install. 2013-04-22 13:36:00 -07:00
Alexey Shamrin 038e1d174b README.md: docker port instead of just port 2013-04-23 00:27:23 +04:00
Thatcher Peskens 6c8dcd5cbb Updated Vagrantfile and documentation to reflect new installation path using Ubuntu's PPA, also switched everything to use Ubuntu 12.04 by default. 2013-04-22 13:10:32 -07:00
Guillaume J. Charmes 16aeb77d51 Move the kernel detection to arch specific files 2013-04-22 12:08:59 -07:00
Guillaume J. Charmes 4ac3b803b9 Make the kernel version detection more generic 2013-04-22 11:39:56 -07:00
Guillaume J. Charmes 3514e47edc Do not prevent docker from running when kernel detection fails 2013-04-22 11:26:34 -07:00
Guillaume J. Charmes acb546cd1b Fix race within TestRunDisconnectTty 2013-04-22 11:16:32 -07:00
Guillaume J. Charmes 2ced94b414 Merge pull request #454 from tianon/master
Update utils.go to not enforce extra constraints on the kernel "flavor" (such as being integral or even comparable one to another)
2013-04-22 08:02:42 -07:00
Guillaume J. Charmes 71b5806614 Do not stop execution if cgroup mountpoint is not found 2013-04-22 00:44:57 -04:00
Tianon Gravi 1f65c6bf4c Update utils.go to not enforce extra constraints on the kernel "flavor" (such as being integral or even comparable one to another)
This is especially to fix the current docker on kernels such as gentoo-sources, where the "flavor" is the string "gentoo", and that obviously fails to be converted to an integer.
2013-04-21 19:19:38 -06:00
Solomon Hykes 965e8a02d2 'docker push' shows an additional progress bar while it buffers the archive to disk. Fixes #451. 2013-04-21 15:29:26 -07:00
Solomon Hykes baacae8345 'docker push' buffers filesystem archives on disk instead of memory. 2013-04-21 14:23:55 -07:00
Solomon Hykes 52cedb8a05 Better title in ubuntu install doc 2013-04-20 18:26:15 -07:00
Solomon Hykes 15c7e72e2a Merge branch 'master' of ssh://github.com/dotcloud/docker 2013-04-20 18:19:04 -07:00
Solomon Hykes 76b40ad6c9 Merge remote-tracking branch 'origin/check_kernel_capabilities' 2013-04-20 17:40:25 -07:00
Solomon Hykes 6909f3911f Merge pull request #422 from shawnsi/arch-docs
Arch docs
2013-04-20 17:35:43 -07:00
Thatcher Peskens 0731d1a582 Updated ubuntu install 2013-04-19 20:59:43 -07:00
Thatcher Peskens 8ecde8f9a5 Updated documentation and fixed Vagrantfile 2013-04-19 20:57:50 -07:00
Guillaume J. Charmes e49af5b6de Use aufs to handle parents whitouts instead of doing it manually 2013-04-19 16:33:25 -07:00
Guillaume J. Charmes f3e89fae28 Use mount to determine the cgroup mountpoint 2013-04-18 21:57:58 -07:00
Guillaume J. Charmes c42a4179fc Add unit tests for CompareKernelVersion 2013-04-18 21:34:34 -07:00
Guillaume J. Charmes 2d32ac8cff Improve the docker version output 2013-04-18 21:08:33 -07:00
Guillaume J. Charmes f68d107a13 Remove the NO_MEMORY_LIMIT constant 2013-04-18 21:08:20 -07:00
Guillaume J. Charmes 640efc2ed2 Add capabilities check to allow docker to run on kernel that does not have all options 2013-04-18 20:55:41 -07:00
Guillaume J. Charmes 003622c8b6 Check kernel version and display warning if too low 2013-04-18 20:47:24 -07:00
Thatcher Peskens 6de5ca1e64 Added redirect from old location of documentation (/documentation), these was the location when we were on github. 2013-04-18 16:00:18 -07:00
Shawn Siefkas 7eda9c64b8 Updating the arch linux installation docs
New AUR package name
Adding systemd service unit info
2013-04-18 09:20:23 -05:00
Shawn Siefkas 84c13a3dcf Adding archlinux packaging documentation 2013-04-18 09:17:31 -05:00
45 changed files with 1240 additions and 458 deletions
+86
View File
@@ -0,0 +1,86 @@
# Changelog
## 0.2.0 (2012-04-23)
- Runtime: ghost containers can be killed and waited for
* Documentation: update install intructions
- Packaging: fix Vagrantfile
- Development: automate releasing binaries and ubuntu packages
+ Add a changelog
- Various bugfixes
## 0.1.8 (2013-04-22)
- Dynamically detect cgroup capabilities
- Issue stability warning on kernels <3.8
- 'docker push' buffers on disk instead of memory
- Fix 'docker diff' for removed files
- Fix 'docker stop' for ghost containers
- Fix handling of pidfile
- Various bugfixes and stability improvements
## 0.1.7 (2013-04-18)
- Container ports are available on localhost
- 'docker ps' shows allocated TCP ports
- Contributors can run 'make hack' to start a continuous integration VM
- Streamline ubuntu packaging & uploading
- Various bugfixes and stability improvements
## 0.1.6 (2013-04-17)
- Record the author an image with 'docker commit -author'
## 0.1.5 (2013-04-17)
- Disable standalone mode
- Use a custom DNS resolver with 'docker -d -dns'
- Detect ghost containers
- Improve diagnosis of missing system capabilities
- Allow disabling memory limits at compile time
- Add debian packaging
- Documentation: installing on Arch Linux
- Documentation: running Redis on docker
- Fixed lxc 0.9 compatibility
- Automatically load aufs module
- Various bugfixes and stability improvements
## 0.1.4 (2013-04-09)
- Full support for TTY emulation
- Detach from a TTY session with the escape sequence `C-p C-q`
- Various bugfixes and stability improvements
- Minor UI improvements
- Automatically create our own bridge interface 'docker0'
## 0.1.3 (2013-04-04)
- Choose TCP frontend port with '-p :PORT'
- Layer format is versioned
- Major reliability improvements to the process manager
- Various bugfixes and stability improvements
## 0.1.2 (2013-04-03)
- Set container hostname with 'docker run -h'
- Selective attach at run with 'docker run -a [stdin[,stdout[,stderr]]]'
- Various bugfixes and stability improvements
- UI polish
- Progress bar on push/pull
- Use XZ compression by default
- Make IP allocator lazy
## 0.1.1 (2013-03-31)
- Display shorthand IDs for convenience
- Stabilize process management
- Layers can include a commit message
- Simplified 'docker attach'
- Fixed support for re-attaching
- Various bugfixes and stability improvements
- Auto-download at run
- Auto-login on push
- Beefed up documentation
## 0.1.0 (2013-03-23)
- First release
- Implement registry in order to push/pull images
- TCP port allocation
- Fix termcaps on Linux
- Add documentation
- Add Vagrant support with Vagrantfile
- Add unit tests
- Add repository/tags to ease image management
- Improve the layer implementation
+27 -6
View File
@@ -1,5 +1,9 @@
DOCKER_PACKAGE := github.com/dotcloud/docker
RELEASE_VERSION := $(shell git tag | grep -E "v[0-9\.]+$$" | sort -nr | head -n 1)
SRCRELEASE := docker-$(RELEASE_VERSION)
BINRELEASE := docker-$(RELEASE_VERSION).tgz
GIT_ROOT := $(shell git rev-parse --show-toplevel)
BUILD_DIR := $(CURDIR)/.gopath
GOPATH ?= $(BUILD_DIR)
@@ -13,10 +17,7 @@ endif
GIT_COMMIT = $(shell git rev-parse --short HEAD)
GIT_STATUS = $(shell test -n "`git status --porcelain`" && echo "+CHANGES")
NO_MEMORY_LIMIT ?= 0
export NO_MEMORY_LIMIT
BUILD_OPTIONS = -ldflags "-X main.GIT_COMMIT $(GIT_COMMIT)$(GIT_STATUS) -X main.NO_MEMORY_LIMIT $(NO_MEMORY_LIMIT)"
BUILD_OPTIONS = -ldflags "-X main.GIT_COMMIT $(GIT_COMMIT)$(GIT_STATUS)"
SRC_DIR := $(GOPATH)/src
@@ -26,18 +27,38 @@ DOCKER_MAIN := $(DOCKER_DIR)/docker
DOCKER_BIN_RELATIVE := bin/docker
DOCKER_BIN := $(CURDIR)/$(DOCKER_BIN_RELATIVE)
.PHONY: all clean test hack
.PHONY: all clean test hack release srcrelease $(BINRELEASE) $(SRCRELEASE) $(DOCKER_BIN) $(DOCKER_DIR)
all: $(DOCKER_BIN)
$(DOCKER_BIN): $(DOCKER_DIR)
@mkdir -p $(dir $@)
@(cd $(DOCKER_MAIN); go get $(GO_OPTIONS); go build $(GO_OPTIONS) $(BUILD_OPTIONS) -o $@)
@(cd $(DOCKER_MAIN); go build $(GO_OPTIONS) $(BUILD_OPTIONS) -o $@)
@echo $(DOCKER_BIN_RELATIVE) is created.
$(DOCKER_DIR):
@mkdir -p $(dir $@)
@rm -f $@
@ln -sf $(CURDIR)/ $@
@(cd $(DOCKER_MAIN); go get $(GO_OPTIONS))
whichrelease:
echo $(RELEASE_VERSION)
release: $(BINRELEASE)
srcrelease: $(SRCRELEASE)
deps: $(DOCKER_DIR)
# A clean checkout of $RELEASE_VERSION, with vendored dependencies
$(SRCRELEASE):
rm -fr $(SRCRELEASE)
git clone $(GIT_ROOT) $(SRCRELEASE)
cd $(SRCRELEASE); git checkout -q $(RELEASE_VERSION)
# A binary release ready to be uploaded to a mirror
$(BINRELEASE): $(SRCRELEASE)
rm -f $(BINRELEASE)
cd $(SRCRELEASE); make; cp -R bin docker-$(RELEASE_VERSION); tar -f ../$(BINRELEASE) -zv -c docker-$(RELEASE_VERSION)
clean:
@rm -rf $(dir $(DOCKER_BIN))
+2 -2
View File
@@ -125,7 +125,7 @@ Running an irc bouncer
```bash
BOUNCER_ID=$(docker run -d -p 6667 -u irc shykes/znc $USER $PASSWORD)
echo "Configure your irc client to connect to port $(port $BOUNCER_ID 6667) of this machine"
echo "Configure your irc client to connect to port $(docker port $BOUNCER_ID 6667) of this machine"
```
Running Redis
@@ -133,7 +133,7 @@ Running Redis
```bash
REDIS_ID=$(docker run -d -p 6379 shykes/redis redis-server)
echo "Configure your redis client to connect to port $(port $REDIS_ID 6379) of this machine"
echo "Configure your redis client to connect to port $(docker port $REDIS_ID 6379) of this machine"
```
Share your own image!
Vendored
+22 -26
View File
@@ -1,41 +1,37 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
def v10(config)
config.vm.box = "quantal64_3.5.0-25"
config.vm.box_url = "http://get.docker.io/vbox/ubuntu/12.10/quantal64_3.5.0-25.box"
BOX_NAME = "ubuntu"
BOX_URI = "http://files.vagrantup.com/precise64.box"
PPA_KEY = "E61D797F63561DC6"
config.vm.share_folder "v-data", "/opt/go/src/github.com/dotcloud/docker", File.dirname(__FILE__)
# Ensure puppet is installed on the instance
config.vm.provision :shell, :inline => "apt-get -qq update; apt-get install -y puppet"
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "puppet/manifests"
puppet.manifest_file = "quantal64.pp"
puppet.module_path = "puppet/modules"
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
# Add docker PPA key to the local repository and install docker
pkg_cmd = "apt-key adv --keyserver keyserver.ubuntu.com --recv-keys #{PPA_KEY}; "
pkg_cmd << "echo 'deb http://ppa.launchpad.net/dotcloud/lxc-docker/ubuntu precise main' >>/etc/apt/sources.list; "
pkg_cmd << "apt-get update -qq; apt-get install -q -y lxc-docker"
if ARGV.include?("--provider=aws".downcase)
# Add AUFS dependency to amazon's VM
pkg_cmd << "; apt-get install linux-image-extra-3.2.0-40-virtual"
end
config.vm.provision :shell, :inline => pkg_cmd
end
Vagrant::VERSION < "1.1.0" and Vagrant::Config.run do |config|
v10(config)
end
Vagrant::VERSION >= "1.1.0" and Vagrant.configure("1") do |config|
v10(config)
end
# Providers were added on Vagrant >= 1.1.0
Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
config.vm.provider :aws do |aws|
config.vm.provider :aws do |aws, override|
config.vm.box = "dummy"
config.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
aws.access_key_id = ENV["AWS_ACCESS_KEY_ID"]
aws.secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"]
aws.keypair_name = ENV["AWS_KEYPAIR_NAME"]
aws.ssh_private_key_path = ENV["AWS_SSH_PRIVKEY"]
override.ssh.private_key_path = ENV["AWS_SSH_PRIVKEY"]
override.ssh.username = "ubuntu"
aws.region = "us-east-1"
aws.ami = "ami-ae9806c7"
aws.ssh_username = "ubuntu"
aws.ami = "ami-d0f89fb9"
aws.instance_type = "t1.micro"
end
@@ -51,7 +47,7 @@ Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
end
config.vm.provider :virtualbox do |vb|
config.vm.box = "quantal64_3.5.0-25"
config.vm.box_url = "http://get.docker.io/vbox/ubuntu/12.10/quantal64_3.5.0-25.box"
config.vm.box = BOX_NAME
config.vm.box_url = BOX_URI
end
end
+36
View File
@@ -4,6 +4,7 @@ import (
"errors"
"io"
"io/ioutil"
"os"
"os/exec"
)
@@ -86,3 +87,38 @@ func CmdStream(cmd *exec.Cmd) (io.Reader, error) {
}
return pipeR, nil
}
// NewTempArchive reads the content of src into a temporary file, and returns the contents
// of that file as an archive. The archive can only be read once - as soon as reading completes,
// the file will be deleted.
func NewTempArchive(src Archive, dir string) (*TempArchive, error) {
f, err := ioutil.TempFile(dir, "")
if err != nil {
return nil, err
}
if _, err := io.Copy(f, src); err != nil {
return nil, err
}
if _, err := f.Seek(0, 0); err != nil {
return nil, err
}
st, err := f.Stat()
if err != nil {
return nil, err
}
size := st.Size()
return &TempArchive{f, size}, nil
}
type TempArchive struct {
*os.File
Size int64 // Pre-computed from Stat().Size() as a convenience
}
func (archive *TempArchive) Read(data []byte) (int, error) {
n, err := archive.File.Read(data)
if err != nil {
os.Remove(archive.File.Name())
}
return n, err
}
+41 -16
View File
@@ -18,11 +18,10 @@ import (
"unicode"
)
const VERSION = "0.1.7"
const VERSION = "0.2.0"
var (
GIT_COMMIT string
NO_MEMORY_LIMIT bool
GIT_COMMIT string
)
func (srv *Server) Name() string {
@@ -184,10 +183,14 @@ func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string
// 'docker version': show version information
func (srv *Server) CmdVersion(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
fmt.Fprintf(stdout, "Version:%s\n", VERSION)
fmt.Fprintf(stdout, "Git Commit:%s\n", GIT_COMMIT)
if NO_MEMORY_LIMIT {
fmt.Fprintf(stdout, "Memory limit disabled\n")
fmt.Fprintf(stdout, "Version: %s\n", VERSION)
fmt.Fprintf(stdout, "Git Commit: %s\n", GIT_COMMIT)
fmt.Fprintf(stdout, "Kernel: %s\n", srv.runtime.kernelVersion)
if !srv.runtime.capabilities.MemoryLimit {
fmt.Fprintf(stdout, "WARNING: No memory limit support\n")
}
if !srv.runtime.capabilities.SwapLimit {
fmt.Fprintf(stdout, "WARNING: No swap limit support\n")
}
return nil
}
@@ -472,9 +475,9 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout rcli.DockerConn, args .
if err != nil {
return err
}
archive = ProgressReader(resp.Body, int(resp.ContentLength), stdout)
archive = ProgressReader(resp.Body, int(resp.ContentLength), stdout, "Importing %v/%v (%v)")
}
img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "")
img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil)
if err != nil {
return err
}
@@ -723,6 +726,8 @@ func (srv *Server) CmdCommit(stdin io.ReadCloser, stdout io.Writer, args ...stri
"Create a new image from a container's changes")
flComment := cmd.String("m", "", "Commit message")
flAuthor := cmd.String("author", "", "Author (eg. \"John Hannibal Smith <hannibal@a-team.com>\"")
flConfig := cmd.String("config", "", "Config automatically applied when the image is run. This option must be the last one.")
flCommand := cmd.String("command", "", "Command to run when starting the image")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -731,7 +736,22 @@ func (srv *Server) CmdCommit(stdin io.ReadCloser, stdout io.Writer, args ...stri
cmd.Usage()
return nil
}
img, err := srv.runtime.Commit(containerName, repository, tag, *flComment, *flAuthor)
var config []string
if *flConfig != "" {
config = strings.Split(*flConfig, " ")
}
if *flCommand != "" {
config = append(config, "", "/bin/sh", "-c", *flCommand)
} else if *flConfig != "" {
config = append(config, "", "")
}
c, err := ParseRun(config, stdout, srv.runtime.capabilities)
if err != nil {
return err
}
img, err := srv.runtime.Commit(containerName, repository, tag, *flComment, *flAuthor, c)
if err != nil {
return err
}
@@ -833,6 +853,10 @@ func (srv *Server) CmdAttach(stdin io.ReadCloser, stdout rcli.DockerConn, args .
return fmt.Errorf("No such container: %s", name)
}
if container.State.Ghost {
return fmt.Errorf("Impossible to attach to a ghost container")
}
if container.Config.Tty {
stdout.SetOptionRawTerminal()
}
@@ -910,7 +934,7 @@ func (srv *Server) CmdTag(stdin io.ReadCloser, stdout io.Writer, args ...string)
}
func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...string) error {
config, err := ParseRun(args, stdout)
config, err := ParseRun(args, stdout, srv.runtime.capabilities)
if err != nil {
return err
}
@@ -918,10 +942,6 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s
fmt.Fprintln(stdout, "Error: Image not specified")
return fmt.Errorf("Image not specified")
}
if len(config.Cmd) == 0 {
fmt.Fprintln(stdout, "Error: Command not specified")
return fmt.Errorf("Command not specified")
}
if config.Tty {
stdout.SetOptionRawTerminal()
@@ -976,8 +996,13 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s
}
Debugf("Waiting for attach to return\n")
<-attachErr
container.Wait()
// Expecting I/O pipe error, discarding
// If we are in stdinonce mode, wait for the process to end
// otherwise, simply return
if config.StdinOnce && !config.Tty {
container.Wait()
}
return nil
}
+15 -2
View File
@@ -228,6 +228,21 @@ func TestRunDisconnectTty(t *testing.T) {
close(c1)
}()
setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() {
for {
// Client disconnect after run -i should keep stdin out in TTY mode
l := runtime.List()
if len(l) == 1 && l[0].State.Running {
break
}
time.Sleep(10 * time.Millisecond)
}
})
// Client disconnect after run -i should keep stdin out in TTY mode
container := runtime.List()[0]
setTimeout(t, "Read/Write assertion timed out", 2*time.Second, func() {
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
t.Fatal(err)
@@ -242,8 +257,6 @@ func TestRunDisconnectTty(t *testing.T) {
// In tty mode, we expect the process to stay alive even after client's stdin closes.
// Do not wait for run to finish
// Client disconnect after run -i should keep stdin out in TTY mode
container := runtime.List()[0]
// Give some time to monitor to do his thing
container.WaitTimeout(500 * time.Millisecond)
if !container.State.Running {
+50 -16
View File
@@ -68,7 +68,7 @@ type Config struct {
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
}
func ParseRun(args []string, stdout io.Writer) (*Config, error) {
func ParseRun(args []string, stdout io.Writer, capabilities *Capabilities) (*Config, error) {
cmd := rcli.Subcmd(stdout, "run", "[OPTIONS] IMAGE COMMAND [ARG...]", "Run a command in a new container")
if len(args) > 0 && args[0] != "--help" {
cmd.SetOutput(ioutil.Discard)
@@ -83,8 +83,8 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
flTty := cmd.Bool("t", false, "Allocate a pseudo-tty")
flMemory := cmd.Int64("m", 0, "Memory limit (in bytes)")
if *flMemory > 0 && NO_MEMORY_LIMIT {
fmt.Fprintf(stdout, "WARNING: This version of docker has been compiled without memory limit support. Discarding -m.")
if *flMemory > 0 && !capabilities.MemoryLimit {
fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
*flMemory = 0
}
@@ -137,6 +137,12 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
Dns: flDns,
Image: image,
}
if *flMemory > 0 && !capabilities.SwapLimit {
fmt.Fprintf(stdout, "WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
config.MemorySwap = -1
}
// When allocating stdin in attached mode, close stdin at client disconnect
if config.OpenStdin && config.AttachStdin {
config.StdinOnce = true
@@ -379,10 +385,15 @@ func (container *Container) Start() error {
return err
}
if container.Config.Memory > 0 && NO_MEMORY_LIMIT {
log.Printf("WARNING: This version of docker has been compiled without memory limit support. Discarding the limit.")
// Make sure the config is compatible with the current kernel
if container.Config.Memory > 0 && !container.runtime.capabilities.MemoryLimit {
log.Printf("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
container.Config.Memory = 0
}
if container.Config.Memory > 0 && !container.runtime.capabilities.SwapLimit {
log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
container.Config.MemorySwap = -1
}
if err := container.generateLXCConfig(); err != nil {
return err
@@ -519,16 +530,42 @@ func (container *Container) releaseNetwork() {
container.NetworkSettings = &NetworkSettings{}
}
// FIXME: replace this with a control socket within docker-init
func (container *Container) waitLxc() error {
for {
if output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput(); err != nil {
return err
} else {
if !strings.Contains(string(output), "RUNNING") {
return nil
}
}
time.Sleep(500 * time.Millisecond)
}
return nil
}
func (container *Container) monitor() {
// Wait for the program to exit
Debugf("Waiting for process")
if err := container.cmd.Wait(); err != nil {
// Discard the error as any signals or non 0 returns will generate an error
Debugf("%s: Process: %s", container.Id, err)
// If the command does not exists, try to wait via lxc
if container.cmd == nil {
if err := container.waitLxc(); err != nil {
Debugf("%s: Process: %s", container.Id, err)
}
} else {
if err := container.cmd.Wait(); err != nil {
// Discard the error as any signals or non 0 returns will generate an error
Debugf("%s: Process: %s", container.Id, err)
}
}
Debugf("Process finished")
exitCode := container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
var exitCode int = -1
if container.cmd != nil {
exitCode = container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
}
// Cleanup
container.releaseNetwork()
@@ -577,7 +614,7 @@ func (container *Container) monitor() {
}
func (container *Container) kill() error {
if !container.State.Running || container.cmd == nil {
if !container.State.Running {
return nil
}
@@ -589,6 +626,9 @@ func (container *Container) kill() error {
// 2. Wait for the process to die, in last resort, try to kill the process directly
if err := container.WaitTimeout(10 * time.Second); err != nil {
if container.cmd == nil {
return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", container.Id)
}
log.Printf("Container %s failed to exit within 10 seconds of lxc SIGKILL - trying direct SIGKILL", container.Id)
if err := container.cmd.Process.Kill(); err != nil {
return err
@@ -606,9 +646,6 @@ func (container *Container) Kill() error {
if !container.State.Running {
return nil
}
if container.State.Ghost {
return fmt.Errorf("Can't kill ghost container")
}
return container.kill()
}
@@ -618,9 +655,6 @@ func (container *Container) Stop(seconds int) error {
if !container.State.Running {
return nil
}
if container.State.Ghost {
return fmt.Errorf("Can't stop ghot container")
}
// 1. Send a SIGTERM
if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil {
+155 -1
View File
@@ -150,6 +150,160 @@ func TestMultipleAttachRestart(t *testing.T) {
}
}
func TestDiff(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
// Create a container and remove a file
container1, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).Id,
Cmd: []string{"/bin/rm", "/etc/passwd"},
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container1)
if err := container1.Run(); err != nil {
t.Fatal(err)
}
// Check the changelog
c, err := container1.Changes()
if err != nil {
t.Fatal(err)
}
success := false
for _, elem := range c {
if elem.Path == "/etc/passwd" && elem.Kind == 2 {
success = true
}
}
if !success {
t.Fatalf("/etc/passwd as been removed but is not present in the diff")
}
// Commit the container
rwTar, err := container1.ExportRw()
if err != nil {
t.Error(err)
}
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image - diff", "", nil)
if err != nil {
t.Error(err)
}
// Create a new container from the commited image
container2, err := runtime.Create(
&Config{
Image: img.Id,
Cmd: []string{"cat", "/etc/passwd"},
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container2)
if err := container2.Run(); err != nil {
t.Fatal(err)
}
// Check the changelog
c, err = container2.Changes()
if err != nil {
t.Fatal(err)
}
for _, elem := range c {
if elem.Path == "/etc/passwd" {
t.Fatalf("/etc/passwd should not be present in the diff after commit.")
}
}
}
func TestCommitAutoRun(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
container1, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).Id,
Cmd: []string{"/bin/sh", "-c", "echo hello > /world"},
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container1)
if container1.State.Running {
t.Errorf("Container shouldn't be running")
}
if err := container1.Run(); err != nil {
t.Fatal(err)
}
if container1.State.Running {
t.Errorf("Container shouldn't be running")
}
rwTar, err := container1.ExportRw()
if err != nil {
t.Error(err)
}
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "", &Config{Cmd: []string{"cat", "/world"}})
if err != nil {
t.Error(err)
}
// FIXME: Make a TestCommit that stops here and check docker.root/layers/img.id/world
container2, err := runtime.Create(
&Config{
Image: img.Id,
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container2)
stdout, err := container2.StdoutPipe()
if err != nil {
t.Fatal(err)
}
stderr, err := container2.StderrPipe()
if err != nil {
t.Fatal(err)
}
if err := container2.Start(); err != nil {
t.Fatal(err)
}
container2.Wait()
output, err := ioutil.ReadAll(stdout)
if err != nil {
t.Fatal(err)
}
output2, err := ioutil.ReadAll(stderr)
if err != nil {
t.Fatal(err)
}
if err := stdout.Close(); err != nil {
t.Fatal(err)
}
if err := stderr.Close(); err != nil {
t.Fatal(err)
}
if string(output) != "hello\n" {
t.Fatalf("Unexpected output. Expected %s, received: %s (err: %s)", "hello\n", output, output2)
}
}
func TestCommitRun(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
@@ -182,7 +336,7 @@ func TestCommitRun(t *testing.T) {
if err != nil {
t.Error(err)
}
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "")
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "", nil)
if err != nil {
t.Error(err)
}
+10 -8
View File
@@ -7,15 +7,16 @@ import (
"github.com/dotcloud/docker/rcli"
"github.com/dotcloud/docker/term"
"io"
"io/ioutil"
"log"
"os"
"os/signal"
"strconv"
"syscall"
)
var (
GIT_COMMIT string
NO_MEMORY_LIMIT string
GIT_COMMIT string
)
func main() {
@@ -39,15 +40,11 @@ func main() {
os.Setenv("DEBUG", "1")
}
docker.GIT_COMMIT = GIT_COMMIT
docker.NO_MEMORY_LIMIT = NO_MEMORY_LIMIT == "1"
if *flDaemon {
if flag.NArg() != 0 {
flag.Usage()
return
}
if NO_MEMORY_LIMIT == "1" {
log.Printf("WARNING: This version of docker has been compiled without memory limit support.")
}
if err := daemon(*pidfile); err != nil {
log.Fatal(err)
}
@@ -59,8 +56,13 @@ func main() {
}
func createPidFile(pidfile string) error {
if _, err := os.Stat(pidfile); err == nil {
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
pid, err := strconv.Atoi(string(pidString))
if err == nil {
if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil {
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
}
}
}
file, err := os.Create(pidfile)
+1
View File
@@ -51,6 +51,7 @@ docs:
cp sources/dotcloud.yml $(BUILDDIR)/html/
cp sources/CNAME $(BUILDDIR)/html/
cp sources/.nojekyll $(BUILDDIR)/html/
cp sources/nginx.conf $(BUILDDIR)/html/
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+1 -1
View File
@@ -10,7 +10,7 @@ Building blocks
Images
------
An original container image. These are stored on disk and are comparable with what you normally expect from a stoppped virtual machine image. Images are stored (and retrieved from) repository
An original container image. These are stored on disk and are comparable with what you normally expect from a stopped virtual machine image. Images are stored (and retrieved from) repository
Images are stored on your local file system under /var/lib/docker/images
+1 -1
View File
@@ -49,7 +49,7 @@ Save the changed we just made in the container to a new image called "_/builds/g
WEB_WORKER=$(docker run -d -p 5000 $BUILD_IMG /usr/local/bin/runapp)
- **"docker run -d "** run a command in a new container. We pass "-d" so it runs as a daemon.
**"-p 5000"* the web app is going to listen on this port, so it must be mapped from the container to the host system.
- **"-p 5000"** the web app is going to listen on this port, so it must be mapped from the container to the host system.
- **"$BUILD_IMG"** is the image we want to run the command inside of.
- **/usr/local/bin/runapp** is the command which starts the web app.
+25 -19
View File
@@ -71,34 +71,40 @@
<h2>
<a name="installing-on-ubuntu-1204-and-1210" class="anchor" href="#installing-on-ubuntu-1204-and-1210"><span class="mini-icon mini-icon-link"></span>
</a>Installing on Ubuntu</h2>
<p><strong>Requirements</strong></p>
<ul>
<li>Ubuntu 12.04 (LTS) (64-bit)</li>
<li> or Ubuntu 12.10 (quantal) (64-bit)</li>
</ul>
<ol>
<li>
<p>Install dependencies:</p>
<p><strong>Install dependencies</strong></p>
The linux-image-extra package is only needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module.
<pre>sudo apt-get install linux-image-extra-`uname -r`</pre>
<div class="highlight">
<pre>sudo apt-get install lxc wget bsdtar curl</pre>
<pre>sudo apt-get install linux-image-extra-<span class="sb">`</span>uname -r<span class="sb">`</span></pre></div>
<p>The <code>linux-image-extra</code> package is needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module.</p>
</li>
<li>
<p>Install the latest docker binary:</p>
<p><strong>Install Docker</strong></p>
<p>Add the Ubuntu PPA (Personal Package Archive) sources to your apt sources list, update and install.</p>
<p>You may see some warnings that the GPG keys cannot be verified.</p>
<div class="highlight">
<pre>sudo sh -c "echo 'deb http://ppa.launchpad.net/dotcloud/lxc-docker/ubuntu precise main' >> /etc/apt/sources.list"</pre>
<pre>sudo apt-get update</pre>
<pre>sudo apt-get install lxc-docker</pre>
</div>
</li>
<li>
<p><strong>Run!</strong></p>
<div class="highlight">
<pre>wget http://get.docker.io/builds/<span class="k">$(</span>uname -s<span class="k">)</span>/<span class="k">$(</span>uname -m<span class="k">)</span>/docker-master.tgz</pre>
<pre>tar -xf docker-master.tgz</pre>
<pre>docker run -i -t ubuntu /bin/bash</pre>
</div>
</li>
<li>
<p>Run your first container!</p>
<div class="highlight"><pre><span class="nb">cd </span>docker-master</pre>
<pre>sudo ./docker run -i -t base /bin/bash</pre>
</div>
<p>Done!</p>
<p>Consider adding docker to your <code>PATH</code> for simplicity.</p>
</li>
Continue with the <a href="http://docs.docker.io/en/latest/examples/hello_world/">Hello world</a> example.
</ol>
</section>
@@ -117,7 +123,7 @@
vagrant and an Ubuntu virtual machine.</strong></p>
<ul>
<li><a href="http://docs.docker.io/en/latest/installation/macos/">Mac OS X and other linuxes</a></li>
<li><a href="http://docs.docker.io/en/latest/installation/vagrant/">Mac OS X and other linuxes</a></li>
<li><a href="http://docs.docker.io/en/latest/installation/windows/">Windows</a></li>
</ul>
+4 -3
View File
@@ -1,8 +1,9 @@
Amazon EC2
==========
Please note this is a community contributed installation path. The only 'official' installation is using the :ref:`ubuntu_linux` installation path. This version
may be out of date because it depends on some binaries to be updated and published
Please note this is a community contributed installation path. The only 'official' installation is using the
:ref:`ubuntu_linux` installation path. This version may sometimes be out of date.
Installation
------------
@@ -17,7 +18,7 @@ Docker can now be installed on Amazon EC2 with a single vagrant command. Vagrant
vagrant plugin install vagrant-aws
3. Get the docker sources, this will give you the latest Vagrantfile and puppet manifests.
3. Get the docker sources, this will give you the latest Vagrantfile.
::
+28 -6
View File
@@ -3,19 +3,23 @@
Arch Linux
==========
Please note this is a community contributed installation path. The only 'official' installation is using the
:ref:`ubuntu_linux` installation path. This version may sometimes be out of date.
Installing on Arch Linux is not officially supported but can be handled via
either of the following AUR packages:
* `dotcloud-docker <https://aur.archlinux.org/packages/dotcloud-docker/>`_
* `dotcloud-docker-git <https://aur.archlinux.org/packages/dotcloud-docker-git/>`_
* `lxc-docker <https://aur.archlinux.org/packages/lxc-docker/>`_
* `lxc-docker-git <https://aur.archlinux.org/packages/lxc-docker-git/>`_
The dotcloud-docker package will install the latest tagged version of docker.
The dotcloud-docker-git package will build from the current master branch.
The lxc-docker package will install the latest tagged version of docker.
The lxc-docker-git package will build from the current master branch.
Dependencies
------------
Docker depends on several packages which will be installed automatically with
Docker depends on several packages which are specified as dependencies in
either AUR package.
* aufs3
@@ -23,6 +27,7 @@ either AUR package.
* go
* iproute2
* linux-aufs_friendly
* lxc
Installation
------------
@@ -37,7 +42,24 @@ new kernel will be compiled and this can take quite a while.
::
yaourt -S dotcloud-docker-git
yaourt -S lxc-docker-git
Starting Docker
---------------
Prior to starting docker modify your bootloader to use the
**linux-aufs_friendly** kernel and reboot your system.
There is a systemd service unit created for docker. To start the docker service:
::
sudo systemctl start docker
To start on system boot:
::
sudo systemctl enable docker
+53
View File
@@ -0,0 +1,53 @@
.. _binaries:
Binaries
========
**Please note this project is currently under heavy development. It should not be used in production.**
Right now, the officially supported distributions are:
- Ubuntu 12.04 (precise LTS) (64-bit)
- Ubuntu 12.10 (quantal) (64-bit)
Install dependencies:
---------------------
::
sudo apt-get install lxc bsdtar
sudo apt-get install linux-image-extra-`uname -r`
The linux-image-extra package is needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module.
Install the docker binary:
::
wget http://get.docker.io/builds/Linux/x86_64/docker-master.tgz
tar -xf docker-master.tgz
sudo cp ./docker-master /usr/local/bin
Note: docker currently only supports 64-bit Linux hosts.
Run the docker daemon
---------------------
::
sudo docker -d &
Run your first container!
-------------------------
::
docker run -i -t ubuntu /bin/bash
Continue with the :ref:`hello_world` example.
+2 -1
View File
@@ -13,8 +13,9 @@ Contents:
:maxdepth: 1
ubuntulinux
binaries
archlinux
macos
vagrant
windows
amazon
upgrading
-66
View File
@@ -1,66 +0,0 @@
Mac OS X and other linux
========================
Please note this is a community contributed installation path. The only 'official' installation is using the :ref:`ubuntu_linux` installation path. This version
may be out of date because it depends on some binaries to be updated and published
Requirements
------------
We currently rely on some Ubuntu-linux specific packages, this will change in the future, but for now we provide a
streamlined path to install Virtualbox with a Ubuntu 12.10 image using Vagrant.
1. Install virtualbox from https://www.virtualbox.org/ (or use your package manager)
2. Install vagrant from http://www.vagrantup.com/ (or use your package manager)
3. Install git if you had not installed it before, check if it is installed by running
``git`` in a terminal window
We recommend having at least about 2Gb of free disk space and 2Gb RAM (or more).
Installation
------------
1. Fetch the docker sources
.. code-block:: bash
git clone https://github.com/dotcloud/docker.git
2. Run vagrant from the sources directory
.. code-block:: bash
vagrant up
Vagrant will:
* Download the Quantal64 base ubuntu virtual machine image from get.docker.io/
* Boot this image in virtualbox
Then it will use Puppet to perform an initial setup in this machine:
* Download & untar the most recent docker binary tarball to vagrant homedir.
* Debootstrap to /var/lib/docker/images/ubuntu.
* Install & run dockerd as service.
* Put docker in /usr/local/bin.
* Put latest Go toolchain in /usr/local/go.
You now have a Ubuntu Virtual Machine running with docker pre-installed.
To access the VM and use Docker, Run ``vagrant ssh`` from the same directory as where you ran
``vagrant up``. Vagrant will make sure to connect you to the correct VM.
.. code-block:: bash
vagrant ssh
Now you are in the VM, run docker
.. code-block:: bash
docker
Continue with the :ref:`hello_world` example.
+41 -36
View File
@@ -6,51 +6,56 @@ Ubuntu Linux
**Please note this project is currently under heavy development. It should not be used in production.**
Installing on Ubuntu 12.04 and 12.10
Right now, the officially supported distributions are:
* Ubuntu 12.04 (precise LTS)
* Ubuntu 12.10 (quantal)
- Ubuntu 12.04 (precise LTS) (64-bit)
- Ubuntu 12.10 (quantal) (64-bit)
Install dependencies:
---------------------
Dependencies
------------
::
The linux-image-extra package is only needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module.
sudo apt-get install lxc bsdtar
sudo apt-get install linux-image-extra-`uname -r`
.. code-block:: bash
The linux-image-extra package is needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module.
Install the docker binary
-------------------------
::
wget http://get.docker.io/builds/Linux/x86_64/docker-master.tgz
tar -xf docker-master.tgz
sudo cp ./docker-master /usr/local/bin
Note: docker currently only supports 64-bit Linux hosts.
sudo apt-get install linux-image-extra-`uname -r`
Run the docker daemon
---------------------
Installation
------------
::
sudo docker -d &
Run your first container!
-------------------------
::
docker run -i -t ubuntu /bin/bash
Docker is available as a Ubuntu PPA (Personal Package Archive),
`hosted on launchpad <https://launchpad.net/~dotcloud/+archive/lxc-docker>`_
which makes installing Docker on Ubuntu very easy.
Check out more examples
-----------------------
Continue with the :ref:`hello_world` example.
Add the custom package sources to your apt sources list. Copy and paste the following lines at once.
.. code-block:: bash
sudo sh -c "echo 'deb http://ppa.launchpad.net/dotcloud/lxc-docker/ubuntu precise main' >> /etc/apt/sources.list"
Update your sources. You will see a warning that GPG signatures cannot be verified.
.. code-block:: bash
sudo apt-get update
Now install it, you will see another warning that the package cannot be authenticated. Confirm install.
.. code-block:: bash
sudo apt-get install lxc-docker
Verify it worked
.. code-block:: bash
docker
**Done!**, now continue with the :ref:`hello_world` example.
+2 -1
View File
@@ -3,7 +3,8 @@
Upgrading
============
We assume you are upgrading from within the operating system which runs your docker daemon.
These instructions are for upgrading your Docker binary for when you had a custom (non package manager) installation.
If you istalled docker using apt-get, use that to upgrade.
Get the latest docker binary:
+70
View File
@@ -0,0 +1,70 @@
.. _install_using_vagrant:
Using Vagrant
=============
Please note this is a community contributed installation path. The only 'official' installation is using the
:ref:`ubuntu_linux` installation path. This version may sometimes be out of date.
**Requirements:**
This guide will setup a new virtual machine with docker installed on your computer. This works on most operating
systems, including MacOX, Windows, Linux, FreeBSD and others. If you can install these and have at least 400Mb RAM
to spare you should be good.
Install Vagrant and Virtualbox
------------------------------
1. Install virtualbox from https://www.virtualbox.org/ (or use your package manager)
2. Install vagrant from http://www.vagrantup.com/ (or use your package manager)
3. Install git if you had not installed it before, check if it is installed by running
``git`` in a terminal window
Spin it up
----------
1. Fetch the docker sources (this includes the Vagrantfile for machine setup).
.. code-block:: bash
git clone https://github.com/dotcloud/docker.git
2. Run vagrant from the sources directory
.. code-block:: bash
vagrant up
Vagrant will:
* Download the 'official' Precise64 base ubuntu virtual machine image from vagrantup.com
* Boot this image in virtualbox
* Add the `Docker PPA sources <https://launchpad.net/~dotcloud/+archive/lxc-docker>`_ to /etc/apt/sources.lst
* Update your sources
* Install lxc-docker
You now have a Ubuntu Virtual Machine running with docker pre-installed.
Connect
-------
To access the VM and use Docker, Run ``vagrant ssh`` from the same directory as where you ran
``vagrant up``. Vagrant will connect you to the correct VM.
.. code-block:: bash
vagrant ssh
Run
-----
Now you are in the VM, run docker
.. code-block:: bash
docker
Continue with the :ref:`hello_world` example.
+2 -2
View File
@@ -3,8 +3,8 @@
:keywords: Docker, Docker documentation, Windows, requirements, virtualbox, vagrant, git, ssh, putty, cygwin
Windows
=========
Windows (with Vagrant)
======================
Please note this is a community contributed installation path. The only 'official' installation is using the :ref:`ubuntu_linux` installation path. This version
may be out of date because it depends on some binaries to be updated and published
+6
View File
@@ -0,0 +1,6 @@
# rule to redirect original links created when hosted on github pages
rewrite ^/documentation/(.*).html http://docs.docker.io/en/latest/$1/ permanent;
# rewrite the stuff which was on the current page
rewrite ^/gettingstarted.html$ /gettingstarted/ permanent;
+9
View File
@@ -0,0 +1,9 @@
package docker
import (
"fmt"
)
func getKernelVersion() (*KernelVersionInfo, error) {
return nil, fmt.Errorf("Kernel version detection is not available on darwin")
}
+69
View File
@@ -0,0 +1,69 @@
package docker
import (
"bytes"
"strconv"
"strings"
"syscall"
)
func getKernelVersion() (*KernelVersionInfo, error) {
var (
uts syscall.Utsname
flavor string
kernel, major, minor int
err error
)
if err := syscall.Uname(&uts); err != nil {
return nil, err
}
release := make([]byte, len(uts.Release))
i := 0
for _, c := range uts.Release {
release[i] = byte(c)
i++
}
// Remove the \x00 from the release for Atoi to parse correctly
release = release[:bytes.IndexByte(release, 0)]
tmp := strings.SplitN(string(release), "-", 2)
tmp2 := strings.SplitN(tmp[0], ".", 3)
if len(tmp2) > 0 {
kernel, err = strconv.Atoi(tmp2[0])
if err != nil {
return nil, err
}
}
if len(tmp2) > 1 {
major, err = strconv.Atoi(tmp2[1])
if err != nil {
return nil, err
}
}
if len(tmp2) > 2 {
minor, err = strconv.Atoi(tmp2[2])
if err != nil {
return nil, err
}
}
if len(tmp) == 2 {
flavor = tmp[1]
} else {
flavor = ""
}
return &KernelVersionInfo{
Kernel: kernel,
Major: major,
Minor: minor,
Flavor: flavor,
}, nil
}
+28 -2
View File
@@ -2,6 +2,7 @@ package docker
import (
"fmt"
"io"
"io/ioutil"
"os"
"path"
@@ -83,13 +84,14 @@ func (graph *Graph) Get(name string) (*Image, error) {
}
// Create creates a new image and registers it in the graph.
func (graph *Graph) Create(layerData Archive, container *Container, comment, author string) (*Image, error) {
func (graph *Graph) Create(layerData Archive, container *Container, comment, author string, config *Config) (*Image, error) {
img := &Image{
Id: GenerateId(),
Comment: comment,
Created: time.Now(),
DockerVersion: VERSION,
Author: author,
Config: config,
}
if container != nil {
img.Parent = container.Image
@@ -129,12 +131,32 @@ func (graph *Graph) Register(layerData Archive, img *Image) error {
return nil
}
// TempLayerArchive creates a temporary archive of the given image's filesystem layer.
// The archive is stored on disk and will be automatically deleted as soon as has been read.
// If output is not nil, a human-readable progress bar will be written to it.
// FIXME: does this belong in Graph? How about MktempFile, let the caller use it for archives?
func (graph *Graph) TempLayerArchive(id string, compression Compression, output io.Writer) (*TempArchive, error) {
image, err := graph.Get(id)
if err != nil {
return nil, err
}
tmp, err := graph.tmp()
if err != nil {
return nil, err
}
archive, err := image.TarLayer(compression)
if err != nil {
return nil, err
}
return NewTempArchive(ProgressReader(ioutil.NopCloser(archive), 0, output, "Buffering to disk %v/%v (%v)"), tmp.Root)
}
// Mktemp creates a temporary sub-directory inside the graph's filesystem.
func (graph *Graph) Mktemp(id string) (string, error) {
if id == "" {
id = GenerateId()
}
tmp, err := NewGraph(path.Join(graph.Root, ":tmp:"))
tmp, err := graph.tmp()
if err != nil {
return "", fmt.Errorf("Couldn't create temp: %s", err)
}
@@ -144,6 +166,10 @@ func (graph *Graph) Mktemp(id string) (string, error) {
return tmp.imageRoot(id), nil
}
func (graph *Graph) tmp() (*Graph, error) {
return NewGraph(path.Join(graph.Root, ":tmp:"))
}
// Check if given error is "not empty".
// Note: this is the way golang does it internally with os.IsNotExists.
func isNotEmpty(err error) bool {
+6 -6
View File
@@ -62,7 +62,7 @@ func TestGraphCreate(t *testing.T) {
if err != nil {
t.Fatal(err)
}
image, err := graph.Create(archive, nil, "Testing", "")
image, err := graph.Create(archive, nil, "Testing", "", nil)
if err != nil {
t.Fatal(err)
}
@@ -122,7 +122,7 @@ func TestMount(t *testing.T) {
if err != nil {
t.Fatal(err)
}
image, err := graph.Create(archive, nil, "Testing", "")
image, err := graph.Create(archive, nil, "Testing", "", nil)
if err != nil {
t.Fatal(err)
}
@@ -166,7 +166,7 @@ func createTestImage(graph *Graph, t *testing.T) *Image {
if err != nil {
t.Fatal(err)
}
img, err := graph.Create(archive, nil, "Test image", "")
img, err := graph.Create(archive, nil, "Test image", "", nil)
if err != nil {
t.Fatal(err)
}
@@ -181,7 +181,7 @@ func TestDelete(t *testing.T) {
t.Fatal(err)
}
assertNImages(graph, t, 0)
img, err := graph.Create(archive, nil, "Bla bla", "")
img, err := graph.Create(archive, nil, "Bla bla", "", nil)
if err != nil {
t.Fatal(err)
}
@@ -192,11 +192,11 @@ func TestDelete(t *testing.T) {
assertNImages(graph, t, 0)
// Test 2 create (same name) / 1 delete
img1, err := graph.Create(archive, nil, "Testing", "")
img1, err := graph.Create(archive, nil, "Testing", "", nil)
if err != nil {
t.Fatal(err)
}
if _, err = graph.Create(archive, nil, "Testing", ""); err != nil {
if _, err = graph.Create(archive, nil, "Testing", "", nil); err != nil {
t.Fatal(err)
}
assertNImages(graph, t, 2)
+17
View File
@@ -0,0 +1,17 @@
# This will build a container capable of producing an official binary build of docker and
# uploading it to S3
from ubuntu:12.10
run apt-get update
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q s3cmd
# Packages required to checkout and build docker
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q build-essential
# Packages required to build an ubuntu package
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q debhelper
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q autotools-dev
copy fake_initctl /usr/local/bin/initctl
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q devscripts
copy dockerbuilder /usr/local/bin/dockerbuilder
copy s3cfg /.s3cfg
# run $img dockerbuilder $REVISION_OR_TAG $S3_ID $S3_KEY
+53
View File
@@ -0,0 +1,53 @@
#!/bin/sh
set -x
set -e
PACKAGE=github.com/dotcloud/docker
if [ $# -gt 1 ]; then
echo "Usage: $0 [REVISION]"
exit 1
fi
export REVISION=$1
if [ -z "$AWS_ID" ]; then
echo "Warning: environment variable AWS_ID is not set. Won't upload to S3."
NO_S3=1
fi
if [ -z "$AWS_KEY" ]; then
echo "Warning: environment variable AWS_KEY is not set. Won't upload to S3."
NO_S3=1
fi
if [ -z "$GPG_KEY" ]; then
echo "Warning: environment variable GPG_KEY is not set. Ubuntu package upload will not succeed."
NO_UBUNTU=1
fi
if [ -z "$REVISION" ]; then
rm -fr docker-master
git clone https://github.com/dotcloud/docker docker-master
cd docker-master
else
rm -fr docker-$REVISION
git init docker-$REVISION
cd docker-$REVISION
git fetch -t https://github.com/dotcloud/docker $REVISION
git reset --hard FETCH_HEAD
fi
if [ -z "$REVISION" ]; then
make release
else
make release RELEASE_VERSION=$REVISION
fi
if [ -z "$NO_S3" ]; then
s3cmd -P put docker-$REVISION.tgz s3://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-$REVISION.tgz
fi
if [ -z "$NO_UBUNTU" ]; then
(cd packaging/ubuntu && make ubuntu)
fi
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
echo Whatever you say, man
+3
View File
@@ -0,0 +1,3 @@
[default]
access_key = $AWS_ID
secret_key = $AWS_KEY
+11 -26
View File
@@ -24,6 +24,7 @@ type Image struct {
ContainerConfig Config `json:"container_config,omitempty"`
DockerVersion string `json:"docker_version,omitempty"`
Author string `json:"author,omitempty"`
Config *Config `json:"config,omitempty"`
graph *Graph
}
@@ -92,7 +93,7 @@ func MountAUFS(ro []string, rw string, target string) error {
rwBranch := fmt.Sprintf("%v=rw", rw)
roBranches := ""
for _, layer := range ro {
roBranches += fmt.Sprintf("%v=ro:", layer)
roBranches += fmt.Sprintf("%v=ro+wh:", layer)
}
branches := fmt.Sprintf("br:%v:%v", rwBranch, roBranches)
@@ -110,6 +111,15 @@ func MountAUFS(ro []string, rw string, target string) error {
return nil
}
// TarLayer returns a tar archive of the image's filesystem layer.
func (image *Image) TarLayer(compression Compression) (Archive, error) {
layerPath, err := image.layer()
if err != nil {
return nil, err
}
return Tar(layerPath, compression)
}
func (image *Image) Mount(root, rw string) error {
if mounted, err := Mounted(root); err != nil {
return err
@@ -127,34 +137,9 @@ func (image *Image) Mount(root, rw string) error {
if err := os.Mkdir(rw, 0755); err != nil && !os.IsExist(err) {
return err
}
// FIXME: @creack shouldn't we do this after going over changes?
if err := MountAUFS(layers, rw, root); err != nil {
return err
}
// FIXME: Create tests for deletion
// FIXME: move this part to change.go
// Retrieve the changeset from the parent and apply it to the container
// - Retrieve the changes
changes, err := Changes(layers, layers[0])
if err != nil {
return err
}
// Iterate on changes
for _, c := range changes {
// If there is a delete
if c.Kind == ChangeDelete {
// Make sure the directory exists
file_path, file_name := path.Dir(c.Path), path.Base(c.Path)
if err := os.MkdirAll(path.Join(rw, file_path), 0755); err != nil {
return err
}
// And create the whiteout (we just need to create empty file, discard the return)
if _, err := os.Create(path.Join(path.Join(rw, file_path),
".wh."+path.Base(file_name))); err != nil {
return err
}
}
}
return nil
}
+25
View File
@@ -0,0 +1,25 @@
Docker on Arch
==============
The AUR lxc-docker and lxc-docker-git packages handle building docker on Arch
linux. The PKGBUILD specifies all dependencies, build, and packaging steps.
Dependencies
============
The only buildtime dependencies are git and go which are available via pacman.
The -s flag can be used on makepkg commands below to automatically install
these dependencies.
Building Package
================
Download the tarball for either AUR packaged to a local directory. In that
directory makepkg can be run to build the package.
# Build the binary package
makepkg
# Build an updated source tarball
makepkg --source
+106 -14
View File
@@ -1,30 +1,122 @@
lxc-docker (0.2.0-1) precise; urgency=low
- Runtime: ghost containers can be killed and waited for
- Documentation: update install intructions
- Packaging: fix Vagrantfile
- Development: automate releasing binaries and ubuntu packages
- Add a changelog
- Various bugfixes
-- dotCloud <ops@dotcloud.com> Mon, 23 Apr 2013 00:00:00 -0700
lxc-docker (0.1.8-1) precise; urgency=low
- Dynamically detect cgroup capabilities
- Issue stability warning on kernels <3.8
- 'docker push' buffers on disk instead of memory
- Fix 'docker diff' for removed files
- Fix 'docker stop' for ghost containers
- Fix handling of pidfile
- Various bugfixes and stability improvements
-- dotCloud <ops@dotcloud.com> Mon, 22 Apr 2013 00:00:00 -0700
lxc-docker (0.1.7-1) precise; urgency=low
- Container ports are available on localhost
- 'docker ps' shows allocated TCP ports
- Contributors can run 'make hack' to start a continuous integration VM
- Streamline ubuntu packaging & uploading
- Various bugfixes and stability improvements
-- dotCloud <ops@dotcloud.com> Thu, 18 Apr 2013 00:00:00 -0700
lxc-docker (0.1.6-1) precise; urgency=low
Improvements [+], Updates [*], Bug fixes [-]:
+ Multiple improvements, updates and bug fixes
- Record the author an image with 'docker commit -author'
-- dotCloud <ops@dotcloud.com> Wed, 17 Apr 2013 20:43:43 -0700
-- dotCloud <ops@dotcloud.com> Wed, 17 Apr 2013 00:00:00 -0700
lxc-docker (0.1.4.1-1) precise; urgency=low
lxc-docker (0.1.5-1) precise; urgency=low
Improvements [+], Updates [*], Bug fixes [-]:
* Test PPA
- Disable standalone mode
- Use a custom DNS resolver with 'docker -d -dns'
- Detect ghost containers
- Improve diagnosis of missing system capabilities
- Allow disabling memory limits at compile time
- Add debian packaging
- Documentation: installing on Arch Linux
- Documentation: running Redis on docker
- Fixed lxc 0.9 compatibility
- Automatically load aufs module
- Various bugfixes and stability improvements
-- dotCloud <ops@dotcloud.com> Mon, 15 Apr 2013 12:14:50 -0700
-- dotCloud <ops@dotcloud.com> Wed, 17 Apr 2013 00:00:00 -0700
lxc-docker (0.1.4-1) precise; urgency=low
Improvements [+], Updates [*], Bug fixes [-]:
* Changed default bridge interface do 'docker0'
- Fix a race condition when running the port allocator
- Full support for TTY emulation
- Detach from a TTY session with the escape sequence `C-p C-q`
- Various bugfixes and stability improvements
- Minor UI improvements
- Automatically create our own bridge interface 'docker0'
-- dotCloud <ops@dotcloud.com> Fri, 12 Apr 2013 12:20:06 -0700
-- dotCloud <ops@dotcloud.com> Tue, 9 Apr 2013 00:00:00 -0700
lxc-docker (0.1.0-1) unstable; urgency=low
lxc-docker (0.1.3-1) precise; urgency=low
* Initial release
- Choose TCP frontend port with '-p :PORT'
- Layer format is versioned
- Major reliability improvements to the process manager
- Various bugfixes and stability improvements
-- dotCloud <ops@dotcloud.com> Mon, 25 Mar 2013 05:51:12 -0700
-- dotCloud <ops@dotcloud.com> Thu, 4 Apr 2013 00:00:00 -0700
lxc-docker (0.1.2-1) precise; urgency=low
- Set container hostname with 'docker run -h'
- Selective attach at run with 'docker run -a [stdin[,stdout[,stderr]]]'
- Various bugfixes and stability improvements
- UI polish
- Progress bar on push/pull
- Use XZ compression by default
- Make IP allocator lazy
-- dotCloud <ops@dotcloud.com> Wed, 3 Apr 2013 00:00:00 -0700
lxc-docker (0.1.1-1) precise; urgency=low
- Display shorthand IDs for convenience
- Stabilize process management
- Layers can include a commit message
- Simplified 'docker attach'
- Fixed support for re-attaching
- Various bugfixes and stability improvements
- Auto-download at run
- Auto-login on push
- Beefed up documentation
-- dotCloud <ops@dotcloud.com> Sun, 31 Mar 2013 00:00:00 -0700
lxc-docker (0.1.0-1) precise; urgency=low
- First release
- Implement registry in order to push/pull images
- TCP port allocation
- Fix termcaps on Linux
- Add documentation
- Add Vagrant support with Vagrantfile
- Add unit tests
- Add repository/tags to ease image management
- Improve the layer implementation
-- dotCloud <ops@dotcloud.com> Sat, 23 Mar 2013 00:00:00 -0700
+8 -4
View File
@@ -15,9 +15,12 @@ accessed adding the following line to /etc/apt/sources.list ::
Releasing a new package
~~~~~~~~~~~~~~~~~~~~~~~
The most relevant information to update is the changelog file:
The most relevant information to update is the packaging/ubuntu/changelog file:
Each new release should create a new first paragraph with new release version,
changes, and the maintainer information.
changes, and the maintainer information. The core of this paragraph is
located on CHANGELOG.md. Make sure to transcribe it and translate the formats
(eg: packaging/ubuntu/changelog uses 2 spaces for body change descriptions
instead of 1 space from CHANGELOG.md)
Assuming your PPA GPG signing key is on /media/usbdrive/docker.key, load it
into the GPG_KEY environment variable with::
@@ -28,8 +31,9 @@ into the GPG_KEY environment variable with::
After this is done and you are ready to upload the package to the PPA, you have
a couple of choices:
* Follow README.debian to generate the actual source packages and upload them
to the PPA
* Follow packaging/ubuntu/README.ubuntu to generate the actual source packages
and upload them to the PPA
* Let vagrant do all the work for you::
( cd docker/packaging/ubuntu; vagrant up )
-17
View File
@@ -1,17 +0,0 @@
node default {
exec {
"apt_update" :
command => "/usr/bin/apt-get update"
}
Package {
require => Exec['apt_update']
}
group { "puppet":
ensure => "present"
}
include "docker"
}
-99
View File
@@ -1,99 +0,0 @@
class virtualbox {
Package { ensure => "installed" }
# remove some files from the base vagrant image because they're old
file { "/home/vagrant/docker-master":
ensure => absent,
recurse => true,
force => true,
purge => true,
}
file { "/usr/local/bin/dockerd":
ensure => absent,
}
file { "/usr/local/bin/docker":
ensure => absent,
}
# Set up VirtualBox guest utils
package { "virtualbox-guest-utils": }
exec { "vbox-add" :
command => "/etc/init.d/vboxadd setup",
require => [
Package["virtualbox-guest-utils"],
Package["linux-headers-3.5.0-25-generic"], ],
}
}
class docker {
# update this with latest go binary dist
$go_url = "http://go.googlecode.com/files/go1.0.3.linux-amd64.tar.gz"
Package { ensure => "installed" }
package { ["lxc", "debootstrap", "wget", "bsdtar", "git",
"linux-image-3.5.0-25-generic",
"linux-image-extra-3.5.0-25-generic",
"linux-headers-3.5.0-25-generic"]: }
$ec2_version = file("/etc/ec2_version", "/dev/null")
$rax_version = inline_template("<%= %x{/usr/bin/xenstore-read vm-data/provider_data/provider} %>")
if ($ec2_version) {
$vagrant_user = "ubuntu"
$vagrant_home = "/home/ubuntu"
} elsif ($rax_version) {
$vagrant_user = "root"
$vagrant_home = "/root"
} else {
# virtualbox is the vagrant default, so it should be safe to assume
$vagrant_user = "vagrant"
$vagrant_home = "/home/vagrant"
include virtualbox
}
exec { "fetch-go":
require => Package["wget"],
command => "/usr/bin/wget -O - $go_url | /bin/tar xz -C /usr/local",
creates => "/usr/local/go/bin/go",
}
file { "/etc/init/dockerd.conf":
mode => 600,
owner => "root",
group => "root",
content => template("docker/dockerd.conf"),
}
file { "/opt/go":
owner => $vagrant_user,
group => $vagrant_user,
recurse => true,
}
file { "${vagrant_home}/.profile":
mode => 644,
owner => $vagrant_user,
group => $vagrant_user,
content => template("docker/profile"),
}
exec { "build-docker" :
cwd => "/opt/go/src/github.com/dotcloud/docker",
user => $vagrant_user,
environment => "GOPATH=/opt/go",
command => "/usr/local/go/bin/go get -v ./... && /usr/local/go/bin/go install ./docker",
creates => "/opt/go/bin/docker",
logoutput => "on_failure",
require => [ Exec["fetch-go"], File["/opt/go"] ],
}
service { "dockerd" :
ensure => "running",
start => "/sbin/initctl start dockerd",
stop => "/sbin/initctl stop dockerd",
require => [ Exec["build-docker"], File["/etc/init/dockerd.conf"] ],
name => "dockerd",
provider => "base"
}
}
@@ -1,12 +0,0 @@
description "Run dockerd"
stop on runlevel [!2345]
start on runlevel [3]
# if you want it to automatically restart if it crashes, leave the next line in
respawn
script
test -f /etc/default/locale && . /etc/default/locale || true
LANG=$LANG LC_ALL=$LANG /opt/go/bin/docker -d >> /var/log/dockerd 2>&1
end script
-30
View File
@@ -1,30 +0,0 @@
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.
# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
export GOPATH=/opt/go
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
docker=/opt/go/src/github.com/dotcloud/docker
if [ -d $docker ]; then
cd $docker
fi
+10 -13
View File
@@ -7,6 +7,7 @@ import (
"io"
"io/ioutil"
"net/http"
"os"
"path"
"strings"
)
@@ -135,7 +136,7 @@ func (graph *Graph) getRemoteImage(stdout io.Writer, imgId string, authConfig *a
if err != nil {
return nil, nil, err
}
return img, ProgressReader(res.Body, int(res.ContentLength), stdout), nil
return img, ProgressReader(res.Body, int(res.ContentLength), stdout, "Downloading %v/%v (%v)"), nil
}
func (graph *Graph) PullImage(stdout io.Writer, imgId string, authConfig *auth.AuthConfig) error {
@@ -269,24 +270,20 @@ func (graph *Graph) PushImage(stdout io.Writer, imgOrig *Image, authConfig *auth
return fmt.Errorf("Failed to retrieve layer upload location: %s", err)
}
// FIXME: Don't do this :D. Check the S3 requierement and implement chunks of 5MB
// FIXME2: I won't stress it enough, DON'T DO THIS! very high priority
layerData2, err := Tar(path.Join(graph.Root, img.Id, "layer"), Xz)
tmp, err := ioutil.ReadAll(layerData2)
// FIXME: stream the archive directly to the registry instead of buffering it on disk. This requires either:
// a) Implementing S3's proprietary streaming logic, or
// b) Stream directly to the registry instead of S3.
// I prefer option b. because it doesn't lock us into a proprietary cloud service.
tmpLayer, err := graph.TempLayerArchive(img.Id, Xz, stdout)
if err != nil {
return err
}
layerLength := len(tmp)
layerData, err := Tar(path.Join(graph.Root, img.Id, "layer"), Xz)
if err != nil {
return fmt.Errorf("Failed to generate layer archive: %s", err)
}
req3, err := http.NewRequest("PUT", url.String(), ProgressReader(layerData.(io.ReadCloser), layerLength, stdout))
defer os.Remove(tmpLayer.Name())
req3, err := http.NewRequest("PUT", url.String(), ProgressReader(tmpLayer, int(tmpLayer.Size), stdout, "Uploading %v/%v (%v)"))
if err != nil {
return err
}
req3.ContentLength = int64(layerLength)
req3.ContentLength = int64(tmpLayer.Size)
req3.TransferEncoding = []string{"none"}
res3, err := client.Do(req3)
+99 -9
View File
@@ -6,6 +6,7 @@ import (
"github.com/dotcloud/docker/auth"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
@@ -14,6 +15,11 @@ import (
"time"
)
type Capabilities struct {
MemoryLimit bool
SwapLimit bool
}
type Runtime struct {
root string
repository string
@@ -23,6 +29,8 @@ type Runtime struct {
repositories *TagStore
authConfig *auth.AuthConfig
idIndex *TruncIndex
capabilities *Capabilities
kernelVersion *KernelVersionInfo
}
var sysInitPath string
@@ -69,12 +77,59 @@ func (runtime *Runtime) containerRoot(id string) string {
return path.Join(runtime.repository, id)
}
func (runtime *Runtime) mergeConfig(userConf, imageConf *Config) {
if userConf.Hostname != "" {
userConf.Hostname = imageConf.Hostname
}
if userConf.User != "" {
userConf.User = imageConf.User
}
if userConf.Memory == 0 {
userConf.Memory = imageConf.Memory
}
if userConf.MemorySwap == 0 {
userConf.MemorySwap = imageConf.MemorySwap
}
if userConf.PortSpecs == nil || len(userConf.PortSpecs) == 0 {
userConf.PortSpecs = imageConf.PortSpecs
}
if !userConf.Tty {
userConf.Tty = userConf.Tty
}
if !userConf.OpenStdin {
userConf.OpenStdin = imageConf.OpenStdin
}
if !userConf.StdinOnce {
userConf.StdinOnce = imageConf.StdinOnce
}
if userConf.Env == nil || len(userConf.Env) == 0 {
userConf.Env = imageConf.Env
}
if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
userConf.Cmd = imageConf.Cmd
}
if userConf.Dns == nil || len(userConf.Dns) == 0 {
userConf.Dns = imageConf.Dns
}
}
func (runtime *Runtime) Create(config *Config) (*Container, error) {
// Lookup image
img, err := runtime.repositories.LookupImage(config.Image)
if err != nil {
return nil, err
}
//runtime.mergeConfig(config, img.Config)
if img.Config != nil {
config = img.Config
}
if config.Cmd == nil {
return nil, fmt.Errorf("No command specified")
}
// Generate id
id := GenerateId()
// Generate default hostname
@@ -95,6 +150,7 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) {
// FIXME: do we need to store this in the container?
SysInitPath: sysInitPath,
}
container.root = runtime.containerRoot(container.Id)
// Step 1: create the container directory.
// This doubles as a barrier to avoid race conditions.
@@ -176,12 +232,6 @@ func (runtime *Runtime) Register(container *Container) error {
}
}
// If the container is not running or just has been flagged not running
// then close the wait lock chan (will be reset upon start)
if !container.State.Running {
close(container.waitLock)
}
// Even if not running, we init the lock (prevents races in start/stop/kill)
container.State.initLock()
@@ -199,6 +249,15 @@ func (runtime *Runtime) Register(container *Container) error {
// done
runtime.containers.PushBack(container)
runtime.idIndex.Add(container.Id)
// If the container is not running or just has been flagged not running
// then close the wait lock chan (will be reset upon start)
if !container.State.Running {
close(container.waitLock)
} else {
container.allocateNetwork()
go container.monitor()
}
return nil
}
@@ -238,7 +297,7 @@ func (runtime *Runtime) Destroy(container *Container) error {
// Commit creates a new filesystem image from the current state of a container.
// The image can optionally be tagged into a repository
func (runtime *Runtime) Commit(id, repository, tag, comment, author string) (*Image, error) {
func (runtime *Runtime) Commit(id, repository, tag, comment, author string, config *Config) (*Image, error) {
container := runtime.Get(id)
if container == nil {
return nil, fmt.Errorf("No such container: %s", id)
@@ -250,7 +309,7 @@ func (runtime *Runtime) Commit(id, repository, tag, comment, author string) (*Im
return nil, err
}
// Create a new image from the container's base layers + a new layer from container changes
img, err := runtime.graph.Create(rwTar, container, comment, author)
img, err := runtime.graph.Create(rwTar, container, comment, author, config)
if err != nil {
return nil, err
}
@@ -282,7 +341,37 @@ func (runtime *Runtime) restore() error {
// FIXME: harmonize with NewGraph()
func NewRuntime() (*Runtime, error) {
return NewRuntimeFromDirectory("/var/lib/docker")
runtime, err := NewRuntimeFromDirectory("/var/lib/docker")
if err != nil {
return nil, err
}
if k, err := GetKernelVersion(); err != nil {
log.Printf("WARNING: %s\n", err)
} else {
runtime.kernelVersion = k
if CompareKernelVersion(k, &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 {
log.Printf("WARNING: You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.8.0.", k.String())
}
}
if cgroupMemoryMountpoint, err := FindCgroupMountpoint("memory"); err != nil {
log.Printf("WARNING: %s\n", err)
} else {
_, err1 := ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.limit_in_bytes"))
_, err2 := ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.soft_limit_in_bytes"))
runtime.capabilities.MemoryLimit = err1 == nil && err2 == nil
if !runtime.capabilities.MemoryLimit {
log.Printf("WARNING: Your kernel does not support cgroup memory limit.")
}
_, err = ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.memsw.limit_in_bytes"))
runtime.capabilities.SwapLimit = err == nil
if !runtime.capabilities.SwapLimit {
log.Printf("WARNING: Your kernel does not support cgroup swap limit.")
}
}
return runtime, nil
}
func NewRuntimeFromDirectory(root string) (*Runtime, error) {
@@ -321,6 +410,7 @@ func NewRuntimeFromDirectory(root string) (*Runtime, error) {
repositories: repositories,
authConfig: authConfig,
idIndex: NewTruncIndex(),
capabilities: &Capabilities{},
}
if err := runtime.restore(); err != nil {
+3 -3
View File
@@ -48,8 +48,6 @@ func layerArchive(tarfile string) (io.Reader, error) {
}
func init() {
NO_MEMORY_LIMIT = os.Getenv("NO_MEMORY_LIMIT") == "1"
// Hack to run sys init during unit testing
if SelfPath() == "/sbin/init" {
SysInit()
@@ -62,6 +60,8 @@ func init() {
panic("docker tests needs to be run as root")
}
NetworkBridgeIface = "testdockbr0"
// Make it our Store root
runtime, err := NewRuntimeFromDirectory(unitTestStoreBase)
if err != nil {
@@ -275,7 +275,7 @@ func TestAllocatePortLocalhost(t *testing.T) {
t.Fatal(err)
}
defer container.Kill()
time.Sleep(300 * time.Millisecond) // Wait for the container to run
time.Sleep(600 * time.Millisecond) // Wait for the container to run
conn, err := net.Dial("tcp",
fmt.Sprintf(
"localhost:%s", container.NetworkSettings.PortMapping["5555"],
+77 -10
View File
@@ -12,6 +12,7 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
@@ -69,23 +70,30 @@ type progressReader struct {
readTotal int // Expected stream length (bytes)
readProgress int // How much has been read so far (bytes)
lastUpdate int // How many bytes read at least update
template string // Template to print. Default "%v/%v (%v)"
}
func (r *progressReader) Read(p []byte) (n int, err error) {
read, err := io.ReadCloser(r.reader).Read(p)
r.readProgress += read
// Only update progress for every 1% read
updateEvery := int(0.01 * float64(r.readTotal))
if r.readProgress-r.lastUpdate > updateEvery || r.readProgress == r.readTotal {
fmt.Fprintf(r.output, "%d/%d (%.0f%%)\r",
r.readProgress,
r.readTotal,
float64(r.readProgress)/float64(r.readTotal)*100)
updateEvery := 4096
if r.readTotal > 0 {
// Only update progress for every 1% read
if increment := int(0.01 * float64(r.readTotal)); increment > updateEvery {
updateEvery = increment
}
}
if r.readProgress-r.lastUpdate > updateEvery || err != nil {
if r.readTotal > 0 {
fmt.Fprintf(r.output, r.template+"\r", r.readProgress, r.readTotal, fmt.Sprintf("%.0f%%", float64(r.readProgress)/float64(r.readTotal)*100))
} else {
fmt.Fprintf(r.output, r.template+"\r", r.readProgress, "?", "n/a")
}
r.lastUpdate = r.readProgress
}
// Send newline when complete
if err == io.EOF {
if err != nil {
fmt.Fprintf(r.output, "\n")
}
@@ -94,8 +102,11 @@ func (r *progressReader) Read(p []byte) (n int, err error) {
func (r *progressReader) Close() error {
return io.ReadCloser(r.reader).Close()
}
func ProgressReader(r io.ReadCloser, size int, output io.Writer) *progressReader {
return &progressReader{r, output, size, 0, 0}
func ProgressReader(r io.ReadCloser, size int, output io.Writer, template string) *progressReader {
if template == "" {
template = "%v/%v (%v)"
}
return &progressReader{r, output, size, 0, 0, template}
}
// HumanDuration returns a human-readable approximation of a duration
@@ -384,3 +395,59 @@ func CopyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error)
}
return written, err
}
type KernelVersionInfo struct {
Kernel int
Major int
Minor int
Flavor string
}
// FIXME: this doens't build on Darwin
func GetKernelVersion() (*KernelVersionInfo, error) {
return getKernelVersion()
}
func (k *KernelVersionInfo) String() string {
return fmt.Sprintf("%d.%d.%d-%s", k.Kernel, k.Major, k.Minor, k.Flavor)
}
// Compare two KernelVersionInfo struct.
// Returns -1 if a < b, = if a == b, 1 it a > b
func CompareKernelVersion(a, b *KernelVersionInfo) int {
if a.Kernel < b.Kernel {
return -1
} else if a.Kernel > b.Kernel {
return 1
}
if a.Major < b.Major {
return -1
} else if a.Major > b.Major {
return 1
}
if a.Minor < b.Minor {
return -1
} else if a.Minor > b.Minor {
return 1
}
return 0
}
func FindCgroupMountpoint(cgroupType string) (string, error) {
output, err := exec.Command("mount").CombinedOutput()
if err != nil {
return "", err
}
reg := regexp.MustCompile(`^.* on (.*) type cgroup \(.*` + cgroupType + `[,\)]`)
for _, line := range strings.Split(string(output), "\n") {
r := reg.FindStringSubmatch(line)
if len(r) == 2 {
return r[1], nil
}
}
return "", fmt.Errorf("cgroup mountpoint not found for %s", cgroupType)
}
+33
View File
@@ -228,3 +228,36 @@ func assertIndexGet(t *testing.T, index *TruncIndex, input, expectedResult strin
t.Fatalf("Getting '%s' returned '%s' instead of '%s'", input, result, expectedResult)
}
}
func assertKernelVersion(t *testing.T, a, b *KernelVersionInfo, result int) {
if r := CompareKernelVersion(a, b); r != result {
t.Fatalf("Unepected kernel version comparaison result. Found %d, expected %d", r, result)
}
}
func TestCompareKernelVersion(t *testing.T) {
assertKernelVersion(t,
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
0)
assertKernelVersion(t,
&KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
-1)
assertKernelVersion(t,
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
&KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
1)
assertKernelVersion(t,
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "0"},
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "16"},
0)
assertKernelVersion(t,
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 5},
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
1)
assertKernelVersion(t,
&KernelVersionInfo{Kernel: 3, Major: 0, Minor: 20, Flavor: "25"},
&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "0"},
-1)
}