Compare commits

..

41 Commits

Author SHA1 Message Date
Michael Crosby 1781b18deb Merge branch 'migrate-aufs-containers' into v0.7-rc3
Conflicts:
	runtime.go
2013-10-08 22:09:04 -07:00
Michael Crosby d67f8d3414 Migrate AUFS containers to devmapper 2013-10-08 22:06:31 -07:00
Alexander Larsson b414d9d4e2 Clean up better from previous unit-test runs
This makes sure we unmount existing mounts (as well as removing the
devmapper devices), and it fails with proper logs rather than just
panic()ing.
2013-10-08 22:06:31 -07:00
Michael Crosby b5a5a56271 Merge branch 'master' into 0.7-staging 2013-10-08 22:05:59 -07:00
Michael Crosby 875b3001f8 Migrate AUFS containers to devmapper 2013-10-08 18:33:49 -07:00
Alexander Larsson a85667f80a Clean up better from previous unit-test runs
This makes sure we unmount existing mounts (as well as removing the
devmapper devices), and it fails with proper logs rather than just
panic()ing.
2013-10-08 14:54:00 +02:00
Alexander Larsson b67c94a963 devmapper: Move all "raw" libdevmapper wrappers to devmapper.go
This separates out the DeviceSet logic a bit better from the raw
device mapper operations.

devicemapper: Serialize addess to the devicemapper deviceset

This code is not safe to run in multiple threads at the same time,
and neither is libdevmapper.

DeviceMapper: Move deactivate into UnmountDevice

This way the deactivate is atomic wrt othe device mapper operations
and will not fail with EBUSY if someone else starts a devicemapper
operation inbetween unmount and deactivate.

devmapper: Fix loopback mounting regression

Some changes were added to attach_loop_device which added
a perror() in a place that caused it to override errno so that
a later errno != EBUSY failed. This fixes that and cleans up
the error reporting a bit.

devmapper: Build on old kernels without LOOP_CTL_GET_FREE define
2013-10-07 22:42:29 +00:00
Guillaume J. Charmes ea5b19cc01 Merge branch 'device-mapper-test' into 0.7-staging
Conflicts:
	Dockerfile
	docker/docker.go
	hack/PACKAGERS.md
	hack/make.sh
	hack/make/binary
	hack/make/test
	runtime.go
	runtime_test.go
	server.go
	utils.go
	utils/utils.go
	utils_test.go
2013-10-04 15:31:04 -07:00
Michael Crosby 86c96da8d0 Allow trun ids with links
Only now full ids with docker ls -a
2013-10-04 13:21:28 -07:00
Michael Crosby 6c091462ed Update based on initial feedback
Hard code root entity name
Remove test from Dockerfile
Name sure container names work across commands
2013-10-04 09:51:35 -07:00
Michael Crosby 1cbe361b08 Fix rebase conflicts from master 2013-10-04 09:51:35 -07:00
Michael Crosby 04f092792f Add docs and maintainers file for new sub pkgs 2013-10-04 09:51:35 -07:00
Michael Crosby aeb4b196bd Remove network connection when link is removed 2013-10-04 09:51:35 -07:00
Michael Crosby f2696470e2 Convert links to upper case 2013-10-04 09:51:35 -07:00
Michael Crosby 623314936e Add support for names with start command 2013-10-04 09:51:35 -07:00
Michael Crosby 9c00d25b04 Update make script for ldl 2013-10-04 09:51:34 -07:00
Michael Crosby bd4b65e882 Add sqlite as graphdb backend
Add build steps to compile docker statically
with CGO enabled
2013-10-04 09:51:34 -07:00
Michael Crosby 1b43908dbb Refactor to use graph for linking 2013-10-04 09:51:34 -07:00
Michael Crosby 784e7647e1 Add gograph database to handle linking 2013-10-04 09:51:34 -07:00
Michael Crosby 99f5fc3116 Remove top level link command and endpoint 2013-10-04 09:51:34 -07:00
Michael Crosby 9d887e5f25 Add name and alias to docker ps output 2013-10-04 09:51:34 -07:00
Michael Crosby f80d778077 Restore container links at runtime start 2013-10-04 09:51:34 -07:00
Michael Crosby 7a3d4b1d3f Update new unittests after rebase 2013-10-04 09:51:34 -07:00
Michael Crosby 27fc64dbc6 Add default port for link
Add links unit test file
2013-10-04 09:51:34 -07:00
Michael Crosby a07d919ea1 Add view all links for the engine 2013-10-04 09:51:34 -07:00
Michael Crosby e1952ae844 Do not reference ports for linking containers 2013-10-04 09:51:34 -07:00
Michael Crosby b184ca1383 Create LinkRepository during runtime init 2013-10-04 09:51:34 -07:00
Michael Crosby 29de4792da Create private link via iptables to linked containers
Allow active links to be removed
2013-10-04 09:51:34 -07:00
Michael Crosby adecaeb40b Prevent inter-container communication 2013-10-04 09:51:34 -07:00
Michael Crosby 9d150f02f9 Add port and ip for links 2013-10-04 09:51:34 -07:00
Michael Crosby 30e4a8e524 Initial commit to add links and inject env 2013-10-04 09:51:34 -07:00
Michael Crosby 48f1f6fa0d Refactor internal port mappings 2013-10-04 09:51:34 -07:00
Michael Crosby 232ec55c1e Add IP to APIPort struct 2013-10-04 09:51:34 -07:00
Michael Crosby 3e4c9d723c Add -expose flag to expose ports without publishing 2013-10-04 09:51:34 -07:00
Michael Crosby 675f1a8069 Add warning and build error for public image ports 2013-10-04 09:50:28 -07:00
Michael Crosby 6c1ec9c28f Add destination to iptables conf 2013-10-04 09:50:28 -07:00
Michael Crosby 46c82d0391 Refactor internal port mappings 2013-10-04 09:50:28 -07:00
Michael Crosby 96d3008465 Add flag to set the default ip ports are bound to 2013-10-04 09:50:28 -07:00
Michael Crosby 729b94d448 Move proxy into sub package 2013-10-04 09:50:28 -07:00
Michael Crosby 193767edd7 Add DaemonConfig
Use a config type for accessing data
Add bridgeiface name to config
Add option to disable iptables
2013-10-04 09:50:28 -07:00
Michael Crosby 2e25dff7b5 Move iptables into sub package 2013-10-04 09:50:28 -07:00
170 changed files with 4086 additions and 4410 deletions
-12
View File
@@ -26,15 +26,3 @@ Roberto Hashioka <roberto_hashioka@hotmail.com>
Konstantin Pelykh <kpelykh@zettaset.com>
David Sissitka <me@dsissitka.com>
Nolan Darilek <nolan@thewordnerd.info>
<mastahyeti@gmail.com> <mastahyeti@users.noreply.github.com>
Benoit Chesneau <bchesneau@gmail.com>
Jordan Arentsen <blissdev@gmail.com>
Daniel Garcia <daniel@danielgarcia.info>
Miguel Angel Fernández <elmendalerenda@gmail.com>
Bhiraj Butala <abhiraj.butala@gmail.com>
Faiz Khan <faizkhan00@gmail.com>
Victor Lyuboslavsky <victor@victoreda.com>
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
Matthew Mueller <mattmuelle@gmail.com>
<mosoni@ebay.com> <mohitsoni1989@gmail.com>
Shih-Yuan Lee <fourdollars@gmail.com>
+1 -67
View File
@@ -5,98 +5,64 @@
#
Al Tobey <al@ooyala.com>
Alex Gaynor <alex.gaynor@gmail.com>
Alexander Larsson <alexl@redhat.com>
Alexey Shamrin <shamrin@gmail.com>
Andrea Luzzardi <aluzzardi@gmail.com>
Andreas Savvides <andreas@editd.com>
Andreas Tiefenthaler <at@an-ti.eu>
Andrew Macgregor <andrew.macgregor@agworld.com.au>
Andrew Munsell <andrew@wizardapps.net>
Andrews Medina <andrewsmedina@gmail.com>
Andy Rothfusz <github@metaliveblog.com>
Andy Smith <github@anarkystic.com>
Anthony Bishopric <git@anthonybishopric.com>
Antony Messerli <amesserl@rackspace.com>
Asbjørn Enge <asbjorn@hanafjedle.net>
Barry Allard <barry.allard@gmail.com>
Ben Toews <mastahyeti@gmail.com>
Benoit Chesneau <bchesneau@gmail.com>
Bhiraj Butala <abhiraj.butala@gmail.com>
Bouke Haarsma <bouke@webatoom.nl>
Brandon Liu <bdon@bdon.org>
Brandon Philips <brandon@ifup.co>
Brian McCallister <brianm@skife.org>
Brian Olsen <brian@maven-group.org>
Brian Shumate <brian@couchbase.com>
Briehan Lombaard <briehan.lombaard@gmail.com>
Bruno Bigras <bigras.bruno@gmail.com>
Caleb Spare <cespare@gmail.com>
Calen Pennington <cale@edx.org>
Charles Hooper <charles.hooper@dotcloud.com>
Christopher Currie <codemonkey+github@gmail.com>
Colin Dunklau <colin.dunklau@gmail.com>
Colin Rice <colin@daedrum.net>
Dan Buch <d.buch@modcloth.com>
Daniel Garcia <daniel@danielgarcia.info>
Daniel Gasienica <daniel@gasienica.ch>
Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com>
Daniel Nordberg <dnordberg@gmail.com>
Daniel Robinson <gottagetmac@gmail.com>
Daniel Von Fange <daniel@leancoder.com>
Daniel YC Lin <dlin.tw@gmail.com>
David Calavera <david.calavera@gmail.com>
David Sissitka <me@dsissitka.com>
Deni Bertovic <deni@kset.org>
Dominik Honnef <dominik@honnef.co>
Don Spaulding <donspauldingii@gmail.com>
Dr Nic Williams <drnicwilliams@gmail.com>
Dražen Lučanin <kermit666@gmail.com>
Elias Probst <mail@eliasprobst.eu>
Emily Rose <emily@contactvibe.com>
Eric Hanchrow <ehanchrow@ine.com>
Eric Myhre <hash@exultant.us>
Erno Hopearuoho <erno.hopearuoho@gmail.com>
Evan Phoenix <evan@fallingsnow.net>
Evan Wies <evan@neomantra.net>
ezbercih <cem.ezberci@gmail.com>
Fabrizio Regini <freegenie@gmail.com>
Faiz Khan <faizkhan00@gmail.com>
Fareed Dudhia <fareeddudhia@googlemail.com>
Flavio Castelli <fcastelli@suse.com>
Francisco Souza <f@souza.cc>
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
Gabriel Monroy <gabriel@opdemand.com>
Gareth Rushgrove <gareth@morethanseven.net>
Greg Thornton <xdissent@me.com>
Guillaume J. Charmes <guillaume.charmes@dotcloud.com>
Guruprasad <lgp171188@gmail.com>
Harley Laue <losinggeneration@gmail.com>
Hector Castro <hectcastro@gmail.com>
Hunter Blanks <hunter@twilio.com>
Isao Jonas <isao.jonas@gmail.com>
James Carr <james.r.carr@gmail.com>
Jason McVetta <jason.mcvetta@gmail.com>
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
Jeff Lindsay <progrium@gmail.com>
Jeremy Grosser <jeremy@synack.me>
Jim Alateras <jima@comware.com.au>
Jimmy Cuadra <jimmy@jimmycuadra.com>
Joe Van Dyk <joe@tanga.com>
Joffrey F <joffrey@dotcloud.com>
Johan Euphrosine <proppy@google.com>
John Costa <john.costa@gmail.com>
Jon Wedaman <jweede@gmail.com>
Jonas Pfenniger <jonas@pfenniger.name>
Jonathan Mueller <j.mueller@apoveda.ch>
Jonathan Rudenberg <jonathan@titanous.com>
Joost Cassee <joost@cassee.net>
Jordan Arentsen <blissdev@gmail.com>
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
Julien Barbier <write0@gmail.com>
Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
Karan Lyons <karan@karanlyons.com>
Karl Grzeszczak <karl@karlgrz.com>
Kawsar Saiyeed <kawsar.saiyeed@projiris.com>
Keli Hu <dev@keli.hu>
Ken Cochrane <kencochrane@gmail.com>
Kevin Clark <kevin.clark@gmail.com>
@@ -105,45 +71,28 @@ kim0 <email.ahmedkamal@googlemail.com>
Kimbro Staken <kstaken@kstaken.com>
Kiran Gangadharan <kiran.daredevil@gmail.com>
Konstantin Pelykh <kpelykh@zettaset.com>
Kyle Conroy <kyle.j.conroy@gmail.com>
Laurie Voss <github@seldo.com>
Louis Opter <kalessin@kalessin.fr>
Manuel Meurer <manuel@krautcomputing.com>
Marco Hennings <marco.hennings@freiheit.com>
Marcus Farkas <toothlessgear@finitebox.com>
Marcus Ramberg <marcus@nordaaker.com>
Mark McGranaghan <mmcgrana@gmail.com>
Marko Mikulicic <mmikulicic@gmail.com>
Markus Fix <lispmeister@gmail.com>
Martin Redmond <martin@tinychat.com>
Matt Apperson <me@mattapperson.com>
Matt Bachmann <bachmann.matt@gmail.com>
Matthew Mueller <mattmuelle@gmail.com>
Martin Redmond <mrtodo@gmail.com>
Maxim Treskin <zerthurd@gmail.com>
meejah <meejah@meejah.ca>
Michael Crosby <crosby.michael@gmail.com>
Michael Gorsuch <gorsuch@github.com>
Miguel Angel Fernández <elmendalerenda@gmail.com>
Mike Gaffney <mike@uberu.com>
Mikhail Sobolev <mss@mawhrin.net>
Mohit Soni <mosoni@ebay.com>
Morten Siebuhr <sbhr@sbhr.dk>
Nan Monnand Deng <monnand@gmail.com>
Nate Jones <nate@endot.org>
Nelson Chen <crazysim@gmail.com>
Niall O'Higgins <niallo@unworkable.org>
Nick Payne <nick@kurai.co.uk>
Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
Nick Stinemates <nick@stinemates.org>
Nolan Darilek <nolan@thewordnerd.info>
odk- <github@odkurzacz.org>
Pascal Borreli <pascal@borreli.com>
Paul Bowsher <pbowsher@globalpersonals.co.uk>
Paul Hammond <paul@paulhammond.org>
Phil Spitler <pspitler@gmail.com>
Piotr Bogdan <ppbogdan@gmail.com>
pysqz <randomq@126.com>
Ramon van Alteren <ramon@vanalteren.nl>
Renato Riccieri Santos Zannon <renato.riccieri@gmail.com>
Rhys Hiltner <rhys@twitch.tv>
Robert Obryk <robryk@gmail.com>
@@ -151,21 +100,14 @@ Roberto Hashioka <roberto_hashioka@hotmail.com>
Ryan Fowler <rwfowler@gmail.com>
Sam Alba <sam.alba@gmail.com>
Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
Sean P. Kane <skane@newrelic.com>
Shawn Siefkas <shawn.siefkas@meredith.com>
Shih-Yuan Lee <fourdollars@gmail.com>
Silas Sewell <silas@sewell.org>
Solomon Hykes <solomon@dotcloud.com>
Song Gao <song@gao.io>
Sridatta Thatipamala <sthatipamala@gmail.com>
Sridhar Ratnakumar <sridharr@activestate.com>
Steeve Morin <steeve.morin@gmail.com>
Stefan Praszalowicz <stefan@greplin.com>
Thatcher Peskens <thatcher@dotcloud.com>
Thermionix <bond711@gmail.com>
Thijs Terlouw <thijsterlouw@gmail.com>
Thomas Bikeev <thomas.bikeev@mac.com>
Thomas Frössman <thomasf@jossystem.se>
Thomas Hansen <thomas.hansen@gmail.com>
Tianon Gravi <admwiggin@gmail.com>
Tim Terhorst <mynamewastaken+git@gmail.com>
@@ -173,16 +115,8 @@ Tobias Bieniek <Tobias.Bieniek@gmx.de>
Tobias Schmidt <ts@soundcloud.com>
Tobias Schwab <tobias.schwab@dynport.de>
Tom Hulihan <hulihan.tom159@gmail.com>
Tommaso Visconti <tommaso.visconti@gmail.com>
Tyler Brock <tyler.brock@gmail.com>
unclejack <unclejacksons@gmail.com>
Victor Coisne <victor.coisne@dotcloud.com>
Victor Lyuboslavsky <victor@victoreda.com>
Victor Vieux <victor.vieux@dotcloud.com>
Vincent Bernat <bernat@luffy.cx>
Vivek Agarwal <me@vivek.im>
Vladimir Kirillov <proger@wilab.org.ua>
Walter Stanish <walter@pratyeka.org>
Wes Morgan <cap10morgan@gmail.com>
Will Dietz <w@wdtz.org>
Zaiste! <oh@zaiste.net>
-78
View File
@@ -1,83 +1,5 @@
# Changelog
## 0.6.4 (2013-10-16)
- Runtime: Add cleanup of container when Start() fails
- Testing: Catch errClosing error when TCP and UDP proxies are terminated
- Testing: Add aggregated docker-ci email report
- Testing: Remove a few errors in tests
* Contrib: Reorganize contributed completion scripts to add zsh completion
* Contrib: Add vim syntax highlighting for Dockerfiles from @honza
* Runtime: Add better comments to utils/stdcopy.go
- Testing: add cleanup to remove leftover containers
* Documentation: Document how to edit and release docs
* Documentation: Add initial draft of the Docker infrastructure doc
* Contrib: Add mkimage-arch.sh
- Builder: Abort build if mergeConfig returns an error and fix duplicate error message
- Runtime: Remove error messages which are not actually errors
* Testing: Only run certain tests with TESTFLAGS='-run TestName' make.sh
* Testing: Prevent docker-ci to test closing PRs
- Documentation: Minor updates to postgresql_service.rst
* Testing: Add nightly release to docker-ci
* Hack: Improve network performance for VirtualBox
* Hack: Add vagrant user to the docker group
* Runtime: Add utils.Errorf for error logging
- Packaging: Remove deprecated packaging directory
* Hack: Revamp install.sh to be usable by more people, and to use official install methods whenever possible (apt repo, portage tree, etc.)
- Hack: Fix contrib/mkimage-debian.sh apt caching prevention
* Documentation: Clarify LGTM process to contributors
- Documentation: Small fixes to parameter names in docs for ADD command
* Runtime: Record termination time in state.
- Registry: Use correct auth config when logging in.
- Documentation: Corrected error in the package name
* Documentation: Document what `vagrant up` is actually doing
- Runtime: Fix `docker rm` with volumes
- Runtime: Use empty string so TempDir uses the OS's temp dir automatically
- Runtime: Make sure to close the network allocators
* Testing: Replace panic by log.Fatal in tests
+ Documentation: improve doc search results
- Runtime: Fix some error cases where a HTTP body might not be closed
* Hack: Add proper bash completion for "docker push"
* Documentation: Add devenvironment link to CONTRIBUTING.md
* Documentation: Cleanup whitespace in API 1.5 docs
* Documentation: use angle brackets in MAINTAINER example email
- Testing: Increase TestRunDetach timeout
* Documentation: Fix help text for -v option
+ Hack: Added Dockerfile.tmLanguage to contrib
+ Runtime: Autorestart containers by default
* Testing: Adding more tests around auth.ResolveAuthConfig
* Hack: Configured FPM to make /etc/init/docker.conf a config file
* Hack: Add xz utils as a runtime dep
* Documentation: Add `apt-get install curl` to Ubuntu docs
* Documentation: Remove Gentoo install notes about #1422 workaround
* Documentation: Fix Ping endpoint documentation
* Runtime: Bump vendor kr/pty to commit 3b1f6487b (syscall.O_NOCTTY)
* Runtime: lxc: Allow set_file_cap capability in container
* Documentation: Update archlinux.rst
- Documentation: Fix ironic typo in changelog
* Documentation: Add explanation for export restrictions
* Hack: Add cleanup/refactor portion of #2010 for hack and Dockerfile updates
+ Documentation: Changes to a new style for the docs. Includes version switcher.
* Documentation: Formatting, add information about multiline json
+ Hack: Add contrib/mkimage-centos.sh back (from #1621), and associated documentation link
- Runtime: Fix panic with wrong dockercfg file
- Runtime: Fix the attach behavior with -i
* Documentation: Add .dockercfg doc
- Runtime: Move run -rm to the cli only
* Hack: Enable SSH Agent forwarding in Vagrant VM
+ Runtime: Add -rm to docker run for removing a container on exit
* Documentation: Improve registry and index REST API documentation
* Runtime: Split stdout stderr
- Documentation: Replace deprecated upgrading reference to docker-latest.tgz, which hasn't been updated since 0.5.3
* Documentation: Update Gentoo installation documentation now that we're in the portage tree proper
- Registry: Fix the error message so it is the same as the regex
* Runtime: Always create a new session for the container
* Hack: Add several of the small make.sh fixes from #1920, and make the output more consistent and contributor-friendly
* Documentation: Various command fixes in postgres example
* Documentation: Cleanup and reorganize docs and tooling for contributors and maintainers
- Documentation: Minor spelling correction of protocoll -> protocol
* Hack: Several small tweaks/fixes for contrib/mkimage-debian.sh
+ Hack: Add @tianon to hack/MAINTAINERS
## 0.6.3 (2013-09-23)
* Packaging: Update tar vendor dependency
- Client: Fix detach issue
+2 -15
View File
@@ -59,10 +59,8 @@ Submit unit tests for your changes. Go has a great test framework built in; use
it! Take a look at existing tests for inspiration. Run the full test suite on
your branch before submitting a pull request.
Update the documentation when creating or modifying features. Test
your documentation changes for clarity, concision, and correctness, as
well as a clean docmuent build. See ``docs/README.md`` for more
information on building the docs and how docs get released.
Make sure you include relevant updates or additions to documentation when
creating or modifying features.
Write clean code. Universally formatted code promotes ease of writing, reading,
and maintenance. Always run `go fmt` before committing your changes. Most
@@ -95,17 +93,6 @@ name and email address match your git configuration. The AUTHORS file is
regenerated occasionally from the git commit history, so a mismatch may result
in your changes being overwritten.
### Approval
Docker maintainers use LGTM (looks good to me) in comments on the code review
to indicate acceptance.
A change requires LGTMs from an absolute majority of the maintainers of each
component affected. For example, if a change affects docs/ and registry/, it
needs an absolute majority from the maintainers of docs/ AND, separately, an
absolute majority of the maintainers of registry
For more details see [MAINTAINERS.md](hack/MAINTAINERS.md)
### How can I become a maintainer?
+1 -1
View File
@@ -12,7 +12,7 @@
#
#
# # Run the test suite:
# docker run -privileged -lxc-conf=lxc.aa_profile=unconfined docker hack/make.sh test
# docker run -privileged -lxc-conf=lxc.aa_profile=unconfined docker go test -v
#
# # Publish a release:
# docker run -privileged -lxc-conf=lxc.aa_profile=unconfined \
+1 -1
View File
@@ -1 +1 @@
0.6.4-dev
0.6.3-dev
Vendored
-4
View File
@@ -39,8 +39,6 @@ Vagrant::Config.run do |config|
"echo 'Installation of VBox Guest Additions is proceeding in the background.'; " \
"echo '\"vagrant reload\" can be used in about 2 minutes to activate the new guest additions.'; "
end
# Add vagrant user to the docker group
pkg_cmd << "usermod -a -G docker vagrant; "
# Activate new kernel
pkg_cmd << "shutdown -r +1; "
config.vm.provision :shell, :inline => pkg_cmd
@@ -80,8 +78,6 @@ Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
config.vm.provider :virtualbox do |vb|
config.vm.box = BOX_NAME
config.vm.box_url = BOX_URI
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
end
end
+32 -17
View File
@@ -15,6 +15,7 @@ import (
"mime"
"net"
"net/http"
"net/url"
"os"
"os/exec"
"regexp"
@@ -71,11 +72,8 @@ func httpError(w http.ResponseWriter, err error) {
} else if strings.Contains(err.Error(), "hasn't been activated") {
statusCode = http.StatusForbidden
}
if err != nil {
utils.Errorf("HTTP Error: statusCode=%d %s", statusCode, err.Error())
http.Error(w, err.Error(), statusCode)
}
utils.Debugf("[error %d] %s", statusCode, err)
http.Error(w, err.Error(), statusCode)
}
func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
@@ -106,7 +104,7 @@ func getBoolParam(value string) (bool, error) {
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())
utils.Debugf("Error parsing media type: %s error: %s", contentType, err.Error())
}
return err == nil && mimetype == expectedType
}
@@ -137,6 +135,7 @@ func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
if err := srv.ContainerKill(name); err != nil {
return err
}
@@ -149,9 +148,10 @@ func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
if err := srv.ContainerExport(name, w); err != nil {
utils.Errorf("%s", err)
utils.Debugf("%s", err)
return err
}
return nil
@@ -196,7 +196,7 @@ func getEvents(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
_, err = wf.Write(b)
if err != nil {
// On error, evict the listener
utils.Errorf("%s", err)
utils.Debugf("%s", err)
srv.Lock()
delete(srv.listeners, r.RemoteAddr)
srv.Unlock()
@@ -350,8 +350,8 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req
return err
}
config := &Config{}
if err := json.NewDecoder(r.Body).Decode(config); err != nil && err != io.EOF {
utils.Errorf("%s", err)
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
utils.Debugf("%s", err)
}
repo := r.Form.Get("repo")
tag := r.Form.Get("tag")
@@ -559,6 +559,7 @@ func postContainersRestart(srv *Server, version float64, w http.ResponseWriter,
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
if err := srv.ContainerRestart(name, t); err != nil {
return err
}
@@ -574,6 +575,7 @@ func deleteContainers(srv *Server, version float64, w http.ResponseWriter, r *ht
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
removeVolume, err := getBoolParam(r.Form.Get("v"))
if err != nil {
@@ -630,7 +632,12 @@ func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var err error
name := vars["name"]
name = decodeName(name)
if err != nil {
return err
}
if err := srv.ContainerStart(name, hostConfig); err != nil {
utils.Debugf("error ContainerStart: %s", err)
return err
@@ -652,6 +659,7 @@ func postContainersStop(srv *Server, version float64, w http.ResponseWriter, r *
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
if err := srv.ContainerStop(name, t); err != nil {
return err
@@ -665,6 +673,7 @@ func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r *
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
status, err := srv.ContainerWait(name)
if err != nil {
@@ -725,6 +734,7 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
c, err := srv.ContainerInspect(name)
if err != nil {
@@ -797,6 +807,7 @@ func wsContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
if _, err := srv.ContainerInspect(name); err != nil {
return err
@@ -806,7 +817,7 @@ func wsContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *
defer ws.Close()
if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, ws, ws, ws); err != nil {
utils.Errorf("Error: %s", err)
utils.Debugf("Error: %s", err)
}
})
h.ServeHTTP(w, r)
@@ -819,6 +830,7 @@ func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
name = decodeName(name)
container, err := srv.ContainerInspect(name)
if err != nil {
@@ -919,7 +931,8 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
b := NewBuildFile(srv, utils.NewWriteFlusher(w), !suppressOutput, !noCache, rm)
id, err := b.Build(context)
if err != nil {
return fmt.Errorf("Error build: %s", err)
fmt.Fprintf(w, "Error build: %s\n", err)
return err
}
if repoName != "" {
srv.runtime.repositories.Set(repoName, tag, id, false)
@@ -951,7 +964,7 @@ func postContainersCopy(srv *Server, version float64, w http.ResponseWriter, r *
}
if err := srv.ContainerCopy(name, copyData.Resource, w); err != nil {
utils.Errorf("%s", err.Error())
utils.Debugf("%s", err.Error())
return err
}
return nil
@@ -996,7 +1009,7 @@ func makeHttpHandler(srv *Server, logging bool, localMethod string, localRoute s
}
if err := handlerFunc(srv, version, w, r, mux.Vars(r)); err != nil {
utils.Errorf("Error: %s", err)
utils.Debugf("Error: %s", err)
httpError(w, err)
}
}
@@ -1060,15 +1073,17 @@ func postContainerLink(srv *Server, version float64, w http.ResponseWriter, r *h
}
if err := srv.runtime.RenameLink(currentName, newName); err != nil {
if strings.HasSuffix(err.Error(), "name are not unique") {
return fmt.Errorf("Conflict, %s already exists", newName)
}
return err
}
return nil
}
func decodeName(name string) string {
s, _ := url.QueryUnescape(name)
return s
}
func createRouter(srv *Server, logging bool) (*mux.Router, error) {
r := mux.NewRouter()
+12 -17
View File
@@ -17,23 +17,18 @@ type APIImages struct {
}
type APIInfo struct {
Debug bool
Containers int
Images int
NFd int `json:",omitempty"`
NGoroutines int `json:",omitempty"`
MemoryLimit bool `json:",omitempty"`
SwapLimit bool `json:",omitempty"`
IPv4Forwarding bool `json:",omitempty"`
LXCVersion string `json:",omitempty"`
NEventsListener int `json:",omitempty"`
KernelVersion string `json:",omitempty"`
IndexServerAddress string `json:",omitempty"`
DevmapperPool string `json:",omitempty"`
DevmapperDataUsed uint64 `json:",omitempty"`
DevmapperDataTotal uint64 `json:",omitempty"`
DevmapperMetadataUsed uint64 `json:",omitempty"`
DevmapperMetadataTotal uint64 `json:",omitempty"`
Debug bool
Containers int
Images int
NFd int `json:",omitempty"`
NGoroutines int `json:",omitempty"`
MemoryLimit bool `json:",omitempty"`
SwapLimit bool `json:",omitempty"`
IPv4Forwarding bool `json:",omitempty"`
LXCVersion string `json:",omitempty"`
NEventsListener int `json:",omitempty"`
KernelVersion string `json:",omitempty"`
IndexServerAddress string `json:",omitempty"`
}
type APITop struct {
+5 -30
View File
@@ -5,7 +5,6 @@ import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"github.com/dotcloud/docker/utils"
"io"
"net"
@@ -13,7 +12,6 @@ import (
"net/http/httptest"
"os"
"path"
"strings"
"testing"
"time"
)
@@ -42,25 +40,6 @@ func TestGetBoolParam(t *testing.T) {
}
}
func TesthttpError(t *testing.T) {
r := httptest.NewRecorder()
httpError(r, fmt.Errorf("No such method"))
if r.Code != http.StatusNotFound {
t.Fatalf("Expected %d, got %d", http.StatusNotFound, r.Code)
}
httpError(r, fmt.Errorf("This accound hasn't been activated"))
if r.Code != http.StatusForbidden {
t.Fatalf("Expected %d, got %d", http.StatusForbidden, r.Code)
}
httpError(r, fmt.Errorf("Some error"))
if r.Code != http.StatusInternalServerError {
t.Fatalf("Expected %d, got %d", http.StatusInternalServerError, r.Code)
}
}
func TestGetVersion(t *testing.T) {
var err error
runtime := mkRuntime(t)
@@ -112,7 +91,6 @@ func TestGetInfo(t *testing.T) {
func TestGetEvents(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
srv := &Server{
runtime: runtime,
events: make([]utils.JSONMessage, 0, 64),
@@ -265,11 +243,7 @@ func TestGetImagesJSON(t *testing.T) {
t.Fatalf("Error expected, received none")
}
if !strings.HasPrefix(err.Error(), "Bad parameter") {
t.Fatalf("Error should starts with \"Bad parameter\"")
}
http.Error(r4, err.Error(), http.StatusBadRequest)
httpError(r4, err)
if r4.Code != http.StatusBadRequest {
t.Fatalf("%d Bad Request expected, received %d\n", http.StatusBadRequest, r4.Code)
}
@@ -474,7 +448,10 @@ func TestGetContainersChanges(t *testing.T) {
func TestGetContainersTop(t *testing.T) {
t.Skip("Fixme. Skipping test for now. Reported error when testing using dind: 'api_test.go:527: Expected 2 processes, found 0.'")
runtime := mkRuntime(t)
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
@@ -809,8 +786,6 @@ func TestPostContainersStart(t *testing.T) {
t.Fatal(err)
}
req.Header.Set("Content-Type", "application/json")
r := httptest.NewRecorder()
if err := postContainersStart(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err)
+1 -11
View File
@@ -120,8 +120,7 @@ func TarFilter(path string, compression Compression, filter []string, recursive
tmpDir := ""
if createFiles != nil {
var err error // Can't use := here or we override the outer tmpDir
tmpDir, err = ioutil.TempDir("", "docker-tar")
tmpDir, err := ioutil.TempDir("", "docker-tar")
if err != nil {
return nil, err
}
@@ -285,9 +284,6 @@ func CmdStream(cmd *exec.Cmd, input *string, atEnd func()) (io.Reader, error) {
if input != nil {
stdin, err := cmd.StdinPipe()
if err != nil {
if atEnd != nil {
atEnd()
}
return nil, err
}
// Write stdin if any
@@ -298,16 +294,10 @@ func CmdStream(cmd *exec.Cmd, input *string, atEnd func()) (io.Reader, error) {
}
stdout, err := cmd.StdoutPipe()
if err != nil {
if atEnd != nil {
atEnd()
}
return nil, err
}
stderr, err := cmd.StderrPipe()
if err != nil {
if atEnd != nil {
atEnd()
}
return nil, err
}
pipeR, pipeW := io.Pipe()
+1 -4
View File
@@ -76,7 +76,7 @@ func TestCreateAccount(t *testing.T) {
}
func setupTempConfigFile() (*ConfigFile, error) {
root, err := ioutil.TempDir("", "docker-test-auth")
root, err := ioutil.TempDir("", "docker-test")
if err != nil {
return nil, err
}
@@ -101,7 +101,6 @@ func TestSameAuthDataPostSave(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(configFile.rootPath)
err = SaveConfig(configFile)
if err != nil {
@@ -128,7 +127,6 @@ func TestResolveAuthConfigIndexServer(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(configFile.rootPath)
for _, registry := range []string{"", IndexServerAddress()} {
resolved := configFile.ResolveAuthConfig(registry)
@@ -143,7 +141,6 @@ func TestResolveAuthConfigFullURL(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(configFile.rootPath)
registryAuth := AuthConfig{
Username: "foo-user",
+3 -4
View File
@@ -176,8 +176,6 @@ func (b *buildFile) CmdEnv(args string) error {
func (b *buildFile) CmdCmd(args string) error {
var cmd []string
if err := json.Unmarshal([]byte(args), &cmd); err != nil {
// If the unmarshal fails, it is not an error, we just use the
// args as a string.
utils.Debugf("Error unmarshalling: %s, setting cmd to /bin/sh -c", err)
cmd = []string{"/bin/sh", "-c", args}
}
@@ -301,7 +299,7 @@ func (b *buildFile) addContext(container *Container, orig, dest string) error {
}
// First try to unpack the source as an archive
} else if err := UntarPath(origPath, destPath); err != nil {
utils.Debugf("[tar] Not a directory nor a tar archive. Copying as a file. Untar error from %s to %s: %s", origPath, destPath, err)
utils.Debugf("Couldn't untar %s to %s: %s", origPath, destPath, err)
// If that fails, just copy it as a regular file
if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil {
return err
@@ -463,8 +461,9 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
var lineContinuation = regexp.MustCompile(`\s*\\\s*\n`)
func (b *buildFile) Build(context io.Reader) (string, error) {
// FIXME: @creack any reason for using /tmp instead of ""?
// FIXME: @creack "name" is a terrible variable name
name, err := ioutil.TempDir("", "docker-build")
name, err := ioutil.TempDir("/tmp", "docker-build")
if err != nil {
return "", err
}
+24 -6
View File
@@ -229,7 +229,10 @@ func TestBuild(t *testing.T) {
func buildImage(context testContextTemplate, t *testing.T, srv *Server, useCache bool) *Image {
if srv == nil {
runtime := mkRuntime(t)
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv = &Server{
@@ -367,7 +370,10 @@ func TestBuildEntrypoint(t *testing.T) {
// testing #1405 - config.Cmd does not get cleaned up if
// utilizing cache
func TestBuildEntrypointRunCleanup(t *testing.T) {
runtime := mkRuntime(t)
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{
@@ -396,7 +402,10 @@ func TestBuildEntrypointRunCleanup(t *testing.T) {
}
func TestBuildImageWithCache(t *testing.T) {
runtime := mkRuntime(t)
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{
@@ -424,7 +433,10 @@ func TestBuildImageWithCache(t *testing.T) {
}
func TestBuildImageWithoutCache(t *testing.T) {
runtime := mkRuntime(t)
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{
@@ -452,7 +464,10 @@ func TestBuildImageWithoutCache(t *testing.T) {
}
func TestForbiddenContextPath(t *testing.T) {
runtime := mkRuntime(t)
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{
@@ -498,7 +513,10 @@ func TestForbiddenContextPath(t *testing.T) {
}
func TestBuildADDFileNotFound(t *testing.T) {
runtime := mkRuntime(t)
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{
+4 -3
View File
@@ -283,8 +283,6 @@ func collectFileInfo(sourceDir string) (*FileInfo, error) {
return root, nil
}
// Compare a directory with an array of layer directories it was based on and
// generate an array of Change objects describing the changes
func ChangesLayers(newDir string, layers []string) ([]Change, error) {
newRoot, err := collectFileInfo(newDir)
if err != nil {
@@ -301,7 +299,6 @@ func ChangesLayers(newDir string, layers []string) ([]Change, error) {
return newRoot.Changes(oldRoot), nil
}
// Compare two directories and generate an array of Change objects describing the changes
func ChangesDirs(newDir, oldDir string) ([]Change, error) {
oldRoot, err := collectFileInfo(oldDir)
if err != nil {
@@ -312,5 +309,9 @@ func ChangesDirs(newDir, oldDir string) ([]Change, error) {
return nil, err
}
// Ignore changes in .docker-id
_ = newRoot.Remove("/.docker-id")
_ = oldRoot.Remove("/.docker-id")
return newRoot.Changes(oldRoot), nil
}
+65 -54
View File
@@ -23,7 +23,6 @@ import (
"os/signal"
"path/filepath"
"reflect"
"regexp"
"runtime"
"sort"
"strconv"
@@ -99,6 +98,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error {
{"kill", "Kill a running container"},
{"login", "Register or Login to the docker registry server"},
{"logs", "Fetch the logs of a container"},
{"ls", "List links for containers"},
{"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"},
{"top", "Lookup the running processes of a container"},
{"ps", "List containers"},
@@ -304,7 +304,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
}
cli.LoadConfigFile()
authconfig, ok := cli.configFile.Configs[serverAddress]
authconfig, ok := cli.configFile.Configs[auth.IndexServerAddress()]
if !ok {
authconfig = auth.AuthConfig{}
}
@@ -419,7 +419,7 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
var out APIVersion
err = json.Unmarshal(body, &out)
if err != nil {
utils.Errorf("Error unmarshal: body: %s, err: %s\n", body, err)
utils.Debugf("Error unmarshal: body: %s, err: %s\n", body, err)
return err
}
if out.Version != "" {
@@ -466,11 +466,6 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, "Containers: %d\n", out.Containers)
fmt.Fprintf(cli.out, "Images: %d\n", out.Images)
if out.DevmapperDataTotal != 0 {
fmt.Fprintf(cli.out, "Devmapper disk use: Data: %.1f/%.1f Metadata: %.1f/%.1f\n",
float64(out.DevmapperDataUsed)/(1024*1024), float64(out.DevmapperDataTotal)/(1024*1024),
float64(out.DevmapperMetadataUsed)/(1024*1024), float64(out.DevmapperMetadataTotal)/(1024*1024))
}
if out.Debug || os.Getenv("DEBUG") != "" {
fmt.Fprintf(cli.out, "Debug mode (server): %v\n", out.Debug)
fmt.Fprintf(cli.out, "Debug mode (client): %v\n", os.Getenv("DEBUG") != "")
@@ -479,7 +474,6 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, "LXC Version: %s\n", out.LXCVersion)
fmt.Fprintf(cli.out, "EventsListeners: %d\n", out.NEventsListener)
fmt.Fprintf(cli.out, "Kernel Version: %s\n", out.KernelVersion)
fmt.Fprintf(cli.out, "Devmapper pool: %s\n", out.DevmapperPool)
}
if len(out.IndexServerAddress) != 0 {
@@ -517,7 +511,8 @@ func (cli *DockerCli) CmdStop(args ...string) error {
v.Set("t", strconv.Itoa(*nSeconds))
for _, name := range cmd.Args() {
_, _, err := cli.call("POST", "/containers/"+name+"/stop?"+v.Encode(), nil)
encName := cleanName(name)
_, _, err := cli.call("POST", "/containers/"+encName+"/stop?"+v.Encode(), nil)
if err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
} else {
@@ -542,7 +537,8 @@ func (cli *DockerCli) CmdRestart(args ...string) error {
v.Set("t", strconv.Itoa(*nSeconds))
for _, name := range cmd.Args() {
_, _, err := cli.call("POST", "/containers/"+name+"/restart?"+v.Encode(), nil)
encName := cleanName(name)
_, _, err := cli.call("POST", "/containers/"+encName+"/restart?"+v.Encode(), nil)
if err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
} else {
@@ -564,7 +560,8 @@ func (cli *DockerCli) CmdStart(args ...string) error {
var encounteredError error
for _, name := range args {
_, _, err := cli.call("POST", "/containers/"+name+"/start", nil)
encName := cleanName(name)
_, _, err := cli.call("POST", "/containers/"+encName+"/start", nil)
if err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
encounteredError = fmt.Errorf("Error: failed to start one or more containers")
@@ -586,10 +583,11 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
}
fmt.Fprintf(cli.out, "[")
for i, name := range args {
encName := cleanName(name)
if i > 0 {
fmt.Fprintf(cli.out, ",")
}
obj, _, err := cli.call("GET", "/containers/"+name+"/json", nil)
obj, _, err := cli.call("GET", "/containers/"+encName+"/json", nil)
if err != nil {
obj, _, err = cli.call("GET", "/images/"+name+"/json", nil)
if err != nil {
@@ -764,7 +762,8 @@ func (cli *DockerCli) CmdRm(args ...string) error {
val.Set("link", "1")
}
for _, name := range cmd.Args() {
_, _, err := cli.call("DELETE", "/containers/"+name+"?"+val.Encode(), nil)
encName := cleanName(name)
_, _, err := cli.call("DELETE", "/containers/"+encName+"?"+val.Encode(), nil)
if err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
} else {
@@ -786,7 +785,8 @@ func (cli *DockerCli) CmdKill(args ...string) error {
}
for _, name := range args {
_, _, err := cli.call("POST", "/containers/"+name+"/kill", nil)
encName := cleanName(name)
_, _, err := cli.call("POST", "/containers/"+encName+"/kill", nil)
if err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
} else {
@@ -997,19 +997,25 @@ func (cli *DockerCli) CmdImages(args ...string) error {
out.Tag = "<none>"
}
if !*noTrunc {
out.ID = utils.TruncateID(out.ID)
}
if !*quiet {
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t", out.Repository, out.Tag, out.ID, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))))
fmt.Fprintf(w, "%s\t%s\t", out.Repository, out.Tag)
if *noTrunc {
fmt.Fprintf(w, "%s\t", out.ID)
} else {
fmt.Fprintf(w, "%s\t", utils.TruncateID(out.ID))
}
fmt.Fprintf(w, "%s ago\t", utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))))
if out.VirtualSize > 0 {
fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.Size), utils.HumanSize(out.VirtualSize))
} else {
fmt.Fprintf(w, "%s\n", utils.HumanSize(out.Size))
}
} else {
fmt.Fprintln(w, out.ID)
if *noTrunc {
fmt.Fprintln(w, out.ID)
} else {
fmt.Fprintln(w, utils.TruncateID(out.ID))
}
}
}
@@ -1088,17 +1094,17 @@ func (cli *DockerCli) CmdPs(args ...string) error {
}
for _, out := range outs {
if !*noTrunc {
out.ID = utils.TruncateID(out.ID)
for i := 0; i < len(out.Names); i++ {
out.Names[i] = utils.Trunc(out.Names[i], 10)
}
names := strings.Join(out.Names, ",")
if !*quiet {
if !*noTrunc {
out.Command = utils.Trunc(out.Command, 20)
for i := 0; i < len(out.Names); i++ {
out.Names[i] = utils.Trunc(out.Names[i], 10)
}
if *noTrunc {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\t%s\t", out.ID, out.Image, out.Command, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, displayablePorts(out.Ports), names)
} else {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\t%s\t", utils.TruncateID(out.ID), out.Image, utils.Trunc(out.Command, 20), utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, displayablePorts(out.Ports), names)
}
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\t%s\t", out.ID, out.Image, out.Command, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, displayablePorts(out.Ports), strings.Join(out.Names, ","))
if *size {
if out.SizeRootFs > 0 {
fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.SizeRw), utils.HumanSize(out.SizeRootFs))
@@ -1109,7 +1115,11 @@ func (cli *DockerCli) CmdPs(args ...string) error {
fmt.Fprint(w, "\n")
}
} else {
fmt.Fprintln(w, out.ID)
if *noTrunc {
fmt.Fprintln(w, out.ID)
} else {
fmt.Fprintln(w, utils.TruncateID(out.ID))
}
}
}
@@ -1294,7 +1304,7 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
cmd.Usage()
return nil
}
name := cmd.Arg(0)
name := cleanName(cmd.Arg(0))
if err := cli.hijack("POST", "/containers/"+name+"/attach?logs=1&stdout=1&stderr=1", false, nil, cli.out, cli.err); err != nil {
return err
@@ -1312,6 +1322,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
return nil
}
name := cmd.Arg(0)
name = cleanName(name)
body, _, err := cli.call("GET", "/containers/"+name+"/json", nil)
if err != nil {
return err
@@ -1392,6 +1403,18 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
// Ports type - Used to parse multiple -p flags
type ports []int
// ListOpts type
type ListOpts []string
func (opts *ListOpts) String() string {
return fmt.Sprint(*opts)
}
func (opts *ListOpts) Set(value string) error {
*opts = append(*opts, value)
return nil
}
// AttachOpts stores arguments to 'docker run -a', eg. which streams to attach to
type AttachOpts map[string]bool
@@ -1587,11 +1610,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
if config.AttachStdin || config.AttachStdout || config.AttachStderr {
if config.Tty {
if err := cli.monitorTtySize(runResult.ID); err != nil {
// When running the test suite, there is no terminal, just pipes.
// Discard the error then.
if os.Getenv("TEST") != "1" {
utils.Errorf("Error monitoring TTY size: %s\n", err)
}
utils.Debugf("Error monitoring TTY size: %s\n", err)
}
}
@@ -1700,10 +1719,6 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int,
params = bytes.NewBuffer(buf)
}
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), params)
if err != nil {
return nil, -1, err
@@ -1749,11 +1764,6 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, h
if (method == "POST" || method == "PUT") && in == nil {
in = bytes.NewReader([]byte{})
}
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), in)
if err != nil {
return err
@@ -1810,9 +1820,6 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, h
}
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer) error {
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), nil)
if err != nil {
@@ -1868,11 +1875,11 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
}
if tcpc, ok := rwc.(*net.TCPConn); ok {
if err := tcpc.CloseWrite(); err != nil {
utils.Errorf("Couldn't send EOF: %s\n", err)
utils.Debugf("Couldn't send EOF: %s\n", err)
}
} else if unixc, ok := rwc.(*net.UnixConn); ok {
if err := unixc.CloseWrite(); err != nil {
utils.Errorf("Couldn't send EOF: %s\n", err)
utils.Debugf("Couldn't send EOF: %s\n", err)
}
}
// Discard errors due to pipe interruption
@@ -1881,14 +1888,14 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
if stdout != nil {
if err := <-receiveStdout; err != nil {
utils.Errorf("Error receiveStdout: %s", err)
utils.Debugf("Error receiveStdout: %s", err)
return err
}
}
if !cli.isTerminal {
if err := <-sendStdin; err != nil {
utils.Errorf("Error sendStdin: %s", err)
utils.Debugf("Error sendStdin: %s", err)
return err
}
}
@@ -1902,7 +1909,7 @@ func (cli *DockerCli) getTtySize() (int, int) {
}
ws, err := term.GetWinsize(cli.terminalFd)
if err != nil {
utils.Errorf("Error getting size: %s", err)
utils.Debugf("Error getting size: %s", err)
if ws == nil {
return 0, 0
}
@@ -1919,7 +1926,7 @@ func (cli *DockerCli) resizeTty(id string) {
v.Set("h", strconv.Itoa(height))
v.Set("w", strconv.Itoa(width))
if _, _, err := cli.call("POST", "/containers/"+id+"/resize?"+v.Encode(), nil); err != nil {
utils.Errorf("Error resize: %s", err)
utils.Debugf("Error resize: %s", err)
}
}
@@ -1990,6 +1997,10 @@ func getExitCode(cli *DockerCli, containerId string) (int, error) {
return c.State.ExitCode, nil
}
func cleanName(name string) string {
return strings.Replace(name, "/", "%252F", -1)
}
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string) *DockerCli {
var (
isTerminal = false
-1
View File
@@ -545,7 +545,6 @@ func TestAttachDisconnect(t *testing.T) {
// Expected behaviour: container gets deleted automatically after exit
func TestRunAutoRemove(t *testing.T) {
t.Skip("Fixme. Skipping test for now, race condition")
stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime)
+10 -10
View File
@@ -5,14 +5,14 @@ import (
)
type DaemonConfig struct {
Pidfile string
GraphPath string
ProtoAddresses []string
AutoRestart bool
EnableCors bool
Dns []string
EnableIptables bool
BridgeIface string
DefaultIp net.IP
InterContainerCommunication bool
Pidfile string
GraphPath string
ProtoAddresses []string
AutoRestart bool
EnableCors bool
Dns []string
EnableIptables bool
BridgeIface string
DefaultIp net.IP
DeviceSet DeviceSet
}
+72 -96
View File
@@ -42,7 +42,6 @@ type Container struct {
ResolvConfPath string
HostnamePath string
HostsPath string
FilesystemType string
cmd *exec.Cmd
stdout *utils.WriteBroadcaster
@@ -168,30 +167,30 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
flCpuShares := cmd.Int64("c", 0, "CPU shares (relative weight)")
var flPublish utils.ListOpts
var flPublish ListOpts
cmd.Var(&flPublish, "p", "Publish a container's port to the host (use 'docker port' to see the actual mapping)")
var flExpose utils.ListOpts
var flExpose ListOpts
cmd.Var(&flExpose, "expose", "Expose a port from the container without publishing it to your host")
var flEnv utils.ListOpts
var flEnv ListOpts
cmd.Var(&flEnv, "e", "Set environment variables")
var flDns utils.ListOpts
var flDns ListOpts
cmd.Var(&flDns, "dns", "Set custom dns servers")
flVolumes := NewPathOpts()
cmd.Var(flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")
var flVolumesFrom utils.ListOpts
var flVolumesFrom ListOpts
cmd.Var(&flVolumesFrom, "volumes-from", "Mount volumes from the specified container")
flEntrypoint := cmd.String("entrypoint", "", "Overwrite the default entrypoint of the image")
var flLxcOpts utils.ListOpts
var flLxcOpts ListOpts
cmd.Var(&flLxcOpts, "lxc-conf", "Add custom lxc options -lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
var flLinks utils.ListOpts
var flLinks ListOpts
cmd.Var(&flLinks, "link", "Add link to another container (containerid:alias)")
if err := cmd.Parse(args); err != nil {
@@ -457,9 +456,9 @@ func (container *Container) startPty() error {
// Copy the PTYs to our broadcasters
go func() {
defer container.stdout.CloseWriters()
utils.Debugf("startPty: begin of stdout pipe")
utils.Debugf("[startPty] Begin of stdout pipe")
io.Copy(container.stdout, ptyMaster)
utils.Debugf("startPty: end of stdout pipe")
utils.Debugf("[startPty] End of stdout pipe")
}()
// stdin
@@ -468,9 +467,9 @@ func (container *Container) startPty() error {
container.cmd.SysProcAttr.Setctty = true
go func() {
defer container.stdin.Close()
utils.Debugf("startPty: begin of stdin pipe")
utils.Debugf("[startPty] Begin of stdin pipe")
io.Copy(ptyMaster, container.stdin)
utils.Debugf("startPty: end of stdin pipe")
utils.Debugf("[startPty] End of stdin pipe")
}()
}
if err := container.cmd.Start(); err != nil {
@@ -490,9 +489,9 @@ func (container *Container) start() error {
}
go func() {
defer stdin.Close()
utils.Debugf("start: begin of stdin pipe")
utils.Debugf("Begin of stdin pipe [start]")
io.Copy(stdin, container.stdin)
utils.Debugf("start: end of stdin pipe")
utils.Debugf("End of stdin pipe [start]")
}()
}
return container.cmd.Start()
@@ -509,8 +508,8 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
errors <- err
} else {
go func() {
utils.Debugf("attach: stdin: begin")
defer utils.Debugf("attach: stdin: end")
utils.Debugf("[start] attach stdin\n")
defer utils.Debugf("[end] attach stdin\n")
// No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
if container.Config.StdinOnce && !container.Config.Tty {
defer cStdin.Close()
@@ -528,7 +527,7 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
_, err = io.Copy(cStdin, stdin)
}
if err != nil {
utils.Errorf("attach: stdin: %s", err)
utils.Debugf("[error] attach stdin: %s\n", err)
}
// Discard error, expecting pipe error
errors <- nil
@@ -542,8 +541,8 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
} else {
cStdout = p
go func() {
utils.Debugf("attach: stdout: begin")
defer utils.Debugf("attach: stdout: end")
utils.Debugf("[start] attach stdout\n")
defer utils.Debugf("[end] attach stdout\n")
// If we are in StdinOnce mode, then close stdin
if container.Config.StdinOnce && stdin != nil {
defer stdin.Close()
@@ -552,11 +551,8 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
defer stdinCloser.Close()
}
_, err := io.Copy(stdout, cStdout)
if err == io.ErrClosedPipe {
err = nil
}
if err != nil {
utils.Errorf("attach: stdout: %s", err)
utils.Debugf("[error] attach stdout: %s\n", err)
}
errors <- err
}()
@@ -566,8 +562,9 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
if stdinCloser != nil {
defer stdinCloser.Close()
}
if cStdout, err := container.StdoutPipe(); err != nil {
utils.Errorf("attach: stdout pipe: %s", err)
utils.Debugf("Error stdout pipe")
} else {
io.Copy(&utils.NopWriter{}, cStdout)
}
@@ -580,8 +577,8 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
} else {
cStderr = p
go func() {
utils.Debugf("attach: stderr: begin")
defer utils.Debugf("attach: stderr: end")
utils.Debugf("[start] attach stderr\n")
defer utils.Debugf("[end] attach stderr\n")
// If we are in StdinOnce mode, then close stdin
if container.Config.StdinOnce && stdin != nil {
defer stdin.Close()
@@ -590,11 +587,8 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
defer stdinCloser.Close()
}
_, err := io.Copy(stderr, cStderr)
if err == io.ErrClosedPipe {
err = nil
}
if err != nil {
utils.Errorf("attach: stderr: %s", err)
utils.Debugf("[error] attach stderr: %s\n", err)
}
errors <- err
}()
@@ -606,7 +600,7 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
}
if cStderr, err := container.StderrPipe(); err != nil {
utils.Errorf("attach: stdout pipe: %s", err)
utils.Debugf("Error stdout pipe")
} else {
io.Copy(&utils.NopWriter{}, cStderr)
}
@@ -620,29 +614,24 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
if cStderr != nil {
defer cStderr.Close()
}
// FIXME: how to clean up the stdin goroutine without the unwanted side effect
// FIXME: how do clean up the stdin goroutine without the unwanted side effect
// of closing the passed stdin? Add an intermediary io.Pipe?
for i := 0; i < nJobs; i += 1 {
utils.Debugf("attach: waiting for job %d/%d", i+1, nJobs)
utils.Debugf("Waiting for job %d/%d\n", i+1, nJobs)
if err := <-errors; err != nil {
utils.Errorf("attach: job %d returned error %s, aborting all jobs", i+1, err)
utils.Debugf("Job %d returned error %s. Aborting all jobs\n", i+1, err)
return err
}
utils.Debugf("attach: job %d completed successfully", i+1)
utils.Debugf("Job %d completed successfully\n", i+1)
}
utils.Debugf("attach: all jobs completed successfully")
utils.Debugf("All jobs completed successfully\n")
return nil
})
}
func (container *Container) Start(hostConfig *HostConfig) (err error) {
func (container *Container) Start(hostConfig *HostConfig) error {
container.State.Lock()
defer container.State.Unlock()
defer func() {
if err != nil {
container.cleanup()
}
}()
if hostConfig == nil { // in docker start of docker restart we want to reuse previous HostConfigFile
hostConfig, _ = container.ReadHostConfig()
@@ -980,14 +969,9 @@ func (container *Container) Output() (output []byte, err error) {
return output, err
}
// Container.StdinPipe returns a WriteCloser which can be used to feed data
// to the standard input of the container's active process.
// Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
// which can be used to retrieve the standard output (and error) generated
// by the container's active process. The output (and error) are actually
// copied and delivered to all StdoutPipe and StderrPipe consumers, using
// a kind of "broadcaster".
// StdinPipe() returns a pipe connected to the standard input of the container's
// active process.
//
func (container *Container) StdinPipe() (io.WriteCloser, error) {
return container.stdinPipe, nil
}
@@ -1088,7 +1072,7 @@ func (container *Container) allocateNetwork(hostConfig *HostConfig) error {
}
func (container *Container) releaseNetwork() {
if container.Config.NetworkDisabled || container.network == nil {
if container.Config.NetworkDisabled {
return
}
container.network.Release()
@@ -1096,7 +1080,7 @@ func (container *Container) releaseNetwork() {
container.NetworkSettings = &NetworkSettings{}
}
// FIXME: replace this with a control socket within dockerinit
// FIXME: replace this with a control socket within docker-init
func (container *Container) waitLxc() error {
for {
output, err := exec.Command("lxc-info", "-n", container.ID).CombinedOutput()
@@ -1112,24 +1096,20 @@ func (container *Container) waitLxc() error {
func (container *Container) monitor(hostConfig *HostConfig) {
// Wait for the program to exit
utils.Debugf("Waiting for process")
// If the command does not exist, try to wait via lxc
// (This probably happens only for ghost containers, i.e. containers that were running when Docker started)
// If the command does not exists, try to wait via lxc
if container.cmd == nil {
utils.Debugf("monitor: waiting for container %s using waitLxc", container.ID)
if err := container.waitLxc(); err != nil {
// Discard the error as any signals or non 0 returns will generate an error
utils.Debugf("monitor: while waiting for container %s, waitLxc had a problem: %s", container.ShortID(), err)
utils.Debugf("%s: Process: %s", container.ID, err)
}
} else {
utils.Debugf("monitor: waiting for container %s using cmd.Wait", container.ID)
if err := container.cmd.Wait(); err != nil {
// Since non-zero exit status and signal terminations will cause err to be non-nil,
// we have to actually discard it. Still, log it anyway, just in case.
utils.Debugf("monitor: cmd.Wait reported exit status %s for container %s", err, container.ID)
// Discard the error as any signals or non 0 returns will generate an error
utils.Debugf("%s: Process: %s", container.ID, err)
}
}
utils.Debugf("monitor: container %s finished", container.ID)
utils.Debugf("Process finished")
exitCode := -1
if container.cmd != nil {
@@ -1144,7 +1124,36 @@ func (container *Container) monitor(hostConfig *HostConfig) {
}
// Cleanup
container.cleanup()
container.releaseNetwork()
// Disable all active links
if container.activeLinks != nil {
for _, link := range container.activeLinks {
link.Disable()
}
}
if container.Config.OpenStdin {
if err := container.stdin.Close(); err != nil {
utils.Debugf("%s: Error close stdin: %s", container.ID, err)
}
}
if err := container.stdout.CloseWriters(); err != nil {
utils.Debugf("%s: Error close stdout: %s", container.ID, err)
}
if err := container.stderr.CloseWriters(); err != nil {
utils.Debugf("%s: Error close stderr: %s", container.ID, err)
}
if container.ptyMaster != nil {
if err := container.ptyMaster.Close(); err != nil {
utils.Debugf("%s: Error closing Pty master: %s", container.ID, err)
}
}
if err := container.Unmount(); err != nil {
log.Printf("%v: Failed to umount filesystem: %v", container.ID, err)
}
// Re-create a brand new stdin pipe once the container exited
if container.Config.OpenStdin {
@@ -1165,39 +1174,6 @@ func (container *Container) monitor(hostConfig *HostConfig) {
}
}
func (container *Container) cleanup() {
container.releaseNetwork()
// Disable all active links
if container.activeLinks != nil {
for _, link := range container.activeLinks {
link.Disable()
}
}
if container.Config.OpenStdin {
if err := container.stdin.Close(); err != nil {
utils.Errorf("%s: Error close stdin: %s", container.ID, err)
}
}
if err := container.stdout.CloseWriters(); err != nil {
utils.Errorf("%s: Error close stdout: %s", container.ID, err)
}
if err := container.stderr.CloseWriters(); err != nil {
utils.Errorf("%s: Error close stderr: %s", container.ID, err)
}
if container.ptyMaster != nil {
if err := container.ptyMaster.Close(); err != nil {
utils.Errorf("%s: Error closing Pty master: %s", container.ID, err)
}
}
if err := container.Unmount(); err != nil {
log.Printf("%v: Failed to umount filesystem: %v", container.ID, err)
}
}
func (container *Container) kill() error {
if !container.State.Running {
return nil
+2 -22
View File
@@ -407,27 +407,6 @@ func TestOutput(t *testing.T) {
}
}
func TestContainerNetwork(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, _, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"ping", "-c", "1", "127.0.0.1"},
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
if err := container.Run(); err != nil {
t.Fatal(err)
}
if container.State.ExitCode != 0 {
t.Errorf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", container.State.ExitCode)
}
}
func TestKillDifferentUser(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
@@ -1093,6 +1072,7 @@ func TestLXCConfig(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
container.generateLXCConfig(nil)
grepFile(t, container.lxcConfigPath(), "lxc.utsname = foobar")
grepFile(t, container.lxcConfigPath(),
@@ -1209,7 +1189,7 @@ func BenchmarkRunParallel(b *testing.B) {
}
func tempDir(t *testing.T) string {
tmpDir, err := ioutil.TempDir("", "docker-test-container")
tmpDir, err := ioutil.TempDir("", "docker-test")
if err != nil {
t.Fatal(err)
}
+1
View File
@@ -1 +1,2 @@
Tianon Gravi <admwiggin@gmail.com> (@tianon)
Kawsar Saiyeed <kawsar.saiyeed@projiris.com> (@KSid)
-242
View File
@@ -1,242 +0,0 @@
#compdef docker
#
# zsh completion for docker (http://docker.io)
#
# version: 0.2.2
# author: Felix Riedel
# license: BSD License
# github: https://github.com/felixr/docker-zsh-completion
#
__parse_docker_list() {
sed -e '/^ID/d' -e 's/[ ]\{2,\}/|/g' -e 's/ \([hdwm]\)\(inutes\|ays\|ours\|eeks\)/\1/' | awk ' BEGIN {FS="|"} { printf("%s:%7s, %s\n", $1, $4, $2)}'
}
__docker_stoppedcontainers() {
local expl
declare -a stoppedcontainers
stoppedcontainers=(${(f)"$(docker ps -a | grep --color=never 'Exit' | __parse_docker_list )"})
_describe -t containers-stopped "Stopped Containers" stoppedcontainers
}
__docker_runningcontainers() {
local expl
declare -a containers
containers=(${(f)"$(docker ps | __parse_docker_list)"})
_describe -t containers-active "Running Containers" containers
}
__docker_containers () {
__docker_stoppedcontainers
__docker_runningcontainers
}
__docker_images () {
local expl
declare -a images
images=(${(f)"$(docker images | awk '(NR > 1){printf("%s\\:%s\n", $1,$2)}')"})
images=($images ${(f)"$(docker images | awk '(NR > 1){printf("%s:%-15s in %s\n", $3,$2,$1)}')"})
_describe -t docker-images "Images" images
}
__docker_tags() {
local expl
declare -a tags
tags=(${(f)"$(docker images | awk '(NR>1){print $2}'| sort | uniq)"})
_describe -t docker-tags "tags" tags
}
__docker_search() {
# declare -a dockersearch
local cache_policy
zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
if [[ -z "$cache_policy" ]]; then
zstyle ":completion:${curcontext}:" cache-policy __docker_caching_policy
fi
local searchterm cachename
searchterm="${words[$CURRENT]%/}"
cachename=_docker-search-$searchterm
local expl
local -a result
if ( [[ ${(P)+cachename} -eq 0 ]] || _cache_invalid ${cachename#_} ) \
&& ! _retrieve_cache ${cachename#_}; then
_message "Searching for ${searchterm}..."
result=(${(f)"$(docker search ${searchterm} | awk '(NR>2){print $1}')"})
_store_cache ${cachename#_} result
fi
_wanted dockersearch expl 'Available images' compadd -a result
}
__docker_caching_policy()
{
# oldp=( "$1"(Nmh+24) ) # 24 hour
oldp=( "$1"(Nmh+1) ) # 24 hour
(( $#oldp ))
}
__docker_repositories () {
local expl
declare -a repos
repos=(${(f)"$(docker images | sed -e '1d' -e 's/[ ].*//' | sort | uniq)"})
_describe -t docker-repos "Repositories" repos
}
__docker_commands () {
# local -a _docker_subcommands
local cache_policy
zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
if [[ -z "$cache_policy" ]]; then
zstyle ":completion:${curcontext}:" cache-policy __docker_caching_policy
fi
if ( [[ ${+_docker_subcommands} -eq 0 ]] || _cache_invalid docker_subcommands) \
&& ! _retrieve_cache docker_subcommands;
then
_docker_subcommands=(${${(f)"$(_call_program commands
docker 2>&1 | sed -e '1,6d' -e '/^[ ]*$/d' -e 's/[ ]*\([^ ]\+\)\s*\([^ ].*\)/\1:\2/' )"}})
_docker_subcommands=($_docker_subcommands 'help:Show help for a command')
_store_cache docker_subcommands _docker_subcommands
fi
_describe -t docker-commands "docker command" _docker_subcommands
}
__docker_subcommand () {
local -a _command_args
case "$words[1]" in
(attach|wait)
_arguments ':containers:__docker_runningcontainers'
;;
(build)
_arguments \
'-t=-:repository:__docker_repositories' \
':path or URL:_directories'
;;
(commit)
_arguments \
':container:__docker_containers' \
':repository:__docker_repositories' \
':tag: '
;;
(diff|export|logs)
_arguments '*:containers:__docker_containers'
;;
(history)
_arguments '*:images:__docker_images'
;;
(images)
_arguments \
'-a[Show all images]' \
':repository:__docker_repositories'
;;
(inspect)
_arguments '*:containers:__docker_containers'
;;
(history)
_arguments ':images:__docker_images'
;;
(insert)
_arguments '1:containers:__docker_containers' \
'2:URL:(http:// file://)' \
'3:file:_files'
;;
(kill)
_arguments '*:containers:__docker_runningcontainers'
;;
(port)
_arguments '1:containers:__docker_runningcontainers'
;;
(start)
_arguments '*:containers:__docker_stoppedcontainers'
;;
(rm)
_arguments '-v[Remove the volumes associated to the container]' \
'*:containers:__docker_stoppedcontainers'
;;
(rmi)
_arguments '-v[Remove the volumes associated to the container]' \
'*:images:__docker_images'
;;
(top)
_arguments '1:containers:__docker_runningcontainers'
;;
(restart|stop)
_arguments '-t=-[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)' \
'*:containers:__docker_runningcontainers'
;;
(top)
_arguments ':containers:__docker_runningcontainers'
;;
(ps)
_arguments '-a[Show all containers. Only running containers are shown by default]' \
'-h[Show help]' \
'-beforeId=-[Show only container created before Id, include non-running one]:containers:__docker_containers' \
'-n=-[Show n last created containers, include non-running one]:n:(1 5 10 25 50)'
;;
(tag)
_arguments \
'-f[force]'\
':image:__docker_images'\
':repository:__docker_repositories' \
':tag:__docker_tags'
;;
(run)
_arguments \
'-a=-[Attach to stdin, stdout or stderr]:toggle:(true false)' \
'-c=-[CPU shares (relative weight)]:CPU shares: ' \
'-d[Detached mode: leave the container running in the background]' \
'*-dns=[Set custom dns servers]:dns server: ' \
'*-e=[Set environment variables]:environment variable: ' \
'-entrypoint=-[Overwrite the default entrypoint of the image]:entry point: ' \
'-h=-[Container host name]:hostname:_hosts' \
'-i[Keep stdin open even if not attached]' \
'-m=-[Memory limit (in bytes)]:limit: ' \
'*-p=-[Expose a container''s port to the host]:port:_ports' \
'-t=-[Allocate a pseudo-tty]:toggle:(true false)' \
'-u=-[Username or UID]:user:_users' \
'*-v=-[Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)]:volume: '\
'-volumes-from=-[Mount volumes from the specified container]:volume: ' \
'(-):images:__docker_images' \
'(-):command: _command_names -e' \
'*::arguments: _normal'
;;
(pull|search)
_arguments ':name:__docker_search'
;;
(help)
_arguments ':subcommand:__docker_commands'
;;
(*)
_message 'Unknown sub command'
esac
}
_docker () {
local curcontext="$curcontext" state line
typeset -A opt_args
_arguments -C \
'-H=-[tcp://host:port to bind/connect to]:socket: ' \
'(-): :->command' \
'(-)*:: :->option-or-argument'
if (( CURRENT == 1 )); then
fi
case $state in
(command)
__docker_commands
;;
(option-or-argument)
curcontext=${curcontext%:*:*}:docker-$words[1]:
__docker_subcommand
;;
esac
}
_docker "$@"
View File
+61
View File
@@ -0,0 +1,61 @@
#!/bin/sh
# This script is meant for quick & easy install via 'curl URL-OF-SCRIPT | sh'
# Original version by Jeff Lindsay <progrium@gmail.com>
# Revamped by Jerome Petazzoni <jerome@dotcloud.com>
#
# This script canonical location is https://get.docker.io/; to update it, run:
# s3cmd put -m text/x-shellscript -P install.sh s3://get.docker.io/index
echo "Ensuring basic dependencies are installed..."
apt-get -qq update
apt-get -qq install lxc wget
echo "Looking in /proc/filesystems to see if we have AUFS support..."
if grep -q aufs /proc/filesystems
then
echo "Found."
else
echo "Ahem, it looks like the current kernel does not support AUFS."
echo "Let's see if we can load the AUFS module with modprobe..."
if modprobe aufs
then
echo "Module loaded."
else
echo "Ahem, things didn't turn out as expected."
KPKG=linux-image-extra-$(uname -r)
echo "Trying to install $KPKG..."
if apt-get -qq install $KPKG
then
echo "Installed."
else
echo "Oops, we couldn't install the -extra kernel."
echo "Are you sure you are running a supported version of Ubuntu?"
echo "Proceeding anyway, but Docker will probably NOT WORK!"
fi
fi
fi
echo "Downloading docker binary to /usr/local/bin..."
curl -s https://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-latest \
> /usr/local/bin/docker
chmod +x /usr/local/bin/docker
if [ -f /etc/init/dockerd.conf ]
then
echo "Upstart script already exists."
else
echo "Creating /etc/init/dockerd.conf..."
cat >/etc/init/dockerd.conf <<EOF
description "Docker daemon"
start on filesystem and started lxc-net
stop on runlevel [!2345]
respawn
exec /usr/local/bin/docker -d
EOF
fi
echo "Starting dockerd..."
start dockerd > /dev/null
echo "Done."
echo
-67
View File
@@ -1,67 +0,0 @@
#!/bin/bash
# Generate a minimal filesystem for archlinux and load it into the local
# docker as "archlinux"
# requires root
set -e
PACSTRAP=$(which pacstrap)
[ "$PACSTRAP" ] || {
echo "Could not find pacstrap. Run pacman -S arch-install-scripts"
exit 1
}
EXPECT=$(which expect)
[ "$EXPECT" ] || {
echo "Could not find expect. Run pacman -S expect"
exit 1
}
ROOTFS=~/rootfs-arch-$$-$RANDOM
mkdir $ROOTFS
#packages to ignore for space savings
PKGIGNORE=linux,jfsutils,lvm2,cryptsetup,groff,man-db,man-pages,mdadm,pciutils,pcmciautils,reiserfsprogs,s-nail,xfsprogs
expect <<EOF
set timeout 60
set send_slow {1 1}
spawn pacstrap -c -d -G -i $ROOTFS base haveged --ignore $PKGIGNORE
expect {
"Install anyway?" { send n\r; exp_continue }
"(default=all)" { send \r; exp_continue }
"Proceed with installation?" { send "\r"; exp_continue }
"skip the above package" {send "y\r"; exp_continue }
"checking" { exp_continue }
"loading" { exp_continue }
"installing" { exp_continue }
}
EOF
arch-chroot $ROOTFS /bin/sh -c "haveged -w 1024; pacman-key --init; pkill haveged; pacman -Rs --noconfirm haveged; pacman-key --populate archlinux"
arch-chroot $ROOTFS /bin/sh -c "ln -s /usr/share/zoneinfo/UTC /etc/localtime"
cat > $ROOTFS/etc/locale.gen <<DELIM
en_US.UTF-8 UTF-8
en_US ISO-8859-1
DELIM
arch-chroot $ROOTFS locale-gen
arch-chroot $ROOTFS /bin/sh -c 'echo "Server = http://mirrors.kernel.org/archlinux/\$repo/os/\$arch" > /etc/pacman.d/mirrorlist'
# udev doesn't work in containers, rebuild /dev
DEV=${ROOTFS}/dev
mv ${DEV} ${DEV}.old
mkdir -p ${DEV}
mknod -m 666 ${DEV}/null c 1 3
mknod -m 666 ${DEV}/zero c 1 5
mknod -m 666 ${DEV}/random c 1 8
mknod -m 666 ${DEV}/urandom c 1 9
mkdir -m 755 ${DEV}/pts
mkdir -m 1777 ${DEV}/shm
mknod -m 666 ${DEV}/tty c 5 0
mknod -m 600 ${DEV}/console c 5 1
mknod -m 666 ${DEV}/tty0 c 4 0
mknod -m 666 ${DEV}/full c 1 7
mknod -m 600 ${DEV}/initctl p
mknod -m 666 ${DEV}/ptmx c 5 2
tar -C $ROOTFS -c . | docker import - archlinux
docker run -i -t archlinux echo Success.
rm -rf $ROOTFS
+5 -22
View File
@@ -10,18 +10,12 @@ variant='minbase'
include='iproute,iputils-ping'
repo="$1"
suite="$2"
suite="${2:-$stableSuite}"
mirror="${3:-}" # stick to the default debootstrap mirror if one is not provided
if [ ! "$repo" ] || [ ! "$suite" ]; then
echo >&2 "usage: $0 repo suite [mirror]"
echo >&2
if [ ! "$repo" ]; then
echo >&2 "usage: $0 repo [suite [mirror]]"
echo >&2 " ie: $0 tianon/debian squeeze"
echo >&2 " $0 tianon/debian squeeze http://ftp.uk.debian.org/debian/"
echo >&2
echo >&2 " ie: $0 tianon/ubuntu precise"
echo >&2 " $0 tianon/ubuntu precise http://mirrors.melbourne.co.uk/ubuntu/"
echo >&2
exit 1
fi
@@ -39,12 +33,8 @@ sudo debootstrap --verbose --variant="$variant" --include="$include" "$suite" "$
cd "$target"
# prevent init scripts from running during install/update
# policy-rc.d (for most scripts)
echo $'#!/bin/sh\nexit 101' | sudo tee usr/sbin/policy-rc.d > /dev/null
sudo chmod +x usr/sbin/policy-rc.d
# initctl (for some pesky upstart scripts)
sudo chroot . dpkg-divert --local --rename --add /sbin/initctl
sudo ln -sf /bin/true sbin/initctl
# see https://github.com/dotcloud/docker/issues/446#issuecomment-16953173
# shrink the image, since apt makes us fat (wheezy: ~157.5MB vs ~120MB)
@@ -52,16 +42,9 @@ sudo chroot . apt-get clean
# while we're at it, apt is unnecessarily slow inside containers
# this forces dpkg not to call sync() after package extraction and speeds up install
# the benefit is huge on spinning disks, and the penalty is nonexistent on SSD or decent server virtualization
echo 'force-unsafe-io' | sudo tee etc/dpkg/dpkg.cfg.d/02apt-speedup > /dev/null
# we want to effectively run "apt-get clean" after every install to keep images small
echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' | sudo tee etc/apt/apt.conf.d/no-cache > /dev/null
# helpful undo lines for each the above tweaks (for lack of a better home to keep track of them):
# rm /usr/sbin/policy-rc.d
# rm /sbin/initctl; dpkg-divert --rename --remove /sbin/initctl
# rm /etc/dpkg/dpkg.cfg.d/02apt-speedup
# rm /etc/apt/apt.conf.d/no-cache
# we don't need an apt cache in a container
echo 'Acquire::http {No-Cache=True;};' | sudo tee etc/apt/apt.conf.d/no-cache > /dev/null
# create the image (and tag $repo:$suite)
sudo tar -c . | docker import - $repo $suite
-22
View File
@@ -1,22 +0,0 @@
Copyright (c) 2013 Honza Pokorny
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-23
View File
@@ -1,23 +0,0 @@
dockerfile.vim
==============
Syntax highlighting for Dockerfiles
Installation
------------
Via pathogen, the usual way...
Features
--------
The syntax highlighting includes:
* The directives (e.g. `FROM`)
* Strings
* Comments
License
-------
BSD, short and sweet
-18
View File
@@ -1,18 +0,0 @@
*dockerfile.txt* Syntax highlighting for Dockerfiles
Author: Honza Pokorny <http://honza.ca>
License: BSD
INSTALLATION *installation*
Drop it on your Pathogen path and you're all set.
FEATURES *features*
The syntax highlighting includes:
* The directives (e.g. FROM)
* Strings
* Comments
vim:tw=78:et:ft=help:norl:
@@ -1 +0,0 @@
au BufNewFile,BufRead Dockerfile set filetype=dockerfile
-22
View File
@@ -1,22 +0,0 @@
" dockerfile.vim - Syntax highlighting for Dockerfiles
" Maintainer: Honza Pokorny <http://honza.ca>
" Version: 0.5
if exists("b:current_syntax")
finish
endif
let b:current_syntax = "dockerfile"
syntax case ignore
syntax match dockerfileKeyword /\v^\s*(FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD)\s/
syntax match dockerfileKeyword /\v^\s*(ENTRYPOINT|VOLUME|USER|WORKDIR)\s/
highlight link dockerfileKeyword Keyword
syntax region dockerfileString start=/\v"/ skip=/\v\\./ end=/\v"/
highlight link dockerfileString String
syntax match dockerfileComment "\v^\s*#.*$"
highlight link dockerfileComment Comment
+14
View File
@@ -0,0 +1,14 @@
package docker
type DeviceSet interface {
AddDevice(hash, baseHash string) error
SetInitialized(hash string) error
DeactivateDevice(hash string) error
RemoveDevice(hash string) error
MountDevice(hash, path string) error
UnmountDevice(hash, path string, deactivate bool) error
HasDevice(hash string) bool
HasInitializedDevice(hash string) bool
HasActivatedDevice(hash string) bool
Shutdown() error
}
@@ -11,31 +11,31 @@ import (
"path"
"path/filepath"
"strconv"
"sync"
"strings"
"syscall"
"time"
"sync"
)
var (
DefaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024
DefaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024
DefaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024
const (
defaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024
defaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024
defaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024
)
type DevInfo struct {
Hash string `json:"-"`
DeviceId int `json:"device_id"`
Size uint64 `json:"size"`
TransactionId uint64 `json:"transaction_id"`
Initialized bool `json:"initialized"`
devices *DeviceSet `json:"-"`
Hash string `json:"-"`
DeviceId int `json:"device_id"`
Size uint64 `json:"size"`
TransactionId uint64 `json:"transaction_id"`
Initialized bool `json:"initialized"`
devices *DeviceSetDM `json:"-"`
}
type MetaData struct {
Devices map[string]*DevInfo `json:devices`
}
type DeviceSet struct {
type DeviceSetDM struct {
MetaData
sync.Mutex
initialized bool
@@ -47,19 +47,6 @@ type DeviceSet struct {
activeMounts map[string]int
}
type DiskUsage struct {
Used uint64
Total uint64
}
type Status struct {
PoolName string
DataLoopback string
MetadataLoopback string
Data DiskUsage
Metadata DiskUsage
}
func getDevName(name string) string {
return "/dev/mapper/" + name
}
@@ -76,23 +63,23 @@ func (info *DevInfo) DevName() string {
return getDevName(info.Name())
}
func (devices *DeviceSet) loopbackDir() string {
return path.Join(devices.root, "devicemapper")
func (devices *DeviceSetDM) loopbackDir() string {
return path.Join(devices.root, "loopback")
}
func (devices *DeviceSet) jsonFile() string {
func (devices *DeviceSetDM) jsonFile() string {
return path.Join(devices.loopbackDir(), "json")
}
func (devices *DeviceSet) getPoolName() string {
func (devices *DeviceSetDM) getPoolName() string {
return devices.devicePrefix + "-pool"
}
func (devices *DeviceSet) getPoolDevName() string {
func (devices *DeviceSetDM) getPoolDevName() string {
return getDevName(devices.getPoolName())
}
func (devices *DeviceSet) hasImage(name string) bool {
func (devices *DeviceSetDM) hasImage(name string) bool {
dirname := devices.loopbackDir()
filename := path.Join(dirname, name)
@@ -100,11 +87,7 @@ func (devices *DeviceSet) hasImage(name string) bool {
return err == nil
}
// ensureImage creates a sparse file of <size> bytes at the path
// <root>/devicemapper/<name>.
// If the file already exists, it does nothing.
// Either way it returns the full path.
func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
func (devices *DeviceSetDM) ensureImage(name string, size int64) (string, error) {
dirname := devices.loopbackDir()
filename := path.Join(dirname, name)
@@ -129,56 +112,62 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
return filename, nil
}
func (devices *DeviceSet) allocateDeviceId() int {
func (devices *DeviceSetDM) allocateDeviceId() int {
// TODO: Add smarter reuse of deleted devices
id := devices.nextFreeDevice
devices.nextFreeDevice = devices.nextFreeDevice + 1
return id
}
func (devices *DeviceSet) allocateTransactionId() uint64 {
func (devices *DeviceSetDM) allocateTransactionId() uint64 {
devices.NewTransactionId = devices.NewTransactionId + 1
return devices.NewTransactionId
}
func (devices *DeviceSet) saveMetadata() error {
func (devices *DeviceSetDM) saveMetadata() error {
jsonData, err := json.Marshal(devices.MetaData)
if err != nil {
return fmt.Errorf("Error encoding metaadata to json: %s", err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
tmpFile, err := ioutil.TempFile(filepath.Dir(devices.jsonFile()), ".json")
if err != nil {
return fmt.Errorf("Error creating metadata file: %s", err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
n, err := tmpFile.Write(jsonData)
if err != nil {
return fmt.Errorf("Error writing metadata to %s: %s", tmpFile.Name(), err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if n < len(jsonData) {
return io.ErrShortWrite
}
if err := tmpFile.Sync(); err != nil {
return fmt.Errorf("Error syncing metadata file %s: %s", tmpFile.Name(), err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := tmpFile.Close(); err != nil {
return fmt.Errorf("Error closing metadata file %s: %s", tmpFile.Name(), err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := os.Rename(tmpFile.Name(), devices.jsonFile()); err != nil {
return fmt.Errorf("Error committing metadata file", err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if devices.NewTransactionId != devices.TransactionId {
if err = setTransactionId(devices.getPoolDevName(), devices.TransactionId, devices.NewTransactionId); err != nil {
return fmt.Errorf("Error setting devmapper transition ID: %s", err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
devices.TransactionId = devices.NewTransactionId
}
return nil
}
func (devices *DeviceSet) registerDevice(id int, hash string, size uint64) (*DevInfo, error) {
utils.Debugf("registerDevice(%v, %v)", id, hash)
func (devices *DeviceSetDM) registerDevice(id int, hash string, size uint64) (*DevInfo, error) {
info := &DevInfo{
Hash: hash,
DeviceId: id,
@@ -198,8 +187,8 @@ func (devices *DeviceSet) registerDevice(id int, hash string, size uint64) (*Dev
return info, nil
}
func (devices *DeviceSet) activateDeviceIfNeeded(hash string) error {
utils.Debugf("activateDeviceIfNeeded(%v)", hash)
func (devices *DeviceSetDM) activateDeviceIfNeeded(hash string) error {
utils.Debugf("activateDeviceIfNeeded()")
info := devices.Devices[hash]
if info == nil {
return fmt.Errorf("Unknown device %s", hash)
@@ -212,7 +201,7 @@ func (devices *DeviceSet) activateDeviceIfNeeded(hash string) error {
return activateDevice(devices.getPoolDevName(), info.Name(), info.DeviceId, info.Size)
}
func (devices *DeviceSet) createFilesystem(info *DevInfo) error {
func (devices *DeviceSetDM) createFilesystem(info *DevInfo) error {
devname := info.DevName()
err := exec.Command("mkfs.ext4", "-E", "discard,lazy_itable_init=0,lazy_journal_init=0", devname).Run()
@@ -226,9 +215,7 @@ func (devices *DeviceSet) createFilesystem(info *DevInfo) error {
return nil
}
func (devices *DeviceSet) loadMetaData() error {
utils.Debugf("loadMetadata()")
defer utils.Debugf("loadMetadata END")
func (devices *DeviceSetDM) loadMetaData() error {
_, _, _, params, err := getStatus(devices.getPoolName())
if err != nil {
utils.Debugf("\n--->Err: %s\n", err)
@@ -272,7 +259,7 @@ func (devices *DeviceSet) loadMetaData() error {
return nil
}
func (devices *DeviceSet) setupBaseImage() error {
func (devices *DeviceSetDM) setupBaseImage() error {
oldInfo := devices.Devices[""]
if oldInfo != nil && oldInfo.Initialized {
return nil
@@ -296,8 +283,7 @@ func (devices *DeviceSet) setupBaseImage() error {
return err
}
utils.Debugf("Registering base device (id %v) with FS size %v", id, DefaultBaseFsSize)
info, err := devices.registerDevice(id, "", DefaultBaseFsSize)
info, err := devices.registerDevice(id, "", defaultBaseFsSize)
if err != nil {
_ = deleteDevice(devices.getPoolDevName(), id)
utils.Debugf("\n--->Err: %s\n", err)
@@ -331,7 +317,7 @@ func setCloseOnExec(name string) {
if fileInfos != nil {
for _, i := range fileInfos {
link, _ := os.Readlink(filepath.Join("/proc/self/fd", i.Name()))
if link == name {
if link == name {
fd, err := strconv.Atoi(i.Name())
if err == nil {
syscall.CloseOnExec(fd)
@@ -341,95 +327,66 @@ func setCloseOnExec(name string) {
}
}
func (devices *DeviceSet) log(level int, file string, line int, dmError int, message string) {
if level >= 7 {
return // Ignore _LOG_DEBUG
}
utils.Debugf("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message)
}
func major(device uint64) uint64 {
return (device >> 8) & 0xfff
}
func minor(device uint64) uint64 {
return (device & 0xff) | ((device >> 12) & 0xfff00)
}
func (devices *DeviceSet) initDevmapper() error {
logInit(devices)
// Make sure the sparse images exist in <root>/devicemapper/data and
// <root>/devicemapper/metadata
createdLoopback := !devices.hasImage("data") || !devices.hasImage("metadata")
data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
if err != nil {
utils.Debugf("Error device ensureImage (data): %s\n", err)
return err
}
metadata, err := devices.ensureImage("metadata", DefaultMetaDataLoopbackSize)
if err != nil {
utils.Debugf("Error device ensureImage (metadata): %s\n", err)
return err
}
// Set the device prefix from the device id and inode of the docker root dir
st, err := os.Stat(devices.root)
if err != nil {
return fmt.Errorf("Error looking up dir %s: %s", devices.root, err)
}
sysSt := st.Sys().(*syscall.Stat_t)
// "reg-" stands for "regular file".
// In the future we might use "dev-" for "device file", etc.
// docker-maj,min[-inode] stands for:
// - Managed by docker
// - The target of this device is at major <maj> and minor <min>
// - If <inode> is defined, use that file inside the device as a loopback image. Otherwise use the device itself.
devices.devicePrefix = fmt.Sprintf("docker-%d:%d-%d", major(sysSt.Dev), minor(sysSt.Dev), sysSt.Ino)
utils.Debugf("Generated prefix: %s", devices.devicePrefix)
// Check for the existence of the device <prefix>-pool
utils.Debugf("Checking for existence of the pool '%s'", devices.getPoolName())
func (devices *DeviceSetDM) initDevmapper() error {
info, err := getInfo(devices.getPoolName())
if info == nil {
utils.Debugf("Error device getInfo: %s", err)
return err
}
utils.Debugf("initDevmapper(). Pool exists: %v", info.Exists)
// It seems libdevmapper opens this without O_CLOEXEC, and go exec will not close files
// that are not Close-on-exec, and lxc-start will die if it inherits any unexpected files,
// so we add this badhack to make sure it closes itself
setCloseOnExec("/dev/mapper/control")
// If the pool doesn't exist, create it
if info.Exists == 0 {
utils.Debugf("Pool doesn't exist. Creating it.")
dataFile, err := AttachLoopDevice(data)
if err != nil {
utils.Debugf("\n--->Err: %s\n", err)
if info.Exists != 0 {
/* Pool exists, assume everything is up */
if err := devices.loadMetaData(); err != nil {
utils.Debugf("Error device loadMetaData: %s\n", err)
return err
}
defer dataFile.Close()
metadataFile, err := AttachLoopDevice(metadata)
if err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
defer metadataFile.Close()
if err := createPool(devices.getPoolName(), dataFile, metadataFile); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
if err := devices.setupBaseImage(); err != nil {
utils.Debugf("Error device setupBaseImage: %s\n", err)
return err
}
return nil
}
/* If we create the loopback mounts we also need to initialize the base fs */
createdLoopback := !devices.hasImage("data") || !devices.hasImage("metadata")
data, err := devices.ensureImage("data", defaultDataLoopbackSize)
if err != nil {
utils.Debugf("Error device ensureImage (data): %s\n", err)
return err
}
metadata, err := devices.ensureImage("metadata", defaultMetaDataLoopbackSize)
if err != nil {
utils.Debugf("Error device ensureImage (metadata): %s\n", err)
return err
}
dataFile, err := AttachLoopDevice(data)
if err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
defer dataFile.Close()
metadataFile, err := AttachLoopDevice(metadata)
if err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
defer metadataFile.Close()
if err := createPool(devices.getPoolName(), dataFile, metadataFile); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
// If we didn't just create the data or metadata image, we need to
// load the metadata from the existing file.
if !createdLoopback {
if err = devices.loadMetaData(); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
@@ -437,16 +394,15 @@ func (devices *DeviceSet) initDevmapper() error {
}
}
// Setup the base image
if err := devices.setupBaseImage(); err != nil {
utils.Debugf("Error device setupBaseImage: %s\n", err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
return nil
}
func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
func (devices *DeviceSetDM) AddDevice(hash, baseHash string) error {
devices.Lock()
defer devices.Unlock()
@@ -461,7 +417,8 @@ func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
baseInfo := devices.Devices[baseHash]
if baseInfo == nil {
return fmt.Errorf("Error adding device for '%s': can't find device for parent '%s'", hash, baseHash)
utils.Debugf("Base Hash not found")
return fmt.Errorf("Unknown base hash %s", baseHash)
}
deviceId := devices.allocateDeviceId()
@@ -479,7 +436,7 @@ func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
return nil
}
func (devices *DeviceSet) removeDevice(hash string) error {
func (devices *DeviceSetDM) removeDevice(hash string) error {
info := devices.Devices[hash]
if info == nil {
return fmt.Errorf("hash %s doesn't exists", hash)
@@ -518,7 +475,7 @@ func (devices *DeviceSet) removeDevice(hash string) error {
return nil
}
func (devices *DeviceSet) RemoveDevice(hash string) error {
func (devices *DeviceSetDM) RemoveDevice(hash string) error {
devices.Lock()
defer devices.Unlock()
@@ -527,112 +484,47 @@ func (devices *DeviceSet) RemoveDevice(hash string) error {
return err
}
return devices.removeDevice(hash)
}
func (devices *DeviceSet) deactivateDevice(hash string) error {
utils.Debugf("[devmapper] deactivateDevice(%s)", hash)
defer utils.Debugf("[devmapper] deactivateDevice END")
var devname string
// FIXME: shouldn't we just register the pool into devices?
devname, err := devices.byHash(hash)
if err != nil {
return err
func (devices *DeviceSetDM) deactivateDevice(hash string) error {
info := devices.Devices[hash]
if info == nil {
return fmt.Errorf("hash %s doesn't exists", hash)
}
devinfo, err := getInfo(devname)
devinfo, err := getInfo(info.Name())
if err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if devinfo.Exists != 0 {
if err := removeDevice(devname); err != nil {
if err := removeDevice(info.Name()); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := devices.waitRemove(hash); err != nil {
return err
}
}
return nil
}
// waitRemove blocks until either:
// a) the device registered at <device_set_prefix>-<hash> is removed,
// or b) the 1 second timeout expires.
func (devices *DeviceSet) waitRemove(hash string) error {
utils.Debugf("[deviceset %s] waitRemove(%s)", devices.devicePrefix, hash)
defer utils.Debugf("[deviceset %s] waitRemove END", devices.devicePrefix, hash)
devname, err := devices.byHash(hash)
if err != nil {
return err
}
i := 0
for ; i < 1000; i += 1 {
devinfo, err := getInfo(devname)
if err != nil {
// If there is an error we assume the device doesn't exist.
// The error might actually be something else, but we can't differentiate.
return nil
}
utils.Debugf("Waiting for removal of %s: exists=%d", devname, devinfo.Exists)
if devinfo.Exists == 0 {
break
}
time.Sleep(1 * time.Millisecond)
}
if i == 1000 {
return fmt.Errorf("Timeout while waiting for device %s to be removed", devname)
}
return nil
}
// waitClose blocks until either:
// a) the device registered at <device_set_prefix>-<hash> is closed,
// or b) the 1 second timeout expires.
func (devices *DeviceSet) waitClose(hash string) error {
devname, err := devices.byHash(hash)
if err != nil {
return err
}
i := 0
for ; i < 1000; i += 1 {
devinfo, err := getInfo(devname)
if err != nil {
return err
}
utils.Debugf("Waiting for unmount of %s: opencount=%d", devname, devinfo.OpenCount)
if devinfo.OpenCount == 0 {
break
}
time.Sleep(1 * time.Millisecond)
}
if i == 1000 {
return fmt.Errorf("Timeout while waiting for device %s to close", devname)
}
return nil
}
// byHash is a hack to allow looking up the deviceset's pool by the hash "pool".
// FIXME: it seems probably cleaner to register the pool in devices.Devices,
// but I am afraid of arcane implications deep in the devicemapper code,
// so this will do.
func (devices *DeviceSet) byHash(hash string) (devname string, err error) {
if hash == "pool" {
return devices.getPoolDevName(), nil
}
info := devices.Devices[hash]
if info == nil {
return "", fmt.Errorf("hash %s doesn't exists", hash)
}
return info.Name(), nil
}
func (devices *DeviceSet) Shutdown() error {
utils.Debugf("[deviceset %s] shutdown()", devices.devicePrefix)
defer utils.Debugf("[deviceset %s] shutdown END", devices.devicePrefix)
func (devices *DeviceSetDM) DeactivateDevice(hash string) error {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
utils.Debugf("DeactivateDevice %s", hash)
return devices.deactivateDevice(hash);
}
func (devices *DeviceSetDM) Shutdown() error {
devices.Lock()
utils.Debugf("[devmapper] Shutting down DeviceSet: %s", devices.root)
defer devices.Unlock()
if !devices.initialized {
@@ -649,9 +541,6 @@ func (devices *DeviceSet) Shutdown() error {
}
for _, d := range devices.Devices {
if err := devices.waitClose(d.Hash); err != nil {
utils.Errorf("Warning: error waiting for device %s to unmount: %s\n", d.Hash, err)
}
if err := devices.deactivateDevice(d.Hash); err != nil {
utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err)
}
@@ -659,7 +548,7 @@ func (devices *DeviceSet) Shutdown() error {
pool := devices.getPoolDevName()
if devinfo, err := getInfo(pool); err == nil && devinfo.Exists != 0 {
if err := devices.deactivateDevice("pool"); err != nil {
if err := removeDevice(pool); err != nil {
utils.Debugf("Shutdown deactivate %s , error: %s\n", pool, err)
}
}
@@ -667,32 +556,29 @@ func (devices *DeviceSet) Shutdown() error {
return nil
}
func (devices *DeviceSet) MountDevice(hash, path string, readOnly bool) error {
func (devices *DeviceSetDM) MountDevice(hash, path string) error {
devices.Lock()
defer devices.Unlock()
if err := devices.ensureInit(); err != nil {
return fmt.Errorf("Error initializing devmapper: %s", err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
if err := devices.activateDeviceIfNeeded(hash); err != nil {
return fmt.Errorf("Error activating devmapper device for '%s': %s", hash, err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
info := devices.Devices[hash]
var flags uintptr = syscall.MS_MGC_VAL
if readOnly {
flags = flags | syscall.MS_RDONLY
}
err := syscall.Mount(info.DevName(), path, "ext4", flags, "discard")
err := syscall.Mount(info.DevName(), path, "ext4", syscall.MS_MGC_VAL, "discard")
if err != nil && err == syscall.EINVAL {
err = syscall.Mount(info.DevName(), path, "ext4", flags, "")
err = syscall.Mount(info.DevName(), path, "ext4", syscall.MS_MGC_VAL, "")
}
if err != nil {
return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), path, err)
utils.Debugf("\n--->Err: %s\n", err)
return err
}
count := devices.activeMounts[path]
@@ -701,23 +587,14 @@ func (devices *DeviceSet) MountDevice(hash, path string, readOnly bool) error {
return nil
}
func (devices *DeviceSet) UnmountDevice(hash, path string, deactivate bool) error {
utils.Debugf("[devmapper] UnmountDevice(hash=%s path=%s)", hash, path)
defer utils.Debugf("[devmapper] UnmountDevice END")
func (devices *DeviceSetDM) UnmountDevice(hash, path string, deactivate bool) error {
devices.Lock()
defer devices.Unlock()
utils.Debugf("[devmapper] Unmount(%s)", path)
if err := syscall.Unmount(path, 0); err != nil {
utils.Debugf("\n--->Err: %s\n", err)
return err
}
utils.Debugf("[devmapper] Unmount done")
// Wait for the unmount to be effective,
// by watching the value of Info.OpenCount for the device
if err := devices.waitClose(hash); err != nil {
return err
}
if count := devices.activeMounts[path]; count > 1 {
devices.activeMounts[path] = count - 1
@@ -732,7 +609,7 @@ func (devices *DeviceSet) UnmountDevice(hash, path string, deactivate bool) erro
return nil
}
func (devices *DeviceSet) HasDevice(hash string) bool {
func (devices *DeviceSetDM) HasDevice(hash string) bool {
devices.Lock()
defer devices.Unlock()
@@ -742,7 +619,7 @@ func (devices *DeviceSet) HasDevice(hash string) bool {
return devices.Devices[hash] != nil
}
func (devices *DeviceSet) HasInitializedDevice(hash string) bool {
func (devices *DeviceSetDM) HasInitializedDevice(hash string) bool {
devices.Lock()
defer devices.Unlock()
@@ -754,7 +631,7 @@ func (devices *DeviceSet) HasInitializedDevice(hash string) bool {
return info != nil && info.Initialized
}
func (devices *DeviceSet) HasActivatedDevice(hash string) bool {
func (devices *DeviceSetDM) HasActivatedDevice(hash string) bool {
devices.Lock()
defer devices.Unlock()
@@ -770,7 +647,7 @@ func (devices *DeviceSet) HasActivatedDevice(hash string) bool {
return devinfo != nil && devinfo.Exists != 0
}
func (devices *DeviceSet) SetInitialized(hash string) error {
func (devices *DeviceSetDM) SetInitialized(hash string) error {
devices.Lock()
defer devices.Unlock()
@@ -794,40 +671,7 @@ func (devices *DeviceSet) SetInitialized(hash string) error {
return nil
}
func (devices *DeviceSet) Status() *Status {
devices.Lock()
defer devices.Unlock()
status := &Status{}
if err := devices.ensureInit(); err != nil {
return status
}
status.PoolName = devices.getPoolName()
status.DataLoopback = path.Join(devices.loopbackDir(), "data")
status.MetadataLoopback = path.Join(devices.loopbackDir(), "metadata")
_, totalSizeInSectors, _, params, err := getStatus(devices.getPoolName())
if err == nil {
var transactionId, dataUsed, dataTotal, metadataUsed, metadataTotal uint64
if _, err := fmt.Sscanf(params, "%d %d/%d %d/%d", &transactionId, &metadataUsed, &metadataTotal, &dataUsed, &dataTotal); err == nil {
// Convert from blocks to bytes
blockSizeInSectors := totalSizeInSectors / dataTotal
status.Data.Used = dataUsed * blockSizeInSectors * 512
status.Data.Total = dataTotal * blockSizeInSectors * 512
// metadata blocks are always 4k
status.Metadata.Used = metadataUsed * 4096
status.Metadata.Total = metadataTotal * 4096
}
}
return status
}
func (devices *DeviceSet) ensureInit() error {
func (devices *DeviceSetDM) ensureInit() error {
if !devices.initialized {
devices.initialized = true
if err := devices.initDevmapper(); err != nil {
@@ -838,12 +682,18 @@ func (devices *DeviceSet) ensureInit() error {
return nil
}
func NewDeviceSet(root string) *DeviceSet {
func NewDeviceSetDM(root string) *DeviceSetDM {
SetDevDir("/dev")
return &DeviceSet{
base := filepath.Base(root)
if !strings.HasPrefix(base, "docker") {
base = "docker-" + base
}
return &DeviceSetDM{
initialized: false,
root: root,
devicePrefix: base,
MetaData: MetaData{Devices: make(map[string]*DevInfo)},
activeMounts: make(map[string]int),
}
+27 -91
View File
@@ -18,7 +18,6 @@ package devmapper
#define LOOP_CTL_GET_FREE 0x4C82
#endif
// FIXME: this could easily be rewritten in go
char* attach_loop_device(const char *filename, int *loop_fd_out)
{
struct loop_info64 loopinfo = {0};
@@ -27,7 +26,6 @@ char* attach_loop_device(const char *filename, int *loop_fd_out)
int i, loop_fd, fd, start_index;
char* loopname;
*loop_fd_out = -1;
start_index = 0;
@@ -49,102 +47,71 @@ char* attach_loop_device(const char *filename, int *loop_fd_out)
loop_fd = -1;
for (i = start_index ; loop_fd < 0 ; i++ ) {
if (sprintf(buf, "/dev/loop%d", i) < 0) {
close(fd);
return NULL;
close(fd);
perror("sprintf");
return NULL;
}
if (stat(buf, &st)) {
if (!S_ISBLK(st.st_mode)) {
fprintf(stderr, "[error] Loopback device %s is not a block device.\n", buf);
} else if (errno == ENOENT) {
fprintf(stderr, "[error] There are no more loopback device available.\n");
} else {
fprintf(stderr, "[error] Unkown error trying to stat the loopback device %s (errno: %d).\n", buf, errno);
}
if (stat(buf, &st) || !S_ISBLK(st.st_mode)) {
close(fd);
return NULL;
}
loop_fd = open(buf, O_RDWR);
if (loop_fd < 0 && errno == ENOENT) {
fprintf(stderr, "[error] The loopback device %s does not exists.\n", buf);
close(fd);
fprintf (stderr, "no available loopback device!");
return NULL;
} else if (loop_fd < 0) {
fprintf(stderr, "[error] Unkown error openning the loopback device %s. (errno: %d)\n", buf, errno);
continue;
}
} else if (loop_fd < 0)
continue;
if (ioctl(loop_fd, LOOP_SET_FD, (void *)(size_t)fd) < 0) {
if (ioctl (loop_fd, LOOP_SET_FD, (void *)(size_t)fd) < 0) {
int errsv = errno;
close(loop_fd);
loop_fd = -1;
if (errsv != EBUSY) {
close(fd);
fprintf(stderr, "cannot set up loopback device %s: %s", buf, strerror(errsv));
close (fd);
fprintf (stderr, "cannot set up loopback device %s: %s", buf, strerror(errsv));
return NULL;
}
continue;
}
close(fd);
close (fd);
strncpy((char*)loopinfo.lo_file_name, buf, LO_NAME_SIZE);
loopinfo.lo_offset = 0;
loopinfo.lo_flags = LO_FLAGS_AUTOCLEAR;
if (ioctl(loop_fd, LOOP_SET_STATUS64, &loopinfo) < 0) {
perror("ioctl LOOP_SET_STATUS64");
perror("ioctl1");
if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) {
perror("ioctl LOOP_CLR_FD");
perror("ioctl2");
}
close(loop_fd);
fprintf (stderr, "cannot set up loopback device info");
return (NULL);
return NULL;
}
loopname = strdup(buf);
if (loopname == NULL) {
close(loop_fd);
return (NULL);
return NULL;
}
*loop_fd_out = loop_fd;
return (loopname);
return loopname;
}
return (NULL);
return NULL;
}
static int64_t get_block_size(int fd)
static int64_t
get_block_size(int fd)
{
uint64_t size;
uint64_t size;
if (ioctl(fd, BLKGETSIZE64, &size) == -1)
return -1;
return ((int64_t)size);
}
extern void DevmapperLogCallback(int level, char *file, int line, int dm_errno_or_class, char *str);
static void
log_cb(int level, const char *file, int line,
int dm_errno_or_class, const char *f, ...)
{
char buffer[256];
va_list ap;
va_start(ap, f);
vsnprintf(buffer, 256, f, ap);
va_end(ap);
DevmapperLogCallback(level, (char *)file, line, dm_errno_or_class, buffer);
}
static void
log_with_errno_init ()
{
dm_log_with_errno_init(log_cb);
return (int64_t)size;
}
*/
@@ -160,10 +127,6 @@ import (
"unsafe"
)
type DevmapperLogger interface {
log(level int, file string, line int, dmError int, message string)
}
const (
DeviceCreate TaskType = iota
DeviceReload
@@ -186,11 +149,6 @@ const (
DeviceSetGeometry
)
const (
AddNodeOnResume AddNodeType = iota
AddNodeOnCreate
)
var (
ErrTaskRun = errors.New("dm_task_run failed")
ErrTaskSetName = errors.New("dm_task_set_name failed")
@@ -224,8 +182,7 @@ type (
ReadOnly int
TargetCount int32
}
TaskType int
AddNodeType int
TaskType int
)
func (t *Task) destroy() {
@@ -257,6 +214,9 @@ func (t *Task) SetName(name string) error {
defer free(c_name)
if res := C.dm_task_set_name(t.unmanaged, c_name); res != 1 {
if os.Getenv("DEBUG") != "" {
C.perror(C.CString(fmt.Sprintf("[debug] Error dm_task_set_name(%s, %#v)", name, t.unmanaged)))
}
return ErrTaskSetName
}
return nil
@@ -288,13 +248,6 @@ func (t *Task) SetCookie(cookie *uint32, flags uint16) error {
return nil
}
func (t *Task) SetAddNode(add_node AddNodeType) error {
if res := C.dm_task_set_add_node(t.unmanaged, C.dm_add_node_t(add_node)); res != 1 {
return ErrTaskSetAddNode
}
return nil
}
func (t *Task) SetRo() error {
if res := C.dm_task_set_ro(t.unmanaged); res != 1 {
return ErrTaskSetRO
@@ -361,9 +314,6 @@ func AttachLoopDevice(filename string) (*os.File, error) {
var fd C.int
res := C.attach_loop_device(c_filename, &fd)
if res == nil {
if os.Getenv("DEBUG") != "" {
C.perror(C.CString(fmt.Sprintf("[debug] Error attach_loop_device(%s, %d)", filename, int(fd))))
}
return nil, ErrAttachLoopbackDevice
}
defer free(res)
@@ -401,13 +351,6 @@ func LogInitVerbose(level int) {
C.dm_log_init_verbose(C.int(level))
}
var dmLogger DevmapperLogger = nil
func logInit(logger DevmapperLogger) {
dmLogger = logger
C.log_with_errno_init()
}
func SetDevDir(dir string) error {
c_dir := C.CString(dir)
defer free(c_dir)
@@ -449,7 +392,6 @@ func free(p *C.char) {
C.free(unsafe.Pointer(p))
}
// This is the programmatic example of "dmsetup create"
func createPool(poolName string, dataFile *os.File, metadataFile *os.File) error {
task, err := createTask(DeviceCreate, poolName)
if task == nil {
@@ -461,7 +403,7 @@ func createPool(poolName string, dataFile *os.File, metadataFile *os.File) error
return fmt.Errorf("Can't get data size")
}
params := metadataFile.Name() + " " + dataFile.Name() + " 128 32768"
params := metadataFile.Name() + " " + dataFile.Name() + " 512 8192"
if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
return fmt.Errorf("Can't add target")
}
@@ -579,7 +521,6 @@ func resumeDevice(name string) error {
}
func createDevice(poolName string, deviceId int) error {
utils.Debugf("[devmapper] createDevice(poolName=%v, deviceId=%v)", poolName, deviceId)
task, err := createTask(DeviceTargetMsg, poolName)
if task == nil {
return err
@@ -620,8 +561,6 @@ func deleteDevice(poolName string, deviceId int) error {
}
func removeDevice(name string) error {
utils.Debugf("[devmapper] removeDevice START")
defer utils.Debugf("[devmapper] removeDevice END")
task, err := createTask(DeviceRemove, name)
if task == nil {
return err
@@ -642,9 +581,6 @@ func activateDevice(poolName string, name string, deviceId int, size uint64) err
if err := task.AddTarget(0, size/512, "thin", params); err != nil {
return fmt.Errorf("Can't add target")
}
if err := task.SetAddNode(AddNodeOnCreate); err != nil {
return fmt.Errorf("Can't add node")
}
var cookie uint32 = 0
if err := task.SetCookie(&cookie, 0); err != nil {
@@ -660,7 +596,7 @@ func activateDevice(poolName string, name string, deviceId int, size uint64) err
return nil
}
func (devices *DeviceSet) createSnapDevice(poolName string, deviceId int, baseName string, baseDeviceId int) error {
func (devices *DeviceSetDM) createSnapDevice(poolName string, deviceId int, baseName string, baseDeviceId int) error {
devinfo, _ := getInfo(baseName)
doSuspend := devinfo != nil && devinfo.Exists != 0
-13
View File
@@ -1,13 +0,0 @@
package devmapper
import "C"
// Due to the way cgo works this has to be in a separate file, as devmapper.go has
// definitions in the cgo block, which is incompatible with using "//export"
//export DevmapperLogCallback
func DevmapperLogCallback(level C.int, file *C.char, line C.int, dm_errno_or_class C.int, message *C.char) {
if dmLogger != nil {
dmLogger.log(int(level), C.GoString(file), int(line), int(dm_errno_or_class), C.GoString(message))
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ func usage() {
}
func main() {
devices := devmapper.NewDeviceSet("/var/lib/docker")
devices := devmapper.NewDeviceSetDM("/var/lib/docker")
if len(os.Args) < 2 {
usage()
@@ -1,7 +1,7 @@
package main
import (
"github.com/dotcloud/docker/sysinit"
"github.com/dotcloud/docker"
)
var (
@@ -11,6 +11,6 @@ var (
func main() {
// Running in init mode
sysinit.SysInit()
docker.SysInit()
return
}
+13 -14
View File
@@ -4,7 +4,7 @@ import (
"flag"
"fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/sysinit"
"github.com/dotcloud/docker/devmapper"
"github.com/dotcloud/docker/utils"
"io/ioutil"
"log"
@@ -24,7 +24,7 @@ var (
func main() {
if selfPath := utils.SelfPath(); selfPath == "/sbin/init" || selfPath == "/.dockerinit" {
// Running in init mode
sysinit.SysInit()
docker.SysInit()
return
}
// FIXME: Switch d and D ? (to be more sshd like)
@@ -37,11 +37,10 @@ func main() {
flGraphPath := flag.String("g", "/var/lib/docker", "Path to graph storage base dir.")
flEnableCors := flag.Bool("api-enable-cors", false, "Enable CORS requests in the remote api.")
flDns := flag.String("dns", "", "Set custom dns servers")
flHosts := utils.ListOpts{fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET)}
flHosts := docker.ListOpts{fmt.Sprintf("unix://%s", docker.DEFAULTUNIXSOCKET)}
flag.Var(&flHosts, "H", "tcp://host:port to bind/connect to or unix://path/to/socket to use")
flEnableIptables := flag.Bool("iptables", true, "Disable iptables within docker")
flDefaultIp := flag.String("ip", "0.0.0.0", "Default ip address to use when binding a containers ports")
flInterContainerComm := flag.Bool("enable-container-comm", false, "Enable inter-container communication")
flag.Parse()
@@ -78,16 +77,16 @@ func main() {
ip := net.ParseIP(*flDefaultIp)
config := &docker.DaemonConfig{
Pidfile: *pidfile,
GraphPath: *flGraphPath,
AutoRestart: *flAutoRestart,
EnableCors: *flEnableCors,
Dns: dns,
EnableIptables: *flEnableIptables,
BridgeIface: bridge,
ProtoAddresses: flHosts,
DefaultIp: ip,
InterContainerCommunication: *flInterContainerComm,
Pidfile: *pidfile,
GraphPath: *flGraphPath,
AutoRestart: *flAutoRestart,
EnableCors: *flEnableCors,
Dns: dns,
EnableIptables: *flEnableIptables,
BridgeIface: bridge,
ProtoAddresses: flHosts,
DefaultIp: ip,
DeviceSet: devmapper.NewDeviceSetDM(*flGraphPath),
}
if err := daemon(config); err != nil {
log.Fatal(err)
+24 -86
View File
@@ -1,93 +1,38 @@
Docker Documentation
====================
Overview
--------
Documentation
-------------
This is your definite place to contribute to the docker documentation. After each push to master the documentation
is automatically generated and made available on [docs.docker.io](http://docs.docker.io)
The source for Docker documentation is here under ``sources/`` in the
form of .rst files. These files use
[reStructuredText](http://docutils.sourceforge.net/rst.html)
formatting with [Sphinx](http://sphinx-doc.org/) extensions for
structure, cross-linking and indexing.
Each of the .rst files under sources reflects a page on the documentation.
The HTML files are built and hosted on
[readthedocs.org](https://readthedocs.org/projects/docker/), appearing
via proxy on https://docs.docker.io. The HTML files update
automatically after each change to the master or release branch of the
[docker files on GitHub](https://github.com/dotcloud/docker) thanks to
post-commit hooks. The "release" branch maps to the "latest"
documentation and the "master" branch maps to the "master"
documentation.
**Warning**: The "master" documentation may include features not yet
part of any official docker release. "Master" docs should be used only
for understanding bleeding-edge development and "latest" should be
used for the latest official release.
If you need to manually trigger a build of an existing branch, then
you can do that through the [readthedocs
interface](https://readthedocs.org/builds/docker/). If you would like
to add new build targets, including new branches or tags, then you
must contact one of the existing maintainers and get your
readthedocs.org account added to the maintainers list, or just file an
issue on GitHub describing the branch/tag and why it needs to be added
to the docs, and one of the maintainers will add it for you.
Getting Started
---------------
To edit and test the docs, you'll need to install the Sphinx tool and
its dependencies. There are two main ways to install this tool:
Native Installation
...................
Installation
------------
* Work in your own fork of the code, we accept pull requests.
* Install sphinx: `pip install sphinx`
* Mac OS X: `[sudo] pip-2.7 install sphinx`
* Mac OS X: `[sudo] pip-2.7 install sphinx`)
* Install sphinx httpdomain contrib package: `pip install sphinxcontrib-httpdomain`
* Mac OS X: `[sudo] pip-2.7 install sphinxcontrib-httpdomain`
* If pip is not available you can probably install it using your favorite package manager as **python-pip**
Alternative Installation: Docker Container
..........................................
If you're running ``docker`` on your development machine then you may
find it easier and cleaner to use the Dockerfile. This installs Sphinx
in a container, adds the local ``docs/`` directory and builds the HTML
docs inside the container, even starting a simple HTTP server on port
8000 so that you can connect and see your changes. Just run ``docker
build .`` and run the resulting image. This is the equivalent to
``make clean server`` since each container starts clean.
Usage
-----
* Follow the contribution guidelines (``../CONTRIBUTING.md``)
* Work in your own fork of the code, we accept pull requests.
* Change the ``.rst`` files with your favorite editor -- try to keep the
lines short and respect RST and Sphinx conventions.
* Run ``make clean docs`` to clean up old files and generate new ones,
or just ``make docs`` to update after small changes.
* Your static website can now be found in the ``_build`` directory.
* To preview what you have generated run ``make server`` and open
http://localhost:8000/ in your favorite browser.
``make clean docs`` must complete without any warnings or errors.
* Change the `.rst` files with your favorite editor to your liking.
* Run `make docs` to clean up old files and generate new ones.
* Your static website can now be found in the `_build` directory.
* To preview what you have generated run `make server` and open http://localhost:8000/ in your favorite browser.
Working using GitHub's file editor
----------------------------------
Alternatively, for small changes and typos you might want to use
GitHub's built in file editor. It allows you to preview your changes
right online (though there can be some differences between GitHub
markdown and Sphinx RST). Just be careful not to create many commits.
Alternatively, for small changes and typo's you might want to use GitHub's built in file editor. It allows
you to preview your changes right online. Just be careful not to create many commits.
Images
------
When you need to add images, try to make them as small as possible
(e.g. as gif). Usually images should go in the same directory as the
.rst file which references them, or in a subdirectory if one already
exists.
When you need to add images, try to make them as small as possible (e.g. as gif).
Notes
-----
@@ -96,7 +41,7 @@ lessc ``lessc main.less`` or watched using watch-lessc ``watch-lessc -i main.les
Guides on using sphinx
----------------------
* To make links to certain sections create a link target like so:
* To make links to certain pages create a link target like so:
```
.. _hello_world:
@@ -107,10 +52,7 @@ Guides on using sphinx
This is.. (etc.)
```
The ``_hello_world:`` will make it possible to link to this position
(page and section heading) from all other pages. See the [Sphinx
docs](http://sphinx-doc.org/markup/inline.html#role-ref) for more
information and examples.
The ``_hello_world:`` will make it possible to link to this position (page and marker) from all other pages.
* Notes, warnings and alarms
@@ -126,17 +68,13 @@ Guides on using sphinx
* Code examples
* Start without $, so it's easy to copy and paste.
* Use "sudo" with docker to ensure that your command is runnable
even if they haven't [used the *docker*
group](http://docs.docker.io/en/latest/use/basics/#why-sudo).
Start without $, so it's easy to copy and paste.
Manpages
--------
* To make the manpages, run ``make man``. Please note there is a bug
in spinx 1.1.3 which makes this fail. Upgrade to the latest version
of Sphinx.
* Then preview the manpage by running ``man _build/man/docker.1``,
where ``_build/man/docker.1`` is the path to the generated manfile
* To make the manpages, simply run 'make man'. Please note there is a bug in spinx 1.1.3 which makes this fail.
Upgrade to the latest version of sphinx.
* Then preview the manpage by running `man _build/man/docker.1`, where _build/man/docker.1 is the path to the generated
manfile
* The manpages are also autogenerated by our hosted readthedocs here: http://docs-docker.dotcloud.com/projects/docker/downloads/
+1 -1
View File
@@ -14,5 +14,5 @@ Your programs and scripts can access Docker's functionality via these interfaces
registry_api
index_api
docker_remote_api
remote_api_client_libraries
+40 -711
View File
@@ -4,8 +4,11 @@
.. _cli:
Command Line Help
-----------------
Overview
======================
Docker Usage
~~~~~~~~~~~~~~~~~~
To list available commands, either run ``docker`` with no parameters or execute
``docker help``::
@@ -18,749 +21,75 @@ To list available commands, either run ``docker`` with no parameters or execute
...
.. _cli_attach:
``attach``
----------
::
Available Commands
~~~~~~~~~~~~~~~~~~
Usage: docker attach CONTAINER
.. include:: command/attach.rst
Attach to a running container.
.. include:: command/build.rst
You can detach from the container again (and leave it running) with
``CTRL-c`` (for a quiet exit) or ``CTRL-\`` to get a stacktrace of
the Docker client when it quits.
.. include:: command/commit.rst
To stop a container, use ``docker stop``
.. include:: command/cp.rst
To kill the container, use ``docker kill``
.. include:: command/diff.rst
.. _cli_attach_examples:
Examples:
~~~~~~~~~
.. include:: command/events.rst
.. code-block:: bash
.. include:: command/export.rst
$ ID=$(sudo docker run -d ubuntu /usr/bin/top -b)
$ sudo docker attach $ID
top - 02:05:52 up 3:05, 0 users, load average: 0.01, 0.02, 0.05
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 373572k total, 355560k used, 18012k free, 27872k buffers
Swap: 786428k total, 0k used, 786428k free, 221740k cached
.. include:: command/history.rst
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 17200 1116 912 R 0 0.3 0:00.03 top
.. include:: command/images.rst
top - 02:05:55 up 3:05, 0 users, load average: 0.01, 0.02, 0.05
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.2%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 373572k total, 355244k used, 18328k free, 27872k buffers
Swap: 786428k total, 0k used, 786428k free, 221776k cached
.. include:: command/import.rst
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top
.. include:: command/info.rst
.. include:: command/insert.rst
top - 02:05:58 up 3:06, 0 users, load average: 0.01, 0.02, 0.05
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.2%us, 0.3%sy, 0.0%ni, 99.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 373572k total, 355780k used, 17792k free, 27880k buffers
Swap: 786428k total, 0k used, 786428k free, 221776k cached
.. include:: command/inspect.rst
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top
^C$
$ sudo docker stop $ID
.. include:: command/kill.rst
.. _cli_build:
.. include:: command/link.rst
``build``
---------
.. include:: command/login.rst
::
.. include:: command/logs.rst
Usage: docker build [OPTIONS] PATH | URL | -
Build a new container image from the source code at PATH
-t="": Repository name (and optionally a tag) to be applied to the resulting image in case of success.
-q=false: Suppress verbose build output.
-no-cache: Do not use the cache when building the image.
-rm: Remove intermediate containers after a successful build
When a single Dockerfile is given as URL, then no context is set. When a git repository is set as URL, the repository is used as context
.. include:: command/ls.rst
.. _cli_build_examples:
.. include:: command/port.rst
Examples:
~~~~~~~~~
.. include:: command/ps.rst
.. code-block:: bash
.. include:: command/pull.rst
sudo docker build .
.. include:: command/push.rst
This will read the ``Dockerfile`` from the current directory. It will
also send any other files and directories found in the current
directory to the ``docker`` daemon.
.. include:: command/restart.rst
The contents of this directory would be used by ``ADD`` commands found
within the ``Dockerfile``. This will send a lot of data to the
``docker`` daemon if the current directory contains a lot of data. If
the absolute path is provided instead of ``.`` then only the files and
directories required by the ADD commands from the ``Dockerfile`` will be
added to the context and transferred to the ``docker`` daemon.
.. include:: command/rm.rst
.. code-block:: bash
.. include:: command/rmi.rst
sudo docker build -t vieux/apache:2.0 .
.. include:: command/run.rst
This will build like the previous example, but it will then tag the
resulting image. The repository name will be ``vieux/apache`` and the
tag will be ``2.0``
.. include:: command/search.rst
.. include:: command/start.rst
.. code-block:: bash
.. include:: command/stop.rst
sudo docker build - < Dockerfile
.. include:: command/tag.rst
This will read a ``Dockerfile`` from *stdin* without context. Due to
the lack of a context, no contents of any local directory will be sent
to the ``docker`` daemon. ``ADD`` doesn't work when running in this
mode because the absence of the context provides no source files to
copy to the container.
.. include:: command/top.rst
.. include:: command/version.rst
.. code-block:: bash
sudo docker build github.com/creack/docker-firefox
This will clone the Github repository and use it as context. The
``Dockerfile`` at the root of the repository is used as
``Dockerfile``. Note that you can specify an arbitrary git repository
by using the ``git://`` schema.
.. _cli_commit:
``commit``
----------
::
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY [TAG]]
Create a new image from a container's changes
-m="": Commit message
-author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>"
-run="": Configuration to be applied when the image is launched with `docker run`.
(ex: '{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')
Full -run example (multiline is ok within a single quote ``'``)
::
$ sudo docker commit -run='
{
"Entrypoint" : null,
"Privileged" : false,
"User" : "",
"VolumesFrom" : "",
"Cmd" : ["cat", "-e", "/etc/resolv.conf"],
"Dns" : ["8.8.8.8", "8.8.4.4"],
"MemorySwap" : 0,
"AttachStdin" : false,
"AttachStderr" : false,
"CpuShares" : 0,
"OpenStdin" : false,
"Volumes" : null,
"Hostname" : "122612f45831",
"PortSpecs" : ["22", "80", "443"],
"Image" : "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
"Tty" : false,
"Env" : [
"HOME=/",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"StdinOnce" : false,
"Domainname" : "",
"WorkingDir" : "/",
"NetworkDisabled" : false,
"Memory" : 0,
"AttachStdout" : false
}' $CONTAINER_ID
.. _cli_cp:
``cp``
------
::
Usage: docker cp CONTAINER:RESOURCE HOSTPATH
Copy files/folders from the containers filesystem to the host
path. Paths are relative to the root of the filesystem.
.. _cli_diff:
``diff``
--------
::
Usage: docker diff CONTAINER [OPTIONS]
Inspect changes on a container's filesystem
.. _cli_events:
``events``
----------
::
Usage: docker events
Get real time events from the server
.. _cli_events_example:
Examples
~~~~~~~~
You'll need two shells for this example.
Shell 1: Listening for events
.............................
.. code-block:: bash
$ sudo docker events
Shell 2: Start and Stop a Container
...................................
.. code-block:: bash
$ sudo docker start 4386fb97867d
$ sudo docker stop 4386fb97867d
Shell 1: (Again .. now showing events)
......................................
.. code-block:: bash
[2013-09-03 15:49:26 +0200 CEST] 4386fb97867d: (from 12de384bfb10) start
[2013-09-03 15:49:29 +0200 CEST] 4386fb97867d: (from 12de384bfb10) die
[2013-09-03 15:49:29 +0200 CEST] 4386fb97867d: (from 12de384bfb10) stop
.. _cli_export:
``export``
----------
::
Usage: docker export CONTAINER
Export the contents of a filesystem as a tar archive
.. _cli_history:
``history``
-----------
::
Usage: docker history [OPTIONS] IMAGE
Show the history of an image
.. _cli_images:
``images``
----------
::
Usage: docker images [OPTIONS] [NAME]
List images
-a=false: show all images
-q=false: only show numeric IDs
-viz=false: output in graphviz format
Displaying images visually
~~~~~~~~~~~~~~~~~~~~~~~~~~
::
sudo docker images -viz | dot -Tpng -o docker.png
.. image:: docker_images.gif
:alt: Example inheritance graph of Docker images.
.. _cli_import:
``import``
----------
::
Usage: docker import URL|- [REPOSITORY [TAG]]
Create a new filesystem image from the contents of a tarball
At this time, the URL must start with ``http`` and point to a single
file archive (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) containing a
root filesystem. If you would like to import from a local directory or
archive, you can use the ``-`` parameter to take the data from
standard in.
Examples
~~~~~~~~
Import from a remote location
.............................
``$ sudo docker import http://example.com/exampleimage.tgz exampleimagerepo``
Import from a local file
........................
Import to docker via pipe and standard in
``$ cat exampleimage.tgz | sudo docker import - exampleimagelocal``
Import from a local directory
.............................
``$ sudo tar -c . | docker import - exampleimagedir``
Note the ``sudo`` in this example -- you must preserve the ownership
of the files (especially root ownership) during the archiving with
tar. If you are not root (or sudo) when you tar, then the ownerships
might not get preserved.
.. _cli_info:
``info``
--------
::
Usage: docker info
Display system-wide information.
.. _cli_insert:
``insert``
----------
::
Usage: docker insert IMAGE URL PATH
Insert a file from URL in the IMAGE at PATH
Examples
~~~~~~~~
Insert file from github
.......................
.. code-block:: bash
$ sudo docker insert 8283e18b24bc https://raw.github.com/metalivedev/django/master/postinstall /tmp/postinstall.sh
.. _cli_inspect:
``inspect``
-----------
::
Usage: docker inspect [OPTIONS] CONTAINER
Return low-level information on a container
.. _cli_kill:
``kill``
--------
::
Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]
Kill a running container
.. _cli_link:
``link``
--------
::
Usage: docker link CURRENT_NAME NEW_NAME
Link a container to a new name.
Examples:
~~~~~~~~~
.. code-block:: bash
$ docker link /59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc /redis
$ docker ls
NAME ID IMAGE
/redis 59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc crosbymichael/redis:latest
/59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc 59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc crosbymichael/redis:latest
This will create a new link for the existing name ``/59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc``
with the new name ``/redis`` so that we can new reference the same container under the new name ``/redis``.
.. _cli_login:
``login``
---------
::
Usage: docker login [OPTIONS] [SERVER]
Register or Login to the docker registry server
-e="": email
-p="": password
-u="": username
If you want to login to a private registry you can
specify this by adding the server name.
example:
docker login localhost:8080
.. _cli_logs:
``logs``
--------
::
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
.. _cli_port:
``port``
--------
::
Usage: docker port [OPTIONS] CONTAINER PRIVATE_PORT
Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
.. _cli_ps:
``ps``
------
::
Usage: docker ps [OPTIONS]
List containers
-a=false: Show all containers. Only running containers are shown by default.
-notrunc=false: Don't truncate output
-q=false: Only display numeric IDs
.. _cli_pull:
``pull``
--------
::
Usage: docker pull NAME
Pull an image or a repository from the registry
.. _cli_push:
``push``
--------
::
Usage: docker push NAME
Push an image or a repository to the registry
.. _cli_restart:
``restart``
-----------
::
Usage: docker restart [OPTIONS] NAME
Restart a running container
.. _cli_rm:
``rm``
------
::
Usage: docker rm [OPTIONS] CONTAINER
Remove one or more containers
-link="": Remove the link instead of the actual container
Examples:
~~~~~~~~~
.. code-block:: bash
$ docker rm /redis
/redis
This will remove the container referenced under the link ``/redis``.
.. code-block:: bash
$ docker rm -link /webapp/redis
/webapp/redis
This will remove the underlying link between ``/webapp`` and the ``/redis`` containers removing all
network communication.
.. _cli_rmi:
``rmi``
-------
::
Usage: docker rmi IMAGE [IMAGE...]
Remove one or more images
.. _cli_run:
``run``
-------
::
Usage: docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...]
Run a command in a new container
-a=map[]: Attach to stdin, stdout or stderr
-c=0: CPU shares (relative weight)
-cidfile="": Write the container ID to the file
-d=false: Detached mode: Run container in the background, print new container id
-e=[]: Set environment variables
-h="": Container host name
-i=false: Keep stdin open even if not attached
-privileged=false: Give extended privileges to this container
-m=0: Memory limit (in bytes)
-n=true: Enable networking for this container
-p=[]: Map a network port to the container
-rm=false: Automatically remove the container when it exits (incompatible with -d)
-t=false: Allocate a pseudo-tty
-u="": Username or UID
-dns=[]: Set custom dns servers for the container
-v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]. If "container-dir" is missing, then docker creates a new volume.
-volumes-from="": Mount all volumes from the given container
-entrypoint="": Overwrite the default entrypoint set by the image
-w="": Working directory inside the container
-lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
-expose=[]: Expose a port from the container without publishing it to your host
-link="": Add link to another container (containerid:alias)
Examples
--------
.. code-block:: bash
sudo docker run -cidfile /tmp/docker_test.cid ubuntu echo "test"
This will create a container and print "test" to the console. The
``cidfile`` flag makes docker attempt to create a new file and write the
container ID to it. If the file exists already, docker will return an
error. Docker will close this file when docker run exits.
.. code-block:: bash
docker run mount -t tmpfs none /var/spool/squid
This will *not* work, because by default, most potentially dangerous
kernel capabilities are dropped; including ``cap_sys_admin`` (which is
required to mount filesystems). However, the ``-privileged`` flag will
allow it to run:
.. code-block:: bash
docker run -privileged mount -t tmpfs none /var/spool/squid
The ``-privileged`` flag gives *all* capabilities to the container,
and it also lifts all the limitations enforced by the ``device``
cgroup controller. In other words, the container can then do almost
everything that the host can do. This flag exists to allow special
use-cases, like running Docker within Docker.
.. code-block:: bash
docker run -w /path/to/dir/ -i -t ubuntu pwd
The ``-w`` lets the command being executed inside directory given,
here /path/to/dir/. If the path does not exists it is created inside the
container.
.. code-block:: bash
docker run -v `pwd`:`pwd` -w `pwd` -i -t ubuntu pwd
The ``-v`` flag mounts the current working directory into the container.
The ``-w`` lets the command being executed inside the current
working directory, by changing into the directory to the value
returned by ``pwd``. So this combination executes the command
using the container, but inside the current working directory.
.. code-block:: bash
docker run -p 127.0.0.0::80 ubuntu bash
This the ``-p`` flag now allows you to bind a port to a specific
interface of the host machine. In this example port ``80`` of the
container will have a dynamically allocated port bound to 127.0.0.1
of the host.
.. code-block:: bash
docker run -p 127.0.0.1:80:80 ubuntu bash
This will bind port ``80`` of the container to port ``80`` on 127.0.0.1 of your
host machine.
.. code-block:: bash
docker run -expose 80 ubuntu bash
This will expose port ``80`` of the container for use within a link
without publishing the port to the host system's interfaces.
.. code-block:: bash
docker run -link /redis:redis ubuntu bash
The ``-link`` flag will link the container named ``/redis`` into the
newly created container with the alias ``redis``. The new container
can access the network and environment of the redis container via
environment variables.
.. _cli_search:
``search``
----------
::
Usage: docker search TERM
Searches for the TERM parameter on the Docker index and prints out
a list of repositories that match.
.. _cli_start:
``start``
---------
::
Usage: docker start [OPTIONS] NAME
Start a stopped container
.. _cli_stop:
``stop``
--------
::
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Stop a running container
-t=10: Number of seconds to wait for the container to stop before killing it.
.. _cli_tag:
``tag``
-------
::
Usage: docker tag [OPTIONS] IMAGE REPOSITORY [TAG]
Tag an image into a repository
-f=false: Force
.. _cli_top:
``top``
-------
::
Usage: docker top CONTAINER
Lookup the running processes of a container
.. _cli_version:
``version``
-----------
Show the version of the docker client, daemon, and latest released version.
.. _cli_wait:
``wait``
--------
::
Usage: docker wait [OPTIONS] NAME
Block until a container stops, then print its exit code.
.. include:: command/wait.rst
@@ -0,0 +1,59 @@
:title: Attach Command
:description: Attach to a running container
:keywords: attach, container, docker, documentation
===========================================
``attach`` -- Attach to a running container
===========================================
::
Usage: docker attach CONTAINER
Attach to a running container.
You can detach from the container again (and leave it running) with
``CTRL-c`` (for a quiet exit) or ``CTRL-\`` to get a stacktrace of
the Docker client when it quits.
To stop a container, use ``docker stop``
To kill the container, use ``docker kill``
Examples:
---------
.. code-block:: bash
$ ID=$(sudo docker run -d ubuntu /usr/bin/top -b)
$ sudo docker attach $ID
top - 02:05:52 up 3:05, 0 users, load average: 0.01, 0.02, 0.05
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 373572k total, 355560k used, 18012k free, 27872k buffers
Swap: 786428k total, 0k used, 786428k free, 221740k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 17200 1116 912 R 0 0.3 0:00.03 top
top - 02:05:55 up 3:05, 0 users, load average: 0.01, 0.02, 0.05
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.2%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 373572k total, 355244k used, 18328k free, 27872k buffers
Swap: 786428k total, 0k used, 786428k free, 221776k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top
top - 02:05:58 up 3:06, 0 users, load average: 0.01, 0.02, 0.05
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.2%us, 0.3%sy, 0.0%ni, 99.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 373572k total, 355780k used, 17792k free, 27880k buffers
Swap: 786428k total, 0k used, 786428k free, 221776k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top
^C$
$ sudo docker stop $ID
@@ -0,0 +1,65 @@
:title: Build Command
:description: Build a new image from the Dockerfile passed via stdin
:keywords: build, docker, container, documentation
================================================
``build`` -- Build a container from a Dockerfile
================================================
::
Usage: docker build [OPTIONS] PATH | URL | -
Build a new container image from the source code at PATH
-t="": Repository name (and optionally a tag) to be applied to the resulting image in case of success.
-q=false: Suppress verbose build output.
-no-cache: Do not use the cache when building the image.
-rm: Remove intermediate containers after a successful build
When a single Dockerfile is given as URL, then no context is set. When a git repository is set as URL, the repository is used as context
Examples
--------
.. code-block:: bash
sudo docker build .
This will read the ``Dockerfile`` from the current directory. It will
also send any other files and directories found in the current
directory to the ``docker`` daemon.
The contents of this directory would be used by ``ADD`` commands found
within the ``Dockerfile``. This will send a lot of data to the
``docker`` daemon if the current directory contains a lot of data. If
the absolute path is provided instead of ``.`` then only the files and
directories required by the ADD commands from the ``Dockerfile`` will be
added to the context and transferred to the ``docker`` daemon.
.. code-block:: bash
sudo docker build -t vieux/apache:2.0 .
This will build like the previous example, but it will then tag the
resulting image. The repository name will be ``vieux/apache`` and the
tag will be ``2.0``
.. code-block:: bash
sudo docker build - < Dockerfile
This will read a ``Dockerfile`` from *stdin* without context. Due to
the lack of a context, no contents of any local directory will be sent
to the ``docker`` daemon. ``ADD`` doesn't work when running in this
mode because the absence of the context provides no source files to
copy to the container.
.. code-block:: bash
sudo docker build github.com/creack/docker-firefox
This will clone the Github repository and use it as context. The
``Dockerfile`` at the root of the repository is used as
``Dockerfile``. Note that you can specify an arbitrary git repository
by using the ``git://`` schema.
@@ -0,0 +1,52 @@
:title: Commit Command
:description: Create a new image from a container's changes
:keywords: commit, docker, container, documentation
===========================================================
``commit`` -- Create a new image from a container's changes
===========================================================
::
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY [TAG]]
Create a new image from a container's changes
-m="": Commit message
-author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>"
-run="": Configuration to be applied when the image is launched with `docker run`.
(ex: '{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')
Full -run example (multiline is ok within a single quote ``'``)
::
$ sudo docker commit -run='
{
"Entrypoint" : null,
"Privileged" : false,
"User" : "",
"VolumesFrom" : "",
"Cmd" : ["cat", "-e", "/etc/resolv.conf"],
"Dns" : ["8.8.8.8", "8.8.4.4"],
"MemorySwap" : 0,
"AttachStdin" : false,
"AttachStderr" : false,
"CpuShares" : 0,
"OpenStdin" : false,
"Volumes" : null,
"Hostname" : "122612f45831",
"PortSpecs" : ["22", "80", "443"],
"Image" : "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
"Tty" : false,
"Env" : [
"HOME=/",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"StdinOnce" : false,
"Domainname" : "",
"WorkingDir" : "/",
"NetworkDisabled" : false,
"Memory" : 0,
"AttachStdout" : false
}' $CONTAINER_ID
+14
View File
@@ -0,0 +1,14 @@
:title: Cp Command
:description: Copy files/folders from the containers filesystem to the host path
:keywords: cp, docker, container, documentation, copy
============================================================================
``cp`` -- Copy files/folders from the containers filesystem to the host path
============================================================================
::
Usage: docker cp CONTAINER:RESOURCE HOSTPATH
Copy files/folders from the containers filesystem to the host
path. Paths are relative to the root of the filesystem.
+13
View File
@@ -0,0 +1,13 @@
:title: Diff Command
:description: Inspect changes on a container's filesystem
:keywords: diff, docker, container, documentation
=======================================================
``diff`` -- Inspect changes on a container's filesystem
=======================================================
::
Usage: docker diff CONTAINER [OPTIONS]
Inspect changes on a container's filesystem
@@ -0,0 +1,34 @@
:title: Events Command
:description: Get real time events from the server
:keywords: events, docker, documentation
=================================================================
``events`` -- Get real time events from the server
=================================================================
::
Usage: docker events
Get real time events from the server
Examples
--------
Starting and stopping a container
.................................
.. code-block:: bash
$ sudo docker start 4386fb97867d
$ sudo docker stop 4386fb97867d
In another shell
.. code-block:: bash
$ sudo docker events
[2013-09-03 15:49:26 +0200 CEST] 4386fb97867d: (from 12de384bfb10) start
[2013-09-03 15:49:29 +0200 CEST] 4386fb97867d: (from 12de384bfb10) die
[2013-09-03 15:49:29 +0200 CEST] 4386fb97867d: (from 12de384bfb10) stop
@@ -0,0 +1,13 @@
:title: Export Command
:description: Export the contents of a filesystem as a tar archive
:keywords: export, docker, container, documentation
=================================================================
``export`` -- Stream the contents of a container as a tar archive
=================================================================
::
Usage: docker export CONTAINER
Export the contents of a filesystem as a tar archive
@@ -0,0 +1,13 @@
:title: History Command
:description: Show the history of an image
:keywords: history, docker, container, documentation
===========================================
``history`` -- Show the history of an image
===========================================
::
Usage: docker history [OPTIONS] IMAGE
Show the history of an image
@@ -0,0 +1,26 @@
:title: Images Command
:description: List images
:keywords: images, docker, container, documentation
=========================
``images`` -- List images
=========================
::
Usage: docker images [OPTIONS] [NAME]
List images
-a=false: show all images
-q=false: only show numeric IDs
-viz=false: output in graphviz format
Displaying images visually
--------------------------
::
sudo docker images -viz | dot -Tpng -o docker.png
.. image:: https://docs.docker.io/en/latest/_static/docker_images.gif
@@ -0,0 +1,44 @@
:title: Import Command
:description: Create a new filesystem image from the contents of a tarball
:keywords: import, tarball, docker, url, documentation
==========================================================================
``import`` -- Create a new filesystem image from the contents of a tarball
==========================================================================
::
Usage: docker import URL|- [REPOSITORY [TAG]]
Create a new filesystem image from the contents of a tarball
At this time, the URL must start with ``http`` and point to a single
file archive (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) containing a
root filesystem. If you would like to import from a local directory or
archive, you can use the ``-`` parameter to take the data from
standard in.
Examples
--------
Import from a remote location
.............................
``$ sudo docker import http://example.com/exampleimage.tgz exampleimagerepo``
Import from a local file
........................
Import to docker via pipe and standard in
``$ cat exampleimage.tgz | sudo docker import - exampleimagelocal``
Import from a local directory
.............................
``$ sudo tar -c . | docker import - exampleimagedir``
Note the ``sudo`` in this example -- you must preserve the ownership
of the files (especially root ownership) during the archiving with
tar. If you are not root (or sudo) when you tar, then the ownerships
might not get preserved.
+13
View File
@@ -0,0 +1,13 @@
:title: Info Command
:description: Display system-wide information.
:keywords: info, docker, information, documentation
===========================================
``info`` -- Display system-wide information
===========================================
::
Usage: docker info
Display system-wide information.
@@ -0,0 +1,23 @@
:title: Insert Command
:description: Insert a file in an image
:keywords: insert, image, docker, documentation
==========================================================================
``insert`` -- Insert a file in an image
==========================================================================
::
Usage: docker insert IMAGE URL PATH
Insert a file from URL in the IMAGE at PATH
Examples
--------
Insert file from github
.......................
.. code-block:: bash
$ sudo docker insert 8283e18b24bc https://raw.github.com/metalivedev/django/master/postinstall /tmp/postinstall.sh
@@ -0,0 +1,13 @@
:title: Inspect Command
:description: Return low-level information on a container
:keywords: inspect, container, docker, documentation
==========================================================
``inspect`` -- Return low-level information on a container
==========================================================
::
Usage: docker inspect [OPTIONS] CONTAINER
Return low-level information on a container
+13
View File
@@ -0,0 +1,13 @@
:title: Kill Command
:description: Kill a running container
:keywords: kill, container, docker, documentation
====================================
``kill`` -- Kill a running container
====================================
::
Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]
Kill a running container
+29
View File
@@ -0,0 +1,29 @@
:title: Link Command
:description: Add a link or rename the link for a container
:keywords: link, docker, container, documentation, link, links
============================================================================
``link`` -- Add a link or rename the link for a container
============================================================================
::
Usage: docker link CURRENT_NAME NEW_NAME
Link a container to a new name.
Examples:
--------
.. code-block:: bash
$ docker link /59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc /redis
$ docker ls
NAME ID IMAGE
/redis 59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc crosbymichael/redis:latest
/59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc 59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc crosbymichael/redis:latest
This will create a new link for the existing name ``/59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc``
with the new name ``/redis`` so that we can new reference the same container under the new name ``/redis``.
@@ -0,0 +1,24 @@
:title: Login Command
:description: Register or Login to the docker registry server
:keywords: login, docker, documentation
============================================================
``login`` -- Register or Login to the docker registry server
============================================================
::
Usage: docker login [OPTIONS] [SERVER]
Register or Login to the docker registry server
-e="": email
-p="": password
-u="": username
If you want to login to a private registry you can
specify this by adding the server name.
example:
docker login localhost:8080
+13
View File
@@ -0,0 +1,13 @@
:title: Logs Command
:description: Fetch the logs of a container
:keywords: logs, container, docker, documentation
=========================================
``logs`` -- Fetch the logs of a container
=========================================
::
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
+29
View File
@@ -0,0 +1,29 @@
:title: Ls Command
:description: Ls all links for containers
:keywords: ls, docker, container, documentation, link, links
============================================================================
``ls`` -- List all links for containers
============================================================================
::
Usage: docker ls
List all links for containers and display the relationship between parent
and child containers.
Examples:
--------
.. code-block:: bash
$ docker ls
NAME ID IMAGE
/redis 39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 crosbymichael/redis:latest
/webapp cffb86ffa80b11cd8777d300759ee53c4e61729431c30ec9552dd9e6d3abc87d demo:latest
/webapp/redis 39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 crosbymichael/redis:latest
This will display all links and the names that you can use the reference the link. Parent child
relationships are also displayed with ls.
+13
View File
@@ -0,0 +1,13 @@
:title: Port Command
:description: Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
:keywords: port, docker, container, documentation
=========================================================================
``port`` -- Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
=========================================================================
::
Usage: docker port [OPTIONS] CONTAINER PRIVATE_PORT
Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
+17
View File
@@ -0,0 +1,17 @@
:title: Ps Command
:description: List containers
:keywords: ps, docker, documentation, container
=========================
``ps`` -- List containers
=========================
::
Usage: docker ps [OPTIONS]
List containers
-a=false: Show all containers. Only running containers are shown by default.
-notrunc=false: Don't truncate output
-q=false: Only display numeric IDs
+13
View File
@@ -0,0 +1,13 @@
:title: Pull Command
:description: Pull an image or a repository from the registry
:keywords: pull, image, repo, repository, documentation, docker
=========================================================================
``pull`` -- Pull an image or a repository from the docker registry server
=========================================================================
::
Usage: docker pull NAME
Pull an image or a repository from the registry
+13
View File
@@ -0,0 +1,13 @@
:title: Push Command
:description: Push an image or a repository to the registry
:keywords: push, docker, image, repository, documentation, repo
=======================================================================
``push`` -- Push an image or a repository to the docker registry server
=======================================================================
::
Usage: docker push NAME
Push an image or a repository to the registry
@@ -0,0 +1,13 @@
:title: Restart Command
:description: Restart a running container
:keywords: restart, container, docker, documentation
==========================================
``restart`` -- Restart a running container
==========================================
::
Usage: docker restart [OPTIONS] NAME
Restart a running container
+36
View File
@@ -0,0 +1,36 @@
:title: Rm Command
:description: Remove a container
:keywords: remove, container, docker, documentation, rm
============================
``rm`` -- Remove a container
============================
::
Usage: docker rm [OPTIONS] CONTAINER
Remove one or more containers
-link="": Remove the link instead of the actual container
Examples:
--------
.. code-block:: bash
$ docker rm /redis
/redis
This will remove the container referenced under the link ``/redis``.
.. code-block:: bash
$ docker rm -link /webapp/redis
/webapp/redis
This will remove the underlying link between ``/webapp`` and the ``/redis`` containers removing all
network communication.
+13
View File
@@ -0,0 +1,13 @@
:title: Rmi Command
:description: Remove an image
:keywords: rmi, remove, image, docker, documentation
==========================
``rmi`` -- Remove an image
==========================
::
Usage: docker rmi IMAGE [IMAGE...]
Remove one or more images
+117
View File
@@ -0,0 +1,117 @@
:title: Run Command
:description: Run a command in a new container
:keywords: run, container, docker, documentation
===========================================
``run`` -- Run a command in a new container
===========================================
::
Usage: docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...]
Run a command in a new container
-a=map[]: Attach to stdin, stdout or stderr
-c=0: CPU shares (relative weight)
-cidfile="": Write the container ID to the file
-d=false: Detached mode: Run container in the background, print new container id
-e=[]: Set environment variables
-h="": Container host name
-i=false: Keep stdin open even if not attached
-privileged=false: Give extended privileges to this container
-m=0: Memory limit (in bytes)
-n=true: Enable networking for this container
-p=[]: Map a network port to the container
-rm=false: Automatically remove the container when it exits (incompatible with -d)
-t=false: Allocate a pseudo-tty
-u="": Username or UID
-dns=[]: Set custom dns servers for the container
-v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]. If "container-dir" is missing, then docker creates a new volume.
-volumes-from="": Mount all volumes from the given container
-entrypoint="": Overwrite the default entrypoint set by the image
-w="": Working directory inside the container
-lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"
-expose=[]: Expose a port from the container without publishing it to your host
-link="": Add link to another container (containerid:alias)
Examples
--------
.. code-block:: bash
sudo docker run -cidfile /tmp/docker_test.cid ubuntu echo "test"
This will create a container and print "test" to the console. The
``cidfile`` flag makes docker attempt to create a new file and write the
container ID to it. If the file exists already, docker will return an
error. Docker will close this file when docker run exits.
.. code-block:: bash
docker run mount -t tmpfs none /var/spool/squid
This will *not* work, because by default, most potentially dangerous
kernel capabilities are dropped; including ``cap_sys_admin`` (which is
required to mount filesystems). However, the ``-privileged`` flag will
allow it to run:
.. code-block:: bash
docker run -privileged mount -t tmpfs none /var/spool/squid
The ``-privileged`` flag gives *all* capabilities to the container,
and it also lifts all the limitations enforced by the ``device``
cgroup controller. In other words, the container can then do almost
everything that the host can do. This flag exists to allow special
use-cases, like running Docker within Docker.
.. code-block:: bash
docker run -w /path/to/dir/ -i -t ubuntu pwd
The ``-w`` lets the command being executed inside directory given,
here /path/to/dir/. If the path does not exists it is created inside the
container.
.. code-block:: bash
docker run -v `pwd`:`pwd` -w `pwd` -i -t ubuntu pwd
The ``-v`` flag mounts the current working directory into the container.
The ``-w`` lets the command being executed inside the current
working directory, by changing into the directory to the value
returned by ``pwd``. So this combination executes the command
using the container, but inside the current working directory.
.. code-block:: bash
docker run -p 127.0.0.0::80 ubuntu bash
This the ``-p`` flag now allows you to bind a port to a specific
interface of the host machine. In this example port ``80`` of the
container will have a dynamically allocated port bound to 127.0.0.1
of the host.
.. code-block:: bash
docker run -p 127.0.0.1:80:80 ubuntu bash
This will bind port ``80`` of the container to port ``80`` on 127.0.0.1 of your
host machine.
.. code-block:: bash
docker run -expose 80 ubuntu bash
This will expose port ``80`` of the container for use within a link
without publishing the port to the host system's interfaces.
.. code-block:: bash
docker run -link /redis:redis ubuntu bash
The ``-link`` flag will link the container named ``/redis`` into the
newly created container with the alias ``redis``. The new container
can access the network and environment of the redis container via
environment variables.
@@ -0,0 +1,14 @@
:title: Search Command
:description: Searches for the TERM parameter on the Docker index and prints out a list of repositories that match.
:keywords: search, docker, image, documentation
===================================================================
``search`` -- Search for an image in the docker index
===================================================================
::
Usage: docker search TERM
Searches for the TERM parameter on the Docker index and prints out
a list of repositories that match.
@@ -0,0 +1,13 @@
:title: Start Command
:description: Start a stopped container
:keywords: start, docker, container, documentation
======================================
``start`` -- Start a stopped container
======================================
::
Usage: docker start [OPTIONS] NAME
Start a stopped container
+15
View File
@@ -0,0 +1,15 @@
:title: Stop Command
:description: Stop a running container
:keywords: stop, container, docker, documentation
====================================
``stop`` -- Stop a running container
====================================
::
Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Stop a running container
-t=10: Number of seconds to wait for the container to stop before killing it.
+15
View File
@@ -0,0 +1,15 @@
:title: Tag Command
:description: Tag an image into a repository
:keywords: tag, docker, image, repository, documentation, repo
=========================================
``tag`` -- Tag an image into a repository
=========================================
::
Usage: docker tag [OPTIONS] IMAGE REPOSITORY [TAG]
Tag an image into a repository
-f=false: Force
+13
View File
@@ -0,0 +1,13 @@
:title: Top Command
:description: Lookup the running processes of a container
:keywords: top, docker, container, documentation
=======================================================
``top`` -- Lookup the running processes of a container
=======================================================
::
Usage: docker top CONTAINER
Lookup the running processes of a container
@@ -0,0 +1,7 @@
:title: Version Command
:description:
:keywords: version, docker, documentation
==================================================
``version`` -- Show the docker version information
==================================================
+13
View File
@@ -0,0 +1,13 @@
:title: Wait Command
:description: Block until a container stops, then print its exit code.
:keywords: wait, docker, container, documentation
===================================================================
``wait`` -- Block until a container stops, then print its exit code
===================================================================
::
Usage: docker wait [OPTIONS] NAME
Block until a container stops, then print its exit code.
+33 -2
View File
@@ -1,6 +1,6 @@
:title: Commands
:description: docker command line interface
:keywords: commands, command line, help, docker
:description: -- todo: change me
:keywords: todo, commands, command line, help, docker, documentation
Commands
@@ -12,3 +12,34 @@ Contents:
:maxdepth: 1
cli
attach <command/attach>
build <command/build>
commit <command/commit>
cp <command/cp>
diff <command/diff>
events <command/events>
export <command/export>
history <command/history>
images <command/images>
import <command/import>
info <command/info>
insert <command/insert>
inspect <command/inspect>
kill <command/kill>
login <command/login>
logs <command/logs>
port <command/port>
ps <command/ps>
pull <command/pull>
push <command/push>
restart <command/restart>
rm <command/rm>
rmi <command/rmi>
run <command/run>
search <command/search>
start <command/start>
stop <command/stop>
tag <command/tag>
top <command/top>
version <command/version>
wait <command/wait>
+1 -1
View File
@@ -124,7 +124,7 @@ You can run an interactive session in the newly built container:
.. note:: The binary is available outside the container in the directory ``./bundles/<version>-dev/binary/``. You can swap your host docker executable with this binary for live testing - for example, on ubuntu: ``sudo service docker stop ; sudo cp $(which docker) $(which docker)_ ; sudo cp ./bundles/<version>-dev/binary/docker-<version>-dev $(which docker);sudo service docker start``.
.. note:: The binary is availalbe outside the container in the directory ``./bundles/<version>-dev/binary/``.
**Need More Help?**
+1 -1
View File
@@ -178,4 +178,4 @@ you could skip to any of the other examples:
* :ref:`running_ssh_service`
* :ref:`running_couchdb_service`
* :ref:`postgresql_service`
* :ref:`mongodb_image`
* :ref:`mongodb`
+16 -2
View File
@@ -54,16 +54,24 @@ Run the redis container
.. code-block:: bash
docker run -d -e PASSWORD=docker crosbymichael/redis --requirepass docker
docker run -d -e PASSWORD=docker crosbymichael/redis --requirepass=docker
This will run our redis container using the default port of 6379 and using
as password to secure our service. Next we will link the redis container to
a new name using ``docker link``.
a new name using ``docker link`` and ``docker ls``.
Linking an existing container
-----------------------------
.. code-block:: bash
docker ls
NAME ID IMAGE
/39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 crosbymichael/redis:latest
Docker will automatically create an initial link with the container's id but
because the is long and not very user friendly we can link the container with
a new name.
@@ -72,6 +80,12 @@ a new name.
docker link /39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 /redis
docker ls
NAME ID IMAGE
/redis 39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 crosbymichael/redis:latest
/39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 crosbymichael/redis:latest
Now we can reference our running redis service using the friendly name ``/redis``.
We can issue all the commands that you would expect; start, stop, attach, using the new name.
+11 -23
View File
@@ -39,12 +39,12 @@ Update its dependencies.
apt-get update
Install ``python-software-properties``.
Install ``python-software-properies``.
.. code-block:: bash
apt-get -y install python-software-properties
apt-get -y install software-properties-common
apt-get install python-software-properties
apt-get install software-properties-common
Add Pitti's PostgreSQL repository. It contains the most recent stable release
of PostgreSQL i.e. ``9.2``.
@@ -77,8 +77,7 @@ role.
Adjust PostgreSQL configuration so that remote connections to the
database are possible. Make sure that inside
``/etc/postgresql/9.2/main/pg_hba.conf`` you have following line (you will need
to install an editor, e.g. ``apt-get install vim``):
``/etc/postgresql/9.2/main/pg_hba.conf`` you have following line:
.. code-block:: bash
@@ -91,17 +90,9 @@ uncomment ``listen_addresses`` so it is as follows:
listen_addresses='*'
.. note::
This PostgreSQL setup is for development only purposes. Refer
to PostgreSQL documentation how to fine-tune these settings so that it
is enough secure.
Exit.
.. code-block:: bash
exit
*Note:* this PostgreSQL setup is for development only purposes. Refer
to PostgreSQL documentation how to fine-tune these settings so that it
is enough secure.
Create an image and assign it a name. ``<container_id>`` is in the
Bash prompt; you can also locate it using ``docker ps -a``.
@@ -120,9 +111,7 @@ Finally, run PostgreSQL server via ``docker``.
-D /var/lib/postgresql/9.2/main \
-c config_file=/etc/postgresql/9.2/main/postgresql.conf')
Connect the PostgreSQL server using ``psql`` (You will need postgres installed
on the machine. For ubuntu, use something like
``sudo apt-get install postgresql``).
Connect the PostgreSQL server using ``psql``.
.. code-block:: bash
@@ -139,7 +128,7 @@ As before, create roles or databases if needed.
docker=# CREATE DATABASE foo OWNER=docker;
CREATE DATABASE
Additionally, publish your newly created image on Docker Index.
Additionally, publish there your newly created image on Docker Index.
.. code-block:: bash
@@ -160,11 +149,10 @@ container starts.
.. code-block:: bash
sudo docker commit -run='{"Cmd": \
sudo docker commit <container_id> <your username> postgresql -run='{"Cmd": \
["/bin/su", "postgres", "-c", "/usr/lib/postgresql/9.2/bin/postgres -D \
/var/lib/postgresql/9.2/main -c \
config_file=/etc/postgresql/9.2/main/postgresql.conf"], "PortSpecs": ["5432"]}' \
<container_id> <your username>/postgresql
config_file=/etc/postgresql/9.2/main/postgresql.conf"], "PortSpecs": ["5432"]}'
From now on, just type ``docker run <your username>/postgresql`` and
PostgreSQL should automatically start.
+2
View File
@@ -2,6 +2,8 @@
:description: An overview of the Docker Documentation
:keywords: containers, lxc, concepts, explanation
.. image:: https://www.docker.io/static/img/linked/dockerlogo-horizontal.png
Introduction
------------
+4 -4
View File
@@ -44,10 +44,10 @@ Security Group to allow SSH.** By default all incoming ports to your
new instance will be blocked by the AWS Security Group, so you might
just get timeouts when you try to connect.
Installing with ``get.docker.io`` (as above) will create a service named
``lxc-docker``. It will also set up a :ref:`docker group <dockergroup>` and you
may want to add the *ubuntu* user to it so that you don't have to use ``sudo``
for every Docker command.
Installing with ``get.docker.io`` (as above) will create a service
named ``dockerd``. You may want to set up a :ref:`docker group
<dockergroup>` and add the *ubuntu* user to it so that you don't have
to use ``sudo`` for every Docker command.
Once you've got Docker installed, you're ready to try it out -- head
on over to the :doc:`../use/basics` or :doc:`../examples/index` section.
+3 -1
View File
@@ -53,7 +53,9 @@ Spin it up
* Download the 'official' Precise64 base ubuntu virtual machine image from vagrantup.com
* Boot this image in virtualbox
* Follow official :ref:`ubuntu_linux` installation path
* 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.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

+5 -11
View File
@@ -54,14 +54,8 @@ Docker evaluates the instructions in a Dockerfile in order. **The
first instruction must be `FROM`** in order to specify the
:ref:`base_image_def` from which you are building.
Docker will treat lines that *begin* with ``#`` as a comment. A ``#``
marker anywhere else in the line will be treated as an argument. This
allows statements like:
::
# Comment
RUN echo 'we are running some # of cool things'
Docker will ignore **comment lines** *beginning* with ``#``. A comment
marker anywhere in the rest of the line will be treated as an argument.
3. Instructions
===============
@@ -232,10 +226,10 @@ The copy obeys the following rules:
with conflicts resolved in favor of 2) on a file-by-file basis.
* If ``<src>`` is any other kind of file, it is copied individually
along with its metadata. In this case, if ``<dest>`` ends with a
along with its metadata. In this case, if ``<dst>`` ends with a
trailing slash ``/``, it will be considered a directory and the
contents of ``<src>`` will be written at ``<dest>/base(<src>)``.
* If ``<dest>`` does not end with a trailing slash, it will be
contents of ``<src>`` will be written at ``<dst>/base(<src>)``.
* If ``<dst>`` does not end with a trailing slash, it will be
considered a regular file and the contents of ``<src>`` will be
written at ``<dst>``.
* If ``<dest>`` doesn't exist, it is created along with all missing
+3 -10
View File
@@ -22,9 +22,7 @@ const (
CONSTRAINT "parent_fk" FOREIGN KEY ("parent_id") REFERENCES "entity" ("id"),
CONSTRAINT "entity_fk" FOREIGN KEY ("entity_id") REFERENCES "entity" ("id")
);
`
createEdgeIndices = `
CREATE UNIQUE INDEX "name_parent_ix" ON "edge" (parent_id, name);
`
)
@@ -69,9 +67,6 @@ func NewDatabase(dbPath string) (*Database, error) {
if _, err := conn.Exec(createEdgeTable); err != nil {
return nil, err
}
if _, err := conn.Exec(createEdgeIndices); err != nil {
return nil, err
}
rollback := func() {
conn.Exec("ROLLBACK")
@@ -104,11 +99,9 @@ func (db *Database) Set(fullPath, id string) (*Entity, error) {
return nil, err
}
defer conn.Close()
// FIXME: is rollback implicit when closing the connection?
rollback := func() {
conn.Exec("ROLLBACK")
}
// FIXME: use exclusive transactions to avoid race conditions
if _, err := conn.Exec("BEGIN"); err != nil {
return nil, err
}
@@ -288,7 +281,7 @@ func (db *Database) Delete(name string) error {
return err
}
if _, err := conn.Exec("DELETE FROM edge WHERE parent_id = ? AND name LIKE ?;", parent.id, n+"%"); err != nil {
if _, err := conn.Exec("DELETE FROM edge WHERE parent_id = ? AND name = ?;", parent.id, n); err != nil {
return err
}
return nil
@@ -356,7 +349,7 @@ func (db *Database) Rename(currentName, newName string) error {
return err
}
rows, err := conn.Exec("UPDATE edge SET name = ? WHERE parent_id = ? AND name LIKE ?;", newEdgeName, parent.id, name+"%")
rows, err := conn.Exec("UPDATE edge SET name = ? WHERE parent_id = ? AND name = ?;", newEdgeName, parent.id, name)
if err != nil {
return err
}
@@ -433,7 +426,7 @@ func (db *Database) children(conn *sql.DB, name string, depth int) <-chan WalkMe
// Return the entity based on the parent path and name
func (db *Database) child(conn *sql.DB, parent *Entity, name string) *Entity {
var id string
if err := conn.QueryRow("SELECT entity_id FROM edge WHERE parent_id = ? AND name LIKE ?;", parent.id, name+"%").Scan(&id); err != nil {
if err := conn.QueryRow("SELECT entity_id FROM edge WHERE parent_id = ? AND name = ?;", parent.id, name).Scan(&id); err != nil {
return nil
}
return &Entity{id}
+1 -13
View File
@@ -22,7 +22,7 @@ func destroyTestDb(db *Database) {
func TestNewDatabase(t *testing.T) {
db := newTestDb(t)
if db == nil {
t.Fatal("Database should not be nil")
t.Fatal("Datbase should not be nil")
}
defer destroyTestDb(db)
}
@@ -59,18 +59,6 @@ func TestSetEntityWithDifferentName(t *testing.T) {
}
}
func TestSetDuplicateEntity(t *testing.T) {
db := newTestDb(t)
defer destroyTestDb(db)
if _, err := db.Set("/foo", "42"); err != nil {
t.Fatal(err)
}
if _, err := db.Set("/foo", "43"); err == nil {
t.Fatalf("Creating an entry with a duplciate path did not cause an error")
}
}
func TestCreateChild(t *testing.T) {
db := newTestDb(t)
defer destroyTestDb(db)
+5 -17
View File
@@ -57,13 +57,7 @@ EXAMPLES:
FIXME
### 5. Test the docs
Make sure that your tree includes documentation for any modified or
new features, syntax or semantic changes. Instructions for building
the docs are in ``docs/README.md``
### 6. Commit and create a pull request to the "release" branch
### 5. Commit and create a pull request to the "release" branch
```bash
git add CHANGELOG.md
@@ -71,9 +65,9 @@ git commit -m "Bump version to $VERSION"
git push origin bump_$VERSION
```
### 7. Get 2 other maintainers to validate the pull request
### 6. Get 2 other maintainers to validate the pull request
### 8. Merge the pull request and apply tags
### 7. Merge the pull request and apply tags
```bash
git checkout release
@@ -84,13 +78,7 @@ git push
git push --tags
```
Merging the pull request to the release branch will automatically
update the documentation on the "latest" revision of the docs. You
should see the updated docs 5-10 minutes after the merge. The docs
will appear on http://docs.docker.io/. For more information about
documentation releases, see ``docs/README.md``
### 9. Publish binaries
### 8. Publish binaries
To run this you will need access to the release credentials.
Get them from [the infrastructure maintainers](
@@ -112,6 +100,6 @@ use get-nightly.docker.io for general testing, and once everything is fine,
switch to get.docker.io).
### 10. Rejoice!
### 9. Rejoice!
Congratulations! You're done.
+2 -80
View File
@@ -1,83 +1,5 @@
# Docker project infrastructure
This is an overview of the Docker infrastructure.
This directory holds all information about the technical infrastructure of the docker project; servers, dns, email, and all the corresponding tools and configuration.
**Note: obviously, credentials should not be stored in this repository.**
However, when there are credentials, we should list how to obtain them
(e.g. who has them).
## Providers
This should be the list of all the entities providing some kind of
infrastructure service to the Docker project (either for free,
or paid by dotCloud).
Provider | Service
--------------|-------------------------------------------------
AWS | packages (S3 bucket), dotCloud PAAS, dev-env, ci
CloudFlare | cdn
Digital Ocean | ci
dotCloud PAAS | website, index, registry, ssl, blog
DynECT | dns (docker.io)
GitHub | repository
Linode | stackbrew
Mailgun | outgoing e-mail
ReadTheDocs | docs
*Ordered-by: lexicographic*
## URLs
This should be the list of all the infrastructure-related URLs
and which service is handling them.
URL | Service
---------------------------------------------|---------------------------------
http://blog.docker.io/ | blog
*http://cdn-registry-1.docker.io/ | registry (pull)
http://debug.docker.io/ | debug tool
http://docs.docker.io/ | docsproxy (proxy to readthedocs)
http://docker-ci.dotcloud.com/ | ci
http://docker.io/ | redirect to www.docker.io (dynect)
http://docker.readthedocs.org/ | docs
*http://get.docker.io/ | packages
https://github.com/dotcloud/docker | repository
*https://index.docker.io/ | index
http://registry-1.docker.io/ | registry (push)
http://staging-docker-ci.dotcloud.com/ | ci
*http://test.docker.io/ | packages
*http://www.docker.io/ | website
http://? (internal URL, not for public use) | stackbrew
*Ordered-by: lexicographic*
**Note:** an asterisk in front of the URL means that it is cached by CloudFlare.
## Services
This should be the list of all services referenced above.
Service | Maintainer(s) | How to update | Source
--------------------|--------------------|------------------|-------
blog | @jbarbier | dotcloud push | https://github.com/dotcloud/blog.docker.io
cdn | @jpetazzo @samalba | cloudflare panel | N/A
ci | @mzdaniel | See [docker-ci] | See [docker-ci]
docs | @metalivedev | github webhook | docker repo
docsproxy | @dhrp | dotcloud push | https://github.com/dotcloud/docker-docs-dotcloud-proxy
index | @kencochrane | dotcloud push | private
packages | @jpetazzo | hack/release | docker repo
registry | @samalba | dotcloud push | https://github.com/dotcloud/docker-registry
repository (github) | N/A | N/A | N/A
ssl (dotcloud) | @jpetazzo | dotcloud ops | N/A
ssl (cloudflare) | @jpetazzo | cloudflare panel | N/A
stackbrew | @shin- | manual | https://github.com/dotcloud/stackbrew/stackbrew
website | @dhrp | dotcloud push | https://github.com/dotcloud/www.docker.io
*Ordered-by: lexicographic*
[docker-ci]: docker-ci.rst
Obviously credentials should not be stored in this repo, but how to obtain and use them should be documented here.
+2 -43
View File
@@ -1,38 +1,5 @@
docker-ci
=========
docker-ci is our buildbot continuous integration server,
building and testing docker, hosted on EC2 and reachable at
http://docker-ci.dotcloud.com
Deployment
==========
# Load AWS credentials
export AWS_ACCESS_KEY_ID=''
export AWS_SECRET_ACCESS_KEY=''
export AWS_KEYPAIR_NAME=''
export AWS_SSH_PRIVKEY=''
# Load buildbot credentials and config
export BUILDBOT_PWD=''
export IRC_PWD=''
export IRC_CHANNEL='docker-dev'
export SMTP_USER=''
export SMTP_PWD=''
export EMAIL_RCP=''
# Load registry test credentials
export REGISTRY_USER=''
export REGISTRY_PWD=''
cd docker/testing
vagrant up --provider=aws
github pull request
===================
docker-ci github pull request
=============================
The entire docker pull request test workflow is event driven by github. Its
usage is fully automatic and the results are logged in docker-ci.dotcloud.com
@@ -46,11 +13,3 @@ buildbot (0.8.7p1) was patched using ./testing/buildbot/github.py, so it
can understand the PR data github sends to it. Originally PR #1603 (ee64e099e0)
implemented this capability. Also we added a new scheduler to exclusively filter
PRs. and the 'pullrequest' builder to rebase the PR on top of master and test it.
nighthly release
================
The nightly release process is done by buildbot, running a DinD container that downloads
the docker repository and builds the release container. The resulting docker
binary is then tested, and if everything is fine, the release is done.
-43
View File
@@ -1,43 +0,0 @@
# VERSION: 0.22
# DOCKER-VERSION 0.6.3
# AUTHOR: Daniel Mizyrycki <daniel@dotcloud.com>
# DESCRIPTION: Deploy docker-ci on Amazon EC2
# COMMENTS:
# CONFIG_JSON is an environment variable json string loaded as:
#
# export CONFIG_JSON='
# { "AWS_TAG": "EC2_instance_name",
# "AWS_ACCESS_KEY": "EC2_access_key",
# "AWS_SECRET_KEY": "EC2_secret_key",
# "DOCKER_CI_PUB": "$(cat docker-ci_ssh_public_key.pub)",
# "DOCKER_CI_KEY": "$(cat docker-ci_ssh_private_key.key)",
# "BUILDBOT_PWD": "Buildbot_server_password",
# "IRC_PWD": "Buildbot_IRC_password",
# "SMTP_USER": "SMTP_server_user",
# "SMTP_PWD": "SMTP_server_password",
# "PKG_ACCESS_KEY": "Docker_release_S3_bucket_access_key",
# "PKG_SECRET_KEY": "Docker_release_S3_bucket_secret_key",
# "PKG_GPG_PASSPHRASE": "Docker_release_gpg_passphrase",
# "INDEX_AUTH": "Index_encripted_user_password",
# "REGISTRY_USER": "Registry_test_user",
# "REGISTRY_PWD": "Registry_test_password",
# "REGISTRY_BUCKET": "Registry_S3_bucket_name",
# "REGISTRY_ACCESS_KEY": "Registry_S3_bucket_access_key",
# "REGISTRY_SECRET_KEY": "Registry_S3_bucket_secret_key",
# "IRC_CHANNEL": "Buildbot_IRC_channel",
# "EMAIL_RCP": "Buildbot_mailing_receipient" }'
#
#
# TO_BUILD: docker build -t docker-ci .
# TO_DEPLOY: docker run -e CONFIG_JSON="${CONFIG_JSON}" docker-ci
from ubuntu:12.04
run echo 'deb http://archive.ubuntu.com/ubuntu precise main universe' > /etc/apt/sources.list
run apt-get update; apt-get install -y python2.7 python-dev python-pip ssh rsync less vim
run pip install boto fabric
# Add deployment code and set default container command
add . /docker-ci
cmd "/docker-ci/deployment.py"
-26
View File
@@ -1,26 +0,0 @@
=======
testing
=======
This directory contains docker-ci testing related files.
Buildbot
========
Buildbot is a continuous integration system designed to automate the
build/test cycle. By automatically rebuilding and testing the tree each time
something has changed, build problems are pinpointed quickly, before other
developers are inconvenienced by the failure.
We are running buildbot in Amazon's EC2 to verify docker passes all
tests when commits get pushed to the master branch and building
nightly releases using Docker in Docker awesome implementation made
by Jerome Petazzoni.
https://github.com/jpetazzo/dind
Docker's buildbot instance is at http://docker-ci.dotcloud.com/waterfall
For deployment instructions, please take a look at
hack/infrastructure/docker-ci/Dockerfile
@@ -1 +0,0 @@
Buildbot configuration and setup files
-155
View File
@@ -1,155 +0,0 @@
#!/usr/bin/env python
import os, sys, re, json, base64
from boto.ec2.connection import EC2Connection
from subprocess import call
from fabric import api
from fabric.api import cd, run, put, sudo
from os import environ as env
from time import sleep
# Remove SSH private key as it needs more processing
CONFIG = json.loads(re.sub(r'("DOCKER_CI_KEY".+?"(.+?)",)','',
env['CONFIG_JSON'], flags=re.DOTALL))
# Populate environment variables
for key in CONFIG:
env[key] = CONFIG[key]
# Load SSH private key
env['DOCKER_CI_KEY'] = re.sub('^.+"DOCKER_CI_KEY".+?"(.+?)".+','\\1',
env['CONFIG_JSON'],flags=re.DOTALL)
AWS_TAG = env.get('AWS_TAG','docker-ci')
AWS_KEY_NAME = 'dotcloud-dev' # Same as CONFIG_JSON['DOCKER_CI_PUB']
AWS_AMI = 'ami-d582d6bc' # Ubuntu 13.04
AWS_REGION = 'us-east-1'
AWS_TYPE = 'm1.small'
AWS_SEC_GROUPS = 'gateway'
AWS_IMAGE_USER = 'ubuntu'
DOCKER_PATH = '/go/src/github.com/dotcloud/docker'
DOCKER_CI_PATH = '/docker-ci'
CFG_PATH = '{}/buildbot'.format(DOCKER_CI_PATH)
class AWS_EC2:
'''Amazon EC2'''
def __init__(self, access_key, secret_key):
'''Set default API parameters'''
self.handler = EC2Connection(access_key, secret_key)
def create_instance(self, tag, instance_type):
reservation = self.handler.run_instances(**instance_type)
instance = reservation.instances[0]
sleep(10)
while instance.state != 'running':
sleep(5)
instance.update()
print "Instance state: %s" % (instance.state)
instance.add_tag("Name",tag)
print "instance %s done!" % (instance.id)
return instance.ip_address
def get_instances(self):
return self.handler.get_all_instances()
def get_tags(self):
return dict([(i.instances[0].id, i.instances[0].tags['Name'])
for i in self.handler.get_all_instances() if i.instances[0].tags])
def del_instance(self, instance_id):
self.handler.terminate_instances(instance_ids=[instance_id])
def json_fmt(data):
'''Format json output'''
return json.dumps(data, sort_keys = True, indent = 2)
# Create EC2 API handler
ec2 = AWS_EC2(env['AWS_ACCESS_KEY'], env['AWS_SECRET_KEY'])
# Stop processing if AWS_TAG exists on EC2
if AWS_TAG in ec2.get_tags().values():
print ('Instance: {} already deployed. Not further processing.'
.format(AWS_TAG))
exit(1)
ip = ec2.create_instance(AWS_TAG, {'image_id':AWS_AMI, 'instance_type':AWS_TYPE,
'security_groups':[AWS_SEC_GROUPS], 'key_name':AWS_KEY_NAME})
# Wait 30 seconds for the machine to boot
sleep(30)
# Create docker-ci ssh private key so docker-ci docker container can communicate
# with its EC2 instance
os.makedirs('/root/.ssh')
open('/root/.ssh/id_rsa','w').write(env['DOCKER_CI_KEY'])
os.chmod('/root/.ssh/id_rsa',0600)
open('/root/.ssh/config','w').write('StrictHostKeyChecking no\n')
api.env.host_string = ip
api.env.user = AWS_IMAGE_USER
api.env.key_filename = '/root/.ssh/id_rsa'
# Correct timezone
sudo('echo "America/Los_Angeles" >/etc/timezone')
sudo('dpkg-reconfigure --frontend noninteractive tzdata')
# Load public docker-ci key
sudo("echo '{}' >> /root/.ssh/authorized_keys".format(env['DOCKER_CI_PUB']))
# Create docker nightly release credentials file
credentials = {
'AWS_ACCESS_KEY': env['PKG_ACCESS_KEY'],
'AWS_SECRET_KEY': env['PKG_SECRET_KEY'],
'GPG_PASSPHRASE': env['PKG_GPG_PASSPHRASE'],
'INDEX_AUTH': env['INDEX_AUTH']}
open(DOCKER_CI_PATH + '/nightlyrelease/release_credentials.json', 'w').write(
base64.b64encode(json.dumps(credentials)))
# Transfer docker
sudo('mkdir -p ' + DOCKER_CI_PATH)
sudo('chown {}.{} {}'.format(AWS_IMAGE_USER, AWS_IMAGE_USER, DOCKER_CI_PATH))
call('/usr/bin/rsync -aH {} {}@{}:{}'.format(DOCKER_CI_PATH, AWS_IMAGE_USER, ip,
os.path.dirname(DOCKER_CI_PATH)), shell=True)
# Install Docker and Buildbot dependencies
sudo('addgroup docker')
sudo('usermod -a -G docker ubuntu')
sudo('mkdir /mnt/docker; ln -s /mnt/docker /var/lib/docker')
sudo('wget -q -O - https://get.docker.io/gpg | apt-key add -')
sudo('echo deb https://get.docker.io/ubuntu docker main >'
' /etc/apt/sources.list.d/docker.list')
sudo('echo -e "deb http://archive.ubuntu.com/ubuntu raring main universe\n'
'deb http://us.archive.ubuntu.com/ubuntu/ raring-security main universe\n"'
' > /etc/apt/sources.list; apt-get update')
sudo('DEBIAN_FRONTEND=noninteractive apt-get install -q -y wget python-dev'
' python-pip supervisor git mercurial linux-image-extra-$(uname -r)'
' aufs-tools make libfontconfig libevent-dev')
sudo('wget -O - https://go.googlecode.com/files/go1.1.2.linux-amd64.tar.gz | '
'tar -v -C /usr/local -xz; ln -s /usr/local/go/bin/go /usr/bin/go')
sudo('GOPATH=/go go get -d github.com/dotcloud/docker')
sudo('pip install -r {}/requirements.txt'.format(CFG_PATH))
# Install docker and testing dependencies
sudo('apt-get install -y -q lxc-docker')
sudo('curl -s https://phantomjs.googlecode.com/files/'
'phantomjs-1.9.1-linux-x86_64.tar.bz2 | tar jx -C /usr/bin'
' --strip-components=2 phantomjs-1.9.1-linux-x86_64/bin/phantomjs')
#### FIXME. Temporarily install docker with proper apparmor handling
sudo('stop docker')
sudo('wget -q -O /usr/bin/docker http://test.docker.io/test/docker')
sudo('start docker')
# Build docker-ci containers
sudo('cd {}; docker build -t docker .'.format(DOCKER_PATH))
sudo('cd {}/nightlyrelease; docker build -t dockerbuilder .'.format(
DOCKER_CI_PATH))
# Setup buildbot
sudo('mkdir /data')
sudo('{0}/setup.sh root {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10}'
' {11} {12}'.format(CFG_PATH, DOCKER_PATH, env['BUILDBOT_PWD'],
env['IRC_PWD'], env['IRC_CHANNEL'], env['SMTP_USER'],
env['SMTP_PWD'], env['EMAIL_RCP'], env['REGISTRY_USER'],
env['REGISTRY_PWD'], env['REGISTRY_BUCKET'], env['REGISTRY_ACCESS_KEY'],
env['REGISTRY_SECRET_KEY']))
@@ -1,32 +0,0 @@
#!/bin/bash
set -x
# Generate a random string of $1 characters
function random {
cat /dev/urandom | tr -cd 'a-f0-9' | head -c $1
}
# Compute test paths
BASE_PATH=`pwd`/test_docker_$(random 12)
DOCKER_PATH=$BASE_PATH/go/src/github.com/dotcloud/docker
export GOPATH=$BASE_PATH/go:$DOCKER_PATH/vendor
# Fetch latest master
mkdir -p $DOCKER_PATH
cd $DOCKER_PATH
git init .
git fetch -q http://github.com/dotcloud/docker master
git reset --hard FETCH_HEAD
# Fetch go coverage
cd $BASE_PATH/go
GOPATH=$BASE_PATH/go go get github.com/axw/gocov/gocov
sudo -E GOPATH=$GOPATH ./bin/gocov test -deps -exclude-goroot -v\
-exclude github.com/gorilla/context,github.com/gorilla/mux,github.com/kr/pty,\
code.google.com/p/go.net/websocket,github.com/dotcloud/tar\
github.com/dotcloud/docker | ./bin/gocov report; exit_status=$?
# Cleanup testing directory
rm -rf $BASE_PATH
exit $exit_status
@@ -1,35 +0,0 @@
#!/bin/bash
set -x
COMMIT=${1-HEAD}
REPO=${2-http://github.com/dotcloud/docker}
BRANCH=${3-master}
# Generate a random string of $1 characters
function random {
cat /dev/urandom | tr -cd 'a-f0-9' | head -c $1
}
# Compute test paths
BASE_PATH=`pwd`/test_docker_$(random 12)
DOCKER_PATH=$BASE_PATH/go/src/github.com/dotcloud/docker
export GOPATH=$BASE_PATH/go:$DOCKER_PATH/vendor
# Fetch latest master
mkdir -p $DOCKER_PATH
cd $DOCKER_PATH
git init .
git fetch -q http://github.com/dotcloud/docker master
git reset --hard FETCH_HEAD
# Merge commit
git fetch -q "$REPO" "$BRANCH"
git merge --no-edit $COMMIT || exit 1
# Test commit
go test -v; exit_status=$?
# Cleanup testing directory
rm -rf $BASE_PATH
exit $exit_status
@@ -1,26 +0,0 @@
#!/bin/sh
set -x
# Cleanup
rm -rf docker-registry
# Setup the environment
export SETTINGS_FLAVOR=test
export DOCKER_REGISTRY_CONFIG=config_test.yml
# Get latest docker registry
git clone -q https://github.com/dotcloud/docker-registry.git
cd docker-registry
# Get dependencies
pip install -q -r requirements.txt
pip install -q -r test-requirements.txt
pip install -q tox
# Run registry tests
tox || exit 1
export PYTHONPATH=$(pwd)/docker-registry
python -m unittest discover -p s3.py -s test || exit 1
python -m unittest discover -p workflow.py -s test
@@ -1,37 +0,0 @@
# VERSION: 1.2
# DOCKER-VERSION 0.6.3
# AUTHOR: Daniel Mizyrycki <daniel@dotcloud.com>
# DESCRIPTION: Build docker nightly release using Docker in Docker.
# REFERENCES: This code reuses the excellent implementation of docker in docker
# made by Jerome Petazzoni. https://github.com/jpetazzo/dind
# COMMENTS:
# release_credentials.json is a base64 json encoded file containing:
# { "AWS_ACCESS_KEY": "Test_docker_AWS_S3_bucket_id",
# "AWS_SECRET_KEY='Test_docker_AWS_S3_bucket_key'
# "GPG_PASSPHRASE='Test_docker_GPG_passphrase_signature'
# "INDEX_AUTH='Encripted_index_authentication' }
# TO_BUILD: docker build -t dockerbuilder .
# TO_RELEASE: docker run -i -t -privileged -lxc-conf="lxc.aa_profile = unconfined" -e AWS_S3_BUCKET="test.docker.io" dockerbuilder
from docker
maintainer Daniel Mizyrycki <daniel@dotcloud.com>
# Add docker dependencies and downloading packages
run echo 'deb http://archive.ubuntu.com/ubuntu precise main universe' > /etc/apt/sources.list
run apt-get update; apt-get install -y -q wget python2.7
# Add production docker binary
run wget -q -O /usr/bin/docker http://get.docker.io/builds/Linux/x86_64/docker-latest; chmod +x /usr/bin/docker
#### FIXME. Temporarily install docker with proper apparmor handling
run wget -q -O /usr/bin/docker http://test.docker.io/test/docker; chmod +x /usr/bin/docker
# Add proto docker builder
add ./dockerbuild /usr/bin/dockerbuild
run chmod +x /usr/bin/dockerbuild
# Add release credentials
add ./release_credentials.json /root/release_credentials.json
# Launch build process in a container
cmd dockerbuild
@@ -1,45 +0,0 @@
#!/bin/bash
# Variables AWS_ACCESS_KEY, AWS_SECRET_KEY, PG_PASSPHRASE and INDEX_AUTH
# are decoded from /root/release_credentials.json
# Variable AWS_S3_BUCKET is passed to the environment from docker run -e
# Enable debugging
set -x
# Fetch docker master branch
rm -rf /go/src/github.com/dotcloud/docker
cd /
git clone -q http://github.com/dotcloud/docker /go/src/github.com/dotcloud/docker
cd /go/src/github.com/dotcloud/docker
echo FIXME. Temporarily add Jerome changeset with proper apparmor handling
git fetch http://github.com/jpetazzo/docker escape-apparmor-confinement:escape-apparmor-confinement
git rebase --onto master master escape-apparmor-confinement
# Launch docker daemon using dind inside the container
./hack/dind /usr/bin/docker -d &
sleep 5
# Add an uncommitted change to generate a timestamped release
date > timestamp
# Build the docker package using /Dockerfile
docker build -t docker .
# Run Docker unittests binary and Ubuntu package
docker run -privileged -lxc-conf=lxc.aa_profile=unconfined docker hack/make.sh || exit 1
# Turn debug off to load credentials from the environment
set +x
eval $(cat /root/release_credentials.json | python -c '
import sys,json,base64;
d=json.loads(base64.b64decode(sys.stdin.read()));
exec("""for k in d: print "export {0}=\\"{1}\\"".format(k,d[k])""")')
echo '{"https://index.docker.io/v1/":{"auth":"'$INDEX_AUTH'","email":"engineering@dotcloud.com"}}' > /.dockercfg
set -x
# Push docker nightly
echo docker run -i -t -privileged -e AWS_S3_BUCKET=$AWS_S3_BUCKET -e AWS_ACCESS_KEY=XXXXX -e AWS_SECRET_KEY=XXXXX -e GPG_PASSPHRASE=XXXXX release hack/release.sh
set +x
docker run -i -t -privileged -e AWS_S3_BUCKET=$AWS_S3_BUCKET -e AWS_ACCESS_KEY=$AWS_ACCESS_KEY -e AWS_SECRET_KEY=$AWS_SECRET_KEY -e GPG_PASSPHRASE=$GPG_PASSPHRASE release hack/release.sh
@@ -1 +0,0 @@
eyAiQVdTX0FDQ0VTU19LRVkiOiAiIiwKICAiQVdTX1NFQ1JFVF9LRVkiOiAiIiwKICAiR1BHX1BBU1NQSFJBU0UiOiAiIiwKICAiSU5ERVhfQVVUSCI6ICIiIH0=
@@ -1,28 +0,0 @@
# VERSION: 0.22
# DOCKER-VERSION 0.6.3
# AUTHOR: Daniel Mizyrycki <daniel@dotcloud.com>
# DESCRIPTION: Generate docker-ci daily report
# COMMENTS: The build process is initiated by deployment.py
Report configuration is passed through ./credentials.json at
# deployment time.
# TO_BUILD: docker build -t report .
# TO_DEPLOY: docker run report
from ubuntu:12.04
maintainer Daniel Mizyrycki <daniel@dotcloud.com>
env PYTHONPATH /report
# Add report dependencies
run echo 'deb http://archive.ubuntu.com/ubuntu precise main universe' > \
/etc/apt/sources.list
run apt-get update; apt-get install -y python2.7 python-pip ssh rsync
# Set San Francisco timezone
run echo "America/Los_Angeles" >/etc/timezone
run dpkg-reconfigure --frontend noninteractive tzdata
# Add report code and set default container command
add . /report
cmd "/report/report.py"

Some files were not shown because too many files have changed in this diff Show More