Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8da76605f | ||
|
|
f16e60665b | ||
|
|
3ba9893786 | ||
|
|
6ee2964a4f | ||
|
|
49c62879b8 | ||
|
|
34745ee0f4 | ||
|
|
d21bd5b964 | ||
|
|
82220ea2ad | ||
|
|
655b16c712 | ||
|
|
eb2d0d4bf5 | ||
|
|
cc851dbb3f | ||
|
|
e40fd1e3e1 | ||
|
|
dab84f7e8b | ||
|
|
7df8ec2093 | ||
|
|
a2ffa637ce | ||
|
|
ed6ca109bf | ||
|
|
6e48b73955 | ||
|
|
664acd2971 | ||
|
|
3acfc60028 | ||
|
|
0e64a4d7e7 | ||
|
|
104a86936a | ||
|
|
df697b4318 | ||
|
|
27fc01271e | ||
|
|
97ab118fbb | ||
|
|
fc659b68e4 | ||
|
|
99f6b43f4f | ||
|
|
2b92aa71f9 | ||
|
|
f854529ae8 | ||
|
|
e32debcf5f | ||
|
|
0e08e1d695 | ||
|
|
65b62307c3 | ||
|
|
03e5d94b12 | ||
|
|
0ca533ca35 | ||
|
|
d94a027da6 | ||
|
|
7250f94874 | ||
|
|
4196c704f0 | ||
|
|
adb48ef319 | ||
|
|
ee7d9b0bde | ||
|
|
2f4526d5c4 | ||
|
|
261285c2c2 | ||
|
|
cbc49d7d76 | ||
|
|
4dc90405e3 | ||
|
|
b7abe9dab5 | ||
|
|
cd455ca6fa | ||
|
|
ca56b35e53 | ||
|
|
ace059e409 | ||
|
|
9da2b3590e | ||
|
|
e99ab1df97 | ||
|
|
fde157425c | ||
|
|
a0e5657cb6 | ||
|
|
f4a98b4598 | ||
|
|
53a07d5475 | ||
|
|
93b258413f | ||
|
|
c0bfb75e5f | ||
|
|
620bc5b9e1 | ||
|
|
6d6097cddf | ||
|
|
42277d0329 | ||
|
|
d62df6b2b5 | ||
|
|
97779ff7cf | ||
|
|
9afa48a92f | ||
|
|
ad723bbfe7 | ||
|
|
f15cd71bb8 | ||
|
|
94bf5b0011 | ||
|
|
d542318d63 | ||
|
|
6e3068700f | ||
|
|
fac190959f | ||
|
|
1dcdc3deb7 | ||
|
|
ee256ce6bf | ||
|
|
5fe699f813 | ||
|
|
7561e2570c | ||
|
|
640ca68e4f | ||
|
|
f9b9dfc82d | ||
|
|
c978f0fa5c | ||
|
|
d91bf33df3 | ||
|
|
310a174260 | ||
|
|
2eb404ab14 | ||
|
|
60e426938e | ||
|
|
9041d6a47b | ||
|
|
8abd328f53 | ||
|
|
ae780fb5ea | ||
|
|
152037f011 | ||
|
|
0367032bd1 | ||
|
|
edca9f7e9c | ||
|
|
e19cc1e843 | ||
|
|
feabce3bcc | ||
|
|
ded74b0bb3 | ||
|
|
ffee5faae8 | ||
|
|
c1bb33ea4d | ||
|
|
6545e53803 | ||
|
|
d30806590c | ||
|
|
823174de4d | ||
|
|
d5f9160441 | ||
|
|
37df1d92d8 | ||
|
|
dabac81824 | ||
|
|
bb62c281f5 | ||
|
|
3565bf8d00 | ||
|
|
f4c17a202b | ||
|
|
9a4b0b9823 | ||
|
|
9107565d06 | ||
|
|
4fda3314d8 | ||
|
|
e906485b07 | ||
|
|
1daf242c8b | ||
|
|
967010ae8c | ||
|
|
d03022b9ca | ||
|
|
6d67ac2a1b | ||
|
|
2d425af1b1 | ||
|
|
ed19693f50 | ||
|
|
ee27444098 | ||
|
|
194c1dbbd8 | ||
|
|
a9eac7eab4 | ||
|
|
7c28683f08 | ||
|
|
c18e849451 | ||
|
|
a665517151 | ||
|
|
0d3c899528 | ||
|
|
863eebe7bd | ||
|
|
3c5350ba92 | ||
|
|
c52c95f97f | ||
|
|
85a5139665 | ||
|
|
ad4b09cdb8 | ||
|
|
e594c788e4 | ||
|
|
f84dc1e908 | ||
|
|
826aaa0e9b | ||
|
|
1328be7c29 | ||
|
|
ff4f32d58f | ||
|
|
462ac1efcf | ||
|
|
1332f400f7 | ||
|
|
a292c04ddb | ||
|
|
37c4513cf9 | ||
|
|
b584c21ca4 | ||
|
|
c92507341d | ||
|
|
9f0feaa2e1 | ||
|
|
0f830aa431 | ||
|
|
5f05cb4817 | ||
|
|
4778039dd2 | ||
|
|
b180770b1d | ||
|
|
4f5c2cbccc | ||
|
|
c3acd9bece | ||
|
|
cb21a40490 | ||
|
|
5025b4d094 | ||
|
|
509e25cf04 | ||
|
|
135c1fce90 | ||
|
|
d517fd3d77 | ||
|
|
b4e1b8d2e2 | ||
|
|
45bd52d472 | ||
|
|
534a991cff | ||
|
|
23015fa14d | ||
|
|
fb46d911c2 | ||
|
|
85b776995c | ||
|
|
fa44555fb4 | ||
|
|
3e7c50e8a1 | ||
|
|
ccefe47897 | ||
|
|
ff85031980 | ||
|
|
017ecefd66 | ||
|
|
88f710f0e7 | ||
|
|
6496059154 | ||
|
|
bcce3cbdd1 | ||
|
|
bbf644ed62 | ||
|
|
d89ce09a76 | ||
|
|
e3e041b6bf | ||
|
|
0a35b1fb36 | ||
|
|
3894add8a9 | ||
|
|
74d54b9b2e | ||
|
|
31fd11860b | ||
|
|
b081a740b3 | ||
|
|
db869ecce5 | ||
|
|
537149829a | ||
|
|
ba10e28927 | ||
|
|
f4855a7cf0 | ||
|
|
22e7e107ad | ||
|
|
edd90d46c7 | ||
|
|
f435970695 | ||
|
|
cb18a6e1b9 | ||
|
|
ce05083d4b | ||
|
|
723de87681 | ||
|
|
c22e377a6d | ||
|
|
3f0d0075f8 | ||
|
|
f8c9f11f06 | ||
|
|
80319add55 | ||
|
|
818ec10da3 | ||
|
|
34e28ccc88 | ||
|
|
792403f2dc | ||
|
|
8f5c33dc1f | ||
|
|
06c1f000e8 | ||
|
|
00b3acb8ab | ||
|
|
420ba9c85a | ||
|
|
0f829bf5cf | ||
|
|
1363de0934 | ||
|
|
d06116d2e8 | ||
|
|
595210a370 | ||
|
|
c9b916b293 | ||
|
|
1e6370fd4b | ||
|
|
a59a66528b | ||
|
|
b048e9dffc | ||
|
|
c000e6a7fc | ||
|
|
aa3de0b849 | ||
|
|
648d759517 | ||
|
|
5c190fa926 | ||
|
|
03fe5632d0 | ||
|
|
edde4f55e0 | ||
|
|
7447867edd | ||
|
|
c1c74cb0b1 | ||
|
|
17b7194d91 | ||
|
|
15ad2915b9 | ||
|
|
d6887b769c | ||
|
|
10362870db | ||
|
|
a7db125480 | ||
|
|
f6c64827c8 | ||
|
|
30b759ffa9 | ||
|
|
35ca35ffb6 | ||
|
|
a4067b1b44 | ||
|
|
b0a49a30c7 | ||
|
|
6097644e4b | ||
|
|
fa3837abf1 | ||
|
|
baff72bc82 | ||
|
|
99377de7d2 | ||
|
|
0ef5bcb17d | ||
|
|
fd1c43f0e0 | ||
|
|
dc06496dc8 | ||
|
|
cfbe76e559 | ||
|
|
2fafe1efce | ||
|
|
8240e37b87 | ||
|
|
23cf3c7a33 | ||
|
|
e37bb50628 | ||
|
|
2819cfb3f3 | ||
|
|
a479f7659d | ||
|
|
b02a591f57 | ||
|
|
c654075654 | ||
|
|
5a3dcbb3f6 | ||
|
|
cce6f00c0c | ||
|
|
4db64111bd | ||
|
|
e97364ecd7 | ||
|
|
2bd089dadb | ||
|
|
5bd0437eed | ||
|
|
a81393787f | ||
|
|
b45e280ee8 | ||
|
|
5867f9e761 | ||
|
|
6132f378e0 | ||
|
|
3cf4b2c7c1 | ||
|
|
d70cbbf1fc | ||
|
|
b7e7104e92 | ||
|
|
7e60a6b1ea | ||
|
|
45979a7ef7 | ||
|
|
5c9213258a | ||
|
|
68074fce68 | ||
|
|
c42056b969 | ||
|
|
341addeccd | ||
|
|
47904290a5 | ||
|
|
a18c26392f | ||
|
|
77ad95d372 | ||
|
|
fee61895f2 | ||
|
|
f6a78f89ba | ||
|
|
081543c49a | ||
|
|
4054f31471 | ||
|
|
76a07371c5 | ||
|
|
5d364fda3c | ||
|
|
28311f61be | ||
|
|
70b731735c | ||
|
|
67453d6b48 | ||
|
|
c14450ae5c | ||
|
|
593566438d | ||
|
|
85f3ec88a6 | ||
|
|
5797e7e34e | ||
|
|
089a60c2cf | ||
|
|
a99a8386fd | ||
|
|
dfd0deefbb | ||
|
|
9946981c61 | ||
|
|
c6b4076125 | ||
|
|
b79bd4e864 | ||
|
|
082d142024 | ||
|
|
e854b7b2e6 | ||
|
|
289350e633 | ||
|
|
8ae5348a51 | ||
|
|
e5239b9859 |
@@ -26,3 +26,15 @@ Roberto Hashioka <roberto_hashioka@hotmail.com>
|
|||||||
Konstantin Pelykh <kpelykh@zettaset.com>
|
Konstantin Pelykh <kpelykh@zettaset.com>
|
||||||
David Sissitka <me@dsissitka.com>
|
David Sissitka <me@dsissitka.com>
|
||||||
Nolan Darilek <nolan@thewordnerd.info>
|
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>
|
||||||
|
|||||||
@@ -5,64 +5,98 @@
|
|||||||
#
|
#
|
||||||
Al Tobey <al@ooyala.com>
|
Al Tobey <al@ooyala.com>
|
||||||
Alex Gaynor <alex.gaynor@gmail.com>
|
Alex Gaynor <alex.gaynor@gmail.com>
|
||||||
|
Alexander Larsson <alexl@redhat.com>
|
||||||
Alexey Shamrin <shamrin@gmail.com>
|
Alexey Shamrin <shamrin@gmail.com>
|
||||||
Andrea Luzzardi <aluzzardi@gmail.com>
|
Andrea Luzzardi <aluzzardi@gmail.com>
|
||||||
|
Andreas Savvides <andreas@editd.com>
|
||||||
Andreas Tiefenthaler <at@an-ti.eu>
|
Andreas Tiefenthaler <at@an-ti.eu>
|
||||||
|
Andrew Macgregor <andrew.macgregor@agworld.com.au>
|
||||||
Andrew Munsell <andrew@wizardapps.net>
|
Andrew Munsell <andrew@wizardapps.net>
|
||||||
Andrews Medina <andrewsmedina@gmail.com>
|
Andrews Medina <andrewsmedina@gmail.com>
|
||||||
Andy Rothfusz <github@metaliveblog.com>
|
Andy Rothfusz <github@metaliveblog.com>
|
||||||
Andy Smith <github@anarkystic.com>
|
Andy Smith <github@anarkystic.com>
|
||||||
Anthony Bishopric <git@anthonybishopric.com>
|
Anthony Bishopric <git@anthonybishopric.com>
|
||||||
Antony Messerli <amesserl@rackspace.com>
|
Antony Messerli <amesserl@rackspace.com>
|
||||||
|
Asbjørn Enge <asbjorn@hanafjedle.net>
|
||||||
Barry Allard <barry.allard@gmail.com>
|
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 Liu <bdon@bdon.org>
|
||||||
|
Brandon Philips <brandon@ifup.co>
|
||||||
Brian McCallister <brianm@skife.org>
|
Brian McCallister <brianm@skife.org>
|
||||||
Brian Olsen <brian@maven-group.org>
|
Brian Olsen <brian@maven-group.org>
|
||||||
|
Brian Shumate <brian@couchbase.com>
|
||||||
|
Briehan Lombaard <briehan.lombaard@gmail.com>
|
||||||
Bruno Bigras <bigras.bruno@gmail.com>
|
Bruno Bigras <bigras.bruno@gmail.com>
|
||||||
Caleb Spare <cespare@gmail.com>
|
Caleb Spare <cespare@gmail.com>
|
||||||
Calen Pennington <cale@edx.org>
|
Calen Pennington <cale@edx.org>
|
||||||
Charles Hooper <charles.hooper@dotcloud.com>
|
Charles Hooper <charles.hooper@dotcloud.com>
|
||||||
Christopher Currie <codemonkey+github@gmail.com>
|
Christopher Currie <codemonkey+github@gmail.com>
|
||||||
|
Colin Dunklau <colin.dunklau@gmail.com>
|
||||||
Colin Rice <colin@daedrum.net>
|
Colin Rice <colin@daedrum.net>
|
||||||
|
Dan Buch <d.buch@modcloth.com>
|
||||||
|
Daniel Garcia <daniel@danielgarcia.info>
|
||||||
Daniel Gasienica <daniel@gasienica.ch>
|
Daniel Gasienica <daniel@gasienica.ch>
|
||||||
Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com>
|
Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com>
|
||||||
|
Daniel Nordberg <dnordberg@gmail.com>
|
||||||
Daniel Robinson <gottagetmac@gmail.com>
|
Daniel Robinson <gottagetmac@gmail.com>
|
||||||
Daniel Von Fange <daniel@leancoder.com>
|
Daniel Von Fange <daniel@leancoder.com>
|
||||||
Daniel YC Lin <dlin.tw@gmail.com>
|
Daniel YC Lin <dlin.tw@gmail.com>
|
||||||
David Calavera <david.calavera@gmail.com>
|
David Calavera <david.calavera@gmail.com>
|
||||||
David Sissitka <me@dsissitka.com>
|
David Sissitka <me@dsissitka.com>
|
||||||
|
Deni Bertovic <deni@kset.org>
|
||||||
Dominik Honnef <dominik@honnef.co>
|
Dominik Honnef <dominik@honnef.co>
|
||||||
Don Spaulding <donspauldingii@gmail.com>
|
Don Spaulding <donspauldingii@gmail.com>
|
||||||
Dr Nic Williams <drnicwilliams@gmail.com>
|
Dr Nic Williams <drnicwilliams@gmail.com>
|
||||||
|
Dražen Lučanin <kermit666@gmail.com>
|
||||||
Elias Probst <mail@eliasprobst.eu>
|
Elias Probst <mail@eliasprobst.eu>
|
||||||
Emily Rose <emily@contactvibe.com>
|
Emily Rose <emily@contactvibe.com>
|
||||||
Eric Hanchrow <ehanchrow@ine.com>
|
Eric Hanchrow <ehanchrow@ine.com>
|
||||||
Eric Myhre <hash@exultant.us>
|
Eric Myhre <hash@exultant.us>
|
||||||
Erno Hopearuoho <erno.hopearuoho@gmail.com>
|
Erno Hopearuoho <erno.hopearuoho@gmail.com>
|
||||||
|
Evan Phoenix <evan@fallingsnow.net>
|
||||||
Evan Wies <evan@neomantra.net>
|
Evan Wies <evan@neomantra.net>
|
||||||
ezbercih <cem.ezberci@gmail.com>
|
ezbercih <cem.ezberci@gmail.com>
|
||||||
Fabrizio Regini <freegenie@gmail.com>
|
Fabrizio Regini <freegenie@gmail.com>
|
||||||
|
Faiz Khan <faizkhan00@gmail.com>
|
||||||
Fareed Dudhia <fareeddudhia@googlemail.com>
|
Fareed Dudhia <fareeddudhia@googlemail.com>
|
||||||
Flavio Castelli <fcastelli@suse.com>
|
Flavio Castelli <fcastelli@suse.com>
|
||||||
Francisco Souza <f@souza.cc>
|
Francisco Souza <f@souza.cc>
|
||||||
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
|
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
|
||||||
Gabriel Monroy <gabriel@opdemand.com>
|
Gabriel Monroy <gabriel@opdemand.com>
|
||||||
Gareth Rushgrove <gareth@morethanseven.net>
|
Gareth Rushgrove <gareth@morethanseven.net>
|
||||||
|
Greg Thornton <xdissent@me.com>
|
||||||
Guillaume J. Charmes <guillaume.charmes@dotcloud.com>
|
Guillaume J. Charmes <guillaume.charmes@dotcloud.com>
|
||||||
|
Guruprasad <lgp171188@gmail.com>
|
||||||
Harley Laue <losinggeneration@gmail.com>
|
Harley Laue <losinggeneration@gmail.com>
|
||||||
|
Hector Castro <hectcastro@gmail.com>
|
||||||
Hunter Blanks <hunter@twilio.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>
|
Jeff Lindsay <progrium@gmail.com>
|
||||||
Jeremy Grosser <jeremy@synack.me>
|
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>
|
Joffrey F <joffrey@dotcloud.com>
|
||||||
Johan Euphrosine <proppy@google.com>
|
Johan Euphrosine <proppy@google.com>
|
||||||
John Costa <john.costa@gmail.com>
|
John Costa <john.costa@gmail.com>
|
||||||
Jon Wedaman <jweede@gmail.com>
|
Jon Wedaman <jweede@gmail.com>
|
||||||
Jonas Pfenniger <jonas@pfenniger.name>
|
Jonas Pfenniger <jonas@pfenniger.name>
|
||||||
|
Jonathan Mueller <j.mueller@apoveda.ch>
|
||||||
Jonathan Rudenberg <jonathan@titanous.com>
|
Jonathan Rudenberg <jonathan@titanous.com>
|
||||||
|
Joost Cassee <joost@cassee.net>
|
||||||
|
Jordan Arentsen <blissdev@gmail.com>
|
||||||
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
|
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
|
||||||
Julien Barbier <write0@gmail.com>
|
Julien Barbier <write0@gmail.com>
|
||||||
Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
|
Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
|
||||||
Karan Lyons <karan@karanlyons.com>
|
Karan Lyons <karan@karanlyons.com>
|
||||||
|
Karl Grzeszczak <karl@karlgrz.com>
|
||||||
|
Kawsar Saiyeed <kawsar.saiyeed@projiris.com>
|
||||||
Keli Hu <dev@keli.hu>
|
Keli Hu <dev@keli.hu>
|
||||||
Ken Cochrane <kencochrane@gmail.com>
|
Ken Cochrane <kencochrane@gmail.com>
|
||||||
Kevin Clark <kevin.clark@gmail.com>
|
Kevin Clark <kevin.clark@gmail.com>
|
||||||
@@ -71,28 +105,45 @@ kim0 <email.ahmedkamal@googlemail.com>
|
|||||||
Kimbro Staken <kstaken@kstaken.com>
|
Kimbro Staken <kstaken@kstaken.com>
|
||||||
Kiran Gangadharan <kiran.daredevil@gmail.com>
|
Kiran Gangadharan <kiran.daredevil@gmail.com>
|
||||||
Konstantin Pelykh <kpelykh@zettaset.com>
|
Konstantin Pelykh <kpelykh@zettaset.com>
|
||||||
|
Kyle Conroy <kyle.j.conroy@gmail.com>
|
||||||
|
Laurie Voss <github@seldo.com>
|
||||||
Louis Opter <kalessin@kalessin.fr>
|
Louis Opter <kalessin@kalessin.fr>
|
||||||
|
Manuel Meurer <manuel@krautcomputing.com>
|
||||||
Marco Hennings <marco.hennings@freiheit.com>
|
Marco Hennings <marco.hennings@freiheit.com>
|
||||||
Marcus Farkas <toothlessgear@finitebox.com>
|
Marcus Farkas <toothlessgear@finitebox.com>
|
||||||
|
Marcus Ramberg <marcus@nordaaker.com>
|
||||||
Mark McGranaghan <mmcgrana@gmail.com>
|
Mark McGranaghan <mmcgrana@gmail.com>
|
||||||
Martin Redmond <mrtodo@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>
|
||||||
Maxim Treskin <zerthurd@gmail.com>
|
Maxim Treskin <zerthurd@gmail.com>
|
||||||
meejah <meejah@meejah.ca>
|
meejah <meejah@meejah.ca>
|
||||||
Michael Crosby <crosby.michael@gmail.com>
|
Michael Crosby <crosby.michael@gmail.com>
|
||||||
|
Michael Gorsuch <gorsuch@github.com>
|
||||||
|
Miguel Angel Fernández <elmendalerenda@gmail.com>
|
||||||
Mike Gaffney <mike@uberu.com>
|
Mike Gaffney <mike@uberu.com>
|
||||||
Mikhail Sobolev <mss@mawhrin.net>
|
Mikhail Sobolev <mss@mawhrin.net>
|
||||||
|
Mohit Soni <mosoni@ebay.com>
|
||||||
|
Morten Siebuhr <sbhr@sbhr.dk>
|
||||||
Nan Monnand Deng <monnand@gmail.com>
|
Nan Monnand Deng <monnand@gmail.com>
|
||||||
Nate Jones <nate@endot.org>
|
Nate Jones <nate@endot.org>
|
||||||
Nelson Chen <crazysim@gmail.com>
|
Nelson Chen <crazysim@gmail.com>
|
||||||
Niall O'Higgins <niallo@unworkable.org>
|
Niall O'Higgins <niallo@unworkable.org>
|
||||||
|
Nick Payne <nick@kurai.co.uk>
|
||||||
Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
|
Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
|
||||||
Nick Stinemates <nick@stinemates.org>
|
Nick Stinemates <nick@stinemates.org>
|
||||||
Nolan Darilek <nolan@thewordnerd.info>
|
Nolan Darilek <nolan@thewordnerd.info>
|
||||||
odk- <github@odkurzacz.org>
|
odk- <github@odkurzacz.org>
|
||||||
|
Pascal Borreli <pascal@borreli.com>
|
||||||
Paul Bowsher <pbowsher@globalpersonals.co.uk>
|
Paul Bowsher <pbowsher@globalpersonals.co.uk>
|
||||||
Paul Hammond <paul@paulhammond.org>
|
Paul Hammond <paul@paulhammond.org>
|
||||||
Phil Spitler <pspitler@gmail.com>
|
Phil Spitler <pspitler@gmail.com>
|
||||||
Piotr Bogdan <ppbogdan@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>
|
Renato Riccieri Santos Zannon <renato.riccieri@gmail.com>
|
||||||
Rhys Hiltner <rhys@twitch.tv>
|
Rhys Hiltner <rhys@twitch.tv>
|
||||||
Robert Obryk <robryk@gmail.com>
|
Robert Obryk <robryk@gmail.com>
|
||||||
@@ -100,14 +151,21 @@ Roberto Hashioka <roberto_hashioka@hotmail.com>
|
|||||||
Ryan Fowler <rwfowler@gmail.com>
|
Ryan Fowler <rwfowler@gmail.com>
|
||||||
Sam Alba <sam.alba@gmail.com>
|
Sam Alba <sam.alba@gmail.com>
|
||||||
Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
|
Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
|
||||||
|
Sean P. Kane <skane@newrelic.com>
|
||||||
Shawn Siefkas <shawn.siefkas@meredith.com>
|
Shawn Siefkas <shawn.siefkas@meredith.com>
|
||||||
|
Shih-Yuan Lee <fourdollars@gmail.com>
|
||||||
Silas Sewell <silas@sewell.org>
|
Silas Sewell <silas@sewell.org>
|
||||||
Solomon Hykes <solomon@dotcloud.com>
|
Solomon Hykes <solomon@dotcloud.com>
|
||||||
|
Song Gao <song@gao.io>
|
||||||
|
Sridatta Thatipamala <sthatipamala@gmail.com>
|
||||||
Sridhar Ratnakumar <sridharr@activestate.com>
|
Sridhar Ratnakumar <sridharr@activestate.com>
|
||||||
|
Steeve Morin <steeve.morin@gmail.com>
|
||||||
Stefan Praszalowicz <stefan@greplin.com>
|
Stefan Praszalowicz <stefan@greplin.com>
|
||||||
Thatcher Peskens <thatcher@dotcloud.com>
|
Thatcher Peskens <thatcher@dotcloud.com>
|
||||||
|
Thermionix <bond711@gmail.com>
|
||||||
Thijs Terlouw <thijsterlouw@gmail.com>
|
Thijs Terlouw <thijsterlouw@gmail.com>
|
||||||
Thomas Bikeev <thomas.bikeev@mac.com>
|
Thomas Bikeev <thomas.bikeev@mac.com>
|
||||||
|
Thomas Frössman <thomasf@jossystem.se>
|
||||||
Thomas Hansen <thomas.hansen@gmail.com>
|
Thomas Hansen <thomas.hansen@gmail.com>
|
||||||
Tianon Gravi <admwiggin@gmail.com>
|
Tianon Gravi <admwiggin@gmail.com>
|
||||||
Tim Terhorst <mynamewastaken+git@gmail.com>
|
Tim Terhorst <mynamewastaken+git@gmail.com>
|
||||||
@@ -115,8 +173,16 @@ Tobias Bieniek <Tobias.Bieniek@gmx.de>
|
|||||||
Tobias Schmidt <ts@soundcloud.com>
|
Tobias Schmidt <ts@soundcloud.com>
|
||||||
Tobias Schwab <tobias.schwab@dynport.de>
|
Tobias Schwab <tobias.schwab@dynport.de>
|
||||||
Tom Hulihan <hulihan.tom159@gmail.com>
|
Tom Hulihan <hulihan.tom159@gmail.com>
|
||||||
|
Tommaso Visconti <tommaso.visconti@gmail.com>
|
||||||
|
Tyler Brock <tyler.brock@gmail.com>
|
||||||
unclejack <unclejacksons@gmail.com>
|
unclejack <unclejacksons@gmail.com>
|
||||||
|
Victor Coisne <victor.coisne@dotcloud.com>
|
||||||
|
Victor Lyuboslavsky <victor@victoreda.com>
|
||||||
Victor Vieux <victor.vieux@dotcloud.com>
|
Victor Vieux <victor.vieux@dotcloud.com>
|
||||||
|
Vincent Bernat <bernat@luffy.cx>
|
||||||
Vivek Agarwal <me@vivek.im>
|
Vivek Agarwal <me@vivek.im>
|
||||||
|
Vladimir Kirillov <proger@wilab.org.ua>
|
||||||
Walter Stanish <walter@pratyeka.org>
|
Walter Stanish <walter@pratyeka.org>
|
||||||
|
Wes Morgan <cap10morgan@gmail.com>
|
||||||
Will Dietz <w@wdtz.org>
|
Will Dietz <w@wdtz.org>
|
||||||
|
Zaiste! <oh@zaiste.net>
|
||||||
|
|||||||
@@ -1,5 +1,96 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.6.4 (2013-10-15)
|
||||||
|
- 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
|
||||||
|
- Runtime: Only copy and change permissions on non-bindmount volumes
|
||||||
|
- Registry: Update regular expression to match index
|
||||||
|
* Runtime: Allow multiple volumes-from
|
||||||
|
* Packaging: Download apt key over HTTPS
|
||||||
|
* Documentation: Update section on extracting the docker binary after build
|
||||||
|
* Documentation: Update development environment docs for new build process
|
||||||
|
* Documentation: Remove 'base' image from documentation
|
||||||
|
* Packaging: Add 'docker' group on install for ubuntu package
|
||||||
|
- Runtime: Fix HTTP imports from STDIN
|
||||||
|
|
||||||
## 0.6.2 (2013-09-17)
|
## 0.6.2 (2013-09-17)
|
||||||
+ Hack: Vendor all dependencies
|
+ Hack: Vendor all dependencies
|
||||||
+ Builder: Add -rm option in order to remove intermediate containers
|
+ Builder: Add -rm option in order to remove intermediate containers
|
||||||
@@ -13,7 +104,7 @@
|
|||||||
* Registry: Implement login with private registry
|
* Registry: Implement login with private registry
|
||||||
* Remote API: Bump to v1.5
|
* Remote API: Bump to v1.5
|
||||||
* Packaging: Break down hack/make.sh into small scripts, one per 'bundle': test, binary, ubuntu etc.
|
* Packaging: Break down hack/make.sh into small scripts, one per 'bundle': test, binary, ubuntu etc.
|
||||||
* Documentation: General improvments
|
* Documentation: General improvements
|
||||||
- Runtime: UID and GID are now also applied to volumes
|
- Runtime: UID and GID are now also applied to volumes
|
||||||
- Runtime: `docker start` set error code upon error
|
- Runtime: `docker start` set error code upon error
|
||||||
- Runtime: `docker run` set the same error code as the process started
|
- Runtime: `docker run` set the same error code as the process started
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
Want to hack on Docker? Awesome! Here are instructions to get you started. They are probably not perfect, please let us know if anything feels
|
Want to hack on Docker? Awesome! Here are instructions to get you started. They are probably not perfect, please let us know if anything feels
|
||||||
wrong or incomplete.
|
wrong or incomplete.
|
||||||
|
|
||||||
|
## Build Environment
|
||||||
|
|
||||||
|
For instructions on setting up your development environment, please see our dedicated [dev environment setup docs](http://docs.docker.io/en/latest/contributing/devenvironment/).
|
||||||
|
|
||||||
## Contribution guidelines
|
## Contribution guidelines
|
||||||
|
|
||||||
### Pull requests are always welcome
|
### Pull requests are always welcome
|
||||||
@@ -55,8 +59,10 @@ 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
|
it! Take a look at existing tests for inspiration. Run the full test suite on
|
||||||
your branch before submitting a pull request.
|
your branch before submitting a pull request.
|
||||||
|
|
||||||
Make sure you include relevant updates or additions to documentation when
|
Update the documentation when creating or modifying features. Test
|
||||||
creating or modifying features.
|
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.
|
||||||
|
|
||||||
Write clean code. Universally formatted code promotes ease of writing, reading,
|
Write clean code. Universally formatted code promotes ease of writing, reading,
|
||||||
and maintenance. Always run `go fmt` before committing your changes. Most
|
and maintenance. Always run `go fmt` before committing your changes. Most
|
||||||
@@ -89,53 +95,17 @@ name and email address match your git configuration. The AUTHORS file is
|
|||||||
regenerated occasionally from the git commit history, so a mismatch may result
|
regenerated occasionally from the git commit history, so a mismatch may result
|
||||||
in your changes being overwritten.
|
in your changes being overwritten.
|
||||||
|
|
||||||
|
### Approval
|
||||||
|
|
||||||
## Decision process
|
Docker maintainers use LGTM (looks good to me) in comments on the code review
|
||||||
|
to indicate acceptance.
|
||||||
|
|
||||||
### How are decisions made?
|
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
|
||||||
|
|
||||||
Short answer: with pull requests to the docker repository.
|
For more details see [MAINTAINERS.md](hack/MAINTAINERS.md)
|
||||||
|
|
||||||
Docker is an open-source project with an open design philosophy. This means that the repository is the source of truth for EVERY aspect of the project,
|
|
||||||
including its philosophy, design, roadmap and APIs. *If it's part of the project, it's in the repo. It's in the repo, it's part of the project.*
|
|
||||||
|
|
||||||
As a result, all decisions can be expressed as changes to the repository. An implementation change is a change to the source code. An API change is a change to
|
|
||||||
the API specification. A philosophy change is a change to the philosophy manifesto. And so on.
|
|
||||||
|
|
||||||
All decisions affecting docker, big and small, follow the same 3 steps:
|
|
||||||
|
|
||||||
* Step 1: Open a pull request. Anyone can do this.
|
|
||||||
|
|
||||||
* Step 2: Discuss the pull request. Anyone can do this.
|
|
||||||
|
|
||||||
* Step 3: Accept or refuse a pull request. The relevant maintainer does this (see below "Who decides what?")
|
|
||||||
|
|
||||||
|
|
||||||
### Who decides what?
|
|
||||||
|
|
||||||
So all decisions are pull requests, and the relevant maintainer makes the decision by accepting or refusing the pull request.
|
|
||||||
But how do we identify the relevant maintainer for a given pull request?
|
|
||||||
|
|
||||||
Docker follows the timeless, highly efficient and totally unfair system known as [Benevolent dictator for life](http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life),
|
|
||||||
with yours truly, Solomon Hykes, in the role of BDFL.
|
|
||||||
This means that all decisions are made by default by me. Since making every decision myself would be highly unscalable, in practice decisions are spread across multiple maintainers.
|
|
||||||
|
|
||||||
The relevant maintainer for a pull request is assigned in 3 steps:
|
|
||||||
|
|
||||||
* Step 1: Determine the subdirectory affected by the pull request. This might be src/registry, docs/source/api, or any other part of the repo.
|
|
||||||
|
|
||||||
* Step 2: Find the MAINTAINERS file which affects this directory. If the directory itself does not have a MAINTAINERS file, work your way up the the repo hierarchy until you find one.
|
|
||||||
|
|
||||||
* Step 3: The first maintainer listed is the primary maintainer. The pull request is assigned to him. He may assign it to other listed maintainers, at his discretion.
|
|
||||||
|
|
||||||
|
|
||||||
### I'm a maintainer, should I make pull requests too?
|
|
||||||
|
|
||||||
Primary maintainers are not required to create pull requests when changing their own subdirectory, but secondary maintainers are.
|
|
||||||
|
|
||||||
### Who assigns maintainers?
|
|
||||||
|
|
||||||
Solomon.
|
|
||||||
|
|
||||||
### How can I become a maintainer?
|
### How can I become a maintainer?
|
||||||
|
|
||||||
@@ -146,15 +116,3 @@ Solomon.
|
|||||||
Don't forget: being a maintainer is a time investment. Make sure you will have time to make yourself available.
|
Don't forget: being a maintainer is a time investment. Make sure you will have time to make yourself available.
|
||||||
You don't have to be a maintainer to make a difference on the project!
|
You don't have to be a maintainer to make a difference on the project!
|
||||||
|
|
||||||
### What are a maintainer's responsibility?
|
|
||||||
|
|
||||||
It is every maintainer's responsibility to:
|
|
||||||
|
|
||||||
* 1) Expose a clear roadmap for improving their component.
|
|
||||||
* 2) Deliver prompt feedback and decisions on pull requests.
|
|
||||||
* 3) Be available to anyone with questions, bug reports, criticism etc. on their component. This includes irc, github requests and the mailing list.
|
|
||||||
* 4) Make sure their component respects the philosophy, design and roadmap of the project.
|
|
||||||
|
|
||||||
### How is this process changed?
|
|
||||||
|
|
||||||
Just like everything else: by making a pull request :)
|
|
||||||
|
|||||||
@@ -12,47 +12,58 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
# # Run the test suite:
|
# # Run the test suite:
|
||||||
# docker run -privileged -lxc-conf=lxc.aa_profile=unconfined docker go test -v
|
# docker run -privileged -lxc-conf=lxc.aa_profile=unconfined docker hack/make.sh test
|
||||||
#
|
#
|
||||||
# # Publish a release:
|
# # Publish a release:
|
||||||
# docker run -privileged -lxc-conf=lxc.aa_profile=unconfined \
|
# docker run -privileged -lxc-conf=lxc.aa_profile=unconfined \
|
||||||
# -e AWS_S3_BUCKET=baz \
|
# -e AWS_S3_BUCKET=baz \
|
||||||
# -e AWS_ACCESS_KEY=foo \
|
# -e AWS_ACCESS_KEY=foo \
|
||||||
# -e AWS_SECRET_KEY=bar \
|
# -e AWS_SECRET_KEY=bar \
|
||||||
# -e GPG_PASSPHRASE=gloubiboulga \
|
# -e GPG_PASSPHRASE=gloubiboulga \
|
||||||
# -lxc-conf=lxc.aa_profile=unconfined -privileged docker hack/release.sh
|
# docker hack/release.sh
|
||||||
#
|
#
|
||||||
|
|
||||||
docker-version 0.6.1
|
docker-version 0.6.1
|
||||||
from ubuntu:12.04
|
from ubuntu:12.04
|
||||||
maintainer Solomon Hykes <solomon@dotcloud.com>
|
maintainer Solomon Hykes <solomon@dotcloud.com>
|
||||||
|
|
||||||
# Build dependencies
|
# Build dependencies
|
||||||
run echo 'deb http://archive.ubuntu.com/ubuntu precise main universe' > /etc/apt/sources.list
|
run echo 'deb http://archive.ubuntu.com/ubuntu precise main universe' > /etc/apt/sources.list
|
||||||
run apt-get update
|
run apt-get update
|
||||||
run apt-get install -y -q curl
|
run apt-get install -y -q curl
|
||||||
run apt-get install -y -q git
|
run apt-get install -y -q git
|
||||||
run apt-get install -y -q mercurial
|
run apt-get install -y -q mercurial
|
||||||
# Install Go
|
run apt-get install -y -q build-essential
|
||||||
run curl -s https://go.googlecode.com/files/go1.1.2.linux-amd64.tar.gz | tar -v -C /usr/local -xz
|
|
||||||
env PATH /usr/local/go/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
|
# Install Go from source (for eventual cross-compiling)
|
||||||
env GOPATH /go:/go/src/github.com/dotcloud/docker/vendor
|
|
||||||
env CGO_ENABLED 0
|
env CGO_ENABLED 0
|
||||||
run cd /tmp && echo 'package main' > t.go && go test -a -i -v
|
run curl -s https://go.googlecode.com/files/go1.1.2.src.tar.gz | tar -v -C / -xz && mv /go /goroot
|
||||||
|
run cd /goroot/src && ./make.bash
|
||||||
|
env GOROOT /goroot
|
||||||
|
env PATH $PATH:/goroot/bin
|
||||||
|
env GOPATH /go:/go/src/github.com/dotcloud/docker/vendor
|
||||||
|
|
||||||
# Ubuntu stuff
|
# Ubuntu stuff
|
||||||
run apt-get install -y -q ruby1.9.3 rubygems libffi-dev
|
run apt-get install -y -q ruby1.9.3 rubygems libffi-dev
|
||||||
run gem install fpm
|
run gem install --no-rdoc --no-ri fpm
|
||||||
run apt-get install -y -q reprepro dpkg-sig
|
run apt-get install -y -q reprepro dpkg-sig
|
||||||
|
|
||||||
# Install s3cmd 1.0.1 (earlier versions don't support env variables in the config)
|
# Install s3cmd 1.0.1 (earlier versions don't support env variables in the config)
|
||||||
run apt-get install -y -q python-pip
|
run apt-get install -y -q python-pip
|
||||||
run pip install s3cmd
|
run pip install s3cmd
|
||||||
run pip install python-magic
|
run pip install python-magic
|
||||||
run /bin/echo -e '[default]\naccess_key=$AWS_ACCESS_KEY\nsecret_key=$AWS_SECRET_KEY\n' > /.s3cfg
|
run /bin/echo -e '[default]\naccess_key=$AWS_ACCESS_KEY\nsecret_key=$AWS_SECRET_KEY\n' > /.s3cfg
|
||||||
|
|
||||||
# Runtime dependencies
|
# Runtime dependencies
|
||||||
run apt-get install -y -q iptables
|
run apt-get install -y -q iptables
|
||||||
run apt-get install -y -q lxc
|
run apt-get install -y -q lxc
|
||||||
|
run apt-get install -y -q aufs-tools
|
||||||
|
|
||||||
volume /var/lib/docker
|
volume /var/lib/docker
|
||||||
workdir /go/src/github.com/dotcloud/docker
|
workdir /go/src/github.com/dotcloud/docker
|
||||||
|
|
||||||
# Wrap all commands in the "docker-in-docker" script to allow nested containers
|
# Wrap all commands in the "docker-in-docker" script to allow nested containers
|
||||||
entrypoint ["hack/dind"]
|
entrypoint ["hack/dind"]
|
||||||
|
|
||||||
# Upload docker source
|
# Upload docker source
|
||||||
add . /go/src/github.com/dotcloud/docker
|
add . /go/src/github.com/dotcloud/docker
|
||||||
|
|||||||
@@ -15,23 +15,16 @@ to put them - so we put them here :)
|
|||||||
* Run linter on codebase
|
* Run linter on codebase
|
||||||
* Unify build commands and regular commands
|
* Unify build commands and regular commands
|
||||||
* Move source code into src/ subdir for clarity
|
* Move source code into src/ subdir for clarity
|
||||||
* Clean up the Makefile, it's a mess
|
|
||||||
* docker build: on non-existent local path for ADD, don't show full absolute path on the host
|
* docker build: on non-existent local path for ADD, don't show full absolute path on the host
|
||||||
* mount into /dockerinit rather than /sbin/init
|
|
||||||
* docker tag foo REPO:TAG
|
* docker tag foo REPO:TAG
|
||||||
* use size header for progress bar in pull
|
* use size header for progress bar in pull
|
||||||
* Clean up context upload in build!!!
|
* Clean up context upload in build!!!
|
||||||
* Parallel pull
|
* Parallel pull
|
||||||
* Ensure /proc/sys/net/ipv4/ip_forward is 1
|
|
||||||
* Force DNS to public!
|
|
||||||
* Always generate a resolv.conf per container, to avoid changing resolv.conf under thne container's feet
|
* Always generate a resolv.conf per container, to avoid changing resolv.conf under thne container's feet
|
||||||
* Save metadata with import/export
|
* Save metadata with import/export (#1974)
|
||||||
* Upgrade dockerd without stopping containers
|
* Upgrade dockerd without stopping containers
|
||||||
* bring back git revision info, looks like it was lost
|
* Simple command to remove all untagged images (`docker rmi $(docker images | awk '/^<none>/ { print $3 }')`)
|
||||||
* Simple command to remove all untagged images
|
|
||||||
* Simple command to clean up containers for disk space
|
* Simple command to clean up containers for disk space
|
||||||
* Caching after an ADD
|
* Caching after an ADD (#880)
|
||||||
* entry point config
|
|
||||||
* bring back git revision info, looks like it was lost
|
|
||||||
* Clean up the ProgressReader api, it's a PITA to use
|
* Clean up the ProgressReader api, it's a PITA to use
|
||||||
* Use netlink instead of iproute2/iptables (#925)
|
* Use netlink instead of iproute2/iptables (#925)
|
||||||
|
|||||||
@@ -1,11 +1,43 @@
|
|||||||
Docker
|
Docker
|
||||||
Copyright 2012-2013 dotCloud, inc.
|
Copyright 2012-2013 dotCloud, inc.
|
||||||
|
|
||||||
This product includes software developed at dotCloud, inc. (http://www.dotcloud.com).
|
This product includes software developed at dotCloud,
|
||||||
|
inc. (http://www.dotcloud.com).
|
||||||
|
|
||||||
This product contains software (https://github.com/kr/pty) developed by Keith Rarick, licensed under the MIT License.
|
This product contains software (https://github.com/kr/pty) developed
|
||||||
|
by Keith Rarick, licensed under the MIT License.
|
||||||
|
|
||||||
Transfers of Docker shall be in accordance with applicable export controls of any country and all other applicable
|
The following is courtesy of our legal counsel:
|
||||||
legal requirements. Docker shall not be distributed or downloaded to or in Cuba, Iran, North Korea, Sudan or Syria
|
|
||||||
and shall not be distributed or downloaded to any person on the Denied Persons List administered by the U.S.
|
Transfers of Docker shall be in accordance with applicable export
|
||||||
|
controls of any country and all other applicable legal requirements.
|
||||||
|
Docker shall not be distributed or downloaded to or in Cuba, Iran,
|
||||||
|
North Korea, Sudan or Syria and shall not be distributed or downloaded
|
||||||
|
to any person on the Denied Persons List administered by the U.S.
|
||||||
Department of Commerce.
|
Department of Commerce.
|
||||||
|
|
||||||
|
What does that mean?
|
||||||
|
Here is a further explanation from our legal counsel:
|
||||||
|
|
||||||
|
Like all software products that utilize cryptography, the export and
|
||||||
|
use of Docker is subject to the U.S. Commerce Department's Export
|
||||||
|
Administration Regulations (EAR) because it uses or contains
|
||||||
|
cryptography (see
|
||||||
|
http://www.bis.doc.gov/index.php/policy-guidance/encryption). Certain
|
||||||
|
free and open source software projects have a lightweight set of
|
||||||
|
requirements, which can generally be met by providing email notice to
|
||||||
|
the appropriate U.S. government agencies that their source code is
|
||||||
|
available on a publicly available repository and making the
|
||||||
|
appropriate statements in the README.
|
||||||
|
|
||||||
|
The restrictions of the EAR apply to certain denied locations
|
||||||
|
(currently Iran, Sudan, Syria, North Korea, or Cuba) and those
|
||||||
|
individuals on the Denied Persons List, which is available here:
|
||||||
|
http://www.bis.doc.gov/index.php/policy-guidance/lists-of-parties-of-concern/denied-persons-list.
|
||||||
|
If you are incorporating Docker into a new open source project, the
|
||||||
|
EAR restrictions apply to your incorporation of Docker into your
|
||||||
|
project in the same manner as other cryptography-enabled projects,
|
||||||
|
such as OpenSSL, almost all Linux distributions, etc.
|
||||||
|
|
||||||
|
For more information, see http://www.apache.org/dev/crypto.html and/or
|
||||||
|
seek legal counsel.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Platform-as-a-Service. It benefits directly from the experience
|
|||||||
accumulated over several years of large-scale operation and support of
|
accumulated over several years of large-scale operation and support of
|
||||||
hundreds of thousands of applications and databases.
|
hundreds of thousands of applications and databases.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Better than VMs
|
## Better than VMs
|
||||||
|
|
||||||
@@ -190,6 +190,9 @@ wrong or incomplete.
|
|||||||
|
|
||||||
### Legal
|
### Legal
|
||||||
|
|
||||||
|
*Brought to you courtesy of our legal counsel. For more context,
|
||||||
|
please see the Notice document.*
|
||||||
|
|
||||||
Transfers of Docker shall be in accordance with applicable export
|
Transfers of Docker shall be in accordance with applicable export
|
||||||
controls of any country and all other applicable legal requirements.
|
controls of any country and all other applicable legal requirements.
|
||||||
Docker shall not be distributed or downloaded to or in Cuba, Iran,
|
Docker shall not be distributed or downloaded to or in Cuba, Iran,
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ Vagrant::Config.run do |config|
|
|||||||
config.vm.box = BOX_NAME
|
config.vm.box = BOX_NAME
|
||||||
config.vm.box_url = BOX_URI
|
config.vm.box_url = BOX_URI
|
||||||
|
|
||||||
|
config.ssh.forward_agent = true
|
||||||
|
|
||||||
# Provision docker and new kernel if deployment was not done.
|
# Provision docker and new kernel if deployment was not done.
|
||||||
# It is assumed Vagrant can successfully launch the provider instance.
|
# It is assumed Vagrant can successfully launch the provider instance.
|
||||||
if Dir.glob("#{File.dirname(__FILE__)}/.vagrant/machines/default/*/id").empty?
|
if Dir.glob("#{File.dirname(__FILE__)}/.vagrant/machines/default/*/id").empty?
|
||||||
@@ -37,6 +39,8 @@ Vagrant::Config.run do |config|
|
|||||||
"echo 'Installation of VBox Guest Additions is proceeding in the background.'; " \
|
"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.'; "
|
"echo '\"vagrant reload\" can be used in about 2 minutes to activate the new guest additions.'; "
|
||||||
end
|
end
|
||||||
|
# Add vagrant user to the docker group
|
||||||
|
pkg_cmd << "usermod -a -G docker vagrant; "
|
||||||
# Activate new kernel
|
# Activate new kernel
|
||||||
pkg_cmd << "shutdown -r +1; "
|
pkg_cmd << "shutdown -r +1; "
|
||||||
config.vm.provision :shell, :inline => pkg_cmd
|
config.vm.provision :shell, :inline => pkg_cmd
|
||||||
@@ -76,6 +80,8 @@ Vagrant::VERSION >= "1.1.0" and Vagrant.configure("2") do |config|
|
|||||||
config.vm.provider :virtualbox do |vb|
|
config.vm.provider :virtualbox do |vb|
|
||||||
config.vm.box = BOX_NAME
|
config.vm.box = BOX_NAME
|
||||||
config.vm.box_url = BOX_URI
|
config.vm.box_url = BOX_URI
|
||||||
|
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
|
||||||
|
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const APIVERSION = 1.5
|
const (
|
||||||
const DEFAULTHTTPHOST = "127.0.0.1"
|
APIVERSION = 1.6
|
||||||
const DEFAULTHTTPPORT = 4243
|
DEFAULTHTTPHOST = "127.0.0.1"
|
||||||
const DEFAULTUNIXSOCKET = "/var/run/docker.sock"
|
DEFAULTHTTPPORT = 4243
|
||||||
|
DEFAULTUNIXSOCKET = "/var/run/docker.sock"
|
||||||
|
)
|
||||||
|
|
||||||
type HttpApiFunc func(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error
|
type HttpApiFunc func(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error
|
||||||
|
|
||||||
@@ -67,9 +69,12 @@ func httpError(w http.ResponseWriter, err error) {
|
|||||||
statusCode = http.StatusUnauthorized
|
statusCode = http.StatusUnauthorized
|
||||||
} else if strings.Contains(err.Error(), "hasn't been activated") {
|
} else if strings.Contains(err.Error(), "hasn't been activated") {
|
||||||
statusCode = http.StatusForbidden
|
statusCode = http.StatusForbidden
|
||||||
}
|
}
|
||||||
utils.Debugf("[error %d] %s", statusCode, err)
|
|
||||||
http.Error(w, err.Error(), statusCode)
|
if err != nil {
|
||||||
|
utils.Errorf("HTTP Error: statusCode=%d %s", statusCode, err.Error())
|
||||||
|
http.Error(w, err.Error(), statusCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
|
func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
|
||||||
@@ -100,7 +105,7 @@ func getBoolParam(value string) (bool, error) {
|
|||||||
func matchesContentType(contentType, expectedType string) bool {
|
func matchesContentType(contentType, expectedType string) bool {
|
||||||
mimetype, _, err := mime.ParseMediaType(contentType)
|
mimetype, _, err := mime.ParseMediaType(contentType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("Error parsing media type: %s error: %s", contentType, err.Error())
|
utils.Errorf("Error parsing media type: %s error: %s", contentType, err.Error())
|
||||||
}
|
}
|
||||||
return err == nil && mimetype == expectedType
|
return err == nil && mimetype == expectedType
|
||||||
}
|
}
|
||||||
@@ -145,7 +150,7 @@ func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r
|
|||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
if err := srv.ContainerExport(name, w); err != nil {
|
if err := srv.ContainerExport(name, w); err != nil {
|
||||||
utils.Debugf("%s", err)
|
utils.Errorf("%s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -190,7 +195,7 @@ func getEvents(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
|
|||||||
_, err = wf.Write(b)
|
_, err = wf.Write(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// On error, evict the listener
|
// On error, evict the listener
|
||||||
utils.Debugf("%s", err)
|
utils.Errorf("%s", err)
|
||||||
srv.Lock()
|
srv.Lock()
|
||||||
delete(srv.listeners, r.RemoteAddr)
|
delete(srv.listeners, r.RemoteAddr)
|
||||||
srv.Unlock()
|
srv.Unlock()
|
||||||
@@ -344,8 +349,8 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config := &Config{}
|
config := &Config{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(config); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(config); err != nil && err != io.EOF {
|
||||||
utils.Debugf("%s", err)
|
utils.Errorf("%s", err)
|
||||||
}
|
}
|
||||||
repo := r.Form.Get("repo")
|
repo := r.Form.Get("repo")
|
||||||
tag := r.Form.Get("tag")
|
tag := r.Form.Get("tag")
|
||||||
@@ -710,32 +715,43 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r
|
|||||||
}
|
}
|
||||||
name := vars["name"]
|
name := vars["name"]
|
||||||
|
|
||||||
if _, err := srv.ContainerInspect(name); err != nil {
|
c, err := srv.ContainerInspect(name)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
in, out, err := hijackServer(w)
|
inStream, outStream, err := hijackServer(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if tcpc, ok := in.(*net.TCPConn); ok {
|
if tcpc, ok := inStream.(*net.TCPConn); ok {
|
||||||
tcpc.CloseWrite()
|
tcpc.CloseWrite()
|
||||||
} else {
|
} else {
|
||||||
in.Close()
|
inStream.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
defer func() {
|
defer func() {
|
||||||
if tcpc, ok := out.(*net.TCPConn); ok {
|
if tcpc, ok := outStream.(*net.TCPConn); ok {
|
||||||
tcpc.CloseWrite()
|
tcpc.CloseWrite()
|
||||||
} else if closer, ok := out.(io.Closer); ok {
|
} else if closer, ok := outStream.(io.Closer); ok {
|
||||||
closer.Close()
|
closer.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
var errStream io.Writer
|
||||||
if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, in, out); err != nil {
|
|
||||||
fmt.Fprintf(out, "Error: %s\n", err)
|
fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
|
||||||
|
|
||||||
|
if !c.Config.Tty && version >= 1.6 {
|
||||||
|
errStream = utils.NewStdWriter(outStream, utils.Stderr)
|
||||||
|
outStream = utils.NewStdWriter(outStream, utils.Stdout)
|
||||||
|
} else {
|
||||||
|
errStream = outStream
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, inStream, outStream, errStream); err != nil {
|
||||||
|
fmt.Fprintf(outStream, "Error: %s\n", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -778,8 +794,8 @@ func wsContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *
|
|||||||
h := websocket.Handler(func(ws *websocket.Conn) {
|
h := websocket.Handler(func(ws *websocket.Conn) {
|
||||||
defer ws.Close()
|
defer ws.Close()
|
||||||
|
|
||||||
if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, ws, ws); err != nil {
|
if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, ws, ws, ws); err != nil {
|
||||||
utils.Debugf("Error: %s", err)
|
utils.Errorf("Error: %s", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
h.ServeHTTP(w, r)
|
h.ServeHTTP(w, r)
|
||||||
@@ -892,8 +908,7 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
|
|||||||
b := NewBuildFile(srv, utils.NewWriteFlusher(w), !suppressOutput, !noCache, rm)
|
b := NewBuildFile(srv, utils.NewWriteFlusher(w), !suppressOutput, !noCache, rm)
|
||||||
id, err := b.Build(context)
|
id, err := b.Build(context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(w, "Error build: %s\n", err)
|
return fmt.Errorf("Error build: %s", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
if repoName != "" {
|
if repoName != "" {
|
||||||
srv.runtime.repositories.Set(repoName, tag, id, false)
|
srv.runtime.repositories.Set(repoName, tag, id, false)
|
||||||
@@ -925,7 +940,7 @@ func postContainersCopy(srv *Server, version float64, w http.ResponseWriter, r *
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := srv.ContainerCopy(name, copyData.Resource, w); err != nil {
|
if err := srv.ContainerCopy(name, copyData.Resource, w); err != nil {
|
||||||
utils.Debugf("%s", err.Error())
|
utils.Errorf("%s", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -970,7 +985,7 @@ func makeHttpHandler(srv *Server, logging bool, localMethod string, localRoute s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := handlerFunc(srv, version, w, r, mux.Vars(r)); err != nil {
|
if err := handlerFunc(srv, version, w, r, mux.Vars(r)); err != nil {
|
||||||
utils.Debugf("Error: %s", err)
|
utils.Errorf("Error: %s", err)
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
@@ -12,6 +13,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -40,6 +42,25 @@ 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) {
|
func TestGetVersion(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
runtime := mkRuntime(t)
|
runtime := mkRuntime(t)
|
||||||
@@ -243,7 +264,11 @@ func TestGetImagesJSON(t *testing.T) {
|
|||||||
t.Fatalf("Error expected, received none")
|
t.Fatalf("Error expected, received none")
|
||||||
}
|
}
|
||||||
|
|
||||||
httpError(r4, err)
|
if !strings.HasPrefix(err.Error(), "Bad parameter") {
|
||||||
|
t.Fatalf("Error should starts with \"Bad parameter\"")
|
||||||
|
}
|
||||||
|
http.Error(r4, err.Error(), http.StatusBadRequest)
|
||||||
|
|
||||||
if r4.Code != http.StatusBadRequest {
|
if r4.Code != http.StatusBadRequest {
|
||||||
t.Fatalf("%d Bad Request expected, received %d\n", http.StatusBadRequest, r4.Code)
|
t.Fatalf("%d Bad Request expected, received %d\n", http.StatusBadRequest, r4.Code)
|
||||||
}
|
}
|
||||||
@@ -566,7 +591,6 @@ func TestPostCommit(t *testing.T) {
|
|||||||
|
|
||||||
srv := &Server{runtime: runtime}
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
|
|
||||||
// Create a container and remove a file
|
// Create a container and remove a file
|
||||||
container, err := runtime.Create(
|
container, err := runtime.Create(
|
||||||
&Config{
|
&Config{
|
||||||
@@ -777,6 +801,8 @@ func TestPostContainersStart(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
r := httptest.NewRecorder()
|
r := httptest.NewRecorder()
|
||||||
if err := postContainersStart(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
|
if err := postContainersStart(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -952,7 +978,96 @@ func TestPostContainersAttach(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
|
setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
|
||||||
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
|
if err := assertPipe("hello\n", string([]byte{1, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 15); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Close pipes (client disconnects)
|
||||||
|
if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for attach to finish, the client disconnected, therefore, Attach finished his job
|
||||||
|
setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
|
||||||
|
<-c1
|
||||||
|
})
|
||||||
|
|
||||||
|
// We closed stdin, expect /bin/cat to still be running
|
||||||
|
// Wait a little bit to make sure container.monitor() did his thing
|
||||||
|
err = container.WaitTimeout(500 * time.Millisecond)
|
||||||
|
if err == nil || !container.State.Running {
|
||||||
|
t.Fatalf("/bin/cat is not running after closing stdin")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to avoid the timeout in destroy. Best effort, don't check error
|
||||||
|
cStdin, _ := container.StdinPipe()
|
||||||
|
cStdin.Close()
|
||||||
|
container.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostContainersAttachStderr(t *testing.T) {
|
||||||
|
runtime := mkRuntime(t)
|
||||||
|
defer nuke(runtime)
|
||||||
|
|
||||||
|
srv := &Server{runtime: runtime}
|
||||||
|
|
||||||
|
container, err := runtime.Create(
|
||||||
|
&Config{
|
||||||
|
Image: GetTestImage(runtime).ID,
|
||||||
|
Cmd: []string{"/bin/sh", "-c", "/bin/cat >&2"},
|
||||||
|
OpenStdin: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer runtime.Destroy(container)
|
||||||
|
|
||||||
|
// Start the process
|
||||||
|
hostConfig := &HostConfig{}
|
||||||
|
if err := container.Start(hostConfig); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stdin, stdinPipe := io.Pipe()
|
||||||
|
stdout, stdoutPipe := io.Pipe()
|
||||||
|
|
||||||
|
// Try to avoid the timeout in destroy. Best effort, don't check error
|
||||||
|
defer func() {
|
||||||
|
closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
|
||||||
|
container.Kill()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Attach to it
|
||||||
|
c1 := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(c1)
|
||||||
|
|
||||||
|
r := &hijackTester{
|
||||||
|
ResponseRecorder: httptest.NewRecorder(),
|
||||||
|
in: stdin,
|
||||||
|
out: stdoutPipe,
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", "/containers/"+container.ID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := postContainersAttach(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Acknowledge hijack
|
||||||
|
setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
|
||||||
|
stdout.Read([]byte{})
|
||||||
|
stdout.Read(make([]byte, 4096))
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
|
||||||
|
if err := assertPipe("hello\n", string([]byte{2, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 15); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -91,11 +91,17 @@ func LoadConfig(rootPath string) (*ConfigFile, error) {
|
|||||||
}
|
}
|
||||||
authConfig := AuthConfig{}
|
authConfig := AuthConfig{}
|
||||||
origAuth := strings.Split(arr[0], " = ")
|
origAuth := strings.Split(arr[0], " = ")
|
||||||
|
if len(origAuth) != 2 {
|
||||||
|
return &configFile, fmt.Errorf("Invalid Auth config file")
|
||||||
|
}
|
||||||
authConfig.Username, authConfig.Password, err = decodeAuth(origAuth[1])
|
authConfig.Username, authConfig.Password, err = decodeAuth(origAuth[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &configFile, err
|
return &configFile, err
|
||||||
}
|
}
|
||||||
origEmail := strings.Split(arr[1], " = ")
|
origEmail := strings.Split(arr[1], " = ")
|
||||||
|
if len(origEmail) != 2 {
|
||||||
|
return &configFile, fmt.Errorf("Invalid Auth config file")
|
||||||
|
}
|
||||||
authConfig.Email = origEmail[1]
|
authConfig.Email = origEmail[1]
|
||||||
authConfig.ServerAddress = IndexServerAddress()
|
authConfig.ServerAddress = IndexServerAddress()
|
||||||
configFile.Configs[IndexServerAddress()] = authConfig
|
configFile.Configs[IndexServerAddress()] = authConfig
|
||||||
@@ -239,7 +245,7 @@ func (config *ConfigFile) ResolveAuthConfig(registry string) AuthConfig {
|
|||||||
// as there is only one auth entry which is fully qualified we need to start
|
// as there is only one auth entry which is fully qualified we need to start
|
||||||
// parsing and matching
|
// parsing and matching
|
||||||
|
|
||||||
swapProtocoll := func(url string) string {
|
swapProtocol := func(url string) string {
|
||||||
if strings.HasPrefix(url, "http:") {
|
if strings.HasPrefix(url, "http:") {
|
||||||
return strings.Replace(url, "http:", "https:", 1)
|
return strings.Replace(url, "http:", "https:", 1)
|
||||||
}
|
}
|
||||||
@@ -253,9 +259,9 @@ func (config *ConfigFile) ResolveAuthConfig(registry string) AuthConfig {
|
|||||||
if c, found := config.Configs[url]; found {
|
if c, found := config.Configs[url]; found {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
registrySwappedProtocoll := swapProtocoll(url)
|
registrySwappedProtocol := swapProtocol(url)
|
||||||
// now try to match with the different protocol
|
// now try to match with the different protocol
|
||||||
if c, found := config.Configs[registrySwappedProtocoll]; found {
|
if c, found := config.Configs[registrySwappedProtocol]; found {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
return AuthConfig{}
|
return AuthConfig{}
|
||||||
|
|||||||
@@ -75,20 +75,31 @@ func TestCreateAccount(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSameAuthDataPostSave(t *testing.T) {
|
func setupTempConfigFile() (*ConfigFile, error) {
|
||||||
root, err := ioutil.TempDir("", "docker-test")
|
root, err := ioutil.TempDir("", "docker-test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
configFile := &ConfigFile{
|
configFile := &ConfigFile{
|
||||||
rootPath: root,
|
rootPath: root,
|
||||||
Configs: make(map[string]AuthConfig, 1),
|
Configs: make(map[string]AuthConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
configFile.Configs["testIndex"] = AuthConfig{
|
for _, registry := range []string{"testIndex", IndexServerAddress()} {
|
||||||
Username: "docker-user",
|
configFile.Configs[registry] = AuthConfig{
|
||||||
Password: "docker-pass",
|
Username: "docker-user",
|
||||||
Email: "docker@docker.io",
|
Password: "docker-pass",
|
||||||
|
Email: "docker@docker.io",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return configFile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSameAuthDataPostSave(t *testing.T) {
|
||||||
|
configFile, err := setupTempConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = SaveConfig(configFile)
|
err = SaveConfig(configFile)
|
||||||
@@ -110,3 +121,68 @@ func TestSameAuthDataPostSave(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolveAuthConfigIndexServer(t *testing.T) {
|
||||||
|
configFile, err := setupTempConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, registry := range []string{"", IndexServerAddress()} {
|
||||||
|
resolved := configFile.ResolveAuthConfig(registry)
|
||||||
|
if resolved != configFile.Configs[IndexServerAddress()] {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolveAuthConfigFullURL(t *testing.T) {
|
||||||
|
configFile, err := setupTempConfigFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
registryAuth := AuthConfig{
|
||||||
|
Username: "foo-user",
|
||||||
|
Password: "foo-pass",
|
||||||
|
Email: "foo@example.com",
|
||||||
|
}
|
||||||
|
localAuth := AuthConfig{
|
||||||
|
Username: "bar-user",
|
||||||
|
Password: "bar-pass",
|
||||||
|
Email: "bar@example.com",
|
||||||
|
}
|
||||||
|
configFile.Configs["https://registry.example.com/v1/"] = registryAuth
|
||||||
|
configFile.Configs["http://localhost:8000/v1/"] = localAuth
|
||||||
|
|
||||||
|
validRegistries := map[string][]string{
|
||||||
|
"https://registry.example.com/v1/": {
|
||||||
|
"https://registry.example.com/v1/",
|
||||||
|
"http://registry.example.com/v1/",
|
||||||
|
"registry.example.com",
|
||||||
|
"registry.example.com/v1/",
|
||||||
|
},
|
||||||
|
"http://localhost:8000/v1/": {
|
||||||
|
"https://localhost:8000/v1/",
|
||||||
|
"http://localhost:8000/v1/",
|
||||||
|
"localhost:8000",
|
||||||
|
"localhost:8000/v1/",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for configKey, registries := range validRegistries {
|
||||||
|
for _, registry := range registries {
|
||||||
|
var (
|
||||||
|
configured AuthConfig
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
resolved := configFile.ResolveAuthConfig(registry)
|
||||||
|
if configured, ok = configFile.Configs[configKey]; !ok {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if resolved.Email != configured.Email {
|
||||||
|
t.Errorf("%s -> %q != %q\n", registry, resolved.Email, configured.Email)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -458,9 +458,8 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
|
|||||||
var lineContinuation = regexp.MustCompile(`\s*\\\s*\n`)
|
var lineContinuation = regexp.MustCompile(`\s*\\\s*\n`)
|
||||||
|
|
||||||
func (b *buildFile) Build(context io.Reader) (string, error) {
|
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
|
// FIXME: @creack "name" is a terrible variable name
|
||||||
name, err := ioutil.TempDir("/tmp", "docker-build")
|
name, err := ioutil.TempDir("", "docker-build")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dotcloud/docker/auth"
|
"github.com/dotcloud/docker/auth"
|
||||||
@@ -36,6 +37,10 @@ var (
|
|||||||
VERSION string
|
VERSION string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrConnectionRefused = errors.New("Can't connect to docker daemon. Is 'docker -d' running on this host?")
|
||||||
|
)
|
||||||
|
|
||||||
func (cli *DockerCli) getMethod(name string) (reflect.Method, bool) {
|
func (cli *DockerCli) getMethod(name string) (reflect.Method, bool) {
|
||||||
methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:])
|
methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:])
|
||||||
return reflect.TypeOf(cli).MethodByName(methodName)
|
return reflect.TypeOf(cli).MethodByName(methodName)
|
||||||
@@ -298,7 +303,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cli.LoadConfigFile()
|
cli.LoadConfigFile()
|
||||||
authconfig, ok := cli.configFile.Configs[auth.IndexServerAddress()]
|
authconfig, ok := cli.configFile.Configs[serverAddress]
|
||||||
if !ok {
|
if !ok {
|
||||||
authconfig = auth.AuthConfig{}
|
authconfig = auth.AuthConfig{}
|
||||||
}
|
}
|
||||||
@@ -413,7 +418,7 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
|
|||||||
var out APIVersion
|
var out APIVersion
|
||||||
err = json.Unmarshal(body, &out)
|
err = json.Unmarshal(body, &out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("Error unmarshal: body: %s, err: %s\n", body, err)
|
utils.Errorf("Error unmarshal: body: %s, err: %s\n", body, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if out.Version != "" {
|
if out.Version != "" {
|
||||||
@@ -795,11 +800,13 @@ func (cli *DockerCli) CmdImport(args ...string) error {
|
|||||||
v.Set("tag", tag)
|
v.Set("tag", tag)
|
||||||
v.Set("fromSrc", src)
|
v.Set("fromSrc", src)
|
||||||
|
|
||||||
err := cli.stream("POST", "/images/create?"+v.Encode(), cli.in, cli.out, nil)
|
var in io.Reader
|
||||||
if err != nil {
|
|
||||||
return err
|
if src == "-" {
|
||||||
|
in = cli.in
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return cli.stream("POST", "/images/create?"+v.Encode(), in, cli.out, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *DockerCli) CmdPush(args ...string) error {
|
func (cli *DockerCli) CmdPush(args ...string) error {
|
||||||
@@ -1223,7 +1230,7 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?logs=1&stdout=1&stderr=1", false, nil, cli.out); err != nil {
|
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?logs=1&stdout=1&stderr=1", false, nil, cli.out, cli.err); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -1256,7 +1263,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
|
|||||||
|
|
||||||
if container.Config.Tty {
|
if container.Config.Tty {
|
||||||
if err := cli.monitorTtySize(cmd.Arg(0)); err != nil {
|
if err := cli.monitorTtySize(cmd.Arg(0)); err != nil {
|
||||||
return err
|
utils.Debugf("Error monitoring tty size: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1266,7 +1273,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
|
|||||||
v.Set("stdout", "1")
|
v.Set("stdout", "1")
|
||||||
v.Set("stderr", "1")
|
v.Set("stderr", "1")
|
||||||
|
|
||||||
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out); err != nil {
|
if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, cli.in, cli.out, cli.err); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -1426,6 +1433,9 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flRm := cmd.Lookup("rm")
|
||||||
|
autoRemove, _ := strconv.ParseBool(flRm.Value.String())
|
||||||
|
|
||||||
var containerIDFile *os.File
|
var containerIDFile *os.File
|
||||||
if len(hostConfig.ContainerIDFile) > 0 {
|
if len(hostConfig.ContainerIDFile) > 0 {
|
||||||
if _, err := ioutil.ReadFile(hostConfig.ContainerIDFile); err == nil {
|
if _, err := ioutil.ReadFile(hostConfig.ContainerIDFile); err == nil {
|
||||||
@@ -1523,14 +1533,14 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||||||
if config.AttachStdin || config.AttachStdout || config.AttachStderr {
|
if config.AttachStdin || config.AttachStdout || config.AttachStderr {
|
||||||
if config.Tty {
|
if config.Tty {
|
||||||
if err := cli.monitorTtySize(runResult.ID); err != nil {
|
if err := cli.monitorTtySize(runResult.ID); err != nil {
|
||||||
utils.Debugf("Error monitoring TTY size: %s\n", err)
|
utils.Errorf("Error monitoring TTY size: %s\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("logs", "1")
|
v.Set("logs", "1")
|
||||||
v.Set("stream", "1")
|
v.Set("stream", "1")
|
||||||
var out io.Writer
|
var out, stderr io.Writer
|
||||||
|
|
||||||
if config.AttachStdin {
|
if config.AttachStdin {
|
||||||
v.Set("stdin", "1")
|
v.Set("stdin", "1")
|
||||||
@@ -1541,7 +1551,11 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||||||
}
|
}
|
||||||
if config.AttachStderr {
|
if config.AttachStderr {
|
||||||
v.Set("stderr", "1")
|
v.Set("stderr", "1")
|
||||||
out = cli.out
|
if config.Tty {
|
||||||
|
stderr = cli.out
|
||||||
|
} else {
|
||||||
|
stderr = cli.err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signals := make(chan os.Signal, 1)
|
signals := make(chan os.Signal, 1)
|
||||||
@@ -1555,7 +1569,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := cli.hijack("POST", "/containers/"+runResult.ID+"/attach?"+v.Encode(), config.Tty, cli.in, out); err != nil {
|
if err := cli.hijack("POST", "/containers/"+runResult.ID+"/attach?"+v.Encode(), config.Tty, cli.in, out, stderr); err != nil {
|
||||||
utils.Debugf("Error hijack: %s", err)
|
utils.Debugf("Error hijack: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1565,12 +1579,18 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|||||||
// Detached mode
|
// Detached mode
|
||||||
<-wait
|
<-wait
|
||||||
} else {
|
} else {
|
||||||
status, err := waitForExit(cli, runResult.ID)
|
status, err := getExitCode(cli, runResult.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if autoRemove {
|
||||||
|
_, _, err = cli.call("DELETE", "/containers/"+runResult.ID, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if status != 0 {
|
if status != 0 {
|
||||||
return &utils.StatusError{status}
|
return &utils.StatusError{Status: status}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1636,7 +1656,7 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int,
|
|||||||
dial, err := net.Dial(cli.proto, cli.addr)
|
dial, err := net.Dial(cli.proto, cli.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "connection refused") {
|
if strings.Contains(err.Error(), "connection refused") {
|
||||||
return nil, -1, fmt.Errorf("Can't connect to docker daemon. Is 'docker -d' running on this host?")
|
return nil, -1, ErrConnectionRefused
|
||||||
}
|
}
|
||||||
return nil, -1, err
|
return nil, -1, err
|
||||||
}
|
}
|
||||||
@@ -1645,7 +1665,7 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int,
|
|||||||
defer clientconn.Close()
|
defer clientconn.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "connection refused") {
|
if strings.Contains(err.Error(), "connection refused") {
|
||||||
return nil, -1, fmt.Errorf("Can't connect to docker daemon. Is 'docker -d' running on this host?")
|
return nil, -1, ErrConnectionRefused
|
||||||
}
|
}
|
||||||
return nil, -1, err
|
return nil, -1, err
|
||||||
}
|
}
|
||||||
@@ -1722,7 +1742,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, h
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, out io.Writer) error {
|
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer) error {
|
||||||
|
|
||||||
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), nil)
|
req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1748,10 +1768,16 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
|
|||||||
rwc, br := clientconn.Hijack()
|
rwc, br := clientconn.Hijack()
|
||||||
defer rwc.Close()
|
defer rwc.Close()
|
||||||
|
|
||||||
var receiveStdout (chan error)
|
var receiveStdout chan error
|
||||||
if out != nil {
|
|
||||||
receiveStdout = utils.Go(func() error {
|
if stdout != nil {
|
||||||
_, err := io.Copy(out, br)
|
receiveStdout = utils.Go(func() (err error) {
|
||||||
|
// When TTY is ON, use regular copy
|
||||||
|
if setRawTerminal {
|
||||||
|
_, err = io.Copy(stdout, br)
|
||||||
|
} else {
|
||||||
|
_, err = utils.StdCopy(stdout, stderr, br)
|
||||||
|
}
|
||||||
utils.Debugf("[hijack] End of stdout")
|
utils.Debugf("[hijack] End of stdout")
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
@@ -1772,27 +1798,27 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
|
|||||||
}
|
}
|
||||||
if tcpc, ok := rwc.(*net.TCPConn); ok {
|
if tcpc, ok := rwc.(*net.TCPConn); ok {
|
||||||
if err := tcpc.CloseWrite(); err != nil {
|
if err := tcpc.CloseWrite(); err != nil {
|
||||||
utils.Debugf("Couldn't send EOF: %s\n", err)
|
utils.Errorf("Couldn't send EOF: %s\n", err)
|
||||||
}
|
}
|
||||||
} else if unixc, ok := rwc.(*net.UnixConn); ok {
|
} else if unixc, ok := rwc.(*net.UnixConn); ok {
|
||||||
if err := unixc.CloseWrite(); err != nil {
|
if err := unixc.CloseWrite(); err != nil {
|
||||||
utils.Debugf("Couldn't send EOF: %s\n", err)
|
utils.Errorf("Couldn't send EOF: %s\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Discard errors due to pipe interruption
|
// Discard errors due to pipe interruption
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if out != nil {
|
if stdout != nil {
|
||||||
if err := <-receiveStdout; err != nil {
|
if err := <-receiveStdout; err != nil {
|
||||||
utils.Debugf("Error receiveStdout: %s", err)
|
utils.Errorf("Error receiveStdout: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cli.isTerminal {
|
if !cli.isTerminal {
|
||||||
if err := <-sendStdin; err != nil {
|
if err := <-sendStdin; err != nil {
|
||||||
utils.Debugf("Error sendStdin: %s", err)
|
utils.Errorf("Error sendStdin: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1806,7 +1832,7 @@ func (cli *DockerCli) getTtySize() (int, int) {
|
|||||||
}
|
}
|
||||||
ws, err := term.GetWinsize(cli.terminalFd)
|
ws, err := term.GetWinsize(cli.terminalFd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("Error getting size: %s", err)
|
utils.Errorf("Error getting size: %s", err)
|
||||||
if ws == nil {
|
if ws == nil {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
@@ -1823,7 +1849,7 @@ func (cli *DockerCli) resizeTty(id string) {
|
|||||||
v.Set("h", strconv.Itoa(height))
|
v.Set("h", strconv.Itoa(height))
|
||||||
v.Set("w", strconv.Itoa(width))
|
v.Set("w", strconv.Itoa(width))
|
||||||
if _, _, err := cli.call("POST", "/containers/"+id+"/resize?"+v.Encode(), nil); err != nil {
|
if _, _, err := cli.call("POST", "/containers/"+id+"/resize?"+v.Encode(), nil); err != nil {
|
||||||
utils.Debugf("Error resize: %s", err)
|
utils.Errorf("Error resize: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1864,7 +1890,11 @@ func (cli *DockerCli) LoadConfigFile() (err error) {
|
|||||||
func waitForExit(cli *DockerCli, containerId string) (int, error) {
|
func waitForExit(cli *DockerCli, containerId string) (int, error) {
|
||||||
body, _, err := cli.call("POST", "/containers/"+containerId+"/wait", nil)
|
body, _, err := cli.call("POST", "/containers/"+containerId+"/wait", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
// If we can't connect, then the daemon probably died.
|
||||||
|
if err != ErrConnectionRefused {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return -1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var out APIWait
|
var out APIWait
|
||||||
@@ -1874,6 +1904,22 @@ func waitForExit(cli *DockerCli, containerId string) (int, error) {
|
|||||||
return out.StatusCode, nil
|
return out.StatusCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getExitCode(cli *DockerCli, containerId string) (int, error) {
|
||||||
|
body, _, err := cli.call("GET", "/containers/"+containerId+"/json", nil)
|
||||||
|
if err != nil {
|
||||||
|
// If we can't connect, then the daemon probably died.
|
||||||
|
if err != ErrConnectionRefused {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
c := &Container{}
|
||||||
|
if err := json.Unmarshal(body, c); err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return c.State.ExitCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string) *DockerCli {
|
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string) *DockerCli {
|
||||||
var (
|
var (
|
||||||
isTerminal = false
|
isTerminal = false
|
||||||
|
|||||||
@@ -369,6 +369,110 @@ func TestRunAttachStdin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestRunDetach checks attaching and detaching with the escape sequence.
|
||||||
|
func TestRunDetach(t *testing.T) {
|
||||||
|
|
||||||
|
stdin, stdinPipe := io.Pipe()
|
||||||
|
stdout, stdoutPipe := io.Pipe()
|
||||||
|
|
||||||
|
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
||||||
|
defer cleanup(globalRuntime)
|
||||||
|
|
||||||
|
ch := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(ch)
|
||||||
|
cli.CmdRun("-i", "-t", unitTestImageID, "cat")
|
||||||
|
}()
|
||||||
|
|
||||||
|
setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() {
|
||||||
|
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
container := globalRuntime.List()[0]
|
||||||
|
|
||||||
|
setTimeout(t, "Escape sequence timeout", 5*time.Second, func() {
|
||||||
|
stdinPipe.Write([]byte{'', ''})
|
||||||
|
if err := stdinPipe.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// wait for CmdRun to return
|
||||||
|
setTimeout(t, "Waiting for CmdRun timed out", 15*time.Second, func() {
|
||||||
|
<-ch
|
||||||
|
})
|
||||||
|
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
if !container.State.Running {
|
||||||
|
t.Fatal("The detached container should be still running")
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(t, "Waiting for container to die timed out", 20*time.Second, func() {
|
||||||
|
container.Kill()
|
||||||
|
container.Wait()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAttachDetach checks that attach in tty mode can be detached
|
||||||
|
func TestAttachDetach(t *testing.T) {
|
||||||
|
stdin, stdinPipe := io.Pipe()
|
||||||
|
stdout, stdoutPipe := io.Pipe()
|
||||||
|
|
||||||
|
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
||||||
|
defer cleanup(globalRuntime)
|
||||||
|
|
||||||
|
go stdout.Read(make([]byte, 1024))
|
||||||
|
setTimeout(t, "Starting container timed out", 2*time.Second, func() {
|
||||||
|
if err := cli.CmdRun("-i", "-t", "-d", unitTestImageID, "cat"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
container := globalRuntime.List()[0]
|
||||||
|
|
||||||
|
stdin, stdinPipe = io.Pipe()
|
||||||
|
stdout, stdoutPipe = io.Pipe()
|
||||||
|
cli = NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
|
||||||
|
|
||||||
|
ch := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(ch)
|
||||||
|
if err := cli.CmdAttach(container.ShortID()); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
setTimeout(t, "First read/write assertion timed out", 2*time.Second, func() {
|
||||||
|
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(t, "Escape sequence timeout", 5*time.Second, func() {
|
||||||
|
stdinPipe.Write([]byte{'', ''})
|
||||||
|
if err := stdinPipe.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// wait for CmdRun to return
|
||||||
|
setTimeout(t, "Waiting for CmdAttach timed out", 15*time.Second, func() {
|
||||||
|
<-ch
|
||||||
|
})
|
||||||
|
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
if !container.State.Running {
|
||||||
|
t.Fatal("The detached container should be still running")
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(t, "Waiting for container to die timedout", 5*time.Second, func() {
|
||||||
|
container.Kill()
|
||||||
|
container.Wait()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Expected behaviour, the process stays alive when the client disconnects
|
// Expected behaviour, the process stays alive when the client disconnects
|
||||||
func TestAttachDisconnect(t *testing.T) {
|
func TestAttachDisconnect(t *testing.T) {
|
||||||
stdin, stdinPipe := io.Pipe()
|
stdin, stdinPipe := io.Pipe()
|
||||||
@@ -438,3 +542,41 @@ func TestAttachDisconnect(t *testing.T) {
|
|||||||
cStdin.Close()
|
cStdin.Close()
|
||||||
container.Wait()
|
container.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
c := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(c)
|
||||||
|
if err := cli.CmdRun("-rm", unitTestImageID, "hostname"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var temporaryContainerID string
|
||||||
|
setTimeout(t, "Reading command output time out", 2*time.Second, func() {
|
||||||
|
cmdOutput, err := bufio.NewReader(stdout).ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
temporaryContainerID = cmdOutput
|
||||||
|
if err := closeWrap(stdout, stdoutPipe); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(t, "CmdRun timed out", 5*time.Second, func() {
|
||||||
|
<-c
|
||||||
|
})
|
||||||
|
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
|
||||||
|
if len(globalRuntime.List()) > 0 {
|
||||||
|
t.Fatalf("failed to remove container automatically: container %s still exists", temporaryContainerID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
|||||||
flContainerIDFile := cmd.String("cidfile", "", "Write the container ID to the file")
|
flContainerIDFile := cmd.String("cidfile", "", "Write the container ID to the file")
|
||||||
flNetwork := cmd.Bool("n", true, "Enable networking for this container")
|
flNetwork := cmd.Bool("n", true, "Enable networking for this container")
|
||||||
flPrivileged := cmd.Bool("privileged", false, "Give extended privileges to this container")
|
flPrivileged := cmd.Bool("privileged", false, "Give extended privileges to this container")
|
||||||
|
flAutoRemove := cmd.Bool("rm", false, "Automatically remove the container when it exits (incompatible with -d)")
|
||||||
|
|
||||||
if capabilities != nil && *flMemory > 0 && !capabilities.MemoryLimit {
|
if capabilities != nil && *flMemory > 0 && !capabilities.MemoryLimit {
|
||||||
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
|
//fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
|
||||||
@@ -146,7 +147,9 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
|||||||
flVolumes := NewPathOpts()
|
flVolumes := NewPathOpts()
|
||||||
cmd.Var(flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")
|
cmd.Var(flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")
|
||||||
|
|
||||||
flVolumesFrom := cmd.String("volumes-from", "", "Mount volumes from the specified container")
|
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")
|
flEntrypoint := cmd.String("entrypoint", "", "Overwrite the default entrypoint of the image")
|
||||||
|
|
||||||
var flLxcOpts ListOpts
|
var flLxcOpts ListOpts
|
||||||
@@ -172,6 +175,10 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *flDetach && *flAutoRemove {
|
||||||
|
return nil, nil, cmd, fmt.Errorf("Conflicting options: -rm and -d")
|
||||||
|
}
|
||||||
|
|
||||||
var binds []string
|
var binds []string
|
||||||
|
|
||||||
// add any bind targets to the list of container volumes
|
// add any bind targets to the list of container volumes
|
||||||
@@ -231,7 +238,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
|
|||||||
Dns: flDns,
|
Dns: flDns,
|
||||||
Image: image,
|
Image: image,
|
||||||
Volumes: flVolumes,
|
Volumes: flVolumes,
|
||||||
VolumesFrom: *flVolumesFrom,
|
VolumesFrom: strings.Join(flVolumesFrom, ","),
|
||||||
Entrypoint: entrypoint,
|
Entrypoint: entrypoint,
|
||||||
Privileged: *flPrivileged,
|
Privileged: *flPrivileged,
|
||||||
WorkingDir: *flWorkingDir,
|
WorkingDir: *flWorkingDir,
|
||||||
@@ -383,20 +390,20 @@ func (container *Container) startPty() error {
|
|||||||
// Copy the PTYs to our broadcasters
|
// Copy the PTYs to our broadcasters
|
||||||
go func() {
|
go func() {
|
||||||
defer container.stdout.CloseWriters()
|
defer container.stdout.CloseWriters()
|
||||||
utils.Debugf("[startPty] Begin of stdout pipe")
|
utils.Debugf("startPty: begin of stdout pipe")
|
||||||
io.Copy(container.stdout, ptyMaster)
|
io.Copy(container.stdout, ptyMaster)
|
||||||
utils.Debugf("[startPty] End of stdout pipe")
|
utils.Debugf("startPty: end of stdout pipe")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// stdin
|
// stdin
|
||||||
if container.Config.OpenStdin {
|
if container.Config.OpenStdin {
|
||||||
container.cmd.Stdin = ptySlave
|
container.cmd.Stdin = ptySlave
|
||||||
container.cmd.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true}
|
container.cmd.SysProcAttr.Setctty = true
|
||||||
go func() {
|
go func() {
|
||||||
defer container.stdin.Close()
|
defer container.stdin.Close()
|
||||||
utils.Debugf("[startPty] Begin of stdin pipe")
|
utils.Debugf("startPty: begin of stdin pipe")
|
||||||
io.Copy(ptyMaster, container.stdin)
|
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 {
|
if err := container.cmd.Start(); err != nil {
|
||||||
@@ -416,9 +423,9 @@ func (container *Container) start() error {
|
|||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer stdin.Close()
|
defer stdin.Close()
|
||||||
utils.Debugf("Begin of stdin pipe [start]")
|
utils.Debugf("start: begin of stdin pipe")
|
||||||
io.Copy(stdin, container.stdin)
|
io.Copy(stdin, container.stdin)
|
||||||
utils.Debugf("End of stdin pipe [start]")
|
utils.Debugf("start: end of stdin pipe")
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
return container.cmd.Start()
|
return container.cmd.Start()
|
||||||
@@ -435,8 +442,8 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
|
|||||||
errors <- err
|
errors <- err
|
||||||
} else {
|
} else {
|
||||||
go func() {
|
go func() {
|
||||||
utils.Debugf("[start] attach stdin\n")
|
utils.Debugf("attach: stdin: begin")
|
||||||
defer utils.Debugf("[end] attach stdin\n")
|
defer utils.Debugf("attach: stdin: end")
|
||||||
// No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
|
// No matter what, when stdin is closed (io.Copy unblock), close stdout and stderr
|
||||||
if container.Config.StdinOnce && !container.Config.Tty {
|
if container.Config.StdinOnce && !container.Config.Tty {
|
||||||
defer cStdin.Close()
|
defer cStdin.Close()
|
||||||
@@ -454,7 +461,7 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
|
|||||||
_, err = io.Copy(cStdin, stdin)
|
_, err = io.Copy(cStdin, stdin)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("[error] attach stdin: %s\n", err)
|
utils.Errorf("attach: stdin: %s", err)
|
||||||
}
|
}
|
||||||
// Discard error, expecting pipe error
|
// Discard error, expecting pipe error
|
||||||
errors <- nil
|
errors <- nil
|
||||||
@@ -468,20 +475,21 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
|
|||||||
} else {
|
} else {
|
||||||
cStdout = p
|
cStdout = p
|
||||||
go func() {
|
go func() {
|
||||||
utils.Debugf("[start] attach stdout\n")
|
utils.Debugf("attach: stdout: begin")
|
||||||
defer utils.Debugf("[end] attach stdout\n")
|
defer utils.Debugf("attach: stdout: end")
|
||||||
// If we are in StdinOnce mode, then close stdin
|
// If we are in StdinOnce mode, then close stdin
|
||||||
if container.Config.StdinOnce {
|
if container.Config.StdinOnce && stdin != nil {
|
||||||
if stdin != nil {
|
defer stdin.Close()
|
||||||
defer stdin.Close()
|
}
|
||||||
}
|
if stdinCloser != nil {
|
||||||
if stdinCloser != nil {
|
defer stdinCloser.Close()
|
||||||
defer stdinCloser.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_, err := io.Copy(stdout, cStdout)
|
_, err := io.Copy(stdout, cStdout)
|
||||||
|
if err == io.ErrClosedPipe {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("[error] attach stdout: %s\n", err)
|
utils.Errorf("attach: stdout: %s", err)
|
||||||
}
|
}
|
||||||
errors <- err
|
errors <- err
|
||||||
}()
|
}()
|
||||||
@@ -491,9 +499,8 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
|
|||||||
if stdinCloser != nil {
|
if stdinCloser != nil {
|
||||||
defer stdinCloser.Close()
|
defer stdinCloser.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if cStdout, err := container.StdoutPipe(); err != nil {
|
if cStdout, err := container.StdoutPipe(); err != nil {
|
||||||
utils.Debugf("Error stdout pipe")
|
utils.Errorf("attach: stdout pipe: %s", err)
|
||||||
} else {
|
} else {
|
||||||
io.Copy(&utils.NopWriter{}, cStdout)
|
io.Copy(&utils.NopWriter{}, cStdout)
|
||||||
}
|
}
|
||||||
@@ -506,20 +513,21 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
|
|||||||
} else {
|
} else {
|
||||||
cStderr = p
|
cStderr = p
|
||||||
go func() {
|
go func() {
|
||||||
utils.Debugf("[start] attach stderr\n")
|
utils.Debugf("attach: stderr: begin")
|
||||||
defer utils.Debugf("[end] attach stderr\n")
|
defer utils.Debugf("attach: stderr: end")
|
||||||
// If we are in StdinOnce mode, then close stdin
|
// If we are in StdinOnce mode, then close stdin
|
||||||
if container.Config.StdinOnce {
|
if container.Config.StdinOnce && stdin != nil {
|
||||||
if stdin != nil {
|
defer stdin.Close()
|
||||||
defer stdin.Close()
|
}
|
||||||
}
|
if stdinCloser != nil {
|
||||||
if stdinCloser != nil {
|
defer stdinCloser.Close()
|
||||||
defer stdinCloser.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_, err := io.Copy(stderr, cStderr)
|
_, err := io.Copy(stderr, cStderr)
|
||||||
|
if err == io.ErrClosedPipe {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("[error] attach stderr: %s\n", err)
|
utils.Errorf("attach: stderr: %s", err)
|
||||||
}
|
}
|
||||||
errors <- err
|
errors <- err
|
||||||
}()
|
}()
|
||||||
@@ -531,7 +539,7 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cStderr, err := container.StderrPipe(); err != nil {
|
if cStderr, err := container.StderrPipe(); err != nil {
|
||||||
utils.Debugf("Error stdout pipe")
|
utils.Errorf("attach: stdout pipe: %s", err)
|
||||||
} else {
|
} else {
|
||||||
io.Copy(&utils.NopWriter{}, cStderr)
|
io.Copy(&utils.NopWriter{}, cStderr)
|
||||||
}
|
}
|
||||||
@@ -545,24 +553,29 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s
|
|||||||
if cStderr != nil {
|
if cStderr != nil {
|
||||||
defer cStderr.Close()
|
defer cStderr.Close()
|
||||||
}
|
}
|
||||||
// FIXME: how do clean up the stdin goroutine without the unwanted side effect
|
// FIXME: how to clean up the stdin goroutine without the unwanted side effect
|
||||||
// of closing the passed stdin? Add an intermediary io.Pipe?
|
// of closing the passed stdin? Add an intermediary io.Pipe?
|
||||||
for i := 0; i < nJobs; i += 1 {
|
for i := 0; i < nJobs; i += 1 {
|
||||||
utils.Debugf("Waiting for job %d/%d\n", i+1, nJobs)
|
utils.Debugf("attach: waiting for job %d/%d", i+1, nJobs)
|
||||||
if err := <-errors; err != nil {
|
if err := <-errors; err != nil {
|
||||||
utils.Debugf("Job %d returned error %s. Aborting all jobs\n", i+1, err)
|
utils.Errorf("attach: job %d returned error %s, aborting all jobs", i+1, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
utils.Debugf("Job %d completed successfully\n", i+1)
|
utils.Debugf("attach: job %d completed successfully", i+1)
|
||||||
}
|
}
|
||||||
utils.Debugf("All jobs completed successfully\n")
|
utils.Debugf("attach: all jobs completed successfully")
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) Start(hostConfig *HostConfig) error {
|
func (container *Container) Start(hostConfig *HostConfig) (err error) {
|
||||||
container.State.Lock()
|
container.State.Lock()
|
||||||
defer container.State.Unlock()
|
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
|
if hostConfig == nil { // in docker start of docker restart we want to reuse previous HostConfigFile
|
||||||
hostConfig, _ = container.ReadHostConfig()
|
hostConfig, _ = container.ReadHostConfig()
|
||||||
@@ -639,21 +652,25 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
|||||||
|
|
||||||
// Apply volumes from another container if requested
|
// Apply volumes from another container if requested
|
||||||
if container.Config.VolumesFrom != "" {
|
if container.Config.VolumesFrom != "" {
|
||||||
c := container.runtime.Get(container.Config.VolumesFrom)
|
volumes := strings.Split(container.Config.VolumesFrom, ",")
|
||||||
if c == nil {
|
for _, v := range volumes {
|
||||||
return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.ID)
|
c := container.runtime.Get(v)
|
||||||
}
|
if c == nil {
|
||||||
for volPath, id := range c.Volumes {
|
return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.ID)
|
||||||
if _, exists := container.Volumes[volPath]; exists {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
for volPath, id := range c.Volumes {
|
||||||
return err
|
if _, exists := container.Volumes[volPath]; exists {
|
||||||
}
|
continue
|
||||||
container.Volumes[volPath] = id
|
}
|
||||||
if isRW, exists := c.VolumesRW[volPath]; exists {
|
if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
||||||
container.VolumesRW[volPath] = isRW
|
return err
|
||||||
|
}
|
||||||
|
container.Volumes[volPath] = id
|
||||||
|
if isRW, exists := c.VolumesRW[volPath]; exists {
|
||||||
|
container.VolumesRW[volPath] = isRW
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,9 +682,11 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var srcPath string
|
var srcPath string
|
||||||
|
var isBindMount bool
|
||||||
srcRW := false
|
srcRW := false
|
||||||
// If an external bind is defined for this volume, use that as a source
|
// If an external bind is defined for this volume, use that as a source
|
||||||
if bindMap, exists := binds[volPath]; exists {
|
if bindMap, exists := binds[volPath]; exists {
|
||||||
|
isBindMount = true
|
||||||
srcPath = bindMap.SrcPath
|
srcPath = bindMap.SrcPath
|
||||||
if strings.ToLower(bindMap.Mode) == "rw" {
|
if strings.ToLower(bindMap.Mode) == "rw" {
|
||||||
srcRW = true
|
srcRW = true
|
||||||
@@ -691,7 +710,9 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
|||||||
if err := os.MkdirAll(rootVolPath, 0755); err != nil {
|
if err := os.MkdirAll(rootVolPath, 0755); err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if srcRW {
|
|
||||||
|
// Do not copy or change permissions if we are mounting from the host
|
||||||
|
if srcRW && !isBindMount {
|
||||||
volList, err := ioutil.ReadDir(rootVolPath)
|
volList, err := ioutil.ReadDir(rootVolPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -702,22 +723,26 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(srcList) == 0 {
|
if len(srcList) == 0 {
|
||||||
|
// If the source volume is empty copy files from the root into the volume
|
||||||
if err := CopyWithTar(rootVolPath, srcPath); err != nil {
|
if err := CopyWithTar(rootVolPath, srcPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
var stat syscall.Stat_t
|
||||||
var stat syscall.Stat_t
|
if err := syscall.Stat(rootVolPath, &stat); err != nil {
|
||||||
if err := syscall.Stat(rootVolPath, &stat); err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
var srcStat syscall.Stat_t
|
||||||
var srcStat syscall.Stat_t
|
if err := syscall.Stat(srcPath, &srcStat); err != nil {
|
||||||
if err := syscall.Stat(srcPath, &srcStat); err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
// Change the source volume's ownership if it differs from the root
|
||||||
if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
|
// files that where just copied
|
||||||
if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
|
if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
|
||||||
return err
|
if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -786,7 +811,8 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
container.cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
||||||
|
|
||||||
if container.Config.Tty {
|
if container.Config.Tty {
|
||||||
err = container.startPty()
|
err = container.startPty()
|
||||||
} else {
|
} else {
|
||||||
@@ -804,7 +830,7 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
|||||||
|
|
||||||
container.ToDisk()
|
container.ToDisk()
|
||||||
container.SaveHostConfig(hostConfig)
|
container.SaveHostConfig(hostConfig)
|
||||||
go container.monitor()
|
go container.monitor(hostConfig)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -832,9 +858,14 @@ func (container *Container) Output() (output []byte, err error) {
|
|||||||
return output, err
|
return output, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// StdinPipe() returns a pipe connected to the standard input of the container's
|
// Container.StdinPipe returns a WriteCloser which can be used to feed data
|
||||||
// active process.
|
// 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".
|
||||||
|
|
||||||
func (container *Container) StdinPipe() (io.WriteCloser, error) {
|
func (container *Container) StdinPipe() (io.WriteCloser, error) {
|
||||||
return container.stdinPipe, nil
|
return container.stdinPipe, nil
|
||||||
}
|
}
|
||||||
@@ -912,7 +943,7 @@ func (container *Container) allocateNetwork() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) releaseNetwork() {
|
func (container *Container) releaseNetwork() {
|
||||||
if container.Config.NetworkDisabled {
|
if container.Config.NetworkDisabled || container.network == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
container.network.Release()
|
container.network.Release()
|
||||||
@@ -934,62 +965,46 @@ func (container *Container) waitLxc() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (container *Container) monitor() {
|
func (container *Container) monitor(hostConfig *HostConfig) {
|
||||||
// Wait for the program to exit
|
// Wait for the program to exit
|
||||||
utils.Debugf("Waiting for process")
|
|
||||||
|
|
||||||
// If the command does not exists, try to wait via lxc
|
// 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 container.cmd == nil {
|
if container.cmd == nil {
|
||||||
|
utils.Debugf("monitor: waiting for container %s using waitLxc", container.ID)
|
||||||
if err := container.waitLxc(); err != nil {
|
if err := container.waitLxc(); err != nil {
|
||||||
utils.Debugf("%s: Process: %s", container.ID, err)
|
utils.Errorf("monitor: while waiting for container %s, waitLxc had a problem: %s", container.ID, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
utils.Debugf("monitor: waiting for container %s using cmd.Wait", container.ID)
|
||||||
if err := container.cmd.Wait(); err != nil {
|
if err := container.cmd.Wait(); err != nil {
|
||||||
// Discard the error as any signals or non 0 returns will generate an error
|
// Since non-zero exit status and signal terminations will cause err to be non-nil,
|
||||||
utils.Debugf("%s: Process: %s", container.ID, err)
|
// 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
utils.Debugf("Process finished")
|
utils.Debugf("monitor: container %s finished", container.ID)
|
||||||
if container.runtime != nil && container.runtime.srv != nil {
|
|
||||||
container.runtime.srv.LogEvent("die", container.ShortID(), container.runtime.repositories.ImageName(container.Image))
|
|
||||||
}
|
|
||||||
exitCode := -1
|
exitCode := -1
|
||||||
if container.cmd != nil {
|
if container.cmd != nil {
|
||||||
exitCode = container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
exitCode = container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Report status back
|
||||||
|
container.State.setStopped(exitCode)
|
||||||
|
|
||||||
|
if container.runtime != nil && container.runtime.srv != nil {
|
||||||
|
container.runtime.srv.LogEvent("die", container.ShortID(), container.runtime.repositories.ImageName(container.Image))
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
container.releaseNetwork()
|
container.cleanup()
|
||||||
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
|
// Re-create a brand new stdin pipe once the container exited
|
||||||
if container.Config.OpenStdin {
|
if container.Config.OpenStdin {
|
||||||
container.stdin, container.stdinPipe = io.Pipe()
|
container.stdin, container.stdinPipe = io.Pipe()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report status back
|
|
||||||
container.State.setStopped(exitCode)
|
|
||||||
|
|
||||||
// Release the lock
|
// Release the lock
|
||||||
close(container.waitLock)
|
close(container.waitLock)
|
||||||
|
|
||||||
@@ -1004,6 +1019,31 @@ func (container *Container) monitor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (container *Container) cleanup() {
|
||||||
|
container.releaseNetwork()
|
||||||
|
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 {
|
func (container *Container) kill() error {
|
||||||
if !container.State.Running {
|
if !container.State.Running {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1202,7 +1202,7 @@ func TestCopyVolumeUidGid(t *testing.T) {
|
|||||||
defer nuke(r)
|
defer nuke(r)
|
||||||
|
|
||||||
// Add directory not owned by root
|
// Add directory not owned by root
|
||||||
container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello && chown daemon.daemon /hello"}, t)
|
container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello && touch /hello/test.txt && chown daemon.daemon /hello"}, t)
|
||||||
defer r.Destroy(container1)
|
defer r.Destroy(container1)
|
||||||
|
|
||||||
if container1.State.Running {
|
if container1.State.Running {
|
||||||
@@ -1227,18 +1227,10 @@ func TestCopyVolumeUidGid(t *testing.T) {
|
|||||||
// Test that the uid and gid is copied from the image to the volume
|
// Test that the uid and gid is copied from the image to the volume
|
||||||
tmpDir1 := tempDir(t)
|
tmpDir1 := tempDir(t)
|
||||||
defer os.RemoveAll(tmpDir1)
|
defer os.RemoveAll(tmpDir1)
|
||||||
stdout1, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello", tmpDir1), img.ID, "stat", "-c", "%U %G", "/hello"}, t)
|
stdout1, _ := runContainer(r, []string{"-v", "/hello", img.ID, "stat", "-c", "%U %G", "/hello"}, t)
|
||||||
if !strings.Contains(stdout1, "daemon daemon") {
|
if !strings.Contains(stdout1, "daemon daemon") {
|
||||||
t.Fatal("Container failed to transfer uid and gid to volume")
|
t.Fatal("Container failed to transfer uid and gid to volume")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the uid and gid is not copied from the image when the volume is read only
|
|
||||||
tmpDir2 := tempDir(t)
|
|
||||||
defer os.RemoveAll(tmpDir1)
|
|
||||||
stdout2, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:ro", tmpDir2), img.ID, "stat", "-c", "%U %G", "/hello"}, t)
|
|
||||||
if strings.Contains(stdout2, "daemon daemon") {
|
|
||||||
t.Fatal("Container transfered uid and gid to volume")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for #1582
|
// Test for #1582
|
||||||
@@ -1272,27 +1264,10 @@ func TestCopyVolumeContent(t *testing.T) {
|
|||||||
// Test that the content is copied from the image to the volume
|
// Test that the content is copied from the image to the volume
|
||||||
tmpDir1 := tempDir(t)
|
tmpDir1 := tempDir(t)
|
||||||
defer os.RemoveAll(tmpDir1)
|
defer os.RemoveAll(tmpDir1)
|
||||||
stdout1, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello", tmpDir1), img.ID, "find", "/hello"}, t)
|
stdout1, _ := runContainer(r, []string{"-v", "/hello", img.ID, "find", "/hello"}, t)
|
||||||
if !(strings.Contains(stdout1, "/hello/local/world") && strings.Contains(stdout1, "/hello/local")) {
|
if !(strings.Contains(stdout1, "/hello/local/world") && strings.Contains(stdout1, "/hello/local")) {
|
||||||
t.Fatal("Container failed to transfer content to volume")
|
t.Fatal("Container failed to transfer content to volume")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that the content is not copied when the volume is readonly
|
|
||||||
tmpDir2 := tempDir(t)
|
|
||||||
defer os.RemoveAll(tmpDir2)
|
|
||||||
stdout2, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:ro", tmpDir2), img.ID, "find", "/hello"}, t)
|
|
||||||
if strings.Contains(stdout2, "/hello/local/world") || strings.Contains(stdout2, "/hello/local") {
|
|
||||||
t.Fatal("Container transfered content to readonly volume")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that the content is not copied when the volume is non-empty
|
|
||||||
tmpDir3 := tempDir(t)
|
|
||||||
defer os.RemoveAll(tmpDir3)
|
|
||||||
writeFile(path.Join(tmpDir3, "touch-me"), "", t)
|
|
||||||
stdout3, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:rw", tmpDir3), img.ID, "find", "/hello"}, t)
|
|
||||||
if strings.Contains(stdout3, "/hello/local/world") || strings.Contains(stdout3, "/hello/local") || !strings.Contains(stdout3, "/hello/touch-me") {
|
|
||||||
t.Fatal("Container transfered content to non-empty volume")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBindMounts(t *testing.T) {
|
func TestBindMounts(t *testing.T) {
|
||||||
@@ -1549,3 +1524,80 @@ func TestPrivilegedCannotMount(t *testing.T) {
|
|||||||
t.Fatal("Could mount into secure container")
|
t.Fatal("Could mount into secure container")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMultipleVolumesFrom(t *testing.T) {
|
||||||
|
runtime := mkRuntime(t)
|
||||||
|
defer nuke(runtime)
|
||||||
|
|
||||||
|
container, err := runtime.Create(&Config{
|
||||||
|
Image: GetTestImage(runtime).ID,
|
||||||
|
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
||||||
|
Volumes: map[string]struct{}{"/test": {}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer runtime.Destroy(container)
|
||||||
|
|
||||||
|
for key := range container.Config.Volumes {
|
||||||
|
if key != "/test" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = container.Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := container.Volumes["/test"]
|
||||||
|
if expected == "" {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
container2, err := runtime.Create(
|
||||||
|
&Config{
|
||||||
|
Image: GetTestImage(runtime).ID,
|
||||||
|
Cmd: []string{"sh", "-c", "echo -n bar > /other/foo"},
|
||||||
|
Volumes: map[string]struct{}{"/other": {}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer runtime.Destroy(container2)
|
||||||
|
|
||||||
|
for key := range container2.Config.Volumes {
|
||||||
|
if key != "/other" {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err := container2.Output(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
container3, err := runtime.Create(
|
||||||
|
&Config{
|
||||||
|
Image: GetTestImage(runtime).ID,
|
||||||
|
Cmd: []string{"/bin/echo", "-n", "foobar"},
|
||||||
|
VolumesFrom: strings.Join([]string{container.ID, container2.ID}, ","),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer runtime.Destroy(container3)
|
||||||
|
|
||||||
|
if _, err := container3.Output(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(container3.Volumes)
|
||||||
|
if container3.Volumes["/test"] != container.Volumes["/test"] {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if container3.Volumes["/other"] != container2.Volumes["/other"] {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# [PackageDev] target_format: plist, ext: tmLanguage
|
||||||
|
---
|
||||||
|
name: Dockerfile
|
||||||
|
scopeName: source.dockerfile
|
||||||
|
uuid: a39d8795-59d2-49af-aa00-fe74ee29576e
|
||||||
|
|
||||||
|
patterns:
|
||||||
|
# Keywords
|
||||||
|
- name: keyword.control.dockerfile
|
||||||
|
match: ^\s*(FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD)\s
|
||||||
|
- name: keyword.operator.dockerfile
|
||||||
|
match: ^\s*(ENTRYPOINT|VOLUME|USER|WORKDIR)\s
|
||||||
|
# String
|
||||||
|
- name: string.quoted.double.dockerfile
|
||||||
|
begin: "\""
|
||||||
|
end: "\""
|
||||||
|
patterns:
|
||||||
|
- name: constant.character.escaped.dockerfile
|
||||||
|
match: \\.
|
||||||
|
# Comment
|
||||||
|
- name: comment.block.dockerfile
|
||||||
|
match: ^\s*#.*$
|
||||||
|
...
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>name</key>
|
||||||
|
<string>Dockerfile</string>
|
||||||
|
<key>patterns</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>match</key>
|
||||||
|
<string>^\s*(FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD)\s</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>keyword.control.dockerfile</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>match</key>
|
||||||
|
<string>^\s*(ENTRYPOINT|VOLUME|USER|WORKDIR)\s</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>keyword.operator.dockerfile</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>begin</key>
|
||||||
|
<string>"</string>
|
||||||
|
<key>end</key>
|
||||||
|
<string>"</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>string.quoted.double.dockerfile</string>
|
||||||
|
<key>patterns</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>match</key>
|
||||||
|
<string>\\.</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>constant.character.escaped.dockerfile</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>match</key>
|
||||||
|
<string>^\s*#.*$</string>
|
||||||
|
<key>name</key>
|
||||||
|
<string>comment.block.dockerfile</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>scopeName</key>
|
||||||
|
<string>source.dockerfile</string>
|
||||||
|
<key>uuid</key>
|
||||||
|
<string>a39d8795-59d2-49af-aa00-fe74ee29576e</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Asbjorn Enge <asbjorn@hanafjedle.net> (@asbjornenge)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Dockerfile.tmLanguage
|
||||||
|
|
||||||
|
Pretty basic Dockerfile.tmLanguage for Sublime Text syntax highlighting.
|
||||||
|
|
||||||
|
PR's with syntax updates, suggestions etc. are all very much appreciated!
|
||||||
|
|
||||||
|
I'll get to making this installable via Package Control soon!
|
||||||
|
|
||||||
|
enjoy.
|
||||||
@@ -1 +1 @@
|
|||||||
Kawsar Saiyeed <kawsar.saiyeed@projiris.com>
|
Tianon Gravi <admwiggin@gmail.com> (@tianon)
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ _docker_pull()
|
|||||||
|
|
||||||
_docker_push()
|
_docker_push()
|
||||||
{
|
{
|
||||||
return
|
__docker_image_repos
|
||||||
}
|
}
|
||||||
|
|
||||||
_docker_restart()
|
_docker_restart()
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
#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 "$@"
|
||||||
@@ -77,7 +77,7 @@ func crashTest() error {
|
|||||||
stop = false
|
stop = false
|
||||||
for i := 0; i < 100 && !stop; {
|
for i := 0; i < 100 && !stop; {
|
||||||
func() error {
|
func() error {
|
||||||
cmd := exec.Command(DOCKERPATH, "run", "base", "echo", fmt.Sprintf("%d", totalTestCount))
|
cmd := exec.Command(DOCKERPATH, "run", "ubuntu", "echo", fmt.Sprintf("%d", totalTestCount))
|
||||||
i++
|
i++
|
||||||
totalTestCount++
|
totalTestCount++
|
||||||
outPipe, err := cmd.StdoutPipe()
|
outPipe, err := cmd.StdoutPipe()
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
#!/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
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#!/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 -c "
|
||||||
|
set timeout 60
|
||||||
|
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 }
|
||||||
|
}"
|
||||||
|
|
||||||
|
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
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Create a CentOS base image for Docker
|
||||||
|
# From unclejack https://github.com/dotcloud/docker/issues/290
|
||||||
|
set -e
|
||||||
|
|
||||||
|
MIRROR_URL="http://centos.netnitco.net/6.4/os/x86_64/"
|
||||||
|
MIRROR_URL_UPDATES="http://centos.netnitco.net/6.4/updates/x86_64/"
|
||||||
|
|
||||||
|
yum install -y febootstrap xz
|
||||||
|
|
||||||
|
febootstrap -i bash -i coreutils -i tar -i bzip2 -i gzip -i vim-minimal -i wget -i patch -i diffutils -i iproute -i yum centos centos64 $MIRROR_URL -u $MIRROR_URL_UPDATES
|
||||||
|
touch centos64/etc/resolv.conf
|
||||||
|
touch centos64/sbin/init
|
||||||
|
|
||||||
|
tar --numeric-owner -Jcpf centos-64.tar.xz -C centos64 .
|
||||||
@@ -10,12 +10,18 @@ variant='minbase'
|
|||||||
include='iproute,iputils-ping'
|
include='iproute,iputils-ping'
|
||||||
|
|
||||||
repo="$1"
|
repo="$1"
|
||||||
suite="${2:-$stableSuite}"
|
suite="$2"
|
||||||
mirror="${3:-}" # stick to the default debootstrap mirror if one is not provided
|
mirror="${3:-}" # stick to the default debootstrap mirror if one is not provided
|
||||||
|
|
||||||
if [ ! "$repo" ]; then
|
if [ ! "$repo" ] || [ ! "$suite" ]; then
|
||||||
echo >&2 "usage: $0 repo [suite [mirror]]"
|
echo >&2 "usage: $0 repo suite [mirror]"
|
||||||
|
echo >&2
|
||||||
echo >&2 " ie: $0 tianon/debian squeeze"
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -32,22 +38,44 @@ sudo debootstrap --verbose --variant="$variant" --include="$include" "$suite" "$
|
|||||||
|
|
||||||
cd "$target"
|
cd "$target"
|
||||||
|
|
||||||
# create the image
|
# prevent init scripts from running during install/update
|
||||||
img=$(sudo tar -c . | docker import -)
|
# policy-rc.d (for most scripts)
|
||||||
|
echo $'#!/bin/sh\nexit 101' | sudo tee usr/sbin/policy-rc.d > /dev/null
|
||||||
|
sudo chmod +x usr/sbin/policy-rc.d
|
||||||
|
# initctl (for some pesky upstart scripts)
|
||||||
|
sudo chroot . dpkg-divert --local --rename --add /sbin/initctl
|
||||||
|
sudo ln -sf /bin/true sbin/initctl
|
||||||
|
# see https://github.com/dotcloud/docker/issues/446#issuecomment-16953173
|
||||||
|
|
||||||
# tag suite
|
# shrink the image, since apt makes us fat (wheezy: ~157.5MB vs ~120MB)
|
||||||
docker tag $img $repo $suite
|
sudo chroot . apt-get clean
|
||||||
|
|
||||||
|
# while we're at it, apt is unnecessarily slow inside containers
|
||||||
|
# this forces dpkg not to call sync() after package extraction and speeds up install
|
||||||
|
# the benefit is huge on spinning disks, and the penalty is nonexistent on SSD or decent server virtualization
|
||||||
|
echo 'force-unsafe-io' | sudo tee etc/dpkg/dpkg.cfg.d/02apt-speedup > /dev/null
|
||||||
|
# we want to effectively run "apt-get clean" after every install to keep images small
|
||||||
|
echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' | sudo tee etc/apt/apt.conf.d/no-cache > /dev/null
|
||||||
|
|
||||||
|
# helpful undo lines for each the above tweaks (for lack of a better home to keep track of them):
|
||||||
|
# rm /usr/sbin/policy-rc.d
|
||||||
|
# rm /sbin/initctl; dpkg-divert --rename --remove /sbin/initctl
|
||||||
|
# rm /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
||||||
|
# rm /etc/apt/apt.conf.d/no-cache
|
||||||
|
|
||||||
|
# create the image (and tag $repo:$suite)
|
||||||
|
sudo tar -c . | docker import - $repo $suite
|
||||||
|
|
||||||
# test the image
|
# test the image
|
||||||
docker run -i -t $repo:$suite echo success
|
docker run -i -t $repo:$suite echo success
|
||||||
|
|
||||||
if [ "$suite" = "$stableSuite" -o "$suite" = 'stable' ]; then
|
if [ "$suite" = "$stableSuite" -o "$suite" = 'stable' ]; then
|
||||||
# tag latest
|
# tag latest
|
||||||
docker tag $img $repo latest
|
docker tag $repo:$suite $repo latest
|
||||||
|
|
||||||
# tag the specific debian release version
|
# tag the specific debian release version
|
||||||
ver=$(docker run $repo:$suite cat /etc/debian_version)
|
ver=$(docker run $repo:$suite cat /etc/debian_version)
|
||||||
docker tag $img $repo $ver
|
docker tag $repo:$suite $repo $ver
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
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.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
*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:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
au BufNewFile,BufRead Dockerfile set filetype=dockerfile
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
" 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
|
||||||
@@ -29,7 +29,7 @@ func main() {
|
|||||||
flVersion := flag.Bool("v", false, "Print version information and quit")
|
flVersion := flag.Bool("v", false, "Print version information and quit")
|
||||||
flDaemon := flag.Bool("d", false, "Daemon mode")
|
flDaemon := flag.Bool("d", false, "Daemon mode")
|
||||||
flDebug := flag.Bool("D", false, "Debug mode")
|
flDebug := flag.Bool("D", false, "Debug mode")
|
||||||
flAutoRestart := flag.Bool("r", false, "Restart previously running containers")
|
flAutoRestart := flag.Bool("r", true, "Restart previously running containers")
|
||||||
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge. Use 'none' to disable container networking")
|
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge. Use 'none' to disable container networking")
|
||||||
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
|
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
|
||||||
flGraphPath := flag.String("g", "/var/lib/docker", "Path to graph storage base dir.")
|
flGraphPath := flag.String("g", "/var/lib/docker", "Path to graph storage base dir.")
|
||||||
|
|||||||
@@ -1,38 +1,93 @@
|
|||||||
Docker Documentation
|
Docker Documentation
|
||||||
====================
|
====================
|
||||||
|
|
||||||
Documentation
|
Overview
|
||||||
-------------
|
--------
|
||||||
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)
|
|
||||||
|
|
||||||
Each of the .rst files under sources reflects a page on the documentation.
|
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.
|
||||||
|
|
||||||
Installation
|
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
|
||||||
|
...................
|
||||||
|
|
||||||
* Work in your own fork of the code, we accept pull requests.
|
|
||||||
* Install sphinx: `pip install sphinx`
|
* 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`
|
* Install sphinx httpdomain contrib package: `pip install sphinxcontrib-httpdomain`
|
||||||
* Mac OS X: `[sudo] pip-2.7 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**
|
* 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
|
Usage
|
||||||
-----
|
-----
|
||||||
* Change the `.rst` files with your favorite editor to your liking.
|
* Follow the contribution guidelines (``../CONTRIBUTING.md``)
|
||||||
* Run `make docs` to clean up old files and generate new ones.
|
* Work in your own fork of the code, we accept pull requests.
|
||||||
* Your static website can now be found in the `_build` directory.
|
* Change the ``.rst`` files with your favorite editor -- try to keep the
|
||||||
* To preview what you have generated run `make server` and open http://localhost:8000/ in your favorite browser.
|
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.
|
||||||
|
|
||||||
Working using GitHub's file editor
|
Working using GitHub's file editor
|
||||||
----------------------------------
|
----------------------------------
|
||||||
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.
|
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.
|
||||||
|
|
||||||
Images
|
Images
|
||||||
------
|
------
|
||||||
When you need to add images, try to make them as small as possible (e.g. as gif).
|
|
||||||
|
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.
|
||||||
|
|
||||||
Notes
|
Notes
|
||||||
-----
|
-----
|
||||||
@@ -41,7 +96,7 @@ lessc ``lessc main.less`` or watched using watch-lessc ``watch-lessc -i main.les
|
|||||||
|
|
||||||
Guides on using sphinx
|
Guides on using sphinx
|
||||||
----------------------
|
----------------------
|
||||||
* To make links to certain pages create a link target like so:
|
* To make links to certain sections create a link target like so:
|
||||||
|
|
||||||
```
|
```
|
||||||
.. _hello_world:
|
.. _hello_world:
|
||||||
@@ -52,7 +107,10 @@ Guides on using sphinx
|
|||||||
This is.. (etc.)
|
This is.. (etc.)
|
||||||
```
|
```
|
||||||
|
|
||||||
The ``_hello_world:`` will make it possible to link to this position (page and marker) from all other pages.
|
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.
|
||||||
|
|
||||||
* Notes, warnings and alarms
|
* Notes, warnings and alarms
|
||||||
|
|
||||||
@@ -68,13 +126,17 @@ Guides on using sphinx
|
|||||||
|
|
||||||
* Code examples
|
* Code examples
|
||||||
|
|
||||||
Start without $, so it's easy to copy and paste.
|
* 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).
|
||||||
|
|
||||||
Manpages
|
Manpages
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* To make the manpages, simply run 'make man'. Please note there is a bug in spinx 1.1.3 which makes this fail.
|
* To make the manpages, run ``make man``. Please note there is a bug
|
||||||
Upgrade to the latest version of sphinx.
|
in spinx 1.1.3 which makes this fail. Upgrade to the latest version
|
||||||
* Then preview the manpage by running `man _build/man/docker.1`, where _build/man/docker.1 is the path to the generated
|
of Sphinx.
|
||||||
manfile
|
* Then preview the manpage by running ``man _build/man/docker.1``,
|
||||||
* The manpages are also autogenerated by our hosted readthedocs here: http://docs-docker.dotcloud.com/projects/docker/downloads/
|
where ``_build/man/docker.1`` is the path to the generated manfile
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
Docker Remote API
|
Docker Remote API
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
1. Brief introduction
|
1. Brief introduction
|
||||||
=====================
|
=====================
|
||||||
@@ -27,16 +26,41 @@ Docker Remote API
|
|||||||
2. Versions
|
2. Versions
|
||||||
===========
|
===========
|
||||||
|
|
||||||
The current version of the API is 1.5
|
The current version of the API is 1.6
|
||||||
|
|
||||||
Calling /images/<name>/insert is the same as calling
|
Calling /images/<name>/insert is the same as calling
|
||||||
/v1.5/images/<name>/insert
|
/v1.6/images/<name>/insert
|
||||||
|
|
||||||
You can still call an old version of the api using
|
You can still call an old version of the api using
|
||||||
/v1.0/images/<name>/insert
|
/v1.0/images/<name>/insert
|
||||||
|
|
||||||
|
v1.6
|
||||||
|
****
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.6`
|
||||||
|
|
||||||
|
What's new
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. http:post:: /containers/(id)/attach
|
||||||
|
|
||||||
|
**New!** You can now split stderr from stdout. This is done by prefixing
|
||||||
|
a header to each transmition. See :http:post:`/containers/(id)/attach`.
|
||||||
|
The WebSocket attach is unchanged.
|
||||||
|
Note that attach calls on the previous API version didn't change. Stdout and
|
||||||
|
stderr are merged.
|
||||||
|
|
||||||
|
|
||||||
|
v1.5
|
||||||
|
****
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.5`
|
:doc:`docker_remote_api_v1.5`
|
||||||
*****************************
|
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
@@ -57,15 +81,20 @@ What's new
|
|||||||
dicts each containing `PublicPort`, `PrivatePort` and `Type` describing a
|
dicts each containing `PublicPort`, `PrivatePort` and `Type` describing a
|
||||||
port mapping.
|
port mapping.
|
||||||
|
|
||||||
|
v1.4
|
||||||
|
****
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.4`
|
:doc:`docker_remote_api_v1.4`
|
||||||
*****************************
|
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
.. http:post:: /images/create
|
.. http:post:: /images/create
|
||||||
|
|
||||||
**New!** When pull a repo, all images are now downloaded in parallel.
|
**New!** When pulling a repo, all images are now downloaded in parallel.
|
||||||
|
|
||||||
.. http:get:: /containers/(id)/top
|
.. http:get:: /containers/(id)/top
|
||||||
|
|
||||||
@@ -75,11 +104,16 @@ What's new
|
|||||||
|
|
||||||
**New!** Image's name added in the events
|
**New!** Image's name added in the events
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.3`
|
v1.3
|
||||||
*****************************
|
****
|
||||||
|
|
||||||
docker v0.5.0 51f6c4a_
|
docker v0.5.0 51f6c4a_
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.3`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -112,11 +146,16 @@ Start containers (/containers/<id>/start):
|
|||||||
- You can now pass host-specific configuration (e.g. bind mounts) in
|
- You can now pass host-specific configuration (e.g. bind mounts) in
|
||||||
the POST body for start calls
|
the POST body for start calls
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.2`
|
v1.2
|
||||||
*****************************
|
****
|
||||||
|
|
||||||
docker v0.4.2 2e7649b_
|
docker v0.4.2 2e7649b_
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.2`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -142,11 +181,16 @@ The client should send it's authConfig as POST on each call of
|
|||||||
deleted/untagged.
|
deleted/untagged.
|
||||||
|
|
||||||
|
|
||||||
:doc:`docker_remote_api_v1.1`
|
v1.1
|
||||||
*****************************
|
****
|
||||||
|
|
||||||
docker v0.4.0 a8ae398_
|
docker v0.4.0 a8ae398_
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.1`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -166,12 +210,16 @@ What's new
|
|||||||
{"error":"Invalid..."}
|
{"error":"Invalid..."}
|
||||||
...
|
...
|
||||||
|
|
||||||
|
v1.0
|
||||||
:doc:`docker_remote_api_v1.0`
|
****
|
||||||
*****************************
|
|
||||||
|
|
||||||
docker v0.3.4 8d73740_
|
docker v0.3.4 8d73740_
|
||||||
|
|
||||||
|
Full Documentation
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:doc:`docker_remote_api_v1.0`
|
||||||
|
|
||||||
What's new
|
What's new
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@@ -182,36 +230,3 @@ Initial version
|
|||||||
.. _8d73740: https://github.com/dotcloud/docker/commit/8d73740343778651c09160cde9661f5f387b36f4
|
.. _8d73740: https://github.com/dotcloud/docker/commit/8d73740343778651c09160cde9661f5f387b36f4
|
||||||
.. _2e7649b: https://github.com/dotcloud/docker/commit/2e7649beda7c820793bd46766cbc2cfeace7b168
|
.. _2e7649b: https://github.com/dotcloud/docker/commit/2e7649beda7c820793bd46766cbc2cfeace7b168
|
||||||
.. _51f6c4a: https://github.com/dotcloud/docker/commit/51f6c4a7372450d164c61e0054daf0223ddbd909
|
.. _51f6c4a: https://github.com/dotcloud/docker/commit/51f6c4a7372450d164c61e0054daf0223ddbd909
|
||||||
|
|
||||||
==================================
|
|
||||||
Docker Remote API Client Libraries
|
|
||||||
==================================
|
|
||||||
|
|
||||||
These libraries have not been tested by the Docker Maintainers for
|
|
||||||
compatibility. Please file issues with the library owners. If you
|
|
||||||
find more library implementations, please list them in Docker doc bugs
|
|
||||||
and we will add the libraries here.
|
|
||||||
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Language/Framework | Name | Repository |
|
|
||||||
+======================+================+============================================+
|
|
||||||
| Python | docker-py | https://github.com/dotcloud/docker-py |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Ruby | docker-client | https://github.com/geku/docker-client |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Ruby | docker-api | https://github.com/swipely/docker-api |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Javascript (NodeJS) | docker.io | https://github.com/appersonlabs/docker.io |
|
|
||||||
| | | Install via NPM: `npm install docker.io` |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Javascript | docker-js | https://github.com/dgoujard/docker-js |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Javascript (Angular) | dockerui | https://github.com/crosbymichael/dockerui |
|
|
||||||
| **WebUI** | | |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Java | docker-java | https://github.com/kpelykh/docker-java |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Erlang | erldocker | https://github.com/proger/erldocker |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
| Go | go-dockerclient| https://github.com/fsouza/go-dockerclient |
|
|
||||||
+----------------------+----------------+--------------------------------------------+
|
|
||||||
|
|||||||
@@ -49,28 +49,28 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
@@ -117,7 +117,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": ""
|
||||||
},
|
},
|
||||||
@@ -490,14 +490,14 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658
|
"Created":1364102658
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658
|
"Created":1364102658
|
||||||
}
|
}
|
||||||
@@ -529,9 +529,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +552,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -572,8 +572,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -608,7 +608,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -638,7 +638,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -660,7 +660,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
|
|||||||
@@ -49,28 +49,28 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0"
|
"Status": "Exit 0"
|
||||||
@@ -117,7 +117,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": ""
|
||||||
},
|
},
|
||||||
@@ -490,14 +490,14 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658
|
"Created":1364102658
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658
|
"Created":1364102658
|
||||||
}
|
}
|
||||||
@@ -529,9 +529,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +552,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -575,8 +575,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -615,7 +615,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -645,7 +645,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -667,7 +667,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -59,7 +59,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -69,7 +69,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -79,7 +79,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -129,7 +129,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": ""
|
||||||
},
|
},
|
||||||
@@ -502,16 +502,16 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
"VirtualSize":180116135
|
"VirtualSize":180116135
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
@@ -545,9 +545,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,7 +568,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -591,8 +591,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -631,7 +631,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -661,7 +661,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
},
|
},
|
||||||
@@ -684,7 +684,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -696,7 +696,7 @@ Get the history of an image
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Tag":["base:latest"],
|
"Tag":["ubuntu:latest"],
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"CreatedBy":"/bin/bash"
|
"CreatedBy":"/bin/bash"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -59,7 +59,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -69,7 +69,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -79,7 +79,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -130,7 +130,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": ""
|
"VolumesFrom": ""
|
||||||
},
|
},
|
||||||
@@ -550,16 +550,16 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
"VirtualSize":180116135
|
"VirtualSize":180116135
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
@@ -593,9 +593,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,7 +616,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -639,8 +639,8 @@ Create an image
|
|||||||
:statuscode 500: server error
|
:statuscode 500: server error
|
||||||
|
|
||||||
|
|
||||||
Insert a file in a image
|
Insert a file in an image
|
||||||
************************
|
*************************
|
||||||
|
|
||||||
.. http:post:: /images/(name)/insert
|
.. http:post:: /images/(name)/insert
|
||||||
|
|
||||||
@@ -679,7 +679,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -709,7 +709,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":""
|
"VolumesFrom":""
|
||||||
},
|
},
|
||||||
@@ -732,7 +732,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ List containers
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": "8dfafdbc3a40",
|
"Id": "8dfafdbc3a40",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 1",
|
"Command": "echo 1",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -56,7 +56,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "9cd87474be90",
|
"Id": "9cd87474be90",
|
||||||
"Image": "base:latest",
|
"Image": "ubuntu:latest",
|
||||||
"Command": "echo 222222",
|
"Command": "echo 222222",
|
||||||
"Created": 1367854155,
|
"Created": 1367854155,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -66,7 +66,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "3176a2479c92",
|
"Id": "3176a2479c92",
|
||||||
"Image": "base:latest",
|
"Image": "centos:latest",
|
||||||
"Command": "echo 3333333333333333",
|
"Command": "echo 3333333333333333",
|
||||||
"Created": 1367854154,
|
"Created": 1367854154,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -76,7 +76,7 @@ List containers
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "4cb07b47f9fb",
|
"Id": "4cb07b47f9fb",
|
||||||
"Image": "base:latest",
|
"Image": "fedora:latest",
|
||||||
"Command": "echo 444444444444444444444444444444444",
|
"Command": "echo 444444444444444444444444444444444",
|
||||||
"Created": 1367854152,
|
"Created": 1367854152,
|
||||||
"Status": "Exit 0",
|
"Status": "Exit 0",
|
||||||
@@ -128,7 +128,7 @@ Create a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns":null,
|
"Dns":null,
|
||||||
"Image":"base",
|
"Image":"ubuntu",
|
||||||
"Volumes":{},
|
"Volumes":{},
|
||||||
"VolumesFrom":"",
|
"VolumesFrom":"",
|
||||||
"WorkingDir":""
|
"WorkingDir":""
|
||||||
@@ -196,7 +196,7 @@ Inspect a container
|
|||||||
"date"
|
"date"
|
||||||
],
|
],
|
||||||
"Dns": null,
|
"Dns": null,
|
||||||
"Image": "base",
|
"Image": "ubuntu",
|
||||||
"Volumes": {},
|
"Volumes": {},
|
||||||
"VolumesFrom": "",
|
"VolumesFrom": "",
|
||||||
"WorkingDir":""
|
"WorkingDir":""
|
||||||
@@ -592,16 +592,16 @@ List Images
|
|||||||
|
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-12.10",
|
"Tag":"precise",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
"VirtualSize":180116135
|
"VirtualSize":180116135
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Repository":"base",
|
"Repository":"ubuntu",
|
||||||
"Tag":"ubuntu-quantal",
|
"Tag":"12.04",
|
||||||
"Id":"b750fe79269d",
|
"Id":"b750fe79269d",
|
||||||
"Created":1364102658,
|
"Created":1364102658,
|
||||||
"Size":24653,
|
"Size":24653,
|
||||||
@@ -635,9 +635,9 @@ List Images
|
|||||||
"d6434d954665" -> "d82cbacda43a"
|
"d6434d954665" -> "d82cbacda43a"
|
||||||
base -> "e9aa60c60128" [style=invis]
|
base -> "e9aa60c60128" [style=invis]
|
||||||
"074be284591f" -> "f71189fff3de"
|
"074be284591f" -> "f71189fff3de"
|
||||||
"b750fe79269d" [label="b750fe79269d\nbase",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"b750fe79269d" [label="b750fe79269d\nubuntu",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"e9aa60c60128" [label="e9aa60c60128\nbase2",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"e9aa60c60128" [label="e9aa60c60128\ncentos",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
"9a33b36209ed" [label="9a33b36209ed\ntest",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
"9a33b36209ed" [label="9a33b36209ed\nfedora",shape=box,fillcolor="paleturquoise",style="filled,rounded"];
|
||||||
base [style=invisible]
|
base [style=invisible]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -658,7 +658,7 @@ Create an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
POST /images/create?fromImage=base HTTP/1.1
|
POST /images/create?fromImage=ubuntu HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -721,7 +721,7 @@ Inspect an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/json HTTP/1.1
|
GET /images/centos/json HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -751,7 +751,7 @@ Inspect an image
|
|||||||
"Env":null,
|
"Env":null,
|
||||||
"Cmd": ["/bin/bash"]
|
"Cmd": ["/bin/bash"]
|
||||||
,"Dns":null,
|
,"Dns":null,
|
||||||
"Image":"base",
|
"Image":"centos",
|
||||||
"Volumes":null,
|
"Volumes":null,
|
||||||
"VolumesFrom":"",
|
"VolumesFrom":"",
|
||||||
"WorkingDir":""
|
"WorkingDir":""
|
||||||
@@ -776,7 +776,7 @@ Get the history of an image
|
|||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|
||||||
GET /images/base/history HTTP/1.1
|
GET /images/fedora/history HTTP/1.1
|
||||||
|
|
||||||
**Example response**:
|
**Example response**:
|
||||||
|
|
||||||
@@ -1126,10 +1126,10 @@ Monitor Docker's events
|
|||||||
HTTP/1.1 200 OK
|
HTTP/1.1 200 OK
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"status":"create","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
|
{"status":"create","id":"dfdf82bd3881","from":"ubuntu:latest","time":1374067924}
|
||||||
{"status":"start","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
|
{"status":"start","id":"dfdf82bd3881","from":"ubuntu:latest","time":1374067924}
|
||||||
{"status":"stop","id":"dfdf82bd3881","from":"base:latest","time":1374067966}
|
{"status":"stop","id":"dfdf82bd3881","from":"ubuntu:latest","time":1374067966}
|
||||||
{"status":"destroy","id":"dfdf82bd3881","from":"base:latest","time":1374067970}
|
{"status":"destroy","id":"dfdf82bd3881","from":"ubuntu:latest","time":1374067970}
|
||||||
|
|
||||||
:query since: timestamp used for polling
|
:query since: timestamp used for polling
|
||||||
:statuscode 200: no error
|
:statuscode 200: no error
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
Docker Index API
|
Docker Index API
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
1. Brief introduction
|
1. Brief introduction
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
@@ -42,7 +40,7 @@ User Repo
|
|||||||
Authorization: Basic akmklmasadalkm==
|
Authorization: Basic akmklmasadalkm==
|
||||||
X-Docker-Token: true
|
X-Docker-Token: true
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”}]
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"}]
|
||||||
|
|
||||||
:parameter namespace: the namespace for the repo
|
:parameter namespace: the namespace for the repo
|
||||||
:parameter repo_name: the name for the repo
|
:parameter repo_name: the name for the repo
|
||||||
@@ -54,7 +52,8 @@ User Repo
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
WWW-Authenticate: Token signature=123abc,repository=”foo/bar”,access=write
|
WWW-Authenticate: Token signature=123abc,repository="foo/bar",access=write
|
||||||
|
X-Docker-Token: signature=123abc,repository="foo/bar",access=write
|
||||||
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
||||||
|
|
||||||
""
|
""
|
||||||
@@ -92,7 +91,8 @@ User Repo
|
|||||||
HTTP/1.1 202
|
HTTP/1.1 202
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
WWW-Authenticate: Token signature=123abc,repository=”foo/bar”,access=delete
|
WWW-Authenticate: Token signature=123abc,repository="foo/bar",access=delete
|
||||||
|
X-Docker-Token: signature=123abc,repository="foo/bar",access=delete
|
||||||
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
||||||
|
|
||||||
""
|
""
|
||||||
@@ -124,7 +124,7 @@ Library Repo
|
|||||||
Authorization: Basic akmklmasadalkm==
|
Authorization: Basic akmklmasadalkm==
|
||||||
X-Docker-Token: true
|
X-Docker-Token: true
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”}]
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"}]
|
||||||
|
|
||||||
:parameter repo_name: the library name for the repo
|
:parameter repo_name: the library name for the repo
|
||||||
|
|
||||||
@@ -135,7 +135,8 @@ Library Repo
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
WWW-Authenticate: Token signature=123abc,repository=”library/foobar”,access=write
|
WWW-Authenticate: Token signature=123abc,repository="library/foobar",access=write
|
||||||
|
X-Docker-Token: signature=123abc,repository="foo/bar",access=write
|
||||||
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
||||||
|
|
||||||
""
|
""
|
||||||
@@ -174,7 +175,8 @@ Library Repo
|
|||||||
HTTP/1.1 202
|
HTTP/1.1 202
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
WWW-Authenticate: Token signature=123abc,repository=”library/foobar”,access=delete
|
WWW-Authenticate: Token signature=123abc,repository="library/foobar",access=delete
|
||||||
|
X-Docker-Token: signature=123abc,repository="foo/bar",access=delete
|
||||||
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
X-Docker-Endpoints: registry-1.docker.io [, registry-2.docker.io]
|
||||||
|
|
||||||
""
|
""
|
||||||
@@ -205,8 +207,8 @@ User Repo Images
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Basic akmklmasadalkm==
|
Authorization: Basic akmklmasadalkm==
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”,
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“checksum”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”}]
|
"checksum": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"}]
|
||||||
|
|
||||||
:parameter namespace: the namespace for the repo
|
:parameter namespace: the namespace for the repo
|
||||||
:parameter repo_name: the name for the repo
|
:parameter repo_name: the name for the repo
|
||||||
@@ -250,10 +252,10 @@ User Repo Images
|
|||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”,
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“checksum”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”},
|
"checksum": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"},
|
||||||
{“id”: “ertwetewtwe38722009fe6857087b486531f9a779a0c1dfddgfgsdgdsgds”,
|
{"id": "ertwetewtwe38722009fe6857087b486531f9a779a0c1dfddgfgsdgdsgds",
|
||||||
“checksum”: “34t23f23fc17e3ed29dae8f12c4f9e89cc6f0bsdfgfsdgdsgdsgerwgew”}]
|
"checksum": "34t23f23fc17e3ed29dae8f12c4f9e89cc6f0bsdfgfsdgdsgdsgerwgew"}]
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
:statuscode 404: Not found
|
:statuscode 404: Not found
|
||||||
@@ -275,8 +277,8 @@ Library Repo Images
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Basic akmklmasadalkm==
|
Authorization: Basic akmklmasadalkm==
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”,
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“checksum”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”}]
|
"checksum": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"}]
|
||||||
|
|
||||||
:parameter repo_name: the library name for the repo
|
:parameter repo_name: the library name for the repo
|
||||||
|
|
||||||
@@ -318,10 +320,10 @@ Library Repo Images
|
|||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
[{“id”: “9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”,
|
[{"id": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“checksum”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”},
|
"checksum": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"},
|
||||||
{“id”: “ertwetewtwe38722009fe6857087b486531f9a779a0c1dfddgfgsdgdsgds”,
|
{"id": "ertwetewtwe38722009fe6857087b486531f9a779a0c1dfddgfgsdgdsgds",
|
||||||
“checksum”: “34t23f23fc17e3ed29dae8f12c4f9e89cc6f0bsdfgfsdgdsgdsgerwgew”}]
|
"checksum": "34t23f23fc17e3ed29dae8f12c4f9e89cc6f0bsdfgfsdgdsgdsgerwgew"}]
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
:statuscode 404: Not found
|
:statuscode 404: Not found
|
||||||
@@ -541,10 +543,11 @@ Search
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"query":"search_term",
|
{"query":"search_term",
|
||||||
"num_results": 2,
|
"num_results": 3,
|
||||||
"results" : [
|
"results" : [
|
||||||
{"name": "dotcloud/base", "description": "A base ubuntu64 image..."},
|
{"name": "ubuntu", "description": "An ubuntu image..."},
|
||||||
{"name": "base2", "description": "A base ubuntu64 image..."},
|
{"name": "centos", "description": "A centos image..."},
|
||||||
|
{"name": "fedora", "description": "A fedora image..."}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
Docker Registry API
|
Docker Registry API
|
||||||
===================
|
===================
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
1. Brief introduction
|
1. Brief introduction
|
||||||
=====================
|
=====================
|
||||||
@@ -61,7 +60,7 @@ Layer
|
|||||||
Host: registry-1.docker.io
|
Host: registry-1.docker.io
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Token akmklmasadalkmsdfgsdgdge33
|
Authorization: Token signature=123abc,repository="foo/bar",access=read
|
||||||
|
|
||||||
:parameter image_id: the id for the layer you want to get
|
:parameter image_id: the id for the layer you want to get
|
||||||
|
|
||||||
@@ -71,39 +70,10 @@ Layer
|
|||||||
|
|
||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
X-Docker-Registry-Version: 0.6.0
|
||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
{
|
{layer binary data stream}
|
||||||
id: "088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c",
|
|
||||||
parent: "aeee6396d62273d180a49c96c62e45438d87c7da4a5cf5d2be6bee4e21bc226f",
|
|
||||||
created: "2013-04-30T17:46:10.843673+03:00",
|
|
||||||
container: "8305672a76cc5e3d168f97221106ced35a76ec7ddbb03209b0f0d96bf74f6ef7",
|
|
||||||
container_config: {
|
|
||||||
Hostname: "host-test",
|
|
||||||
User: "",
|
|
||||||
Memory: 0,
|
|
||||||
MemorySwap: 0,
|
|
||||||
AttachStdin: false,
|
|
||||||
AttachStdout: false,
|
|
||||||
AttachStderr: false,
|
|
||||||
PortSpecs: null,
|
|
||||||
Tty: false,
|
|
||||||
OpenStdin: false,
|
|
||||||
StdinOnce: false,
|
|
||||||
Env: null,
|
|
||||||
Cmd: [
|
|
||||||
"/bin/bash",
|
|
||||||
"-c",
|
|
||||||
"apt-get -q -yy -f install libevent-dev"
|
|
||||||
],
|
|
||||||
Dns: null,
|
|
||||||
Image: "imagename/blah",
|
|
||||||
Volumes: { },
|
|
||||||
VolumesFrom: ""
|
|
||||||
},
|
|
||||||
docker_version: "0.1.7"
|
|
||||||
}
|
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
:statuscode 401: Requires authorization
|
:statuscode 401: Requires authorization
|
||||||
@@ -120,40 +90,10 @@ Layer
|
|||||||
|
|
||||||
PUT /v1/images/088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c/layer HTTP/1.1
|
PUT /v1/images/088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c/layer HTTP/1.1
|
||||||
Host: registry-1.docker.io
|
Host: registry-1.docker.io
|
||||||
Accept: application/json
|
Transfer-Encoding: chunked
|
||||||
Content-Type: application/json
|
Authorization: Token signature=123abc,repository="foo/bar",access=write
|
||||||
Authorization: Token akmklmasadalkmsdfgsdgdge33
|
|
||||||
|
|
||||||
{
|
{layer binary data stream}
|
||||||
id: "088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c",
|
|
||||||
parent: "aeee6396d62273d180a49c96c62e45438d87c7da4a5cf5d2be6bee4e21bc226f",
|
|
||||||
created: "2013-04-30T17:46:10.843673+03:00",
|
|
||||||
container: "8305672a76cc5e3d168f97221106ced35a76ec7ddbb03209b0f0d96bf74f6ef7",
|
|
||||||
container_config: {
|
|
||||||
Hostname: "host-test",
|
|
||||||
User: "",
|
|
||||||
Memory: 0,
|
|
||||||
MemorySwap: 0,
|
|
||||||
AttachStdin: false,
|
|
||||||
AttachStdout: false,
|
|
||||||
AttachStderr: false,
|
|
||||||
PortSpecs: null,
|
|
||||||
Tty: false,
|
|
||||||
OpenStdin: false,
|
|
||||||
StdinOnce: false,
|
|
||||||
Env: null,
|
|
||||||
Cmd: [
|
|
||||||
"/bin/bash",
|
|
||||||
"-c",
|
|
||||||
"apt-get -q -yy -f install libevent-dev"
|
|
||||||
],
|
|
||||||
Dns: null,
|
|
||||||
Image: "imagename/blah",
|
|
||||||
Volumes: { },
|
|
||||||
VolumesFrom: ""
|
|
||||||
},
|
|
||||||
docker_version: "0.1.7"
|
|
||||||
}
|
|
||||||
|
|
||||||
:parameter image_id: the id for the layer you want to get
|
:parameter image_id: the id for the layer you want to get
|
||||||
|
|
||||||
@@ -165,6 +105,7 @@ Layer
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -191,13 +132,38 @@ Image
|
|||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
{
|
{
|
||||||
“id”: “088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c”,
|
id: "088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c",
|
||||||
“checksum”: “sha256:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”
|
parent: "aeee6396d62273d180a49c96c62e45438d87c7da4a5cf5d2be6bee4e21bc226f",
|
||||||
}
|
created: "2013-04-30T17:46:10.843673+03:00",
|
||||||
|
container: "8305672a76cc5e3d168f97221106ced35a76ec7ddbb03209b0f0d96bf74f6ef7",
|
||||||
|
container_config: {
|
||||||
|
Hostname: "host-test",
|
||||||
|
User: "",
|
||||||
|
Memory: 0,
|
||||||
|
MemorySwap: 0,
|
||||||
|
AttachStdin: false,
|
||||||
|
AttachStdout: false,
|
||||||
|
AttachStderr: false,
|
||||||
|
PortSpecs: null,
|
||||||
|
Tty: false,
|
||||||
|
OpenStdin: false,
|
||||||
|
StdinOnce: false,
|
||||||
|
Env: null,
|
||||||
|
Cmd: [
|
||||||
|
"/bin/bash",
|
||||||
|
"-c",
|
||||||
|
"apt-get -q -yy -f install libevent-dev"
|
||||||
|
],
|
||||||
|
Dns: null,
|
||||||
|
Image: "imagename/blah",
|
||||||
|
Volumes: { },
|
||||||
|
VolumesFrom: ""
|
||||||
|
},
|
||||||
|
docker_version: "0.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
:parameter image_id: the id for the layer you want to get
|
:parameter image_id: the id for the layer you want to get
|
||||||
|
|
||||||
|
|
||||||
**Example Response**:
|
**Example Response**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -205,6 +171,7 @@ Image
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -234,11 +201,40 @@ Image
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
X-Docker-Size: 456789
|
||||||
|
X-Docker-Checksum: b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087
|
||||||
|
|
||||||
{
|
{
|
||||||
“id”: “088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c”,
|
id: "088b4505aa3adc3d35e79c031fa126b403200f02f51920fbd9b7c503e87c7a2c",
|
||||||
“checksum”: “sha256:b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”
|
parent: "aeee6396d62273d180a49c96c62e45438d87c7da4a5cf5d2be6bee4e21bc226f",
|
||||||
}
|
created: "2013-04-30T17:46:10.843673+03:00",
|
||||||
|
container: "8305672a76cc5e3d168f97221106ced35a76ec7ddbb03209b0f0d96bf74f6ef7",
|
||||||
|
container_config: {
|
||||||
|
Hostname: "host-test",
|
||||||
|
User: "",
|
||||||
|
Memory: 0,
|
||||||
|
MemorySwap: 0,
|
||||||
|
AttachStdin: false,
|
||||||
|
AttachStdout: false,
|
||||||
|
AttachStderr: false,
|
||||||
|
PortSpecs: null,
|
||||||
|
Tty: false,
|
||||||
|
OpenStdin: false,
|
||||||
|
StdinOnce: false,
|
||||||
|
Env: null,
|
||||||
|
Cmd: [
|
||||||
|
"/bin/bash",
|
||||||
|
"-c",
|
||||||
|
"apt-get -q -yy -f install libevent-dev"
|
||||||
|
],
|
||||||
|
Dns: null,
|
||||||
|
Image: "imagename/blah",
|
||||||
|
Volumes: { },
|
||||||
|
VolumesFrom: ""
|
||||||
|
},
|
||||||
|
docker_version: "0.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
:statuscode 401: Requires authorization
|
:statuscode 401: Requires authorization
|
||||||
@@ -271,6 +267,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
["088b4502f51920fbd9b7c503e87c7a2c05aa3adc3d35e79c031fa126b403200f",
|
["088b4502f51920fbd9b7c503e87c7a2c05aa3adc3d35e79c031fa126b403200f",
|
||||||
"aeee63968d87c7da4a5cf5d2be6bee4e21bc226fd62273d180a49c96c62e4543",
|
"aeee63968d87c7da4a5cf5d2be6bee4e21bc226fd62273d180a49c96c62e4543",
|
||||||
@@ -297,6 +294,7 @@ Ancestry
|
|||||||
Host: registry-1.docker.io
|
Host: registry-1.docker.io
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
:parameter namespace: namespace for the repo
|
:parameter namespace: namespace for the repo
|
||||||
@@ -309,10 +307,11 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
{
|
{
|
||||||
"latest": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
"latest": "9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f",
|
||||||
“0.1.1”: “b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087”
|
"0.1.1": "b486531f9a779a0c17e3ed29dae8f12c4f9e89cc6f0bc3c38722009fe6857087"
|
||||||
}
|
}
|
||||||
|
|
||||||
:statuscode 200: OK
|
:statuscode 200: OK
|
||||||
@@ -332,6 +331,7 @@ Ancestry
|
|||||||
Host: registry-1.docker.io
|
Host: registry-1.docker.io
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
:parameter namespace: namespace for the repo
|
:parameter namespace: namespace for the repo
|
||||||
@@ -345,6 +345,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
"9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"
|
"9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"
|
||||||
|
|
||||||
@@ -377,6 +378,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -399,7 +401,7 @@ Ancestry
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Cookie: (Cookie provided by the Registry)
|
Cookie: (Cookie provided by the Registry)
|
||||||
|
|
||||||
“9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f”
|
"9e89cc6f0bc3c38722009fe6857087b486531f9a779a0c17e3ed29dae8f12c4f"
|
||||||
|
|
||||||
:parameter namespace: namespace for the repo
|
:parameter namespace: namespace for the repo
|
||||||
:parameter repository: name for the repo
|
:parameter repository: name for the repo
|
||||||
@@ -412,6 +414,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -449,6 +452,7 @@ Ancestry
|
|||||||
HTTP/1.1 200
|
HTTP/1.1 200
|
||||||
Vary: Accept
|
Vary: Accept
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
""
|
""
|
||||||
|
|
||||||
@@ -456,8 +460,41 @@ Ancestry
|
|||||||
:statuscode 401: Requires authorization
|
:statuscode 401: Requires authorization
|
||||||
:statuscode 404: Repository not found
|
:statuscode 404: Repository not found
|
||||||
|
|
||||||
3.0 Authorization
|
2.4 Status
|
||||||
=================
|
----------
|
||||||
|
|
||||||
|
.. http:get:: /v1/_ping
|
||||||
|
|
||||||
|
Check status of the registry. This endpoint is also used to determine if
|
||||||
|
the registry supports SSL.
|
||||||
|
|
||||||
|
**Example Request**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
GET /v1/_ping HTTP/1.1
|
||||||
|
Host: registry-1.docker.io
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
""
|
||||||
|
|
||||||
|
**Example Response**:
|
||||||
|
|
||||||
|
.. sourcecode:: http
|
||||||
|
|
||||||
|
HTTP/1.1 200
|
||||||
|
Vary: Accept
|
||||||
|
Content-Type: application/json
|
||||||
|
X-Docker-Registry-Version: 0.6.0
|
||||||
|
|
||||||
|
""
|
||||||
|
|
||||||
|
:statuscode 200: OK
|
||||||
|
|
||||||
|
|
||||||
|
3 Authorization
|
||||||
|
===============
|
||||||
This is where we describe the authorization process, including the tokens and cookies.
|
This is where we describe the authorization process, including the tokens and cookies.
|
||||||
|
|
||||||
TODO: add more info.
|
TODO: add more info.
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
Registry & Index Spec
|
Registry & Index Spec
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
1. The 3 roles
|
1. The 3 roles
|
||||||
===============
|
===============
|
||||||
|
|
||||||
@@ -564,8 +562,8 @@ Next request::
|
|||||||
Cookie: session="wD/J7LqL5ctqw8haL10vgfhrb2Q=?foo=UydiYXInCnAxCi4=×tamp=RjEzNjYzMTQ5NDcuNDc0NjQzCi4="
|
Cookie: session="wD/J7LqL5ctqw8haL10vgfhrb2Q=?foo=UydiYXInCnAxCi4=×tamp=RjEzNjYzMTQ5NDcuNDc0NjQzCi4="
|
||||||
|
|
||||||
|
|
||||||
7.0 Document Version
|
7 Document Version
|
||||||
---------------------
|
====================
|
||||||
|
|
||||||
- 1.0 : May 6th 2013 : initial release
|
- 1.0 : May 6th 2013 : initial release
|
||||||
- 1.1 : June 1st 2013 : Added Delete Repository and way to handle new source namespace.
|
- 1.1 : June 1st 2013 : Added Delete Repository and way to handle new source namespace.
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
:title: Registry API
|
||||||
|
:description: Various client libraries available to use with the Docker remote API
|
||||||
|
:keywords: API, Docker, index, registry, REST, documentation, clients, Python, Ruby, Javascript, Erlang, Go
|
||||||
|
|
||||||
|
|
||||||
|
==================================
|
||||||
|
Docker Remote API Client Libraries
|
||||||
|
==================================
|
||||||
|
|
||||||
|
These libraries have not been tested by the Docker Maintainers for
|
||||||
|
compatibility. Please file issues with the library owners. If you
|
||||||
|
find more library implementations, please list them in Docker doc bugs
|
||||||
|
and we will add the libraries here.
|
||||||
|
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Language/Framework | Name | Repository |
|
||||||
|
+======================+================+============================================+
|
||||||
|
| Python | docker-py | https://github.com/dotcloud/docker-py |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Ruby | docker-client | https://github.com/geku/docker-client |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Ruby | docker-api | https://github.com/swipely/docker-api |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Javascript (NodeJS) | docker.io | https://github.com/appersonlabs/docker.io |
|
||||||
|
| | | Install via NPM: `npm install docker.io` |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Javascript | docker-js | https://github.com/dgoujard/docker-js |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Javascript (Angular) | dockerui | https://github.com/crosbymichael/dockerui |
|
||||||
|
| **WebUI** | | |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Java | docker-java | https://github.com/kpelykh/docker-java |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Erlang | erldocker | https://github.com/proger/erldocker |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
|
| Go | go-dockerclient| https://github.com/fsouza/go-dockerclient |
|
||||||
|
+----------------------+----------------+--------------------------------------------+
|
||||||
@@ -8,7 +8,7 @@ Overview
|
|||||||
======================
|
======================
|
||||||
|
|
||||||
Docker Usage
|
Docker Usage
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
To list available commands, either run ``docker`` with no parameters or execute
|
To list available commands, either run ``docker`` with no parameters or execute
|
||||||
``docker help``::
|
``docker help``::
|
||||||
@@ -21,40 +21,71 @@ To list available commands, either run ``docker`` with no parameters or execute
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Available Commands
|
Available Commands
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. toctree::
|
.. include:: command/attach.rst
|
||||||
:maxdepth: 2
|
|
||||||
|
.. include:: command/build.rst
|
||||||
|
|
||||||
|
.. include:: command/commit.rst
|
||||||
|
|
||||||
|
.. include:: command/cp.rst
|
||||||
|
|
||||||
|
.. include:: command/diff.rst
|
||||||
|
|
||||||
|
.. include:: command/events.rst
|
||||||
|
|
||||||
|
.. include:: command/export.rst
|
||||||
|
|
||||||
|
.. include:: command/history.rst
|
||||||
|
|
||||||
|
.. include:: command/images.rst
|
||||||
|
|
||||||
|
.. include:: command/import.rst
|
||||||
|
|
||||||
|
.. include:: command/info.rst
|
||||||
|
|
||||||
|
.. include:: command/insert.rst
|
||||||
|
|
||||||
|
.. include:: command/inspect.rst
|
||||||
|
|
||||||
|
.. include:: command/kill.rst
|
||||||
|
|
||||||
|
.. include:: command/login.rst
|
||||||
|
|
||||||
|
.. include:: command/logs.rst
|
||||||
|
|
||||||
|
.. include:: command/port.rst
|
||||||
|
|
||||||
|
.. include:: command/ps.rst
|
||||||
|
|
||||||
|
.. include:: command/pull.rst
|
||||||
|
|
||||||
|
.. include:: command/push.rst
|
||||||
|
|
||||||
|
.. include:: command/restart.rst
|
||||||
|
|
||||||
|
.. include:: command/rm.rst
|
||||||
|
|
||||||
|
.. include:: command/rmi.rst
|
||||||
|
|
||||||
|
.. include:: command/run.rst
|
||||||
|
|
||||||
|
.. include:: command/search.rst
|
||||||
|
|
||||||
|
.. include:: command/start.rst
|
||||||
|
|
||||||
|
.. include:: command/stop.rst
|
||||||
|
|
||||||
|
.. include:: command/tag.rst
|
||||||
|
|
||||||
|
.. include:: command/top.rst
|
||||||
|
|
||||||
|
.. include:: command/version.rst
|
||||||
|
|
||||||
|
.. include:: command/wait.rst
|
||||||
|
|
||||||
|
|
||||||
command/attach
|
|
||||||
command/build
|
|
||||||
command/commit
|
|
||||||
command/cp
|
|
||||||
command/diff
|
|
||||||
command/events
|
|
||||||
command/export
|
|
||||||
command/history
|
|
||||||
command/images
|
|
||||||
command/import
|
|
||||||
command/info
|
|
||||||
command/insert
|
|
||||||
command/inspect
|
|
||||||
command/kill
|
|
||||||
command/login
|
|
||||||
command/logs
|
|
||||||
command/port
|
|
||||||
command/ps
|
|
||||||
command/pull
|
|
||||||
command/push
|
|
||||||
command/restart
|
|
||||||
command/rm
|
|
||||||
command/rmi
|
|
||||||
command/run
|
|
||||||
command/search
|
|
||||||
command/start
|
|
||||||
command/stop
|
|
||||||
command/tag
|
|
||||||
command/top
|
|
||||||
command/version
|
|
||||||
command/wait
|
|
||||||
|
|||||||
@@ -14,12 +14,15 @@
|
|||||||
|
|
||||||
-m="": Commit message
|
-m="": Commit message
|
||||||
-author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>"
|
-author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>"
|
||||||
-run="": Config automatically applied when the image is
|
-run="": Configuration to be applied when the image is launched with `docker run`.
|
||||||
run. "+`(ex: {"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')
|
(ex: '{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')
|
||||||
|
|
||||||
Full -run example::
|
Full -run example (multiline is ok within a single quote ``'``)
|
||||||
|
|
||||||
{
|
::
|
||||||
|
|
||||||
|
$ sudo docker commit -run='
|
||||||
|
{
|
||||||
"Entrypoint" : null,
|
"Entrypoint" : null,
|
||||||
"Privileged" : false,
|
"Privileged" : false,
|
||||||
"User" : "",
|
"User" : "",
|
||||||
@@ -46,4 +49,4 @@ Full -run example::
|
|||||||
"NetworkDisabled" : false,
|
"NetworkDisabled" : false,
|
||||||
"Memory" : 0,
|
"Memory" : 0,
|
||||||
"AttachStdout" : false
|
"AttachStdout" : false
|
||||||
}
|
}' $CONTAINER_ID
|
||||||
|
|||||||
@@ -23,4 +23,4 @@ Displaying images visually
|
|||||||
|
|
||||||
sudo docker images -viz | dot -Tpng -o docker.png
|
sudo docker images -viz | dot -Tpng -o docker.png
|
||||||
|
|
||||||
.. image:: images/docker_images.gif
|
.. image:: https://docs.docker.io/en/latest/_static/docker_images.gif
|
||||||
|
|||||||
@@ -23,10 +23,11 @@
|
|||||||
-m=0: Memory limit (in bytes)
|
-m=0: Memory limit (in bytes)
|
||||||
-n=true: Enable networking for this container
|
-n=true: Enable networking for this container
|
||||||
-p=[]: Map a network port to the 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
|
-t=false: Allocate a pseudo-tty
|
||||||
-u="": Username or UID
|
-u="": Username or UID
|
||||||
-dns=[]: Set custom dns servers for the container
|
-dns=[]: Set custom dns servers for the container
|
||||||
-v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]. If "host-dir" is missing, then docker creates a new volume.
|
-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.
|
-volumes-from="": Mount all volumes from the given container.
|
||||||
-entrypoint="": Overwrite the default entrypoint set by the image.
|
-entrypoint="": Overwrite the default entrypoint set by the image.
|
||||||
-w="": Working directory inside the container
|
-w="": Working directory inside the container
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
:keywords: Docker, documentation, developers, contributing, dev environment
|
:keywords: Docker, documentation, developers, contributing, dev environment
|
||||||
|
|
||||||
Setting Up a Dev Environment
|
Setting Up a Dev Environment
|
||||||
============================
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
To make it easier to contribute to Docker, we provide a standard
|
To make it easier to contribute to Docker, we provide a standard
|
||||||
development environment. It is important that the same environment be
|
development environment. It is important that the same environment be
|
||||||
@@ -12,11 +12,11 @@ environment defines all build dependencies: system libraries and
|
|||||||
binaries, go environment, go dependencies, etc.
|
binaries, go environment, go dependencies, etc.
|
||||||
|
|
||||||
|
|
||||||
Step 1: install docker
|
Step 1: Install Docker
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Docker's build environment itself is a Docker container, so the first
|
Docker's build environment itself is a Docker container, so the first
|
||||||
step is to install docker on your system.
|
step is to install Docker on your system.
|
||||||
|
|
||||||
You can follow the `install instructions most relevant to your system
|
You can follow the `install instructions most relevant to your system
|
||||||
<https://docs.docker.io/en/latest/installation/>`_. Make sure you have
|
<https://docs.docker.io/en/latest/installation/>`_. Make sure you have
|
||||||
@@ -24,40 +24,109 @@ a working, up-to-date docker installation, then continue to the next
|
|||||||
step.
|
step.
|
||||||
|
|
||||||
|
|
||||||
Step 2: check out the source
|
Step 2: Check out the Source
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
::
|
.. code-block:: bash
|
||||||
|
|
||||||
git clone http://git@github.com/dotcloud/docker
|
git clone http://git@github.com/dotcloud/docker
|
||||||
cd docker
|
cd docker
|
||||||
|
|
||||||
|
To checkout a different revision just use ``git checkout`` with the name of branch or revision number.
|
||||||
|
|
||||||
Step 3: build
|
|
||||||
-------------
|
|
||||||
|
|
||||||
When you are ready to build docker, run this command:
|
Step 3: Build the Environment
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
::
|
This following command will build a development environment using the Dockerfile in the current directory. Essentially, it will install all the build and runtime dependencies necessary to build and test Docker. This command will take some time to complete when you first execute it.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
sudo docker build -t docker .
|
sudo docker build -t docker .
|
||||||
|
|
||||||
This will build the revision currently checked out in the
|
|
||||||
repository. Feel free to check out the version of your choice.
|
|
||||||
|
|
||||||
If the build is successful, congratulations! You have produced a clean
|
|
||||||
build of docker, neatly encapsulated in a standard build environment.
|
|
||||||
|
|
||||||
You can run an interactive session in the newly built container:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
sudo docker run -i -t docker bash
|
|
||||||
|
|
||||||
|
|
||||||
To extract the binaries from the container:
|
If the build is successful, congratulations! You have produced a clean build of docker, neatly encapsulated in a standard build environment.
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
sudo docker run docker sh -c 'cat $(which docker)' > docker-build && chmod +x docker-build
|
Step 4: Build the Docker Binary
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
To create the Docker binary, run this command:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker run -lxc-conf=lxc.aa_profile=unconfined -privileged -v `pwd`:/go/src/github.com/dotcloud/docker docker hack/make.sh binary
|
||||||
|
|
||||||
|
This will create the Docker binary in ``./bundles/<version>-dev/binary/``
|
||||||
|
|
||||||
|
|
||||||
|
Step 5: Run the Tests
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
To run the Docker test cases you first need to disable `AppArmor <https://wiki.ubuntu.com/AppArmor>`_ using the following commands
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo /etc/init.d/apparmor stop
|
||||||
|
sudo /etc/init.d/apparmor teardown
|
||||||
|
|
||||||
|
To execute the test cases, run this command:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker run -lxc-conf=lxc.aa_profile=unconfined -privileged -v `pwd`:/go/src/github.com/dotcloud/docker docker hack/make.sh test
|
||||||
|
|
||||||
|
|
||||||
|
If the test are successful then the tail of the output should look something like this
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
--- PASS: TestWriteBroadcaster (0.00 seconds)
|
||||||
|
=== RUN TestRaceWriteBroadcaster
|
||||||
|
--- PASS: TestRaceWriteBroadcaster (0.00 seconds)
|
||||||
|
=== RUN TestTruncIndex
|
||||||
|
--- PASS: TestTruncIndex (0.00 seconds)
|
||||||
|
=== RUN TestCompareKernelVersion
|
||||||
|
--- PASS: TestCompareKernelVersion (0.00 seconds)
|
||||||
|
=== RUN TestHumanSize
|
||||||
|
--- PASS: TestHumanSize (0.00 seconds)
|
||||||
|
=== RUN TestParseHost
|
||||||
|
--- PASS: TestParseHost (0.00 seconds)
|
||||||
|
=== RUN TestParseRepositoryTag
|
||||||
|
--- PASS: TestParseRepositoryTag (0.00 seconds)
|
||||||
|
=== RUN TestGetResolvConf
|
||||||
|
--- PASS: TestGetResolvConf (0.00 seconds)
|
||||||
|
=== RUN TestCheckLocalDns
|
||||||
|
--- PASS: TestCheckLocalDns (0.00 seconds)
|
||||||
|
=== RUN TestParseRelease
|
||||||
|
--- PASS: TestParseRelease (0.00 seconds)
|
||||||
|
=== RUN TestDependencyGraphCircular
|
||||||
|
--- PASS: TestDependencyGraphCircular (0.00 seconds)
|
||||||
|
=== RUN TestDependencyGraph
|
||||||
|
--- PASS: TestDependencyGraph (0.00 seconds)
|
||||||
|
PASS
|
||||||
|
ok github.com/dotcloud/docker/utils 0.017s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Step 6: Use Docker
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
You can run an interactive session in the newly built container:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sudo docker run -privileged -i -t docker bash
|
||||||
|
|
||||||
|
# type 'exit' to exit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. 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``.
|
||||||
|
|
||||||
|
|
||||||
|
**Need More Help?**
|
||||||
|
|
||||||
|
If you need more help then hop on to the `#docker-dev IRC channel <irc://chat.freenode.net#docker-dev>`_ or post a message on the `Docker developer mailinglist <https://groups.google.com/d/forum/docker-dev>`_.
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
:description: A simple hello world example with Docker
|
:description: A simple hello world example with Docker
|
||||||
:keywords: docker, example, hello world
|
:keywords: docker, example, hello world
|
||||||
|
|
||||||
|
.. _examples:
|
||||||
|
|
||||||
|
Hello World
|
||||||
|
-----------
|
||||||
|
|
||||||
.. _running_examples:
|
.. _running_examples:
|
||||||
|
|
||||||
Running the Examples
|
Running the Examples
|
||||||
@@ -166,13 +171,11 @@ See the example in action
|
|||||||
The next example in the series is a :ref:`python_web_app` example, or
|
The next example in the series is a :ref:`python_web_app` example, or
|
||||||
you could skip to any of the other examples:
|
you could skip to any of the other examples:
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 1
|
|
||||||
|
|
||||||
python_web_app
|
* :ref:`python_web_app`
|
||||||
nodejs_web_app
|
* :ref:`nodejs_web_app`
|
||||||
running_redis_service
|
* :ref:`running_redis_service`
|
||||||
running_ssh_service
|
* :ref:`running_ssh_service`
|
||||||
couchdb_data_volumes
|
* :ref:`running_couchdb_service`
|
||||||
postgresql_service
|
* :ref:`postgresql_service`
|
||||||
mongodb
|
* :ref:`mongodb`
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
:keywords: docker, hello world, node, nodejs, python, couch, couchdb, redis, ssh, sshd, examples, postgresql
|
:keywords: docker, hello world, node, nodejs, python, couch, couchdb, redis, ssh, sshd, examples, postgresql
|
||||||
|
|
||||||
|
|
||||||
|
.. _example_list:
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
========
|
========
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ Update its dependencies.
|
|||||||
|
|
||||||
apt-get update
|
apt-get update
|
||||||
|
|
||||||
Install ``python-software-properies``.
|
Install ``python-software-properties``.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
apt-get install python-software-properties
|
apt-get -y install python-software-properties
|
||||||
apt-get install software-properties-common
|
apt-get -y install software-properties-common
|
||||||
|
|
||||||
Add Pitti's PostgreSQL repository. It contains the most recent stable release
|
Add Pitti's PostgreSQL repository. It contains the most recent stable release
|
||||||
of PostgreSQL i.e. ``9.2``.
|
of PostgreSQL i.e. ``9.2``.
|
||||||
@@ -66,18 +66,19 @@ other roles. Following Vagrant's convention the role will be named
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
sudo -u postgres createuser -P -d -r -s docker
|
su postgres -c "createuser -P -d -r -s docker"
|
||||||
|
|
||||||
Create a test database also named ``docker`` owned by previously created ``docker``
|
Create a test database also named ``docker`` owned by previously created ``docker``
|
||||||
role.
|
role.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
sudo -u postgres createdb -O docker docker
|
su postgres -c "createdb -O docker docker"
|
||||||
|
|
||||||
Adjust PostgreSQL configuration so that remote connections to the
|
Adjust PostgreSQL configuration so that remote connections to the
|
||||||
database are possible. Make sure that inside
|
database are possible. Make sure that inside
|
||||||
``/etc/postgresql/9.2/main/pg_hba.conf`` you have following line:
|
``/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``):
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
@@ -90,9 +91,17 @@ uncomment ``listen_addresses`` so it is as follows:
|
|||||||
|
|
||||||
listen_addresses='*'
|
listen_addresses='*'
|
||||||
|
|
||||||
*Note:* this PostgreSQL setup is for development only purposes. Refer
|
.. note::
|
||||||
to PostgreSQL documentation how to fine-tune these settings so that it
|
|
||||||
is enough secure.
|
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
|
||||||
|
|
||||||
Create an image and assign it a name. ``<container_id>`` is in the
|
Create an image and assign it a name. ``<container_id>`` is in the
|
||||||
Bash prompt; you can also locate it using ``docker ps -a``.
|
Bash prompt; you can also locate it using ``docker ps -a``.
|
||||||
@@ -111,7 +120,9 @@ Finally, run PostgreSQL server via ``docker``.
|
|||||||
-D /var/lib/postgresql/9.2/main \
|
-D /var/lib/postgresql/9.2/main \
|
||||||
-c config_file=/etc/postgresql/9.2/main/postgresql.conf')
|
-c config_file=/etc/postgresql/9.2/main/postgresql.conf')
|
||||||
|
|
||||||
Connect the PostgreSQL server using ``psql``.
|
Connect the PostgreSQL server using ``psql`` (You will need postgres installed
|
||||||
|
on the machine. For ubuntu, use something like
|
||||||
|
``sudo apt-get install postgresql``).
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
@@ -128,7 +139,7 @@ As before, create roles or databases if needed.
|
|||||||
docker=# CREATE DATABASE foo OWNER=docker;
|
docker=# CREATE DATABASE foo OWNER=docker;
|
||||||
CREATE DATABASE
|
CREATE DATABASE
|
||||||
|
|
||||||
Additionally, publish there your newly created image on Docker Index.
|
Additionally, publish your newly created image on Docker Index.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
@@ -149,10 +160,11 @@ container starts.
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
sudo docker commit <container_id> <your username>/postgresql -run='{"Cmd": \
|
sudo docker commit -run='{"Cmd": \
|
||||||
["/bin/su", "postgres", "-c", "/usr/lib/postgresql/9.2/bin/postgres -D \
|
["/bin/su", "postgres", "-c", "/usr/lib/postgresql/9.2/bin/postgres -D \
|
||||||
/var/lib/postgresql/9.2/main -c \
|
/var/lib/postgresql/9.2/main -c \
|
||||||
config_file=/etc/postgresql/9.2/main/postgresql.conf"], PortSpecs": ["5432"]}
|
config_file=/etc/postgresql/9.2/main/postgresql.conf"], "PortSpecs": ["5432"]}' \
|
||||||
|
<container_id> <your username>/postgresql
|
||||||
|
|
||||||
From now on, just type ``docker run <your username>/postgresql`` and
|
From now on, just type ``docker run <your username>/postgresql`` and
|
||||||
PostgreSQL should automatically start.
|
PostgreSQL should automatically start.
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ The password is 'screencast'
|
|||||||
# I had it so it was quick
|
# I had it so it was quick
|
||||||
# now let's connect using -i for interactive and with -t for terminal
|
# now let's connect using -i for interactive and with -t for terminal
|
||||||
# we execute /bin/bash to get a prompt.
|
# we execute /bin/bash to get a prompt.
|
||||||
$ docker run -i -t base /bin/bash
|
$ docker run -i -t ubuntu /bin/bash
|
||||||
# yes! we are in!
|
# yes! we are in!
|
||||||
# now lets install openssh
|
# now lets install openssh
|
||||||
$ apt-get update
|
$ apt-get update
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
:description: An overview of the Docker Documentation
|
:description: An overview of the Docker Documentation
|
||||||
:keywords: containers, lxc, concepts, explanation
|
:keywords: containers, lxc, concepts, explanation
|
||||||
|
|
||||||
.. image:: static_files/dockerlogo-h.png
|
.. image:: https://www.docker.io/static/img/linked/dockerlogo-horizontal.png
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|||||||
@@ -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
|
new instance will be blocked by the AWS Security Group, so you might
|
||||||
just get timeouts when you try to connect.
|
just get timeouts when you try to connect.
|
||||||
|
|
||||||
Installing with ``get.docker.io`` (as above) will create a service
|
Installing with ``get.docker.io`` (as above) will create a service named
|
||||||
named ``dockerd``. You may want to set up a :ref:`docker group
|
``lxc-docker``. It will also set up a :ref:`docker group <dockergroup>` and you
|
||||||
<dockergroup>` and add the *ubuntu* user to it so that you don't have
|
may want to add the *ubuntu* user to it so that you don't have to use ``sudo``
|
||||||
to use ``sudo`` for every Docker command.
|
for every Docker command.
|
||||||
|
|
||||||
Once you've got Docker installed, you're ready to try it out -- head
|
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.
|
on over to the :doc:`../use/basics` or :doc:`../examples/index` section.
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ To enable the forwarding, run as root on the host system:
|
|||||||
|
|
||||||
sysctl net.ipv4.ip_forward=1
|
sysctl net.ipv4.ip_forward=1
|
||||||
|
|
||||||
And, to make it persistent across reboots, enable it on the host's **/etc/sysctl.conf**:
|
And, to make it persistent across reboots, enable it on the host's **/etc/sysctl.d/docker.conf**:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|||||||
@@ -11,63 +11,45 @@ Gentoo Linux
|
|||||||
|
|
||||||
.. include:: install_unofficial.inc
|
.. include:: install_unofficial.inc
|
||||||
|
|
||||||
Installing Docker on Gentoo Linux can be accomplished by using the overlay
|
Installing Docker on Gentoo Linux can be accomplished using one of two methods.
|
||||||
provided at https://github.com/tianon/docker-overlay. The most up-to-date
|
The first and best way if you're looking for a stable experience is to use the
|
||||||
documentation for properly installing the overlay can be found in the overlay
|
official `app-emulation/docker` package directly in the portage tree.
|
||||||
README. The information here is provided for reference, and may be out of date.
|
|
||||||
|
If you're looking for a ``-bin`` ebuild, a live ebuild, or bleeding edge
|
||||||
|
ebuild changes/fixes, the second installation method is to use the overlay
|
||||||
|
provided at https://github.com/tianon/docker-overlay which can be added using
|
||||||
|
``app-portage/layman``. The most accurate and up-to-date documentation for
|
||||||
|
properly installing and using the overlay can be found in `the overlay README
|
||||||
|
<https://github.com/tianon/docker-overlay/blob/master/README.md#using-this-overlay>`_.
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
Ensure that layman is installed:
|
The package should properly pull in all the necessary dependencies and prompt
|
||||||
|
for all necessary kernel options. For the most straightforward installation
|
||||||
.. code-block:: bash
|
experience, use ``sys-kernel/aufs-sources`` as your kernel sources. If you
|
||||||
|
prefer not to use ``sys-kernel/aufs-sources``, the portage tree also contains
|
||||||
sudo emerge -av app-portage/layman
|
``sys-fs/aufs3``, which includes the patches necessary for adding AUFS support
|
||||||
|
to other kernel source packages such as ``sys-kernel/gentoo-sources`` (and a
|
||||||
Using your favorite editor, add
|
``kernel-patch`` USE flag to perform the patching to ``/usr/src/linux``
|
||||||
``https://raw.github.com/tianon/docker-overlay/master/repositories.xml`` to the
|
automatically).
|
||||||
``overlays`` section in ``/etc/layman/layman.cfg`` (as per instructions on the
|
|
||||||
`Gentoo Wiki <http://wiki.gentoo.org/wiki/Layman#Adding_custom_overlays>`_),
|
|
||||||
then invoke the following:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
sudo layman -f -a docker
|
|
||||||
|
|
||||||
Once that completes, the ``app-emulation/docker`` package will be available
|
|
||||||
for emerge:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
sudo emerge -av app-emulation/docker
|
sudo emerge -av app-emulation/docker
|
||||||
|
|
||||||
If you prefer to use the official binaries, or just do not wish to compile
|
|
||||||
docker, emerge ``app-emulation/docker-bin`` instead. It is important to
|
|
||||||
remember that Gentoo is still an unsupported platform, even when using the
|
|
||||||
official binaries.
|
|
||||||
|
|
||||||
The package should already include all the necessary dependencies. For the
|
|
||||||
simplest installation experience, use ``sys-kernel/aufs-sources`` directly as
|
|
||||||
your kernel sources. If you prefer not to use ``sys-kernel/aufs-sources``, the
|
|
||||||
portage tree also contains ``sys-fs/aufs3``, which contains the patches
|
|
||||||
necessary for adding AUFS support to other kernel source packages (and a
|
|
||||||
``kernel-patch`` use flag to perform the patching automatically).
|
|
||||||
|
|
||||||
Between ``app-emulation/lxc`` and ``app-emulation/docker``, all the
|
|
||||||
necessary kernel configuration flags should be checked for and warned about in
|
|
||||||
the standard manner.
|
|
||||||
|
|
||||||
If any issues arise from this ebuild or the resulting binary, including and
|
If any issues arise from this ebuild or the resulting binary, including and
|
||||||
especially missing kernel configuration flags and/or dependencies, `open an
|
especially missing kernel configuration flags and/or dependencies, `open an
|
||||||
issue <https://github.com/tianon/docker-overlay/issues>`_ on the docker-overlay
|
issue on the docker-overlay repository
|
||||||
repository or ping tianon in the #docker IRC channel.
|
<https://github.com/tianon/docker-overlay/issues>`_ or ping tianon directly in
|
||||||
|
the #docker IRC channel on the freenode network.
|
||||||
|
|
||||||
Starting Docker
|
Starting Docker
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Ensure that you are running a kernel that includes the necessary AUFS support
|
Ensure that you are running a kernel that includes the necessary AUFS
|
||||||
and includes all the necessary modules and/or configuration for LXC.
|
patches/support and includes all the necessary modules and/or configuration for
|
||||||
|
LXC.
|
||||||
|
|
||||||
OpenRC
|
OpenRC
|
||||||
------
|
------
|
||||||
@@ -114,12 +96,3 @@ Or, to enable it more permanently:
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
echo net.ipv4.ip_forward = 1 | sudo tee /etc/sysctl.d/docker.conf
|
echo net.ipv4.ip_forward = 1 | sudo tee /etc/sysctl.d/docker.conf
|
||||||
|
|
||||||
fork/exec /usr/sbin/lxc-start: operation not permitted
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Unfortunately, Gentoo suffers from `issue #1422
|
|
||||||
<https://github.com/dotcloud/docker/issues/1422>`_, meaning that after every
|
|
||||||
fresh start of docker, the first docker run fails due to some tricky terminal
|
|
||||||
issues, so be sure to run something trivial (such as ``docker run -i -t busybox
|
|
||||||
echo hi``) before attempting to run anything important.
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ Docker is available as a Debian package, which makes installation easy.
|
|||||||
|
|
||||||
# Add the Docker repository key to your local keychain
|
# Add the Docker repository key to your local keychain
|
||||||
# using apt-key finger you can check the fingerprint matches 36A1 D786 9245 C895 0F96 6E92 D857 6A8B A88D 21E9
|
# using apt-key finger you can check the fingerprint matches 36A1 D786 9245 C895 0F96 6E92 D857 6A8B A88D 21E9
|
||||||
sudo sh -c "curl https://get.docker.io/gpg | apt-key add -"
|
sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"
|
||||||
|
|
||||||
# Add the Docker repository to your apt sources list.
|
# Add the Docker repository to your apt sources list.
|
||||||
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
|
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
|
||||||
@@ -129,7 +129,7 @@ to follow them again.*
|
|||||||
|
|
||||||
# Add the Docker repository key to your local keychain
|
# Add the Docker repository key to your local keychain
|
||||||
# using apt-key finger you can check the fingerprint matches 36A1 D786 9245 C895 0F96 6E92 D857 6A8B A88D 21E9
|
# using apt-key finger you can check the fingerprint matches 36A1 D786 9245 C895 0F96 6E92 D857 6A8B A88D 21E9
|
||||||
sudo sh -c "curl http://get.docker.io/gpg | apt-key add -"
|
sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"
|
||||||
|
|
||||||
# Add the Docker repository to your apt sources list.
|
# Add the Docker repository to your apt sources list.
|
||||||
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
|
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
|
||||||
|
|||||||
@@ -53,13 +53,10 @@ If you installed the Docker :ref:`binaries` then follow these steps:
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# get the latest binary
|
# get the latest binary
|
||||||
wget http://get.docker.io/builds/Linux/x86_64/docker-latest.tgz
|
wget http://get.docker.io/builds/Linux/x86_64/docker-latest -O docker
|
||||||
|
|
||||||
|
# make it executable
|
||||||
.. code-block:: bash
|
chmod +x docker
|
||||||
|
|
||||||
# Unpack it to your current dir
|
|
||||||
tar -xf docker-latest.tgz
|
|
||||||
|
|
||||||
|
|
||||||
Start docker in daemon mode (``-d``) and disconnect, running the
|
Start docker in daemon mode (``-d``) and disconnect, running the
|
||||||
@@ -73,4 +70,4 @@ which might reside in your path.
|
|||||||
sudo ./docker -d &
|
sudo ./docker -d &
|
||||||
|
|
||||||
|
|
||||||
Alternatively you can replace the docker binary in ``/usr/local/bin``
|
Alternatively you can replace the docker binary in ``/usr/local/bin``.
|
||||||
|
|||||||
@@ -53,9 +53,7 @@ Spin it up
|
|||||||
|
|
||||||
* Download the 'official' Precise64 base ubuntu virtual machine image from vagrantup.com
|
* Download the 'official' Precise64 base ubuntu virtual machine image from vagrantup.com
|
||||||
* Boot this image in virtualbox
|
* Boot this image in virtualbox
|
||||||
* Add the `Docker PPA sources <https://launchpad.net/~dotcloud/+archive/lxc-docker>`_ to /etc/apt/sources.lst
|
* Follow official :ref:`ubuntu_linux` installation path
|
||||||
* Update your sources
|
|
||||||
* Install lxc-docker
|
|
||||||
|
|
||||||
You now have a Ubuntu Virtual Machine running with docker pre-installed.
|
You now have a Ubuntu Virtual Machine running with docker pre-installed.
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
@@ -8,7 +8,7 @@ Documentation
|
|||||||
This documentation has the following resources:
|
This documentation has the following resources:
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:titlesonly:
|
:maxdepth: 1
|
||||||
|
|
||||||
Introduction <index>
|
Introduction <index>
|
||||||
installation/index
|
installation/index
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ It can be as simple as this to create an Ubuntu base image::
|
|||||||
$ sudo debootstrap raring raring > /dev/null
|
$ sudo debootstrap raring raring > /dev/null
|
||||||
$ sudo tar -C raring -c . | sudo docker import - raring
|
$ sudo tar -C raring -c . | sudo docker import - raring
|
||||||
a29c15f1bf7a
|
a29c15f1bf7a
|
||||||
$ sudo docker run raring cat /etc/lsb-release
|
$ sudo docker run raring cat /etc/lsb-release
|
||||||
DISTRIB_ID=Ubuntu
|
DISTRIB_ID=Ubuntu
|
||||||
DISTRIB_RELEASE=13.04
|
DISTRIB_RELEASE=13.04
|
||||||
DISTRIB_CODENAME=raring
|
DISTRIB_CODENAME=raring
|
||||||
@@ -39,5 +39,5 @@ Docker Github Repo:
|
|||||||
* `BusyBox <https://github.com/dotcloud/docker/blob/master/contrib/mkimage-busybox.sh>`_
|
* `BusyBox <https://github.com/dotcloud/docker/blob/master/contrib/mkimage-busybox.sh>`_
|
||||||
* `CentOS
|
* `CentOS
|
||||||
<https://github.com/dotcloud/docker/blob/master/contrib/mkimage-centos.sh>`_
|
<https://github.com/dotcloud/docker/blob/master/contrib/mkimage-centos.sh>`_
|
||||||
* `Debian
|
* `Debian/Ubuntu
|
||||||
<https://github.com/dotcloud/docker/blob/master/contrib/mkimage-debian.sh>`_
|
<https://github.com/dotcloud/docker/blob/master/contrib/mkimage-debian.sh>`_
|
||||||
|
|||||||
@@ -54,8 +54,14 @@ Docker evaluates the instructions in a Dockerfile in order. **The
|
|||||||
first instruction must be `FROM`** in order to specify the
|
first instruction must be `FROM`** in order to specify the
|
||||||
:ref:`base_image_def` from which you are building.
|
:ref:`base_image_def` from which you are building.
|
||||||
|
|
||||||
Docker will ignore **comment lines** *beginning* with ``#``. A comment
|
Docker will treat lines that *begin* with ``#`` as a comment. A ``#``
|
||||||
marker anywhere in the rest of the line will be treated as an argument.
|
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'
|
||||||
|
|
||||||
3. Instructions
|
3. Instructions
|
||||||
===============
|
===============
|
||||||
@@ -226,10 +232,10 @@ The copy obeys the following rules:
|
|||||||
with conflicts resolved in favor of 2) on a file-by-file basis.
|
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
|
* If ``<src>`` is any other kind of file, it is copied individually
|
||||||
along with its metadata. In this case, if ``<dst>`` ends with a
|
along with its metadata. In this case, if ``<dest>`` ends with a
|
||||||
trailing slash ``/``, it will be considered a directory and the
|
trailing slash ``/``, it will be considered a directory and the
|
||||||
contents of ``<src>`` will be written at ``<dst>/base(<src>)``.
|
contents of ``<src>`` will be written at ``<dest>/base(<src>)``.
|
||||||
* If ``<dst>`` does not end with a trailing slash, it will be
|
* If ``<dest>`` does not end with a trailing slash, it will be
|
||||||
considered a regular file and the contents of ``<src>`` will be
|
considered a regular file and the contents of ``<src>`` will be
|
||||||
written at ``<dst>``.
|
written at ``<dst>``.
|
||||||
* If ``<dest>`` doesn't exist, it is created along with all missing
|
* If ``<dest>`` doesn't exist, it is created along with all missing
|
||||||
@@ -321,7 +327,7 @@ the command given by ``CMD`` is executed.
|
|||||||
# VERSION 0.0.1
|
# VERSION 0.0.1
|
||||||
|
|
||||||
FROM ubuntu
|
FROM ubuntu
|
||||||
MAINTAINER Guillaume J. Charmes "guillaume@dotcloud.com"
|
MAINTAINER Guillaume J. Charmes <guillaume@dotcloud.com>
|
||||||
|
|
||||||
# make sure the package repository is up to date
|
# make sure the package repository is up to date
|
||||||
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
|
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
|
||||||
|
|||||||
@@ -52,31 +52,58 @@ repositories in these examples.
|
|||||||
* User images are not checked, it is therefore up to you whether or
|
* User images are not checked, it is therefore up to you whether or
|
||||||
not you trust the creator of this image.
|
not you trust the creator of this image.
|
||||||
|
|
||||||
Find public images available on the Central Index
|
.. _searching_central_index:
|
||||||
-------------------------------------------------
|
|
||||||
|
|
||||||
Search by name, namespace or description
|
Find Public Images on the Central Index
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
You can search the Central Index `online <https://index.docker.io>`_
|
||||||
|
or by the CLI. Searching can find images by name, user name or
|
||||||
|
description:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
sudo docker search <value>
|
$ sudo docker help search
|
||||||
|
Usage: docker search NAME
|
||||||
|
|
||||||
|
Search the docker index for images
|
||||||
|
|
||||||
Download them simply by their name
|
-notrunc=false: Don't truncate output
|
||||||
|
$ sudo docker search centos
|
||||||
|
Found 25 results matching your query ("centos")
|
||||||
|
NAME DESCRIPTION
|
||||||
|
centos
|
||||||
|
slantview/centos-chef-solo CentOS 6.4 with chef-solo.
|
||||||
|
...
|
||||||
|
|
||||||
|
There you can see two example results: ``centos`` and
|
||||||
|
``slantview/centos-chef-solo``. The second result shows that it comes
|
||||||
|
from the public repository of a user, ``slantview/``, while the first
|
||||||
|
result (``centos``) doesn't explicitly list a repository so it comes
|
||||||
|
from the trusted Central Repository. The ``/`` character separates a
|
||||||
|
user's repository and the image name.
|
||||||
|
|
||||||
|
Once you have found the image name, you can download it:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
sudo docker pull <value>
|
# sudo docker pull <value>
|
||||||
|
$ sudo docker pull centos
|
||||||
|
Pulling repository centos
|
||||||
|
539c0211cd76: Download complete
|
||||||
|
|
||||||
|
What can you do with that image? Check out the :ref:`example_list`
|
||||||
|
and, when you're ready with your own image, come back here to learn
|
||||||
|
how to share it.
|
||||||
|
|
||||||
Very similarly you can search for and browse the index online on
|
Contributing to the Central Registry
|
||||||
https://index.docker.io
|
------------------------------------
|
||||||
|
|
||||||
|
Anyone can pull public images from the Central Registry, but if you
|
||||||
Connecting to the Central Registry
|
would like to share one of your own images, then you must register a
|
||||||
----------------------------------
|
unique user name first. You can create your username and login on the
|
||||||
|
`central Docker Index online
|
||||||
You can create a user on the central Docker Index online, or by running
|
<https://index.docker.io/account/signup/>`_, or by running
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
@@ -85,22 +112,27 @@ You can create a user on the central Docker Index online, or by running
|
|||||||
This will prompt you for a username, which will become a public
|
This will prompt you for a username, which will become a public
|
||||||
namespace for your public repositories.
|
namespace for your public repositories.
|
||||||
|
|
||||||
If your username does not exist it will prompt you to also enter a
|
If your username is available then ``docker`` will also prompt you to
|
||||||
password and your e-mail address. It will then automatically log you
|
enter a password and your e-mail address. It will then automatically
|
||||||
in.
|
log you in. Now you're ready to commit and push your own images!
|
||||||
|
|
||||||
.. _container_commit:
|
.. _container_commit:
|
||||||
|
|
||||||
Committing a container to a named image
|
Committing a Container to a Named Image
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
In order to commit to the repository it is required to have committed
|
When you make changes to an existing image, those changes get saved to
|
||||||
your container to an image within your username namespace.
|
a container's file system. You can then promote that container to
|
||||||
|
become an image by making a ``commit``. In addition to converting the
|
||||||
|
container to an image, this is also your opportunity to name the
|
||||||
|
image, specifically a name that includes your user name from the
|
||||||
|
Central Docker Index (as you did a ``login`` above) and a meaningful
|
||||||
|
name for the image.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# for example docker commit $CONTAINER_ID dhrp/kickassapp
|
# format is "sudo docker commit <container_id> <username>/<imagename>"
|
||||||
sudo docker commit <container_id> <username>/<repo_name>
|
$ sudo docker commit $CONTAINER_ID myname/kickassapp
|
||||||
|
|
||||||
.. _image_push:
|
.. _image_push:
|
||||||
|
|
||||||
@@ -115,15 +147,15 @@ or tag.
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# for example docker push dhrp/kickassapp
|
# format is "docker push <username>/<repo_name>"
|
||||||
sudo docker push <username>/<repo_name>
|
$ sudo docker push myname/kickassapp
|
||||||
|
|
||||||
.. _using_private_repositories:
|
.. _using_private_repositories:
|
||||||
|
|
||||||
Private Repositories
|
Private Repositories
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
Right now (version 0.5), private repositories are only possible by
|
Right now (version 0.6), private repositories are only possible by
|
||||||
hosting `your own registry
|
hosting `your own registry
|
||||||
<https://github.com/dotcloud/docker-registry>`_. To push or pull to a
|
<https://github.com/dotcloud/docker-registry>`_. To push or pull to a
|
||||||
repository on your own registry, you must prefix the tag with the
|
repository on your own registry, you must prefix the tag with the
|
||||||
@@ -144,3 +176,30 @@ you can push and pull it like any other repository, but it will
|
|||||||
**not** be searchable (or indexed at all) in the Central Index, and
|
**not** be searchable (or indexed at all) in the Central Index, and
|
||||||
there will be no user name checking performed. Your registry will
|
there will be no user name checking performed. Your registry will
|
||||||
function completely independently from the Central Index.
|
function completely independently from the Central Index.
|
||||||
|
|
||||||
|
Authentication file
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The authentication is stored in a json file, ``.dockercfg`` located in your
|
||||||
|
home directory. It supports multiple registry urls.
|
||||||
|
|
||||||
|
``docker login`` will create the "https://index.docker.io/v1/" key.
|
||||||
|
|
||||||
|
``docker login https://my-registry.com`` will create the "https://my-registry.com" key.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"https://index.docker.io/v1/": {
|
||||||
|
"auth": "xXxXxXxXxXx=",
|
||||||
|
"email": "email@example.com"
|
||||||
|
},
|
||||||
|
"https://my-registry.com": {
|
||||||
|
"auth": "XxXxXxXxXxX=",
|
||||||
|
"email": "email@my-registry.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``auth`` field represents ``base64(<username>:<password>)``
|
||||||
|
|||||||
@@ -1,51 +1,47 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
|
|
||||||
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
|
|
||||||
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
|
|
||||||
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="google-site-verification" content="UxV66EKuPe87dgnH1sbrldrx6VsoWMrx5NjwkgUFxXI" />
|
<meta name="google-site-verification" content="UxV66EKuPe87dgnH1sbrldrx6VsoWMrx5NjwkgUFxXI" />
|
||||||
|
|
||||||
<title>{{ meta['title'] if meta and meta['title'] else title }} - Docker Documentation</title>
|
<title>{{ meta['title'] if meta and meta['title'] else title }} - Docker Documentation</title>
|
||||||
|
|
||||||
<meta name="description" content="{{ meta['description'] if meta }}" />
|
<meta name="description" content="{{ meta['description'] if meta }}" />
|
||||||
<meta name="keywords" content="{{ meta['keywords'] if meta }}" />
|
<meta name="keywords" content="{{ meta['keywords'] if meta }}" />
|
||||||
|
<!-- Swiftype tags: https://swiftype.com/documentation/meta_tags -->
|
||||||
|
<meta property='st:popularity' content='4' />
|
||||||
|
<meta property='st:type' content='docker_doc' />
|
||||||
|
|
||||||
{%- set url_root = pathto('', 1) %}
|
{%- set url_root = pathto('', 1) %}
|
||||||
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
|
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// This is probably used by the search engine
|
// This is included here for Javascript that doesn't have access to the templates.
|
||||||
var DOCUMENTATION_OPTIONS = {
|
var doc_version = "{{ current_version }}";
|
||||||
URL_ROOT: '{{ url_root }}',
|
var doc_slug = "{{ slug }}";
|
||||||
VERSION: '{{ release|e }}',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
|
|
||||||
HAS_SOURCE: {{ has_source|lower }}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{%- set css_files = css_files + ['_static/css/bootstrap.css'] %}
|
{%- set css_files = css_files + ['_static/css/bootstrap.css'] %}
|
||||||
{%- set css_files = css_files + ['_static/css/bootstrap-responsive.css'] %}
|
|
||||||
{%- set css_files = css_files + ['_static/pygments.css'] %}
|
{%- set css_files = css_files + ['_static/pygments.css'] %}
|
||||||
{%- set css_files = css_files + ['_static/css/main.css'] %}
|
{%- set css_files = css_files + ['_static/css/main.css'] %}
|
||||||
|
|
||||||
{%- set script_files =
|
{%- set script_files =
|
||||||
['https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js']
|
['//code.jquery.com/jquery-1.10.1.min.js']
|
||||||
+ ['https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.12/jquery-ui.min.js']
|
+ ['//fonts.googleapis.com/css?family=Cabin:400,700,400italic']
|
||||||
+ script_files
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
{%- set script_files = script_files + ['_static/js/docs.js'] %}
|
{#
|
||||||
|
This part is hopefully complex because things like |cut '/index/' are not available in spinx jinja
|
||||||
|
and will make it crash. (and we need index/ out.
|
||||||
|
#}
|
||||||
|
<link rel="canonical" href="http://docs.docker.io/en/latest/
|
||||||
|
{%- for word in pagename.split('/') -%}
|
||||||
|
{%- if word != 'index' -%}
|
||||||
|
{%- if word != '' -%}
|
||||||
|
{{ word }}/
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
">
|
||||||
|
|
||||||
{%- if pagename == 'index' %}
|
|
||||||
<link rel="canonical" href="http://docs.docker.io/en/latest/">
|
|
||||||
{% else %}
|
|
||||||
<link rel="canonical" href="http://docs.docker.io/en/latest/{{ pagename }}/">
|
|
||||||
{% endif %}
|
|
||||||
{%- for cssfile in css_files %}
|
{%- for cssfile in css_files %}
|
||||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
@@ -53,19 +49,17 @@
|
|||||||
{%- for scriptfile in script_files if scriptfile != '_static/jquery.js' %}
|
{%- for scriptfile in script_files if scriptfile != '_static/jquery.js' %}
|
||||||
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|
||||||
<link rel="shortcut icon" href="{{ pathto('_static/favicon.png', 1) }}"/>
|
<link rel="shortcut icon" href="{{ pathto('_static/favicon.png', 1) }}"/>
|
||||||
|
|
||||||
|
|
||||||
{%- block extrahead %}{% endblock %}
|
{%- block extrahead %}{% endblock %}
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="navbar navbar-fixed-top">
|
<div id="wrap">
|
||||||
|
<div class="navbar navbar-static-top navbar-inner navbar-fixed-top ">
|
||||||
<div class="navbar-dotcloud">
|
<div class="navbar-dotcloud">
|
||||||
<div class="container" style="text-align: center;">
|
<div class="container">
|
||||||
|
|
||||||
<div style="float: right" class="pull-right">
|
<div style="float: right" class="pull-right">
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
@@ -75,49 +69,37 @@
|
|||||||
<li id="nav-community"><a href="http://www.docker.io/community/" title="Community">Community</a></li>
|
<li id="nav-community"><a href="http://www.docker.io/community/" title="Community">Community</a></li>
|
||||||
<li id="nav-documentation" class="active"><a href="http://docs.docker.io/en/latest/">Documentation</a></li>
|
<li id="nav-documentation" class="active"><a href="http://docs.docker.io/en/latest/">Documentation</a></li>
|
||||||
<li id="nav-blog"><a href="http://blog.docker.io/" title="Docker Blog">Blog</a></li>
|
<li id="nav-blog"><a href="http://blog.docker.io/" title="Docker Blog">Blog</a></li>
|
||||||
<li id="nav-index"><a href="http://index.docker.io/" title="Docker Image Index, find images here">INDEX <img class="inline-icon" src="{{ pathto('_static/img/external-link-icon.png', 1) }}" title="external link"> </a></li>
|
<li id="nav-index"><a href="http://index.docker.io/" title="Docker Image Index, find images here">INDEX <img class="inline-icon" alt="link to external site" src="{{ pathto('_static/img/external-link-icon.png', 1) }}" title="external link"> </a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-left: -12px; float: left;">
|
<div class="brand-logo">
|
||||||
<a href="http://www.docker.io" title="Docker Homepage"><img style="margin-top: 0px; height: 60px; width: 160px; margin-left: 10px;" src="{{ pathto('_static/img/docker-top-logo.png', 1) }}"></a>
|
<a href="http://www.docker.io" title="Docker Homepage"><img src="{{ pathto('_static/img/docker-top-logo.png', 1) }}" alt="Docker logo"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="span12 titlebar">
|
|
||||||
<!--<span class="pull-right" style="margin-left: 20px; font-size: 20px">{{version}}</span>-->
|
|
||||||
<div class="pull-right" id="fork-us" style="margin-top: 16px; margin-right: 16px;">
|
|
||||||
<a href="https://github.com/dotcloud/docker/blob/master/docs/sources/{{ pagename }}.rst"><img src="{{ pathto('_static/img/fork-us.png', 1) }}"> Edit this page on Github</a>
|
|
||||||
</div>
|
|
||||||
<h1 class="pageheader"><a href="http://docs.docker.io/en/latest/" title="Documentation" style="color: white;">DOCUMENTATION</a></h1>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<!-- Docs nav
|
<!-- Docs nav
|
||||||
================================================== -->
|
================================================== -->
|
||||||
<div class="row" style="position: relative">
|
<div class="row main-row">
|
||||||
|
|
||||||
<div class="span3 sidebar bs-docs-sidebar">
|
<div class="span3 sidebar bs-docs-sidebar">
|
||||||
|
<div class="page-title" >
|
||||||
|
<h4>DOCUMENTATION</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{ toctree(collapse=False, maxdepth=3) }}
|
{{ toctree(collapse=False, maxdepth=3) }}
|
||||||
<form>
|
<form>
|
||||||
<input type="text" id="st-search-input" class="st-search-input span3" style="width:160px;" />
|
<input type="text" id="st-search-input" class="st-search-input span3" style="width:160px;" />
|
||||||
|
<div id="st-results-container"></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- body block -->
|
<!-- body block -->
|
||||||
<div class="span9">
|
<div class="span9 main-content">
|
||||||
|
|
||||||
<!-- Main section
|
<!-- Main section
|
||||||
================================================== -->
|
================================================== -->
|
||||||
@@ -125,167 +107,100 @@
|
|||||||
{% block body %}{% endblock %}
|
{% block body %}{% endblock %}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Swiftype search -->
|
<div class="pull-right"><a href="https://github.com/dotcloud/docker/blob/{{ current_version }}/docs/sources/{{ pagename }}.rst" title="edit this article">Edit this article on GitHub</a></div>
|
||||||
<div id="st-results-container"></div>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var Swiftype = window.Swiftype || {};
|
|
||||||
(function() {
|
|
||||||
Swiftype.key = 'pWPnnyvwcfpcrw1o51Sz';
|
|
||||||
Swiftype.inputElement = '#st-search-input';
|
|
||||||
Swiftype.resultContainingElement = '#st-results-container';
|
|
||||||
Swiftype.attachElement = '#st-search-input';
|
|
||||||
Swiftype.renderStyle = "overlay";
|
|
||||||
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.type = 'text/javascript';
|
|
||||||
script.async = true;
|
|
||||||
script.src = "//swiftype.com/embed.js";
|
|
||||||
var entry = document.getElementsByTagName('script')[0];
|
|
||||||
entry.parentNode.insertBefore(script, entry);
|
|
||||||
}());
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="footer" class="container" >
|
<div id="push-the-footer"></div>
|
||||||
<div class="row">
|
</div> <!-- end wrap for pushing footer -->
|
||||||
|
|
||||||
<div class="span12 footer">
|
<div id="footer">
|
||||||
<div class="tbox textright forceleftmargin social links pull-right">
|
<div class="footer-landscape">
|
||||||
<a class="twitter" href="http://twitter.com/docker">Twitter</a>
|
<div class="footer-landscape-image">
|
||||||
<a class="github" href="https://github.com/dotcloud/docker/">GitHub</a>
|
<!-- footer -->
|
||||||
|
<div class="container">
|
||||||
|
<div class="row footer">
|
||||||
|
<div class="span12 tbox">
|
||||||
|
<div class="tbox">
|
||||||
|
<p>Docker is an open source project, sponsored by <a href="https://dotcloud.com">dotCloud</a>, under the <a href="https://github.com/dotcloud/docker/blob/master/LICENSE" title="Docker licence, hosted in the Github repository">apache 2.0 licence</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="social links">
|
||||||
|
<a class="twitter" href="http://twitter.com/docker">Twitter</a>
|
||||||
|
<a class="github" href="https://github.com/dotcloud/docker/">GitHub</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tbox version-flyer ">
|
||||||
|
<div class="content">
|
||||||
|
<small>Current version:</small>
|
||||||
|
<ul class="inline">
|
||||||
|
{% for slug, url in versions %}
|
||||||
|
<li class="alternative"><a href="{{ url }}{%- for word in pagename.split('/') -%}
|
||||||
|
{%- if word != 'index' -%}
|
||||||
|
{%- if word != '' -%}
|
||||||
|
{{ word }}/
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}"
|
||||||
|
title="Switch to {{ slug }}">{{ slug }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Docker is a project by <a href="http://www.dotcloud.com">dotCloud</a>
|
|
||||||
|
|
||||||
|
|
||||||
{# {%- if show_source and has_source and sourcename %}#}
|
|
||||||
{# ·#}
|
|
||||||
{# <a href="{{ pathto('_sources/' + sourcename, true)|e }}"#}
|
|
||||||
{# rel="nofollow">View the RST source of this page</a>#}
|
|
||||||
{# {%- endif %}#}
|
|
||||||
{# {%- if pagename != "search" %}#}
|
|
||||||
|
|
||||||
{#TODO: Make a proper location for the search #}
|
|
||||||
{# Search:#}
|
|
||||||
{# <form#}
|
|
||||||
{# style="display: inline;"#}
|
|
||||||
{# class="search" action="{{ pathto('search') }}" method="get">#}
|
|
||||||
{# <input type="text" name="q" size="18" />#}
|
|
||||||
{# <input type="hidden" name="check_keywords" value="yes" />#}
|
|
||||||
{# <input type="hidden" name="area" value="default" />#}
|
|
||||||
{# </form>#}
|
|
||||||
{# {%- endif %}#}
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- end of footer -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- script which should be loaded after everything else -->
|
<script type="text/javascript" src="{{ pathto('_static/js/docs.js', 1) }}"></script>
|
||||||
|
|
||||||
|
<!-- Swiftype search -->
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
var Swiftype = window.Swiftype || {};
|
||||||
|
(function() {
|
||||||
|
Swiftype.key = 'pWPnnyvwcfpcrw1o51Sz';
|
||||||
|
Swiftype.inputElement = '#st-search-input';
|
||||||
|
Swiftype.resultContainingElement = '#st-results-container';
|
||||||
|
Swiftype.attachElement = '#st-search-input';
|
||||||
|
Swiftype.renderStyle = "overlay";
|
||||||
|
// from https://swiftype.com/questions/how-can-i-make-more-popular-content-rank-higher
|
||||||
|
// Use "page" for now -- they don't subgroup by document type yet.
|
||||||
|
Swiftype.searchFunctionalBoosts = {"page": {"popularity": "linear"}};
|
||||||
|
|
||||||
// Function to make the sticky header possible
|
var script = document.createElement('script');
|
||||||
var shiftWindow = function() {
|
script.type = 'text/javascript';
|
||||||
scrollBy(0, -70);
|
script.async = true;
|
||||||
console.log("window shifted")
|
script.src = "//swiftype.com/embed.js";
|
||||||
};
|
var entry = document.getElementsByTagName('script')[0];
|
||||||
window.addEventListener("hashchange", shiftWindow);
|
entry.parentNode.insertBefore(script, entry);
|
||||||
|
}());
|
||||||
function loadShift() {
|
|
||||||
if (window.location.hash) {
|
|
||||||
console.log("window has hash");
|
|
||||||
shiftWindow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(window).load(function() {
|
|
||||||
loadShift();
|
|
||||||
console.log("late loadshift");
|
|
||||||
});
|
|
||||||
|
|
||||||
$(function(){
|
|
||||||
|
|
||||||
// sidebar accordian-ing
|
|
||||||
// don't apply on last object (it should be the FAQ)
|
|
||||||
|
|
||||||
// define an array to which all opened items should be added
|
|
||||||
var openmenus = [];
|
|
||||||
|
|
||||||
var elements = $('.toctree-l2');
|
|
||||||
for (var i = 0; i < elements.length; i += 1) { var current = $(elements[i]); current.children('ul').hide();}
|
|
||||||
|
|
||||||
|
|
||||||
// set initial collapsed state
|
|
||||||
var elements = $('.toctree-l1');
|
|
||||||
for (var i = 0; i < elements.length; i += 1) {
|
|
||||||
var current = $(elements[i]);
|
|
||||||
if (current.hasClass('current')) {
|
|
||||||
|
|
||||||
currentlink = current.children('a')[0].href;
|
|
||||||
openmenus.push(currentlink);
|
|
||||||
|
|
||||||
// do nothing
|
|
||||||
} else {
|
|
||||||
// collapse children
|
|
||||||
current.children('ul').hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// attached handler on click
|
|
||||||
// Do not attach to first element or last (intro, faq) so that
|
|
||||||
// first and last link directly instead of accordian
|
|
||||||
$('.sidebar > ul > li > a').not(':last').not(':first').click(function(){
|
|
||||||
|
|
||||||
var index = $.inArray(this.href, openmenus)
|
|
||||||
|
|
||||||
if (index > -1) {
|
|
||||||
console.log(index);
|
|
||||||
openmenus.splice(index, 1);
|
|
||||||
|
|
||||||
|
|
||||||
$(this).parent().children('ul').slideUp(200, function() {
|
|
||||||
// $(this).parent().removeClass('current'); // toggle after effect
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
openmenus.push(this.href);
|
|
||||||
console.log(this);
|
|
||||||
|
|
||||||
var current = $(this);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
$('.sidebar > ul > li').removeClass('current');
|
|
||||||
current.parent().addClass('current'); // toggle before effect
|
|
||||||
current.parent().children('ul').hide();
|
|
||||||
current.parent().children('ul').slideDown(200);
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Google analytics -->
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var _gaq = _gaq || [];
|
<!-- Google analytics -->
|
||||||
_gaq.push(['_setAccount', 'UA-6096819-11']);
|
<script type="text/javascript">
|
||||||
_gaq.push(['_setDomainName', 'docker.io']);
|
|
||||||
_gaq.push(['_setAllowLinker', true]);
|
|
||||||
_gaq.push(['_trackPageview']);
|
|
||||||
|
|
||||||
(function() {
|
var _gaq = _gaq || [];
|
||||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
_gaq.push(['_setAccount', 'UA-6096819-11']);
|
||||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
_gaq.push(['_setDomainName', 'docker.io']);
|
||||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
_gaq.push(['_setAllowLinker', true]);
|
||||||
})();
|
_gaq.push(['_trackPageview']);
|
||||||
|
|
||||||
</script>
|
(function() {
|
||||||
|
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||||
|
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||||
|
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||||
|
})();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,280 +1,205 @@
|
|||||||
/* ==========================================================================
|
.debug {
|
||||||
Author's custom styles
|
border: 2px dotted red !important;
|
||||||
========================================================================== */
|
box-sizing: border-box;
|
||||||
.red {
|
-moz-box-sizing: border-box;
|
||||||
background-color: red;
|
|
||||||
}
|
|
||||||
.blue {
|
|
||||||
background-color: blue;
|
|
||||||
}
|
|
||||||
.orange {
|
|
||||||
background-color: orange;
|
|
||||||
}
|
|
||||||
.gray {
|
|
||||||
background-color: grey;
|
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
padding-top: 58px;
|
min-width: 940px;
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: "Cabin", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
h1,
|
p a {
|
||||||
h2,
|
text-decoration: underline;
|
||||||
h3,
|
|
||||||
h4 {
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
}
|
||||||
/* ===================
|
p a.btn {
|
||||||
Top navigation
|
text-decoration: none;
|
||||||
===================== */
|
}
|
||||||
.navbar {
|
.brand.logo a {
|
||||||
z-index: 999;
|
text-decoration: none;
|
||||||
background-color: white;
|
}
|
||||||
|
.navbar .navbar-inner {
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
}
|
}
|
||||||
.navbar .nav li a {
|
.navbar .nav li a {
|
||||||
padding: 22px 15px 22px;
|
padding: 24.2857142855px 17px 24.2857142855px;
|
||||||
|
color: #777777;
|
||||||
|
text-decoration: none;
|
||||||
|
text-shadow: 0 1px 0 #f2f2f2;
|
||||||
}
|
}
|
||||||
.navbar-dotcloud .container {
|
.navbar .nav > li {
|
||||||
border-bottom: 2px #000000 solid;
|
float: left;
|
||||||
|
}
|
||||||
|
.nav-underline {
|
||||||
|
height: 6px;
|
||||||
|
background-color: #71afc0;
|
||||||
|
}
|
||||||
|
.nav-login li a {
|
||||||
|
color: white;
|
||||||
|
padding: 10px 15px 10px;
|
||||||
|
}
|
||||||
|
.navbar .brand {
|
||||||
|
margin-left: 0px;
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.navbar-inner {
|
||||||
|
min-height: 70px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
background-color: #ededed;
|
||||||
|
background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
|
||||||
|
background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
|
||||||
|
background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
|
||||||
|
background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
|
||||||
|
border: 1px solid #c7c7c7;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||||
|
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||||
|
}
|
||||||
|
.brand.logo a {
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
.inline-icon {
|
.inline-icon {
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
/*
|
.row {
|
||||||
* Responsive YouTube, Vimeo, Embed, and HTML5 Videos with CSS
|
|
||||||
* http://www.jonsuh.com
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 Jonathan Suh
|
|
||||||
* Free to use under the MIT license.
|
|
||||||
* http://www.opensource.org/licenses/mit-license.php
|
|
||||||
*/
|
|
||||||
.js-video {
|
|
||||||
height: 0;
|
|
||||||
padding-top: 25px;
|
|
||||||
padding-bottom: 67.5%;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.js-video.vimeo {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
.js-video.widescreen {
|
|
||||||
padding-bottom: 57.25%;
|
|
||||||
}
|
|
||||||
.js-video embed,
|
|
||||||
.js-video iframe,
|
|
||||||
.js-video object,
|
|
||||||
.js-video video {
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
/* Responsive */
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
.js-video {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* button style from http://charliepark.org/bootstrap_buttons/ */
|
|
||||||
.btn-custom {
|
|
||||||
background-color: #292929 !important;
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#515151", endColorstr="#282828");
|
|
||||||
background-image: -khtml-gradient(linear, left top, left bottom, from(#515151), to(#282828));
|
|
||||||
background-image: -moz-linear-gradient(top, #515151, #282828);
|
|
||||||
background-image: -ms-linear-gradient(top, #515151, #282828);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #515151), color-stop(100%, #282828));
|
|
||||||
background-image: -webkit-linear-gradient(top, #515151, #282828);
|
|
||||||
background-image: -o-linear-gradient(top, #515151, #282828);
|
|
||||||
background-image: linear-gradient(#515151, #282828);
|
|
||||||
border-color: #282828 #282828 #1f1f1f;
|
|
||||||
color: #fff !important;
|
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.26);
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
}
|
|
||||||
/* ===================
|
|
||||||
Page title bar
|
|
||||||
===================== */
|
|
||||||
h1.pageheader {
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 20px;
|
|
||||||
font-family: "Arial Black", Tahoma, sans-serif;
|
|
||||||
margin: 8px;
|
|
||||||
margin-left: 22px;
|
|
||||||
}
|
|
||||||
/* ===================
|
|
||||||
Hero unit
|
|
||||||
===================== */
|
|
||||||
section.header {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
.hero-unit {
|
|
||||||
background-color: #292e33;
|
|
||||||
}
|
|
||||||
.hero-unit h5 {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
/* ===================
|
|
||||||
Main content layout
|
|
||||||
===================== */
|
|
||||||
.contentblock {
|
|
||||||
margin-top: 20px;
|
|
||||||
border-width: 3px;
|
|
||||||
background-color: #eeeeee;
|
|
||||||
box-sizing: content-box;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
.section img {
|
|
||||||
margin: 15px 15px 15px 0;
|
|
||||||
border: 2px solid gray;
|
|
||||||
}
|
|
||||||
.admonition {
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid grey;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
margin-top: 10px;
|
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.admonition .admonition-title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.admonition.note {
|
|
||||||
background-color: #f1ebba;
|
|
||||||
}
|
|
||||||
.admonition.warning {
|
|
||||||
background-color: #eed9af;
|
|
||||||
}
|
|
||||||
.admonition.danger {
|
|
||||||
background-color: #e9bcab;
|
|
||||||
}
|
|
||||||
/* ===================
|
|
||||||
left navigation
|
|
||||||
===================== */
|
|
||||||
.dotcloudsidebar {
|
|
||||||
float: left;
|
|
||||||
height: 100%;
|
|
||||||
top: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
position: relative;
|
|
||||||
min-height: 100%;
|
|
||||||
margin-top: 78px;
|
|
||||||
margin-bottom: 22px;
|
|
||||||
}
|
|
||||||
.sidebar {
|
|
||||||
font-weight: normal;
|
|
||||||
float: left;
|
|
||||||
/* min-height: 475px;*/
|
|
||||||
|
|
||||||
background: #ececec;
|
|
||||||
/* border-left: 1px solid #bbbbbb;*/
|
|
||||||
|
|
||||||
/* border-right: 1px solid #cccccc;*/
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.sidebar ul {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
.sidebar ul li {
|
|
||||||
font-size: 14px;
|
|
||||||
list-style-type: none;
|
|
||||||
list-style-position: outside;
|
|
||||||
list-style-image: none;
|
|
||||||
margin-left: -25px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
.sidebar ul li a {
|
|
||||||
display: block;
|
|
||||||
color: #443331;
|
|
||||||
outline: 1px solid #dddddd;
|
|
||||||
padding: 12px 12px 10px 12px;
|
|
||||||
margin-top: 1px;
|
|
||||||
background-color: #d2d2d2;
|
|
||||||
}
|
|
||||||
.sidebar ul li .toctree-l1 {
|
|
||||||
font-size: larger;
|
|
||||||
}
|
|
||||||
.sidebar ul li .toctree-l1 a {
|
|
||||||
background-color: #dfdfdf;
|
|
||||||
}
|
|
||||||
.sidebar ul li .toctree-l1 .current {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.sidebar ul li .toctree-l2 a {
|
|
||||||
padding-left: 18px;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
.sidebar ul li .toctree-l2 .current {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.sidebar ul li .toctree-l3 {
|
|
||||||
font-size: smaller;
|
|
||||||
}
|
|
||||||
.sidebar ul li .toctree-l3 a {
|
|
||||||
padding-left: 36px;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
.sidebar ul li .toctree-l3 .current {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.brand img {
|
|
||||||
height: 38px;
|
|
||||||
margin-left: -6px;
|
|
||||||
}
|
|
||||||
.border-box {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 20px;
|
|
||||||
background-color: #111188;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.titlebar {
|
|
||||||
background-color: #000000;
|
|
||||||
margin-top: 0px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
min-height: 40px;
|
|
||||||
color: white;
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
}
|
|
||||||
.footer {
|
|
||||||
border-top: 2px solid black;
|
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 15px;
|
||||||
min-height: 40px;
|
|
||||||
padding-left: 8px;
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
}
|
}
|
||||||
/* This is the default */
|
div[class*='span'] {
|
||||||
.span6.with-padding {
|
-moz-box-sizing: border-box;
|
||||||
background-color: #111188;
|
box-sizing: border-box;
|
||||||
height: 200px;
|
|
||||||
color: white;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
}
|
||||||
#global {
|
.box {
|
||||||
min-height: 500px;
|
padding: 30px;
|
||||||
|
background-color: white;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
.paper {
|
||||||
|
background-color: white;
|
||||||
|
padding-top: 30px;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
}
|
||||||
|
.copy-headline {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
.box h1,
|
||||||
|
.box h2,
|
||||||
|
.box h3,
|
||||||
|
.box h4 {
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
.nested {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.box.div {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
span.read-more {
|
||||||
|
margin-left: 15px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.forcetopalign {
|
||||||
|
margin-top: 15px !important;
|
||||||
|
}
|
||||||
|
.forcetopmargin {
|
||||||
|
margin-top: 23px !important;
|
||||||
|
}
|
||||||
|
.forceleftalign {
|
||||||
|
margin-left: 15px !important;
|
||||||
|
}
|
||||||
|
.forceleftmargin {
|
||||||
|
margin-left: 21px !important;
|
||||||
|
}
|
||||||
|
.textcenter {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.textright {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.textsmaller {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.modal-backdrop {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
/* generic page copy styles */
|
||||||
|
.copy-headline h1 {
|
||||||
|
font-size: 21px;
|
||||||
}
|
}
|
||||||
/* =======================
|
/* =======================
|
||||||
Row size
|
Sticky footer
|
||||||
======================= */
|
======================= */
|
||||||
.row1 {
|
html,
|
||||||
background-color: #999999;
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
/* The html and body elements cannot have any padding or margin. */
|
||||||
|
|
||||||
|
}
|
||||||
|
/* Wrapper for page content to push down footer */
|
||||||
|
#wrap {
|
||||||
|
min-height: 100%;
|
||||||
|
height: auto !important;
|
||||||
|
height: 100%;
|
||||||
|
/* Negative indent footer by it's height */
|
||||||
|
|
||||||
|
margin: 0 auto -280px;
|
||||||
|
}
|
||||||
|
/* Set the fixed height of the footer here */
|
||||||
|
#push-the-footer,
|
||||||
|
#footer {
|
||||||
|
height: 280px;
|
||||||
|
}
|
||||||
|
.main-row {
|
||||||
|
padding-top: 50px;
|
||||||
|
}
|
||||||
|
#footer .footer {
|
||||||
|
margin-top: 160px;
|
||||||
|
}
|
||||||
|
#footer .footer .ligaturesymbols {
|
||||||
|
font-size: 30px;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
#footer .footer .ligaturesymbols a {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
#footer .footer .footerlist h3,
|
||||||
|
#footer .footer .footerlist h4 {
|
||||||
|
/* correct the top alignment */
|
||||||
|
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
.footer-landscape-image {
|
||||||
|
position: absolute:
|
||||||
|
bottom: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
background-image: url('https://www.docker.io/static/img/website-footer_clean.svg');
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
height: 280px;
|
||||||
|
}
|
||||||
|
.main-row {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
.main-content {
|
||||||
|
padding: 16px 18px inherit;
|
||||||
}
|
}
|
||||||
/* =======================
|
/* =======================
|
||||||
Social footer
|
Social footer
|
||||||
======================= */
|
======================= */
|
||||||
|
.social {
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
.social .twitter,
|
.social .twitter,
|
||||||
.social .github,
|
.social .github,
|
||||||
.social .googleplus {
|
.social .googleplus {
|
||||||
background: url("../img/footer-links.png") no-repeat transparent;
|
background: url("https://www.docker.io/static/img/footer-links.png") no-repeat transparent;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -288,93 +213,160 @@ section.header {
|
|||||||
.social .github {
|
.social .github {
|
||||||
background-position: -59px 2px;
|
background-position: -59px 2px;
|
||||||
}
|
}
|
||||||
#fork-us {
|
form table th {
|
||||||
/*font-family: 'Maven Pro';*/
|
vertical-align: top;
|
||||||
|
text-align: right;
|
||||||
/*font-weight: bold;*/
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
form .labeldd label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
form .helptext {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
/*text-transform: uppercase;*/
|
margin-top: -4px;
|
||||||
|
margin-bottom: 10px;
|
||||||
display: block;
|
|
||||||
padding: 0px 1em;
|
|
||||||
height: 28px;
|
|
||||||
line-height: 28px;
|
|
||||||
background-color: #43484c;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFF6E56', endColorstr='#FFED4F35');
|
|
||||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #747474), color-stop(100%, #43484c));
|
|
||||||
background-image: -webkit-linear-gradient(top, #747474 0%, #43484c 100%);
|
|
||||||
background-image: -moz-linear-gradient(top, #747474 0%, #43484c 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #747474 0%, #43484c 100%);
|
|
||||||
background-image: linear-gradient(top, #747474 0%, #43484c 100%);
|
|
||||||
border: 1px solid #43484c;
|
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
-ms-border-radius: 4px;
|
|
||||||
-o-border-radius: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
-webkit-box-shadow: inset rgba(255, 255, 255, 0.17) 0 1px 1px;
|
|
||||||
-moz-box-shadow: inset rgba(255, 255, 255, 0.17) 0 1px 1px;
|
|
||||||
box-shadow: inset rgba(255, 255, 255, 0.17) 0 1px 1px;
|
|
||||||
margin: 8px;
|
|
||||||
}
|
}
|
||||||
#fork-us a {
|
form .fielddd input {
|
||||||
color: #faf2ee;
|
width: 250px;
|
||||||
text-shadow: rgba(0, 0, 0, 0.3) 0px 1px 0px;
|
|
||||||
}
|
}
|
||||||
|
form .error {
|
||||||
|
color: #a30000;
|
||||||
|
}
|
||||||
|
div.alert.alert-block {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
/* ======================= =======================
|
||||||
|
Documentation
|
||||||
|
========================= ========================= */
|
||||||
/* =======================
|
/* =======================
|
||||||
Media size overrides
|
Styles for the sidebar
|
||||||
======================= */
|
========================= */
|
||||||
/* Large desktop */
|
.page-title {
|
||||||
@media (min-width: 1200px) {
|
background-color: white;
|
||||||
.span6.with-padding {
|
border: 1px solid transparent;
|
||||||
background-color: #dc143c;
|
text-align: center;
|
||||||
width: 540px;
|
width: 100%;
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Normal desktop */
|
.page-title h4 {
|
||||||
@media (min-width: 980px) and (max-width: 1199px) {
|
font-size: 20px;
|
||||||
.span6.with-padding {
|
|
||||||
background-color: #ee1111;
|
|
||||||
width: 440px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Portrait tablet to landscape and desktop */
|
.bs-docs-sidebar {
|
||||||
@media (min-width: 768px) and (max-width: 979px) {
|
padding-left: 5px;
|
||||||
body {
|
max-width: 100%;
|
||||||
padding-top: 0px;
|
box-sizing: border-box;
|
||||||
}
|
-moz-box-sizing: border-box;
|
||||||
.span6.with-padding {
|
margin-top: 18px;
|
||||||
background-color: #292e33;
|
|
||||||
width: 332px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Landscape phone to portrait tablet */
|
.bs-docs-sidebar ul {
|
||||||
@media (max-width: 767px) {
|
list-style: none;
|
||||||
body {
|
margin-left: 0px;
|
||||||
padding-top: 0px;
|
|
||||||
}
|
|
||||||
#global {
|
|
||||||
/* TODO: Fix this to be relative to the navigation size */
|
|
||||||
|
|
||||||
}
|
|
||||||
#fork-us {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Landscape phones and down */
|
.bs-docs-sidebar .toctree-l2 > ul {
|
||||||
@media (max-width: 480px) {
|
width: 100%;
|
||||||
#nav-gettingstarted {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Misc fixes */
|
.bs-docs-sidebar ul > li.toctree-l1.has-children {
|
||||||
table th {
|
background-image: url('../img/menu_arrow_right.gif');
|
||||||
text-align: left;
|
background-repeat: no-repeat;
|
||||||
|
background-position: 13px 13px;
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0px 0px 0px 0px;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
.bs-docs-sidebar ul > li.toctree-l1.has-children.open {
|
||||||
|
background-image: url('../img/menu_arrow_down.gif');
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar ul > li > a {
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
padding-left: 35px;
|
||||||
|
padding-right: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-bottom: 1.5px solid #595959;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar ul > li:first-child.active > a {
|
||||||
|
border-top: 1.5px solid #595959;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar ul > li:last-child > a {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar ul > li:last-child.active > a {
|
||||||
|
border-bottom: 1.5px solid #595959;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar ul > li.active > a {
|
||||||
|
border-right: 1.5px solid #595959;
|
||||||
|
border-left: 1.5px solid #595959;
|
||||||
|
color: #394d54;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar ul > li:hover {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar.toctree-l3 ul {
|
||||||
|
display: inherit;
|
||||||
|
margin-left: 15px;
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar .toctree-l3 a {
|
||||||
|
border: none;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 15px;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar ul > li > ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.bs-docs-sidebar ul > li.current > ul {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.toctree-l2.current > a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.toctree-l2.current {
|
||||||
|
border: 1.5px solid #595959;
|
||||||
|
color: #394d54;
|
||||||
|
}
|
||||||
|
/* =====================================
|
||||||
|
Styles for the floating version widget
|
||||||
|
====================================== */
|
||||||
|
.version-flyer {
|
||||||
|
position: fixed;
|
||||||
|
float: right;
|
||||||
|
right: 0;
|
||||||
|
bottom: 40px;
|
||||||
|
background-color: #E0E0E0;
|
||||||
|
border: 1px solid #88BABC;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
.version-flyer .content {
|
||||||
|
padding-right: 45px;
|
||||||
|
margin-top: 7px;
|
||||||
|
margin-left: 7px;
|
||||||
|
background-image: url('../img/container3.png');
|
||||||
|
background-position: right center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
.version-flyer .alternative {
|
||||||
|
visibility: hidden;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.version-flyer .active-slug {
|
||||||
|
visibility: visible;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.version-flyer:hover .alternative {
|
||||||
|
animation-duration: 1s;
|
||||||
|
display: inline-block;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
/* =====================================
|
||||||
|
Styles for
|
||||||
|
====================================== */
|
||||||
h1:hover > a.headerlink,
|
h1:hover > a.headerlink,
|
||||||
h2:hover > a.headerlink,
|
h2:hover > a.headerlink,
|
||||||
h3:hover > a.headerlink,
|
h3:hover > a.headerlink,
|
||||||
@@ -391,21 +383,30 @@ dt:hover > a.headerlink {
|
|||||||
float: right;
|
float: right;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
/* =====================================
|
||||||
/* Swiftype style */
|
Miscellaneous information
|
||||||
|
====================================== */
|
||||||
#st-search-input {
|
.admonition.warning,
|
||||||
margin-right: 14px;
|
.admonition.note,
|
||||||
margin-left: 9px;
|
.admonition.seealso,
|
||||||
height: 19px;
|
.admonition.todo {
|
||||||
width: 120px;
|
border: 3px solid black;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 5px auto 10px;
|
||||||
|
}
|
||||||
|
.admonition .admonition-title {
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
.admonition.warning,
|
||||||
|
.admonition.danger {
|
||||||
|
border-color: #ac0004;
|
||||||
|
}
|
||||||
|
.admonition.note {
|
||||||
|
border-color: #cbc200;
|
||||||
|
}
|
||||||
|
.admonition.todo {
|
||||||
|
border-color: orange;
|
||||||
|
}
|
||||||
|
.admonition.seealso {
|
||||||
|
border-color: #23cb1f;
|
||||||
}
|
}
|
||||||
#swiftype-img {
|
|
||||||
border: none;
|
|
||||||
width: 145px;
|
|
||||||
height: auto;
|
|
||||||
margin: 0px auto;
|
|
||||||
margin-left: 13px;
|
|
||||||
margin-top: -30px;
|
|
||||||
}
|
|
||||||
@@ -1,376 +1,337 @@
|
|||||||
|
// Main CSS configuration file
|
||||||
|
// by Thatcher Peskens, thatcher@dotcloud.com
|
||||||
|
//
|
||||||
|
// Please note variables.less is customized to include custom font, background-color, and link colors.
|
||||||
|
|
||||||
|
|
||||||
/* ==========================================================================
|
|
||||||
Author's custom styles
|
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
@import "variables.less";
|
@import "variables.less";
|
||||||
|
|
||||||
@red: crimson;
|
// Variables for main.less
|
||||||
@lightblue: #118;
|
// -----------------------
|
||||||
@lightred: #e11;
|
|
||||||
@darkblue: #292E33;
|
|
||||||
|
|
||||||
@borderGray: #888;
|
@box-top-margin: 8px;
|
||||||
|
@box-padding-size: 30px;
|
||||||
|
@docker-background-color: #71AFC0;
|
||||||
|
@very-dark-sea-green: #394D54;
|
||||||
|
|
||||||
|
// Custom colors for Docker
|
||||||
|
// --------------------------
|
||||||
|
@gray-super-light: #F2F2F2;
|
||||||
|
@deep-red: #A30000;
|
||||||
|
@deep-blue: #1B2033;
|
||||||
|
@deep-green: #007035;
|
||||||
|
@link-blue: #213B8F;
|
||||||
|
|
||||||
|
|
||||||
.red {
|
.debug {
|
||||||
background-color: red;
|
border: 2px dotted red !important;
|
||||||
}
|
box-sizing: border-box;
|
||||||
.blue {
|
-moz-box-sizing: border-box;
|
||||||
background-color: blue;
|
|
||||||
}
|
|
||||||
.orange {
|
|
||||||
background-color: orange;
|
|
||||||
}
|
|
||||||
.gray {
|
|
||||||
background-color: grey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Other custom colors for Docker
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
|
// ** are defined in sources/less/variables **
|
||||||
|
//@import "bootstrap/variables.less";
|
||||||
|
|
||||||
|
|
||||||
|
// Styles generic for each and every page
|
||||||
|
// ----------------------------------- // -----------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// moving body down to make place for fixed navigation
|
||||||
body {
|
body {
|
||||||
padding-top: 58px;
|
min-width: 940px;
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: @font-family-base;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
h1, h2, h3, h4 {
|
p a {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
text-decoration: underline;
|
||||||
// font-weight: bold;
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================
|
&.btn {
|
||||||
Top navigation
|
text-decoration: none;
|
||||||
===================== */
|
|
||||||
|
|
||||||
.navbar {
|
|
||||||
z-index: 999;
|
|
||||||
.nav {
|
|
||||||
// float: right;
|
|
||||||
|
|
||||||
li a{
|
|
||||||
padding: 22px 15px 22px;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
background-color: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-dotcloud .container {
|
.brand.logo a {
|
||||||
border-bottom: 2px @black solid;
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styles for top navigation
|
||||||
|
// ----------------------------------
|
||||||
|
.navbar .navbar-inner {
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .nav {
|
||||||
|
li a {
|
||||||
|
padding: ((@navbar-height - @line-height-base) / 2) 17px ((@navbar-height - @line-height-base) / 2);
|
||||||
|
color: #777777;
|
||||||
|
text-decoration: none;
|
||||||
|
text-shadow: 0 1px 0 #f2f2f2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.navbar .nav > li {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-underline {
|
||||||
|
height: 6px;
|
||||||
|
background-color: @docker-background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-login {
|
||||||
|
li {
|
||||||
|
a {
|
||||||
|
color: white;
|
||||||
|
padding: 10px 15px 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.navbar .brand {
|
||||||
|
margin-left: 0px;
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-inner {
|
||||||
|
min-height: 70px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
background-color: #ededed;
|
||||||
|
background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
|
||||||
|
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
|
||||||
|
background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
|
||||||
|
background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
|
||||||
|
background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
|
||||||
|
border: 1px solid #c7c7c7;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||||
|
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand.logo a {
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
// background-color: #A30000;
|
||||||
|
// color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inline-icon {
|
.inline-icon {
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Bootstrap elements
|
||||||
* Responsive YouTube, Vimeo, Embed, and HTML5 Videos with CSS
|
// ----------------------------------
|
||||||
* http://www.jonsuh.com
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 Jonathan Suh
|
|
||||||
* Free to use under the MIT license.
|
|
||||||
* http://www.opensource.org/licenses/mit-license.php
|
|
||||||
*/
|
|
||||||
|
|
||||||
.js-video {
|
.row {
|
||||||
height: 0;
|
|
||||||
padding-top: 25px;
|
|
||||||
padding-bottom: 67.5%;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.js-video.vimeo {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
.js-video.widescreen {
|
|
||||||
padding-bottom: 57.25%;
|
|
||||||
}
|
|
||||||
.js-video embed, .js-video iframe, .js-video object, .js-video video {
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive */
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
.js-video {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* button style from http://charliepark.org/bootstrap_buttons/ */
|
|
||||||
.btn-custom {
|
|
||||||
background-color: hsl(0, 0%, 16%) !important;
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#515151", endColorstr="#282828");
|
|
||||||
background-image: -khtml-gradient(linear, left top, left bottom, from(#515151), to(#282828));
|
|
||||||
background-image: -moz-linear-gradient(top, #515151, #282828);
|
|
||||||
background-image: -ms-linear-gradient(top, #515151, #282828);
|
|
||||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #515151), color-stop(100%, #282828));
|
|
||||||
background-image: -webkit-linear-gradient(top, #515151, #282828);
|
|
||||||
background-image: -o-linear-gradient(top, #515151, #282828);
|
|
||||||
background-image: linear-gradient(#515151, #282828);
|
|
||||||
border-color: #282828 #282828 hsl(0, 0%, 12%);
|
|
||||||
color: #fff !important;
|
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.26);
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ===================
|
|
||||||
Page title bar
|
|
||||||
===================== */
|
|
||||||
|
|
||||||
h1.pageheader {
|
|
||||||
color: @white;
|
|
||||||
font-size: 20px;
|
|
||||||
font-family: "Arial Black", Tahoma, sans-serif;
|
|
||||||
margin: 8px;
|
|
||||||
margin-left: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================
|
|
||||||
Hero unit
|
|
||||||
===================== */
|
|
||||||
|
|
||||||
section.header {
|
|
||||||
margin-top:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-unit {
|
|
||||||
background-color: @darkblue;
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
color: @white;
|
|
||||||
}
|
|
||||||
.subtitle {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================
|
|
||||||
Main content layout
|
|
||||||
===================== */
|
|
||||||
|
|
||||||
.contentblock {
|
|
||||||
margin-top: 20px;
|
|
||||||
border-width: 3px;
|
|
||||||
// border-color: #E00;
|
|
||||||
// border-style:solid;
|
|
||||||
// border-color: @borderGray;
|
|
||||||
// box-sizing: border-box;
|
|
||||||
background-color: @grayLighter;
|
|
||||||
box-sizing: content-box;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section img {
|
|
||||||
margin: 15px 15px 15px 0;
|
|
||||||
border: 2px solid gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admonition {
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid grey;
|
|
||||||
|
|
||||||
margin-bottom: 10px;
|
|
||||||
margin-top: 10px;
|
|
||||||
|
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admonition .admonition-title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admonition.note {
|
|
||||||
background-color: rgb(241, 235, 186);
|
|
||||||
}
|
|
||||||
|
|
||||||
.admonition.warning {
|
|
||||||
background-color: rgb(238, 217, 175);
|
|
||||||
}
|
|
||||||
|
|
||||||
.admonition.danger {
|
|
||||||
background-color: rgb(233, 188, 171);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===================
|
|
||||||
left navigation
|
|
||||||
===================== */
|
|
||||||
|
|
||||||
.dotcloudsidebar {
|
|
||||||
// background-color: #ee3;
|
|
||||||
// border: 1px red dotted;
|
|
||||||
float: left;
|
|
||||||
height: 100%;
|
|
||||||
top: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
position: relative;
|
|
||||||
// margin: 0px;
|
|
||||||
min-height: 100%;
|
|
||||||
margin-top: 78px;
|
|
||||||
margin-bottom: 22px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
// font-family: "Maven Pro";
|
|
||||||
font-weight: normal;
|
|
||||||
// margin-top: 38px;
|
|
||||||
float: left;
|
|
||||||
// width: 220px;
|
|
||||||
/* min-height: 475px;*/
|
|
||||||
// margin-bottom: 28px;
|
|
||||||
// padding-bottom: 120px;
|
|
||||||
background: #ececec;
|
|
||||||
/* border-left: 1px solid #bbbbbb;*/
|
|
||||||
/* border-right: 1px solid #cccccc;*/
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ul {
|
|
||||||
padding: 0px;
|
|
||||||
li {
|
|
||||||
font-size: 14px;
|
|
||||||
// list-style: none;
|
|
||||||
list-style-type: none;
|
|
||||||
list-style-position: outside;
|
|
||||||
list-style-image: none;
|
|
||||||
margin-left: -25px;
|
|
||||||
padding: 0px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: block;
|
|
||||||
color: #443331;
|
|
||||||
outline: 1px solid #dddddd;
|
|
||||||
padding: 12px 12px 10px 12px;
|
|
||||||
margin-top: 1px;
|
|
||||||
background-color: #d2d2d2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toctree-l1, .toctree-l2 {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.toctree-l1 {
|
|
||||||
font-size: larger;
|
|
||||||
a {
|
|
||||||
background-color: rgb(223, 223, 223);
|
|
||||||
}
|
|
||||||
.current {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
// margin-left: -25px;
|
|
||||||
}
|
|
||||||
.toctree-l2 {
|
|
||||||
a {
|
|
||||||
padding-left: 18px;
|
|
||||||
background-color: rgb(255, 255, 255);
|
|
||||||
}
|
|
||||||
.current {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.toctree-l3 {
|
|
||||||
font-size: smaller;
|
|
||||||
a {
|
|
||||||
padding-left: 36px;
|
|
||||||
background-color: rgb(255, 255, 255);
|
|
||||||
}
|
|
||||||
.current {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand img {
|
|
||||||
height: 38px;
|
|
||||||
margin-left: -6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border-box {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 20px;
|
|
||||||
background-color: @lightblue;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.titlebar {
|
|
||||||
background-color: @black;
|
|
||||||
margin-top: 0px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
min-height: 40px;
|
|
||||||
color: white;
|
|
||||||
// box-sizing: border-box;
|
|
||||||
padding-top: 8px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
border-top: 2px solid black;
|
|
||||||
|
|
||||||
// background-color: #d2d2d2;
|
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
min-height: 40px;
|
.container {
|
||||||
|
// background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
padding-left: 8px;
|
// Styles on blocks of content
|
||||||
padding-top: 8px;
|
// ----------------------------------
|
||||||
padding-bottom: 8px;
|
|
||||||
|
// everything which is a block should have box-sizing: border-box;
|
||||||
|
|
||||||
|
div[class*='span']
|
||||||
|
{
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Box for making white with a border, and some nice spacings
|
||||||
/* This is the default */
|
.box {
|
||||||
.span6.with-padding {
|
padding: @box-padding-size;
|
||||||
background-color: @lightblue;
|
background-color: white;
|
||||||
height: 200px;
|
margin-top: @box-top-margin;
|
||||||
color: white;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#global {
|
.paper {
|
||||||
min-height: 500px;
|
background-color: white;
|
||||||
|
padding-top: 30px;
|
||||||
|
padding-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.copy-headline {
|
||||||
|
margin-top: 0px;
|
||||||
|
// border-bottom: 1.2px solid @veryDarkSeaGreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
h1, h2, h3, h4 {
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nested {
|
||||||
|
padding: @box-padding-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box.div {
|
||||||
|
padding: @box-padding-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.read-more {
|
||||||
|
margin-left: 15px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set a top margin of @box-top-margin + 8 px to make it show a margin
|
||||||
|
//instead of the div being flush against the side. Typically only
|
||||||
|
// required for a stacked div in a column, w.o. using row.
|
||||||
|
.forcetopalign {
|
||||||
|
margin-top: 15px !important;
|
||||||
|
}
|
||||||
|
.forcetopmargin {
|
||||||
|
margin-top: 23px !important;
|
||||||
|
}
|
||||||
|
.forceleftalign {
|
||||||
|
margin-left: 15px !important;
|
||||||
|
}
|
||||||
|
.forceleftmargin {
|
||||||
|
margin-left: 21px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// simple text aligns
|
||||||
|
.textcenter {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textright {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textsmaller {
|
||||||
|
font-size: @font-size-small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-backdrop {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* generic page copy styles */
|
||||||
|
|
||||||
|
.copy-headline h1 {
|
||||||
|
font-size: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* =======================
|
/* =======================
|
||||||
Row size
|
Sticky footer
|
||||||
======================= */
|
======================= */
|
||||||
|
|
||||||
.row1 {
|
@sticky-footer-height: 280px;
|
||||||
background-color: @grayLight;
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
/* The html and body elements cannot have any padding or margin. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrapper for page content to push down footer */
|
||||||
|
#wrap {
|
||||||
|
min-height: 100%;
|
||||||
|
height: auto !important;
|
||||||
|
height: 100%;
|
||||||
|
/* Negative indent footer by it's height */
|
||||||
|
margin: 0 auto -@sticky-footer-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the fixed height of the footer here */
|
||||||
|
#push-the-footer,
|
||||||
|
#footer {
|
||||||
|
height: @sticky-footer-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
// margin-bottom: -60px;
|
||||||
|
// margin-top: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-row {
|
||||||
|
padding-top: @navbar-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Styles on the footer
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
//
|
||||||
|
#footer .footer {
|
||||||
|
margin-top: 160px;
|
||||||
|
.ligaturesymbols {
|
||||||
|
font-size: 30px;
|
||||||
|
color: black;
|
||||||
|
a {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerlist {
|
||||||
|
h3, h4 {
|
||||||
|
/* correct the top alignment */
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-landscape-image {
|
||||||
|
position: absolute:
|
||||||
|
bottom: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
background-image: url('https://www.docker.io/static/img/website-footer_clean.svg');
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
height: @sticky-footer-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-row {
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
padding: 16px 18px inherit;
|
||||||
|
}
|
||||||
|
|
||||||
/* =======================
|
/* =======================
|
||||||
Social footer
|
Social footer
|
||||||
======================= */
|
======================= */
|
||||||
|
|
||||||
|
.social {
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.social .twitter, .social .github, .social .googleplus {
|
.social .twitter, .social .github, .social .googleplus {
|
||||||
background: url("../img/footer-links.png") no-repeat transparent;
|
background: url("https://www.docker.io/static/img/footer-links.png") no-repeat transparent;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -387,107 +348,219 @@ section.header {
|
|||||||
background-position: -59px 2px;
|
background-position: -59px 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Styles on the forms
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
#fork-us {
|
form table {
|
||||||
/*font-family: 'Maven Pro';*/
|
th {
|
||||||
/*font-weight: bold;*/
|
vertical-align: top;
|
||||||
font-size: 12px;
|
text-align: right;
|
||||||
/*text-transform: uppercase;*/
|
white-space: nowrap;
|
||||||
display: block;
|
|
||||||
padding: 0px 1em;
|
|
||||||
height: 28px;
|
|
||||||
line-height: 28px;
|
|
||||||
background-color: #43484c;
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFF6E56', endColorstr='#FFED4F35');
|
|
||||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #747474), color-stop(100%, #43484c));
|
|
||||||
background-image: -webkit-linear-gradient(top, #747474 0%, #43484c 100%);
|
|
||||||
background-image: -moz-linear-gradient(top, #747474 0%, #43484c 100%);
|
|
||||||
background-image: -o-linear-gradient(top, #747474 0%, #43484c 100%);
|
|
||||||
background-image: linear-gradient(top, #747474 0%, #43484c 100%);
|
|
||||||
border: 1px solid #43484c;
|
|
||||||
-webkit-border-radius: 4px;
|
|
||||||
-moz-border-radius: 4px;
|
|
||||||
-ms-border-radius: 4px;
|
|
||||||
-o-border-radius: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
-webkit-box-shadow: inset rgba(255, 255, 255, 0.17) 0 1px 1px;
|
|
||||||
-moz-box-shadow: inset rgba(255, 255, 255, 0.17) 0 1px 1px;
|
|
||||||
box-shadow: inset rgba(255, 255, 255, 0.17) 0 1px 1px;
|
|
||||||
margin: 8px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #faf2ee;
|
|
||||||
text-shadow: rgba(0, 0, 0, 0.3) 0px 1px 0px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
.labeldd label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helptext {
|
||||||
|
font-size: @font-size-small;
|
||||||
|
margin-top: -4px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fielddd input {
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: @deep-red;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=submit] {
|
||||||
|
// margin-top: -8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.alert.alert-block {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ======================= =======================
|
||||||
|
Documentation
|
||||||
|
========================= ========================= */
|
||||||
|
|
||||||
|
|
||||||
/* =======================
|
/* =======================
|
||||||
Media size overrides
|
Styles for the sidebar
|
||||||
======================= */
|
========================= */
|
||||||
|
|
||||||
/* Large desktop */
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
.span6.with-padding {
|
|
||||||
background-color: @red;
|
|
||||||
|
|
||||||
width: (@gridColumnWidth1200 * 6) + (@gridGutterWidth1200 * 5) - @gridGutterWidth1200;
|
@sidebar-navigation-border: 1.5px solid #595959;
|
||||||
padding: @gridGutterWidth1200/2;
|
@sidebar-navigation-width: 225px;
|
||||||
|
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
// border-bottom: 1px solid #bbbbbb;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
h4 {
|
||||||
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Normal desktop */
|
.bs-docs-sidebar {
|
||||||
@media (min-width: 980px) and (max-width: 1199px) {
|
padding-left: 5px;
|
||||||
.span6.with-padding {
|
max-width: 100%;
|
||||||
background-color: @lightred;
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
margin-top: 18px;
|
||||||
|
|
||||||
width: (@gridColumnWidth * 6) + (@gridGutterWidth * 5) - @gridGutterWidth;
|
ul {
|
||||||
padding: @gridGutterWidth/2;
|
list-style: none;
|
||||||
|
margin-left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
.toctree-l2 > ul {
|
||||||
|
width: 100%;
|
||||||
/* Portrait tablet to landscape and desktop */
|
|
||||||
@media (min-width: 768px) and (max-width: 979px) {
|
|
||||||
body {
|
|
||||||
padding-top: 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul > li {
|
||||||
|
&.toctree-l1.has-children {
|
||||||
|
background-image: url('../img/menu_arrow_right.gif');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 13px 13px;
|
||||||
|
list-style-type: none;
|
||||||
|
// margin-left: px;
|
||||||
|
padding: 0px 0px 0px 0px;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
.span6.with-padding {
|
&.open {
|
||||||
background-color: @darkblue;
|
background-image: url('../img/menu_arrow_down.gif');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
width: (@gridColumnWidth768 * 6) + (@gridGutterWidth768 * 5) - @gridGutterWidth768;
|
& > a {
|
||||||
padding: @gridGutterWidth768/2;
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
display:inline-block;
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
padding-left: 35px;
|
||||||
|
padding-right: 20px;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
border-bottom: @sidebar-navigation-border;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child.active > a {
|
||||||
|
border-top: @sidebar-navigation-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child > a {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child.active > a {
|
||||||
|
border-bottom: @sidebar-navigation-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active > a {
|
||||||
|
border-right: @sidebar-navigation-border;
|
||||||
|
border-left: @sidebar-navigation-border;
|
||||||
|
color: @very-dark-sea-green;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Landscape phone to portrait tablet */
|
&.toctree-l3 ul {
|
||||||
@media (max-width: 767px) {
|
display: inherit;
|
||||||
body {
|
|
||||||
padding-top: 0px;
|
margin-left: 15px;
|
||||||
|
font-size: smaller;
|
||||||
}
|
}
|
||||||
#global {
|
|
||||||
/* TODO: Fix this to be relative to the navigation size */
|
.toctree-l3 a {
|
||||||
// padding-top: 600px;
|
border: none;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 15px;
|
||||||
}
|
}
|
||||||
#fork-us {
|
|
||||||
|
ul > li > ul {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
ul > li.current > ul {
|
||||||
/* Landscape phones and down */
|
display: inline-block;
|
||||||
@media (max-width: 480px) {
|
padding-left: 0px;
|
||||||
#nav-gettingstarted {
|
width: 100%;
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Misc fixes */
|
.toctree-l2 {
|
||||||
table th {
|
&.current > a {
|
||||||
text-align: left;
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
&.current {
|
||||||
|
border: 1.5px solid #595959;
|
||||||
|
color: #394d54;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =====================================
|
||||||
|
Styles for the floating version widget
|
||||||
|
====================================== */
|
||||||
|
|
||||||
|
.version-flyer {
|
||||||
|
position: fixed;
|
||||||
|
float: right;
|
||||||
|
right: 0;
|
||||||
|
bottom: 40px;
|
||||||
|
background-color: #E0E0E0;
|
||||||
|
border: 1px solid #88BABC;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: larger;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding-right: 45px;
|
||||||
|
margin-top: 7px;
|
||||||
|
margin-left: 7px;
|
||||||
|
// display: inline-block;
|
||||||
|
background-image: url('../img/container3.png');
|
||||||
|
background-position: right center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alternative {
|
||||||
|
visibility: hidden;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active-slug {
|
||||||
|
visibility: visible;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .alternative {
|
||||||
|
animation-duration: 1s;
|
||||||
|
display: inline-block;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================
|
||||||
|
Styles for
|
||||||
|
====================================== */
|
||||||
|
|
||||||
h1:hover > a.headerlink,
|
h1:hover > a.headerlink,
|
||||||
h2:hover > a.headerlink,
|
h2:hover > a.headerlink,
|
||||||
h3:hover > a.headerlink,
|
h3:hover > a.headerlink,
|
||||||
@@ -504,4 +577,38 @@ dt:hover > a.headerlink {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
float: right;
|
float: right;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =====================================
|
||||||
|
Miscellaneous information
|
||||||
|
====================================== */
|
||||||
|
|
||||||
|
.admonition {
|
||||||
|
&.warning, &.note, &.seealso, &.todo {
|
||||||
|
border: 3px solid black;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 5px auto 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-title {
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning, &.danger {
|
||||||
|
border-color: #ac0004;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.note {
|
||||||
|
border-color: #cbc200;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.todo {
|
||||||
|
border-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.seealso {
|
||||||
|
border-color: #23cb1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,128 +9,175 @@
|
|||||||
|
|
||||||
// Grays
|
// Grays
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@black: #000;
|
|
||||||
@grayDarker: #222;
|
|
||||||
@grayDark: #333;
|
|
||||||
@gray: #555;
|
|
||||||
@grayLight: #999;
|
|
||||||
@grayLighter: #eee;
|
|
||||||
@white: #fff;
|
|
||||||
|
|
||||||
|
@gray-darker: lighten(#000, 13.5%); // #222
|
||||||
|
@gray-dark: lighten(#000, 20%); // #333
|
||||||
|
@gray: lighten(#000, 33.5%); // #555
|
||||||
|
@gray-light: lighten(#000, 60%); // #999
|
||||||
|
@gray-lighter: lighten(#000, 93.5%); // #eee
|
||||||
|
|
||||||
// Accent colors
|
// Brand colors
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@blue: #049cdb;
|
|
||||||
@blueDark: #0064cd;
|
|
||||||
@green: #46a546;
|
|
||||||
@red: #9d261d;
|
|
||||||
@yellow: #ffc40d;
|
|
||||||
@orange: #f89406;
|
|
||||||
@pink: #c3325f;
|
|
||||||
@purple: #7a43b6;
|
|
||||||
|
|
||||||
|
@brand-primary: #428bca;
|
||||||
|
@brand-success: #5cb85c;
|
||||||
|
@brand-warning: #f0ad4e;
|
||||||
|
@brand-danger: #d9534f;
|
||||||
|
@brand-info: #5bc0de;
|
||||||
|
|
||||||
// Scaffolding
|
// Scaffolding
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@bodyBackground: @white;
|
|
||||||
@textColor: @grayDark;
|
|
||||||
|
|
||||||
|
@body-bg: #fff;
|
||||||
|
@text-color: @gray-dark;
|
||||||
|
|
||||||
// Links
|
// Links
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@linkColor: #08c;
|
|
||||||
@linkColorHover: darken(@linkColor, 15%);
|
|
||||||
|
|
||||||
|
@link-color: @brand-primary;
|
||||||
|
@link-hover-color: darken(@link-color, 15%);
|
||||||
|
|
||||||
// Typography
|
// Typography
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@sansFontFamily: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
@serifFontFamily: Georgia, "Times New Roman", Times, serif;
|
|
||||||
@monoFontFamily: Monaco, Menlo, Consolas, "Courier New", monospace;
|
|
||||||
|
|
||||||
@baseFontSize: 14px;
|
@font-family-sans-serif: "Cabin", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
@baseFontFamily: @sansFontFamily;
|
@font-family-serif: Georgia, "Times New Roman", Times, serif;
|
||||||
@baseLineHeight: 20px;
|
@font-family-monospace: Monaco, Menlo, Consolas, "Courier New", monospace;
|
||||||
@altFontFamily: @serifFontFamily;
|
@font-family-base: @font-family-sans-serif;
|
||||||
|
|
||||||
@headingsFontFamily: inherit; // empty to use BS default, @baseFontFamily
|
@font-size-base: 14px;
|
||||||
@headingsFontWeight: bold; // instead of browser default, bold
|
@font-size-large: ceil(@font-size-base * 1.25); // ~18px
|
||||||
@headingsColor: inherit; // empty to use BS default, @textColor
|
@font-size-small: ceil(@font-size-base * 0.85); // ~12px
|
||||||
|
|
||||||
|
@line-height-base: 1.428571429; // 20/14
|
||||||
|
@line-height-computed: floor(@font-size-base * @line-height-base); // ~20px
|
||||||
|
|
||||||
// Component sizing
|
@headings-font-family: @font-family-base;
|
||||||
|
@headings-font-weight: 500;
|
||||||
|
@headings-line-height: 1.1;
|
||||||
|
|
||||||
|
// Iconography
|
||||||
// -------------------------
|
// -------------------------
|
||||||
// Based on 14px font-size and 20px line-height
|
|
||||||
|
|
||||||
@fontSizeLarge: @baseFontSize * 1.25; // ~18px
|
@icon-font-path: "../fonts/";
|
||||||
@fontSizeSmall: @baseFontSize * 0.85; // ~12px
|
@icon-font-name: "glyphicons-halflings-regular";
|
||||||
@fontSizeMini: @baseFontSize * 0.75; // ~11px
|
|
||||||
|
|
||||||
@paddingLarge: 11px 19px; // 44px
|
|
||||||
@paddingSmall: 2px 10px; // 26px
|
|
||||||
@paddingMini: 0 6px; // 22px
|
|
||||||
|
|
||||||
@baseBorderRadius: 4px;
|
// Components
|
||||||
@borderRadiusLarge: 6px;
|
// -------------------------
|
||||||
@borderRadiusSmall: 3px;
|
// Based on 14px font-size and 1.428 line-height (~20px to start)
|
||||||
|
|
||||||
|
@padding-base-vertical: 6px;
|
||||||
|
@padding-base-horizontal: 12px;
|
||||||
|
|
||||||
|
@padding-large-vertical: 10px;
|
||||||
|
@padding-large-horizontal: 16px;
|
||||||
|
|
||||||
|
@padding-small-vertical: 5px;
|
||||||
|
@padding-small-horizontal: 10px;
|
||||||
|
|
||||||
|
@line-height-large: 1.33;
|
||||||
|
@line-height-small: 1.5;
|
||||||
|
|
||||||
|
@border-radius-base: 4px;
|
||||||
|
@border-radius-large: 6px;
|
||||||
|
@border-radius-small: 3px;
|
||||||
|
|
||||||
|
@component-active-bg: @brand-primary;
|
||||||
|
|
||||||
|
@caret-width-base: 4px;
|
||||||
|
@caret-width-large: 5px;
|
||||||
|
|
||||||
// Tables
|
// Tables
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@tableBackground: transparent; // overall background-color
|
|
||||||
@tableBackgroundAccent: #f9f9f9; // for striping
|
@table-cell-padding: 8px;
|
||||||
@tableBackgroundHover: #f5f5f5; // for hover
|
@table-condensed-cell-padding: 5px;
|
||||||
@tableBorder: #ddd; // table and cell border
|
|
||||||
|
@table-bg: transparent; // overall background-color
|
||||||
|
@table-bg-accent: #f9f9f9; // for striping
|
||||||
|
@table-bg-hover: #f5f5f5;
|
||||||
|
@table-bg-active: @table-bg-hover;
|
||||||
|
|
||||||
|
@table-border-color: #ddd; // table and cell border
|
||||||
|
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@btnBackground: @white;
|
|
||||||
@btnBackgroundHighlight: darken(@white, 10%);
|
|
||||||
@btnBorder: #ccc;
|
|
||||||
|
|
||||||
@btnPrimaryBackground: @linkColor;
|
@btn-font-weight: normal;
|
||||||
@btnPrimaryBackgroundHighlight: spin(@btnPrimaryBackground, 20%);
|
|
||||||
|
|
||||||
@btnInfoBackground: #5bc0de;
|
@btn-default-color: #333;
|
||||||
@btnInfoBackgroundHighlight: #2f96b4;
|
@btn-default-bg: #fff;
|
||||||
|
@btn-default-border: #ccc;
|
||||||
|
|
||||||
@btnSuccessBackground: #62c462;
|
@btn-primary-color: #fff;
|
||||||
@btnSuccessBackgroundHighlight: #51a351;
|
@btn-primary-bg: @brand-primary;
|
||||||
|
@btn-primary-border: darken(@btn-primary-bg, 5%);
|
||||||
|
|
||||||
@btnWarningBackground: lighten(@orange, 15%);
|
@btn-success-color: #fff;
|
||||||
@btnWarningBackgroundHighlight: @orange;
|
@btn-success-bg: @brand-success;
|
||||||
|
@btn-success-border: darken(@btn-success-bg, 5%);
|
||||||
|
|
||||||
@btnDangerBackground: #ee5f5b;
|
@btn-warning-color: #fff;
|
||||||
@btnDangerBackgroundHighlight: #bd362f;
|
@btn-warning-bg: @brand-warning;
|
||||||
|
@btn-warning-border: darken(@btn-warning-bg, 5%);
|
||||||
|
|
||||||
@btnInverseBackground: #444;
|
@btn-danger-color: #fff;
|
||||||
@btnInverseBackgroundHighlight: @grayDarker;
|
@btn-danger-bg: @brand-danger;
|
||||||
|
@btn-danger-border: darken(@btn-danger-bg, 5%);
|
||||||
|
|
||||||
|
@btn-info-color: #fff;
|
||||||
|
@btn-info-bg: @brand-info;
|
||||||
|
@btn-info-border: darken(@btn-info-bg, 5%);
|
||||||
|
|
||||||
|
@btn-link-disabled-color: @gray-light;
|
||||||
|
|
||||||
|
|
||||||
// Forms
|
// Forms
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@inputBackground: @white;
|
|
||||||
@inputBorder: #ccc;
|
@input-bg: #fff;
|
||||||
@inputBorderRadius: @baseBorderRadius;
|
@input-bg-disabled: @gray-lighter;
|
||||||
@inputDisabledBackground: @grayLighter;
|
|
||||||
@formActionsBackground: #f5f5f5;
|
@input-color: @gray;
|
||||||
@inputHeight: @baseLineHeight + 10px; // base line-height + 8px vertical padding + 2px top/bottom border
|
@input-border: #ccc;
|
||||||
|
@input-border-radius: @border-radius-base;
|
||||||
|
@input-border-focus: #66afe9;
|
||||||
|
|
||||||
|
@input-color-placeholder: @gray-light;
|
||||||
|
|
||||||
|
@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);
|
||||||
|
@input-height-large: (floor(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
|
||||||
|
@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
|
||||||
|
|
||||||
|
@legend-color: @gray-dark;
|
||||||
|
@legend-border-color: #e5e5e5;
|
||||||
|
|
||||||
|
@input-group-addon-bg: @gray-lighter;
|
||||||
|
@input-group-addon-border-color: @input-border;
|
||||||
|
|
||||||
|
|
||||||
// Dropdowns
|
// Dropdowns
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@dropdownBackground: @white;
|
|
||||||
@dropdownBorder: rgba(0,0,0,.2);
|
|
||||||
@dropdownDividerTop: #e5e5e5;
|
|
||||||
@dropdownDividerBottom: @white;
|
|
||||||
|
|
||||||
@dropdownLinkColor: @grayDark;
|
@dropdown-bg: #fff;
|
||||||
@dropdownLinkColorHover: @white;
|
@dropdown-border: rgba(0,0,0,.15);
|
||||||
@dropdownLinkColorActive: @white;
|
@dropdown-fallback-border: #ccc;
|
||||||
|
@dropdown-divider-bg: #e5e5e5;
|
||||||
|
|
||||||
@dropdownLinkBackgroundActive: @linkColor;
|
@dropdown-link-active-color: #fff;
|
||||||
@dropdownLinkBackgroundHover: @dropdownLinkBackgroundActive;
|
@dropdown-link-active-bg: @component-active-bg;
|
||||||
|
|
||||||
|
@dropdown-link-color: @gray-dark;
|
||||||
|
@dropdown-link-hover-color: #fff;
|
||||||
|
@dropdown-link-hover-bg: @dropdown-link-active-bg;
|
||||||
|
|
||||||
|
@dropdown-link-disabled-color: @gray-light;
|
||||||
|
|
||||||
|
@dropdown-header-color: @gray-light;
|
||||||
|
|
||||||
|
@dropdown-caret-color: #000;
|
||||||
|
|
||||||
|
|
||||||
// COMPONENT VARIABLES
|
// COMPONENT VARIABLES
|
||||||
@@ -141,161 +188,435 @@
|
|||||||
// -------------------------
|
// -------------------------
|
||||||
// Used for a bird's eye view of components dependent on the z-axis
|
// Used for a bird's eye view of components dependent on the z-axis
|
||||||
// Try to avoid customizing these :)
|
// Try to avoid customizing these :)
|
||||||
@zindexDropdown: 1000;
|
|
||||||
@zindexPopover: 1010;
|
@zindex-navbar: 1000;
|
||||||
@zindexTooltip: 1030;
|
@zindex-dropdown: 1000;
|
||||||
@zindexFixedNavbar: 1030;
|
@zindex-popover: 1010;
|
||||||
@zindexModalBackdrop: 1040;
|
@zindex-tooltip: 1030;
|
||||||
@zindexModal: 1050;
|
@zindex-navbar-fixed: 1030;
|
||||||
|
@zindex-modal-background: 1040;
|
||||||
|
@zindex-modal: 1050;
|
||||||
|
|
||||||
|
// Media queries breakpoints
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
// Extra small screen / phone
|
||||||
|
@screen-xs: 480px;
|
||||||
|
@screen-phone: @screen-xs;
|
||||||
|
|
||||||
|
// Small screen / tablet
|
||||||
|
@screen-sm: 768px;
|
||||||
|
@screen-tablet: @screen-sm;
|
||||||
|
|
||||||
|
// Medium screen / desktop
|
||||||
|
@screen-md: 992px;
|
||||||
|
@screen-desktop: @screen-md;
|
||||||
|
|
||||||
|
// Large screen / wide desktop
|
||||||
|
@screen-lg: 1600px;
|
||||||
|
@screen-lg-desktop: @screen-lg;
|
||||||
|
|
||||||
|
// So media queries don't overlap when required, provide a maximum
|
||||||
|
@screen-xs-max: (@screen-sm - 1);
|
||||||
|
@screen-sm-max: (@screen-md - 1);
|
||||||
|
@screen-md-max: (@screen-lg - 1);
|
||||||
|
|
||||||
|
|
||||||
// Sprite icons path
|
// Grid system
|
||||||
// -------------------------
|
// --------------------------------------------------
|
||||||
@iconSpritePath: "../img/glyphicons-halflings.png";
|
|
||||||
@iconWhiteSpritePath: "../img/glyphicons-halflings-white.png";
|
|
||||||
|
|
||||||
|
// Number of columns in the grid system
|
||||||
// Input placeholder text color
|
@grid-columns: 12;
|
||||||
// -------------------------
|
// Padding, to be divided by two and applied to the left and right of all columns
|
||||||
@placeholderText: @grayLight;
|
@grid-gutter-width: 30px;
|
||||||
|
// Point at which the navbar stops collapsing
|
||||||
|
@grid-float-breakpoint: @screen-desktop;
|
||||||
// Hr border color
|
|
||||||
// -------------------------
|
|
||||||
@hrBorder: @grayLighter;
|
|
||||||
|
|
||||||
|
|
||||||
// Horizontal forms & lists
|
|
||||||
// -------------------------
|
|
||||||
@horizontalComponentOffset: 180px;
|
|
||||||
|
|
||||||
|
|
||||||
// Wells
|
|
||||||
// -------------------------
|
|
||||||
@wellBackground: #f5f5f5;
|
|
||||||
|
|
||||||
|
|
||||||
// Navbar
|
// Navbar
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@navbarCollapseWidth: 979px;
|
|
||||||
@navbarCollapseDesktopWidth: @navbarCollapseWidth + 1;
|
|
||||||
|
|
||||||
@navbarHeight: 40px;
|
|
||||||
@navbarBackgroundHighlight: #ffffff;
|
|
||||||
@navbarBackground: darken(@navbarBackgroundHighlight, 5%);
|
|
||||||
@navbarBorder: darken(@navbarBackground, 12%);
|
|
||||||
|
|
||||||
@navbarText: #777;
|
// Basics of a navbar
|
||||||
@navbarLinkColor: #777;
|
@navbar-height: 50px;
|
||||||
@navbarLinkColorHover: @grayDark;
|
@navbar-margin-bottom: @line-height-computed;
|
||||||
@navbarLinkColorActive: @gray;
|
@navbar-default-color: #777;
|
||||||
@navbarLinkBackgroundHover: transparent;
|
@navbar-default-bg: #f8f8f8;
|
||||||
@navbarLinkBackgroundActive: darken(@navbarBackground, 5%);
|
@navbar-default-border: darken(@navbar-default-bg, 6.5%);
|
||||||
|
@navbar-border-radius: @border-radius-base;
|
||||||
|
@navbar-padding-horizontal: floor(@grid-gutter-width / 2);
|
||||||
|
@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);
|
||||||
|
|
||||||
|
// Navbar links
|
||||||
|
@navbar-default-link-color: #777;
|
||||||
|
@navbar-default-link-hover-color: #333;
|
||||||
|
@navbar-default-link-hover-bg: transparent;
|
||||||
|
@navbar-default-link-active-color: #555;
|
||||||
|
@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);
|
||||||
|
@navbar-default-link-disabled-color: #ccc;
|
||||||
|
@navbar-default-link-disabled-bg: transparent;
|
||||||
|
|
||||||
|
// Navbar brand label
|
||||||
|
@navbar-default-brand-color: @navbar-default-link-color;
|
||||||
|
@navbar-default-brand-hover-color: darken(@navbar-default-link-color, 10%);
|
||||||
|
@navbar-default-brand-hover-bg: transparent;
|
||||||
|
|
||||||
|
// Navbar toggle
|
||||||
|
@navbar-default-toggle-hover-bg: #ddd;
|
||||||
|
@navbar-default-toggle-icon-bar-bg: #ccc;
|
||||||
|
@navbar-default-toggle-border-color: #ddd;
|
||||||
|
|
||||||
@navbarBrandColor: @navbarLinkColor;
|
|
||||||
|
|
||||||
// Inverted navbar
|
// Inverted navbar
|
||||||
@navbarInverseBackground: #111111;
|
//
|
||||||
@navbarInverseBackgroundHighlight: #222222;
|
// Reset inverted navbar basics
|
||||||
@navbarInverseBorder: #252525;
|
@navbar-inverse-color: @gray-light;
|
||||||
|
@navbar-inverse-bg: #222;
|
||||||
|
@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);
|
||||||
|
|
||||||
@navbarInverseText: @grayLight;
|
// Inverted navbar links
|
||||||
@navbarInverseLinkColor: @grayLight;
|
@navbar-inverse-link-color: @gray-light;
|
||||||
@navbarInverseLinkColorHover: @white;
|
@navbar-inverse-link-hover-color: #fff;
|
||||||
@navbarInverseLinkColorActive: @navbarInverseLinkColorHover;
|
@navbar-inverse-link-hover-bg: transparent;
|
||||||
@navbarInverseLinkBackgroundHover: transparent;
|
@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;
|
||||||
@navbarInverseLinkBackgroundActive: @navbarInverseBackground;
|
@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);
|
||||||
|
@navbar-inverse-link-disabled-color: #444;
|
||||||
|
@navbar-inverse-link-disabled-bg: transparent;
|
||||||
|
|
||||||
@navbarInverseSearchBackground: lighten(@navbarInverseBackground, 25%);
|
// Inverted navbar brand label
|
||||||
@navbarInverseSearchBackgroundFocus: @white;
|
@navbar-inverse-brand-color: @navbar-inverse-link-color;
|
||||||
@navbarInverseSearchBorder: @navbarInverseBackground;
|
@navbar-inverse-brand-hover-color: #fff;
|
||||||
@navbarInverseSearchPlaceholderColor: #ccc;
|
@navbar-inverse-brand-hover-bg: transparent;
|
||||||
|
|
||||||
@navbarInverseBrandColor: @navbarInverseLinkColor;
|
// Inverted navbar search
|
||||||
|
// Normal navbar needs no special styles or vars
|
||||||
|
@navbar-inverse-search-bg: lighten(@navbar-inverse-bg, 25%);
|
||||||
|
@navbar-inverse-search-bg-focus: #fff;
|
||||||
|
@navbar-inverse-search-border: @navbar-inverse-bg;
|
||||||
|
@navbar-inverse-search-placeholder-color: #ccc;
|
||||||
|
|
||||||
|
// Inverted navbar toggle
|
||||||
|
@navbar-inverse-toggle-hover-bg: #333;
|
||||||
|
@navbar-inverse-toggle-icon-bar-bg: #fff;
|
||||||
|
@navbar-inverse-toggle-border-color: #333;
|
||||||
|
|
||||||
|
|
||||||
|
// Navs
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
@nav-link-padding: 10px 15px;
|
||||||
|
@nav-link-hover-bg: @gray-lighter;
|
||||||
|
|
||||||
|
@nav-disabled-link-color: @gray-light;
|
||||||
|
@nav-disabled-link-hover-color: @gray-light;
|
||||||
|
|
||||||
|
@nav-open-link-hover-color: #fff;
|
||||||
|
@nav-open-caret-border-color: #fff;
|
||||||
|
|
||||||
|
// Tabs
|
||||||
|
@nav-tabs-border-color: #ddd;
|
||||||
|
|
||||||
|
@nav-tabs-link-hover-border-color: @gray-lighter;
|
||||||
|
|
||||||
|
@nav-tabs-active-link-hover-bg: @body-bg;
|
||||||
|
@nav-tabs-active-link-hover-color: @gray;
|
||||||
|
@nav-tabs-active-link-hover-border-color: #ddd;
|
||||||
|
|
||||||
|
@nav-tabs-justified-link-border-color: #ddd;
|
||||||
|
@nav-tabs-justified-active-link-border-color: @body-bg;
|
||||||
|
|
||||||
|
// Pills
|
||||||
|
@nav-pills-active-link-hover-bg: @component-active-bg;
|
||||||
|
@nav-pills-active-link-hover-color: #fff;
|
||||||
|
|
||||||
|
|
||||||
// Pagination
|
// Pagination
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@paginationBackground: #fff;
|
|
||||||
@paginationBorder: #ddd;
|
@pagination-bg: #fff;
|
||||||
@paginationActiveBackground: #f5f5f5;
|
@pagination-border: #ddd;
|
||||||
|
|
||||||
|
@pagination-hover-bg: @gray-lighter;
|
||||||
|
|
||||||
|
@pagination-active-bg: @brand-primary;
|
||||||
|
@pagination-active-color: #fff;
|
||||||
|
|
||||||
|
@pagination-disabled-color: @gray-light;
|
||||||
|
|
||||||
|
|
||||||
// Hero unit
|
// Pager
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@heroUnitBackground: @grayLighter;
|
|
||||||
@heroUnitHeadingColor: inherit;
|
@pager-border-radius: 15px;
|
||||||
@heroUnitLeadColor: inherit;
|
@pager-disabled-color: @gray-light;
|
||||||
|
|
||||||
|
|
||||||
|
// Jumbotron
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
@jumbotron-padding: 30px;
|
||||||
|
@jumbotron-color: inherit;
|
||||||
|
@jumbotron-bg: @gray-lighter;
|
||||||
|
|
||||||
|
@jumbotron-heading-color: inherit;
|
||||||
|
|
||||||
|
|
||||||
// Form states and alerts
|
// Form states and alerts
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@warningText: #c09853;
|
|
||||||
@warningBackground: #fcf8e3;
|
|
||||||
@warningBorder: darken(spin(@warningBackground, -10), 3%);
|
|
||||||
|
|
||||||
@errorText: #b94a48;
|
@state-warning-text: #c09853;
|
||||||
@errorBackground: #f2dede;
|
@state-warning-bg: #fcf8e3;
|
||||||
@errorBorder: darken(spin(@errorBackground, -10), 3%);
|
@state-warning-border: darken(spin(@state-warning-bg, -10), 3%);
|
||||||
|
|
||||||
@successText: #468847;
|
@state-danger-text: #b94a48;
|
||||||
@successBackground: #dff0d8;
|
@state-danger-bg: #f2dede;
|
||||||
@successBorder: darken(spin(@successBackground, -10), 5%);
|
@state-danger-border: darken(spin(@state-danger-bg, -10), 3%);
|
||||||
|
|
||||||
@infoText: #3a87ad;
|
@state-success-text: #468847;
|
||||||
@infoBackground: #d9edf7;
|
@state-success-bg: #dff0d8;
|
||||||
@infoBorder: darken(spin(@infoBackground, -10), 7%);
|
@state-success-border: darken(spin(@state-success-bg, -10), 5%);
|
||||||
|
|
||||||
|
@state-info-text: #3a87ad;
|
||||||
|
@state-info-bg: #d9edf7;
|
||||||
|
@state-info-border: darken(spin(@state-info-bg, -10), 7%);
|
||||||
|
|
||||||
|
|
||||||
// Tooltips and popovers
|
// Tooltips
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@tooltipColor: #fff;
|
@tooltip-max-width: 200px;
|
||||||
@tooltipBackground: #000;
|
@tooltip-color: #fff;
|
||||||
@tooltipArrowWidth: 5px;
|
@tooltip-bg: #000;
|
||||||
@tooltipArrowColor: @tooltipBackground;
|
|
||||||
|
|
||||||
@popoverBackground: #fff;
|
@tooltip-arrow-width: 5px;
|
||||||
@popoverArrowWidth: 10px;
|
@tooltip-arrow-color: @tooltip-bg;
|
||||||
@popoverArrowColor: #fff;
|
|
||||||
@popoverTitleBackground: darken(@popoverBackground, 3%);
|
|
||||||
|
|
||||||
// Special enhancement for popovers
|
|
||||||
@popoverArrowOuterWidth: @popoverArrowWidth + 1;
|
|
||||||
@popoverArrowOuterColor: rgba(0,0,0,.25);
|
|
||||||
|
|
||||||
|
|
||||||
|
// Popovers
|
||||||
|
// -------------------------
|
||||||
|
@popover-bg: #fff;
|
||||||
|
@popover-max-width: 276px;
|
||||||
|
@popover-border-color: rgba(0,0,0,.2);
|
||||||
|
@popover-fallback-border-color: #ccc;
|
||||||
|
|
||||||
// GRID
|
@popover-title-bg: darken(@popover-bg, 3%);
|
||||||
|
|
||||||
|
@popover-arrow-width: 10px;
|
||||||
|
@popover-arrow-color: #fff;
|
||||||
|
|
||||||
|
@popover-arrow-outer-width: (@popover-arrow-width + 1);
|
||||||
|
@popover-arrow-outer-color: rgba(0,0,0,.25);
|
||||||
|
@popover-arrow-outer-fallback-color: #999;
|
||||||
|
|
||||||
|
|
||||||
|
// Labels
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
@label-default-bg: @gray-light;
|
||||||
|
@label-primary-bg: @brand-primary;
|
||||||
|
@label-success-bg: @brand-success;
|
||||||
|
@label-info-bg: @brand-info;
|
||||||
|
@label-warning-bg: @brand-warning;
|
||||||
|
@label-danger-bg: @brand-danger;
|
||||||
|
|
||||||
|
@label-color: #fff;
|
||||||
|
@label-link-hover-color: #fff;
|
||||||
|
|
||||||
|
|
||||||
|
// Modals
|
||||||
|
// -------------------------
|
||||||
|
@modal-inner-padding: 20px;
|
||||||
|
|
||||||
|
@modal-title-padding: 15px;
|
||||||
|
@modal-title-line-height: @line-height-base;
|
||||||
|
|
||||||
|
@modal-content-bg: #fff;
|
||||||
|
@modal-content-border-color: rgba(0,0,0,.2);
|
||||||
|
@modal-content-fallback-border-color: #999;
|
||||||
|
|
||||||
|
@modal-backdrop-bg: #000;
|
||||||
|
@modal-header-border-color: #e5e5e5;
|
||||||
|
@modal-footer-border-color: @modal-header-border-color;
|
||||||
|
|
||||||
|
|
||||||
|
// Alerts
|
||||||
|
// -------------------------
|
||||||
|
@alert-padding: 15px;
|
||||||
|
@alert-border-radius: @border-radius-base;
|
||||||
|
@alert-link-font-weight: bold;
|
||||||
|
|
||||||
|
@alert-success-bg: @state-success-bg;
|
||||||
|
@alert-success-text: @state-success-text;
|
||||||
|
@alert-success-border: @state-success-border;
|
||||||
|
|
||||||
|
@alert-info-bg: @state-info-bg;
|
||||||
|
@alert-info-text: @state-info-text;
|
||||||
|
@alert-info-border: @state-info-border;
|
||||||
|
|
||||||
|
@alert-warning-bg: @state-warning-bg;
|
||||||
|
@alert-warning-text: @state-warning-text;
|
||||||
|
@alert-warning-border: @state-warning-border;
|
||||||
|
|
||||||
|
@alert-danger-bg: @state-danger-bg;
|
||||||
|
@alert-danger-text: @state-danger-text;
|
||||||
|
@alert-danger-border: @state-danger-border;
|
||||||
|
|
||||||
|
|
||||||
|
// Progress bars
|
||||||
|
// -------------------------
|
||||||
|
@progress-bg: #f5f5f5;
|
||||||
|
@progress-bar-color: #fff;
|
||||||
|
|
||||||
|
@progress-bar-bg: @brand-primary;
|
||||||
|
@progress-bar-success-bg: @brand-success;
|
||||||
|
@progress-bar-warning-bg: @brand-warning;
|
||||||
|
@progress-bar-danger-bg: @brand-danger;
|
||||||
|
@progress-bar-info-bg: @brand-info;
|
||||||
|
|
||||||
|
|
||||||
|
// List group
|
||||||
|
// -------------------------
|
||||||
|
@list-group-bg: #fff;
|
||||||
|
@list-group-border: #ddd;
|
||||||
|
@list-group-border-radius: @border-radius-base;
|
||||||
|
|
||||||
|
@list-group-hover-bg: #f5f5f5;
|
||||||
|
@list-group-active-color: #fff;
|
||||||
|
@list-group-active-bg: @component-active-bg;
|
||||||
|
@list-group-active-border: @list-group-active-bg;
|
||||||
|
|
||||||
|
@list-group-link-color: #555;
|
||||||
|
@list-group-link-heading-color: #333;
|
||||||
|
|
||||||
|
|
||||||
|
// Panels
|
||||||
|
// -------------------------
|
||||||
|
@panel-bg: #fff;
|
||||||
|
@panel-inner-border: #ddd;
|
||||||
|
@panel-border-radius: @border-radius-base;
|
||||||
|
@panel-footer-bg: #f5f5f5;
|
||||||
|
|
||||||
|
@panel-default-text: @gray-dark;
|
||||||
|
@panel-default-border: #ddd;
|
||||||
|
@panel-default-heading-bg: #f5f5f5;
|
||||||
|
|
||||||
|
@panel-primary-text: #fff;
|
||||||
|
@panel-primary-border: @brand-primary;
|
||||||
|
@panel-primary-heading-bg: @brand-primary;
|
||||||
|
|
||||||
|
@panel-success-text: @state-success-text;
|
||||||
|
@panel-success-border: @state-success-border;
|
||||||
|
@panel-success-heading-bg: @state-success-bg;
|
||||||
|
|
||||||
|
@panel-warning-text: @state-warning-text;
|
||||||
|
@panel-warning-border: @state-warning-border;
|
||||||
|
@panel-warning-heading-bg: @state-warning-bg;
|
||||||
|
|
||||||
|
@panel-danger-text: @state-danger-text;
|
||||||
|
@panel-danger-border: @state-danger-border;
|
||||||
|
@panel-danger-heading-bg: @state-danger-bg;
|
||||||
|
|
||||||
|
@panel-info-text: @state-info-text;
|
||||||
|
@panel-info-border: @state-info-border;
|
||||||
|
@panel-info-heading-bg: @state-info-bg;
|
||||||
|
|
||||||
|
|
||||||
|
// Thumbnails
|
||||||
|
// -------------------------
|
||||||
|
@thumbnail-padding: 4px;
|
||||||
|
@thumbnail-bg: @body-bg;
|
||||||
|
@thumbnail-border: #ddd;
|
||||||
|
@thumbnail-border-radius: @border-radius-base;
|
||||||
|
|
||||||
|
@thumbnail-caption-color: @text-color;
|
||||||
|
@thumbnail-caption-padding: 9px;
|
||||||
|
|
||||||
|
|
||||||
|
// Wells
|
||||||
|
// -------------------------
|
||||||
|
@well-bg: #f5f5f5;
|
||||||
|
|
||||||
|
|
||||||
|
// Badges
|
||||||
|
// -------------------------
|
||||||
|
@badge-color: #fff;
|
||||||
|
@badge-link-hover-color: #fff;
|
||||||
|
@badge-bg: @gray-light;
|
||||||
|
|
||||||
|
@badge-active-color: @link-color;
|
||||||
|
@badge-active-bg: #fff;
|
||||||
|
|
||||||
|
@badge-font-weight: bold;
|
||||||
|
@badge-line-height: 1;
|
||||||
|
@badge-border-radius: 10px;
|
||||||
|
|
||||||
|
|
||||||
|
// Breadcrumbs
|
||||||
|
// -------------------------
|
||||||
|
@breadcrumb-bg: #f5f5f5;
|
||||||
|
@breadcrumb-color: #ccc;
|
||||||
|
@breadcrumb-active-color: @gray-light;
|
||||||
|
|
||||||
|
|
||||||
|
// Carousel
|
||||||
|
// ------------------------
|
||||||
|
|
||||||
|
@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
|
||||||
|
|
||||||
|
@carousel-control-color: #fff;
|
||||||
|
@carousel-control-width: 15%;
|
||||||
|
@carousel-control-opacity: .5;
|
||||||
|
@carousel-control-font-size: 20px;
|
||||||
|
|
||||||
|
@carousel-indicator-active-bg: #fff;
|
||||||
|
@carousel-indicator-border-color: #fff;
|
||||||
|
|
||||||
|
@carousel-caption-color: #fff;
|
||||||
|
|
||||||
|
|
||||||
|
// Close
|
||||||
|
// ------------------------
|
||||||
|
@close-color: #000;
|
||||||
|
@close-font-weight: bold;
|
||||||
|
@close-text-shadow: 0 1px 0 #fff;
|
||||||
|
|
||||||
|
|
||||||
|
// Code
|
||||||
|
// ------------------------
|
||||||
|
@code-color: #c7254e;
|
||||||
|
@code-bg: #f9f2f4;
|
||||||
|
|
||||||
|
@pre-bg: #f5f5f5;
|
||||||
|
@pre-color: @gray-dark;
|
||||||
|
@pre-border-color: #ccc;
|
||||||
|
@pre-scrollable-max-height: 340px;
|
||||||
|
|
||||||
|
// Type
|
||||||
|
// ------------------------
|
||||||
|
@text-muted: @gray-light;
|
||||||
|
@abbr-border-color: @gray-light;
|
||||||
|
@headings-small-color: @gray-light;
|
||||||
|
@blockquote-small-color: @gray-light;
|
||||||
|
@blockquote-border-color: @gray-lighter;
|
||||||
|
@page-header-border-color: @gray-lighter;
|
||||||
|
|
||||||
|
// Miscellaneous
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
// Hr border color
|
||||||
|
@hr-border: @gray-lighter;
|
||||||
|
|
||||||
|
// Horizontal forms & lists
|
||||||
|
@component-offset-horizontal: 180px;
|
||||||
|
|
||||||
|
|
||||||
|
// Container sizes
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
// Small screen / tablet
|
||||||
|
@container-tablet: ((720px + @grid-gutter-width));
|
||||||
|
|
||||||
// Default 940px grid
|
// Medium screen / desktop
|
||||||
// -------------------------
|
@container-desktop: ((940px + @grid-gutter-width));
|
||||||
@gridColumns: 12;
|
|
||||||
@gridColumnWidth: 60px;
|
|
||||||
@gridGutterWidth: 20px;
|
|
||||||
@gridRowWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1));
|
|
||||||
|
|
||||||
// 1200px min
|
// Large screen / wide desktop
|
||||||
@gridColumnWidth1200: 70px;
|
@container-lg-desktop: ((1140px + @grid-gutter-width));
|
||||||
@gridGutterWidth1200: 30px;
|
|
||||||
@gridRowWidth1200: (@gridColumns * @gridColumnWidth1200) + (@gridGutterWidth1200 * (@gridColumns - 1));
|
|
||||||
|
|
||||||
// 768px-979px
|
|
||||||
@gridColumnWidth768: 42px;
|
|
||||||
@gridGutterWidth768: 20px;
|
|
||||||
@gridRowWidth768: (@gridColumns * @gridColumnWidth768) + (@gridGutterWidth768 * (@gridColumns - 1));
|
|
||||||
|
|
||||||
|
|
||||||
// Fluid grid
|
|
||||||
// -------------------------
|
|
||||||
@fluidGridColumnWidth: percentage(@gridColumnWidth/@gridRowWidth);
|
|
||||||
@fluidGridGutterWidth: percentage(@gridGutterWidth/@gridRowWidth);
|
|
||||||
|
|
||||||
// 1200px min
|
|
||||||
@fluidGridColumnWidth1200: percentage(@gridColumnWidth1200/@gridRowWidth1200);
|
|
||||||
@fluidGridGutterWidth1200: percentage(@gridGutterWidth1200/@gridRowWidth1200);
|
|
||||||
|
|
||||||
// 768px-979px
|
|
||||||
@fluidGridColumnWidth768: percentage(@gridColumnWidth768/@gridRowWidth768);
|
|
||||||
@fluidGridGutterWidth768: percentage(@gridGutterWidth768/@gridRowWidth768);
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 263 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
@@ -1,37 +1,98 @@
|
|||||||
|
|
||||||
|
// This script should be included at the END of the document.
|
||||||
|
// For the fastest loading it does not inlude $(document).ready()
|
||||||
|
|
||||||
|
// This Document contains a few helper functions for the documentation to display the current version,
|
||||||
|
// collapse and expand the menu etc.
|
||||||
|
|
||||||
|
|
||||||
|
// Function to make the sticky header possible
|
||||||
|
function shiftWindow() {
|
||||||
|
scrollBy(0, -70);
|
||||||
|
console.log("window shifted")
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("hashchange", shiftWindow);
|
||||||
|
|
||||||
|
function loadShift() {
|
||||||
|
if (window.location.hash) {
|
||||||
|
console.log("window has hash");
|
||||||
|
shiftWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(window).load(function() {
|
||||||
|
loadShift();
|
||||||
|
});
|
||||||
|
|
||||||
$(function(){
|
$(function(){
|
||||||
|
|
||||||
// init multi-vers stuff
|
// sidebar accordian-ing
|
||||||
$('.tabswitcher').each(function(i, multi_vers){
|
// don't apply on last object (it should be the FAQ) or the first (it should be introduction)
|
||||||
var tabs = $('<ul></ul>');
|
|
||||||
$(multi_vers).prepend(tabs);
|
// define an array to which all opened items should be added
|
||||||
$(multi_vers).children('.tab').each(function(j, vers_content){
|
var openmenus = [];
|
||||||
vers = $(vers_content).children(':first').text();
|
|
||||||
var id = 'multi_vers_' + '_' + i + '_' + j;
|
var elements = $('.toctree-l2');
|
||||||
$(vers_content).attr('id', id);
|
// for (var i = 0; i < elements.length; i += 1) { var current = $(elements[i]); current.children('ul').hide();}
|
||||||
$(tabs).append('<li><a href="#' + id + '">' + vers + '</a></li>');
|
|
||||||
});
|
|
||||||
|
// set initial collapsed state
|
||||||
|
var elements = $('.toctree-l1');
|
||||||
|
for (var i = 0; i < elements.length; i += 1) {
|
||||||
|
var current = $(elements[i]);
|
||||||
|
if (current.hasClass('current')) {
|
||||||
|
current.addClass('open');
|
||||||
|
currentlink = current.children('a')[0].href;
|
||||||
|
openmenus.push(currentlink);
|
||||||
|
|
||||||
|
// do nothing
|
||||||
|
} else {
|
||||||
|
// collapse children
|
||||||
|
current.children('ul').hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc_version == "") {
|
||||||
|
$('.version-flyer ul').html('<li class="alternative active-slug"><a href="" title="Switch to local">Local</a></li>');
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark the active documentation in the version widget
|
||||||
|
$(".version-flyer a:contains('" + doc_version + "')").parent().addClass('active-slug');
|
||||||
|
|
||||||
|
|
||||||
|
// attached handler on click
|
||||||
|
// Do not attach to first element or last (intro, faq) so that
|
||||||
|
// first and last link directly instead of accordian
|
||||||
|
$('.sidebar > ul > li > a').not(':last').not(':first').click(function(){
|
||||||
|
|
||||||
|
var index = $.inArray(this.href, openmenus)
|
||||||
|
|
||||||
|
if (index > -1) {
|
||||||
|
console.log(index);
|
||||||
|
openmenus.splice(index, 1);
|
||||||
|
|
||||||
|
|
||||||
|
$(this).parent().children('ul').slideUp(200, function() {
|
||||||
|
$(this).parent().removeClass('open'); // toggle after effect
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
openmenus.push(this.href);
|
||||||
|
|
||||||
|
var current = $(this);
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
// $('.sidebar > ul > li').removeClass('current');
|
||||||
|
current.parent().addClass('current').addClass('open'); // toggle before effect
|
||||||
|
current.parent().children('ul').hide();
|
||||||
|
current.parent().children('ul').slideDown(200);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
$( ".tabswitcher" ).tabs();
|
|
||||||
|
// add class to all those which have children
|
||||||
// sidebar acordian-ing
|
$('.sidebar > ul > li').not(':last').not(':first').addClass('has-children');
|
||||||
// don't apply on last object (it should be the FAQ)
|
|
||||||
$('nav > ul > li > a').not(':last').click(function(){
|
|
||||||
if ($(this).parent().hasClass('current')) {
|
|
||||||
$(this).parent().children('ul').slideUp(200, function() {
|
|
||||||
$(this).parent().removeClass('current'); // toggle after effect
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$('nav > ul > li > ul').slideUp(100);
|
|
||||||
var current = $(this);
|
|
||||||
setTimeout(function() {
|
|
||||||
$('nav > ul > li').removeClass('current');
|
|
||||||
current.parent().addClass('current'); // toggle before effect
|
|
||||||
current.parent().children('ul').hide();
|
|
||||||
current.parent().children('ul').slideDown(200);
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
|
|
||||||
* http://benalman.com/projects/jquery-bbq-plugin/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
|
||||||
* Dual licensed under the MIT and GPL licenses.
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*/
|
|
||||||
(function($,p){var i,m=Array.prototype.slice,r=decodeURIComponent,a=$.param,c,l,v,b=$.bbq=$.bbq||{},q,u,j,e=$.event.special,d="hashchange",A="querystring",D="fragment",y="elemUrlAttr",g="location",k="href",t="src",x=/^.*\?|#.*$/g,w=/^.*\#/,h,C={};function E(F){return typeof F==="string"}function B(G){var F=m.call(arguments,1);return function(){return G.apply(this,F.concat(m.call(arguments)))}}function n(F){return F.replace(/^[^#]*#?(.*)$/,"$1")}function o(F){return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/,"$1")}function f(H,M,F,I,G){var O,L,K,N,J;if(I!==i){K=F.match(H?/^([^#]*)\#?(.*)$/:/^([^#?]*)\??([^#]*)(#?.*)/);J=K[3]||"";if(G===2&&E(I)){L=I.replace(H?w:x,"")}else{N=l(K[2]);I=E(I)?l[H?D:A](I):I;L=G===2?I:G===1?$.extend({},I,N):$.extend({},N,I);L=a(L);if(H){L=L.replace(h,r)}}O=K[1]+(H?"#":L||!K[1]?"?":"")+L+J}else{O=M(F!==i?F:p[g][k])}return O}a[A]=B(f,0,o);a[D]=c=B(f,1,n);c.noEscape=function(G){G=G||"";var F=$.map(G.split(""),encodeURIComponent);h=new RegExp(F.join("|"),"g")};c.noEscape(",/");$.deparam=l=function(I,F){var H={},G={"true":!0,"false":!1,"null":null};$.each(I.replace(/\+/g," ").split("&"),function(L,Q){var K=Q.split("="),P=r(K[0]),J,O=H,M=0,R=P.split("]["),N=R.length-1;if(/\[/.test(R[0])&&/\]$/.test(R[N])){R[N]=R[N].replace(/\]$/,"");R=R.shift().split("[").concat(R);N=R.length-1}else{N=0}if(K.length===2){J=r(K[1]);if(F){J=J&&!isNaN(J)?+J:J==="undefined"?i:G[J]!==i?G[J]:J}if(N){for(;M<=N;M++){P=R[M]===""?O.length:R[M];O=O[P]=M<N?O[P]||(R[M+1]&&isNaN(R[M+1])?{}:[]):J}}else{if($.isArray(H[P])){H[P].push(J)}else{if(H[P]!==i){H[P]=[H[P],J]}else{H[P]=J}}}}else{if(P){H[P]=F?i:""}}});return H};function z(H,F,G){if(F===i||typeof F==="boolean"){G=F;F=a[H?D:A]()}else{F=E(F)?F.replace(H?w:x,""):F}return l(F,G)}l[A]=B(z,0);l[D]=v=B(z,1);$[y]||($[y]=function(F){return $.extend(C,F)})({a:k,base:k,iframe:t,img:t,input:t,form:"action",link:k,script:t});j=$[y];function s(I,G,H,F){if(!E(H)&&typeof H!=="object"){F=H;H=G;G=i}return this.each(function(){var L=$(this),J=G||j()[(this.nodeName||"").toLowerCase()]||"",K=J&&L.attr(J)||"";L.attr(J,a[I](K,H,F))})}$.fn[A]=B(s,A);$.fn[D]=B(s,D);b.pushState=q=function(I,F){if(E(I)&&/^#/.test(I)&&F===i){F=2}var H=I!==i,G=c(p[g][k],H?I:{},H?F:2);p[g][k]=G+(/#/.test(G)?"":"#")};b.getState=u=function(F,G){return F===i||typeof F==="boolean"?v(F):v(G)[F]};b.removeState=function(F){var G={};if(F!==i){G=u();$.each($.isArray(F)?F:arguments,function(I,H){delete G[H]})}q(G,2)};e[d]=$.extend(e[d],{add:function(F){var H;function G(J){var I=J[D]=c();J.getState=function(K,L){return K===i||typeof K==="boolean"?l(I,K):l(I,L)[K]};H.apply(this,arguments)}if($.isFunction(F)){H=F;return G}else{H=F.handler;F.handler=G}}})})(jQuery,this);
|
|
||||||
/*
|
|
||||||
* jQuery hashchange event - v1.2 - 2/11/2010
|
|
||||||
* http://benalman.com/projects/jquery-hashchange-plugin/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
|
||||||
* Dual licensed under the MIT and GPL licenses.
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*/
|
|
||||||
(function($,i,b){var j,k=$.event.special,c="location",d="hashchange",l="href",f=$.browser,g=document.documentMode,h=f.msie&&(g===b||g<8),e="on"+d in i&&!h;function a(m){m=m||i[c][l];return m.replace(/^[^#]*#?(.*)$/,"$1")}$[d+"Delay"]=100;k[d]=$.extend(k[d],{setup:function(){if(e){return false}$(j.start)},teardown:function(){if(e){return false}$(j.stop)}});j=(function(){var m={},r,n,o,q;function p(){o=q=function(s){return s};if(h){n=$('<iframe src="javascript:0"/>').hide().insertAfter("body")[0].contentWindow;q=function(){return a(n.document[c][l])};o=function(u,s){if(u!==s){var t=n.document;t.open().close();t[c].hash="#"+u}};o(a())}}m.start=function(){if(r){return}var t=a();o||p();(function s(){var v=a(),u=q(t);if(v!==t){o(t=v,u);$(i).trigger(d)}else{if(u!==t){i[c][l]=i[c][l].replace(/#.*/,"")+"#"+u}}r=setTimeout(s,$[d+"Delay"])})()};m.stop=function(){if(!n){r&&clearTimeout(r);r=0}};return m})()})(jQuery,this);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
/*
|
|
||||||
* urlInternal - v1.0 - 10/7/2009
|
|
||||||
* http://benalman.com/projects/jquery-urlinternal-plugin/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009 "Cowboy" Ben Alman
|
|
||||||
* Dual licensed under the MIT and GPL licenses.
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*/
|
|
||||||
(function($){var g,i=!0,r=!1,m=window.location,h=Array.prototype.slice,b=m.href.match(/^((https?:\/\/.*?\/)?[^#]*)#?.*$/),u=b[1]+"#",t=b[2],e,l,f,q,c,j,x="elemUrlAttr",k="href",y="src",p="urlInternal",d="urlExternal",n="urlFragment",a,s={};function w(A){var z=h.call(arguments,1);return function(){return A.apply(this,z.concat(h.call(arguments)))}}$.isUrlInternal=q=function(z){if(!z||j(z)){return g}if(a.test(z)){return i}if(/^(?:https?:)?\/\//i.test(z)){return r}if(/^[a-z\d.-]+:/i.test(z)){return g}return i};$.isUrlExternal=c=function(z){var A=q(z);return typeof A==="boolean"?!A:A};$.isUrlFragment=j=function(z){var A=(z||"").match(/^([^#]?)([^#]*#).*$/);return !!A&&(A[2]==="#"||z.indexOf(u)===0||(A[1]==="/"?t+A[2]===u:!/^https?:\/\//i.test(z)&&$('<a href="'+z+'"/>')[0].href.indexOf(u)===0))};function v(A,z){return this.filter(":"+A+(z?"("+z+")":""))}$.fn[p]=w(v,p);$.fn[d]=w(v,d);$.fn[n]=w(v,n);function o(D,C,B,A){var z=A[3]||e()[(C.nodeName||"").toLowerCase()]||"";return z?!!D(C.getAttribute(z)):r}$.expr[":"][p]=w(o,q);$.expr[":"][d]=w(o,c);$.expr[":"][n]=w(o,j);$[x]||($[x]=function(z){return $.extend(s,z)})({a:k,base:k,iframe:y,img:y,input:y,form:"action",link:k,script:y});e=$[x];$.urlInternalHost=l=function(B){B=B?"(?:(?:"+Array.prototype.join.call(arguments,"|")+")\\.)?":"";var A=new RegExp("^"+B+"(.*)","i"),z="^(?:"+m.protocol+")?//"+m.hostname.replace(A,B+"$1").replace(/\\?\./g,"\\.")+(m.port?":"+m.port:"")+"/";return f(z)};$.urlInternalRegExp=f=function(z){if(z){a=typeof z==="string"?new RegExp(z,"i"):z}return a};l("www")})(jQuery);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../CONTRIBUTING.md
|
||||||
@@ -1 +1,2 @@
|
|||||||
Solomon Hykes <solomon@dotcloud.com> (@shykes)
|
Solomon Hykes <solomon@dotcloud.com> (@shykes)
|
||||||
|
Tianon Gravi <admwiggin@gmail.com> (@tianon)
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
# The Docker maintainer manual
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Dear maintainer. Thank you for investing the time and energy to help make Docker as
|
||||||
|
useful as possible. Maintaining a project is difficult, sometimes unrewarding work.
|
||||||
|
Sure, you will get to contribute cool features to the project. But most of your time
|
||||||
|
will be spent reviewing, cleaning up, documenting, andswering questions, justifying
|
||||||
|
design decisions - while everyone has all the fun! But remember - the quality of the
|
||||||
|
maintainers work is what distinguishes the good projects from the great.
|
||||||
|
So please be proud of your work, even the unglamourous parts, and encourage a culture
|
||||||
|
of appreciation and respect for *every* aspect of improving the project - not just the
|
||||||
|
hot new features.
|
||||||
|
|
||||||
|
This document is a manual for maintainers old and new. It explains what is expected of
|
||||||
|
maintainers, how they should work, and what tools are available to them.
|
||||||
|
|
||||||
|
This is a living document - if you see something out of date or missing, speak up!
|
||||||
|
|
||||||
|
|
||||||
|
## What are a maintainer's responsibility?
|
||||||
|
|
||||||
|
It is every maintainer's responsibility to:
|
||||||
|
|
||||||
|
* 1) Expose a clear roadmap for improving their component.
|
||||||
|
* 2) Deliver prompt feedback and decisions on pull requests.
|
||||||
|
* 3) Be available to anyone with questions, bug reports, criticism etc. on their component. This includes irc, github requests and the mailing list.
|
||||||
|
* 4) Make sure their component respects the philosophy, design and roadmap of the project.
|
||||||
|
|
||||||
|
|
||||||
|
## How are decisions made?
|
||||||
|
|
||||||
|
Short answer: with pull requests to the docker repository.
|
||||||
|
|
||||||
|
Docker is an open-source project with an open design philosophy. This means that the repository is the source of truth for EVERY aspect of the project,
|
||||||
|
including its philosophy, design, roadmap and APIs. *If it's part of the project, it's in the repo. It's in the repo, it's part of the project.*
|
||||||
|
|
||||||
|
As a result, all decisions can be expressed as changes to the repository. An implementation change is a change to the source code. An API change is a change to
|
||||||
|
the API specification. A philosophy change is a change to the philosophy manifesto. And so on.
|
||||||
|
|
||||||
|
All decisions affecting docker, big and small, follow the same 3 steps:
|
||||||
|
|
||||||
|
* Step 1: Open a pull request. Anyone can do this.
|
||||||
|
|
||||||
|
* Step 2: Discuss the pull request. Anyone can do this.
|
||||||
|
|
||||||
|
* Step 3: Accept or refuse a pull request. The relevant maintainer does this (see below "Who decides what?")
|
||||||
|
|
||||||
|
|
||||||
|
## Who decides what?
|
||||||
|
|
||||||
|
So all decisions are pull requests, and the relevant maintainer makes the decision by accepting or refusing the pull request.
|
||||||
|
But how do we identify the relevant maintainer for a given pull request?
|
||||||
|
|
||||||
|
Docker follows the timeless, highly efficient and totally unfair system known as [Benevolent dictator for life](http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life),
|
||||||
|
with yours truly, Solomon Hykes, in the role of BDFL.
|
||||||
|
This means that all decisions are made by default by me. Since making every decision myself would be highly unscalable, in practice decisions are spread across multiple maintainers.
|
||||||
|
|
||||||
|
The relevant maintainer for a pull request is assigned in 3 steps:
|
||||||
|
|
||||||
|
* Step 1: Determine the subdirectory affected by the pull request. This might be src/registry, docs/source/api, or any other part of the repo.
|
||||||
|
|
||||||
|
* Step 2: Find the MAINTAINERS file which affects this directory. If the directory itself does not have a MAINTAINERS file, work your way up the the repo hierarchy until you find one.
|
||||||
|
|
||||||
|
* Step 3: The first maintainer listed is the primary maintainer. The pull request is assigned to him. He may assign it to other listed maintainers, at his discretion.
|
||||||
|
|
||||||
|
|
||||||
|
### I'm a maintainer, should I make pull requests too?
|
||||||
|
|
||||||
|
Yes. Nobody should ever push to master directly. All changes should be made through a pull request.
|
||||||
|
|
||||||
|
### Who assigns maintainers?
|
||||||
|
|
||||||
|
Solomon.
|
||||||
|
|
||||||
|
### How is this process changed?
|
||||||
|
|
||||||
|
Just like everything else: by making a pull request :)
|
||||||
@@ -116,6 +116,7 @@ To run properly, docker needs the following software to be installed at runtime:
|
|||||||
* iptables version 1.4 or later
|
* iptables version 1.4 or later
|
||||||
* The lxc utility scripts (http://lxc.sourceforge.net) version 0.8 or later.
|
* The lxc utility scripts (http://lxc.sourceforge.net) version 0.8 or later.
|
||||||
* Git version 1.7 or later
|
* Git version 1.7 or later
|
||||||
|
* XZ Utils 4.9 or later
|
||||||
|
|
||||||
## Kernel dependencies
|
## Kernel dependencies
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Hacking on Docker
|
||||||
|
|
||||||
|
The hack/ directory holds information and tools for everyone involved in the process of creating and
|
||||||
|
distributing Docker, specifically:
|
||||||
|
|
||||||
|
## Guides
|
||||||
|
|
||||||
|
If you're a *contributor* or aspiring contributor, you should read CONTRIBUTORS.md.
|
||||||
|
|
||||||
|
If you're a *maintainer* or aspiring maintainer, you should read MAINTAINERS.md.
|
||||||
|
|
||||||
|
If you're a *packager* or aspiring packager, you should read PACKAGERS.md.
|
||||||
|
|
||||||
|
If you're a maintainer in charge of a *release*, you should read RELEASE-CHECKLIST.md.
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
A high-level roadmap is available at ROADMAP.md.
|
||||||
|
|
||||||
|
|
||||||
|
## Build tools
|
||||||
|
|
||||||
|
make.sh is the primary build tool for docker. It is used for compiling the official binary,
|
||||||
|
running the test suite, and pushing releases.
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
This directory contains material helpful for hacking on docker.
|
|
||||||
|
|
||||||
make hack
|
|
||||||
=========
|
|
||||||
|
|
||||||
Set up an Ubuntu 12.04 virtual machine for developers including kernel 3.8
|
|
||||||
go1.1 and buildbot. The environment is setup in a way that can be used through
|
|
||||||
the usual go workflow and/or the root Makefile. You can either edit on
|
|
||||||
your host, or inside the VM (using make ssh-dev) and run and test docker
|
|
||||||
inside the VM.
|
|
||||||
|
|
||||||
dependencies: vagrant, virtualbox packages and python package requests
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
When running 'make hack' at the docker root directory, it spawns a virtual
|
|
||||||
machine in the background running a buildbot instance and adds a git
|
|
||||||
post-commit hook that automatically run docker tests for you each time you
|
|
||||||
commit in your local docker repository.
|
|
||||||
|
|
||||||
You can check your buildbot instance at http://192.168.33.21:8010/waterfall
|
|
||||||
@@ -55,11 +55,15 @@ EXAMPLES:
|
|||||||
|
|
||||||
### 4. Run all tests
|
### 4. Run all tests
|
||||||
|
|
||||||
```bash
|
FIXME
|
||||||
go test
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Commit and create a pull request
|
### 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
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add CHANGELOG.md
|
git add CHANGELOG.md
|
||||||
@@ -67,12 +71,12 @@ git commit -m "Bump version to $VERSION"
|
|||||||
git push origin bump_$VERSION
|
git push origin bump_$VERSION
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Get 2 other maintainers to validate the pull request
|
### 7. Get 2 other maintainers to validate the pull request
|
||||||
|
|
||||||
### 7. Merge the pull request and apply tags
|
### 8. Merge the pull request and apply tags
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git checkout master
|
git checkout release
|
||||||
git merge bump_$VERSION
|
git merge bump_$VERSION
|
||||||
git tag -a v$VERSION # Don't forget the v!
|
git tag -a v$VERSION # Don't forget the v!
|
||||||
git tag -f -a latest
|
git tag -f -a latest
|
||||||
@@ -80,20 +84,27 @@ git push
|
|||||||
git push --tags
|
git push --tags
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8. Publish binaries
|
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
|
||||||
|
|
||||||
To run this you will need access to the release credentials.
|
To run this you will need access to the release credentials.
|
||||||
Get them from [the infrastructure maintainers](
|
Get them from [the infrastructure maintainers](
|
||||||
https://github.com/dotcloud/docker/blob/master/hack/infrastructure/MAINTAINERS).
|
https://github.com/dotcloud/docker/blob/master/hack/infrastructure/MAINTAINERS).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t releasedocker .
|
docker build -t docker .
|
||||||
docker run \
|
docker run \
|
||||||
-e AWS_S3_BUCKET=get-nightly.docker.io \
|
-e AWS_S3_BUCKET=get-nightly.docker.io \
|
||||||
-e AWS_ACCESS_KEY=$(cat ~/.aws/access_key) \
|
-e AWS_ACCESS_KEY=$(cat ~/.aws/access_key) \
|
||||||
-e AWS_SECRET_KEY=$(cat ~/.aws/secret_key) \
|
-e AWS_SECRET_KEY=$(cat ~/.aws/secret_key) \
|
||||||
-e GPG_PASSPHRASE=supersecretsesame \
|
-e GPG_PASSPHRASE=supersecretsesame \
|
||||||
releasedocker
|
docker
|
||||||
|
hack/release.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
It will build and upload the binaries on the specified bucket (you should
|
It will build and upload the binaries on the specified bucket (you should
|
||||||
@@ -101,6 +112,6 @@ use get-nightly.docker.io for general testing, and once everything is fine,
|
|||||||
switch to get.docker.io).
|
switch to get.docker.io).
|
||||||
|
|
||||||
|
|
||||||
### 9. Rejoice!
|
### 10. Rejoice!
|
||||||
|
|
||||||
Congratulations! You're done.
|
Congratulations! You're done.
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
# -*- mode: ruby -*-
|
|
||||||
# vi: set ft=ruby :
|
|
||||||
|
|
||||||
BOX_NAME = "ubuntu-dev"
|
|
||||||
BOX_URI = "http://files.vagrantup.com/precise64.box"
|
|
||||||
VM_IP = "192.168.33.21"
|
|
||||||
USER = "vagrant"
|
|
||||||
GOPATH = "/data/docker"
|
|
||||||
DOCKER_PATH = "#{GOPATH}/src/github.com/dotcloud/docker"
|
|
||||||
CFG_PATH = "#{DOCKER_PATH}/hack/environment"
|
|
||||||
BUILDBOT_PATH = "/data/buildbot"
|
|
||||||
|
|
||||||
Vagrant::Config.run do |config|
|
|
||||||
# Setup virtual machine box
|
|
||||||
config.vm.box = BOX_NAME
|
|
||||||
config.vm.box_url = BOX_URI
|
|
||||||
config.vm.share_folder "v-data", DOCKER_PATH, "#{File.dirname(__FILE__)}/.."
|
|
||||||
config.vm.network :hostonly, VM_IP
|
|
||||||
# Stop if deployment has been done
|
|
||||||
config.vm.provision :shell, :inline => "[ ! -f /usr/bin/git ]"
|
|
||||||
# Touch for makefile
|
|
||||||
pkg_cmd = "touch #{DOCKER_PATH}; "
|
|
||||||
# Install docker dependencies
|
|
||||||
pkg_cmd << "apt-get update -qq; apt-get install -y python-software-properties; " \
|
|
||||||
"add-apt-repository -y ppa:dotcloud/docker-golang/ubuntu; apt-get update -qq; " \
|
|
||||||
"apt-get install -y linux-image-generic-lts-raring lxc git aufs-tools golang-stable make; " \
|
|
||||||
"chown -R #{USER}.#{USER} #{GOPATH}; " \
|
|
||||||
"install -m 0664 #{CFG_PATH}/bash_profile /home/#{USER}/.bash_profile"
|
|
||||||
config.vm.provision :shell, :inline => pkg_cmd
|
|
||||||
# Deploy buildbot CI
|
|
||||||
pkg_cmd = "apt-get install -q -y python-dev python-pip supervisor; " \
|
|
||||||
"pip install -q -r #{CFG_PATH}/requirements.txt; " \
|
|
||||||
"chown #{USER}.#{USER} /data; cd /data; " \
|
|
||||||
"#{CFG_PATH}/setup.sh #{USER} #{GOPATH} #{DOCKER_PATH} #{CFG_PATH} #{BUILDBOT_PATH}"
|
|
||||||
config.vm.provision :shell, :inline => pkg_cmd
|
|
||||||
end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Files used to setup the developer virtual machine
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# ~/.bash_profile : executed by the command interpreter for login shells.
|
|
||||||
|
|
||||||
# if running bash
|
|
||||||
if [ -n "$BASH_VERSION" ]; then
|
|
||||||
# include .bashrc if it exists
|
|
||||||
if [ -f "$HOME/.bashrc" ]; then
|
|
||||||
. "$HOME/.bashrc"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# set PATH so it includes user's private bin if it exists
|
|
||||||
[ -d "$HOME/bin" ] && PATH="$HOME/bin:$PATH"
|
|
||||||
|
|
||||||
docker=/data/docker/src/github.com/dotcloud/docker
|
|
||||||
[ -d $docker ] && cd $docker
|
|
||||||
|
|
||||||
export GOPATH=/data/docker
|
|
||||||
export PATH=$PATH:$GOPATH/bin
|
|
||||||
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
[program:buildmaster]
|
|
||||||
command=su vagrant -c "buildbot start master"
|
|
||||||
directory=/data/buildbot
|
|
||||||
chown= root:root
|
|
||||||
redirect_stderr=true
|
|
||||||
stdout_logfile=/var/log/supervisor/buildbot-master.log
|
|
||||||
stderr_logfile=/var/log/supervisor/buildbot-master.log
|
|
||||||
|
|
||||||
[program:buildworker]
|
|
||||||
command=buildslave start slave
|
|
||||||
directory=/data/buildbot
|
|
||||||
chown= root:root
|
|
||||||
redirect_stderr=true
|
|
||||||
stdout_logfile=/var/log/supervisor/buildbot-slave.log
|
|
||||||
stderr_logfile=/var/log/supervisor/buildbot-slave.log
|
|
||||||
|
|
||||||
[group:buildbot]
|
|
||||||
programs=buildmaster,buildworker
|
|
||||||