Compare commits

..

1 Commits

Author SHA1 Message Date
Arnaud Porterie 7e803ba6b2 Bump to version v1.5.0
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2015-01-22 13:30:47 -08:00
97 changed files with 733 additions and 2278 deletions
+1 -1
View File
@@ -10,5 +10,5 @@ script:
- rm integration-cli/docker_cli_daemon_test.go
- rm integration-cli/docker_cli_exec_test.go
# Validate and test.
- hack/make.sh validate-dco validate-gofmt validate-toml
- hack/make.sh validate-dco validate-gofmt
- hack/make.sh binary cross test-unit test-integration-cli test-integration test-docker-py
+2 -19
View File
@@ -6,24 +6,6 @@
#
# For explanation on this file format: man git-shortlog
Patrick Stapleton <github@gdi2290.com>
Shishir Mahajan <shishir.mahajan@redhat.com> <smahajan@redhat.com>
Erwin van der Koogh <info@erronis.nl>
Ahmed Kamal <email.ahmedkamal@googlemail.com>
Tejesh Mehta <tejesh.mehta@gmail.com> <tj@init.me>
Cristian Staretu <cristian.staretu@gmail.com>
Cristian Staretu <cristian.staretu@gmail.com> <unclejacksons@gmail.com>
Cristian Staretu <cristian.staretu@gmail.com> <unclejack@users.noreply.github.com>
Marcus Linke <marcus.linke@gmx.de>
Aleksandrs Fadins <aleks@s-ko.net>
Christopher Latham <sudosurootdev@gmail.com>
Hu Keping <hukeping@huawei.com>
Wayne Chang <wayne@neverfear.org>
Chen Chao <cc272309126@gmail.com>
Daehyeok Mun <daehyeok@gmail.com>
<daehyeok@gmail.com> <daehyeok@daehyeokui-MacBook-Air.local>
<jt@yadutaf.fr> <admin@jtlebi.fr>
<jeff@docker.com> <jefferya@programmerq.net>
<charles.hooper@dotcloud.com> <chooper@plumata.com>
<daniel.mizyrycki@dotcloud.com> <daniel@dotcloud.com>
<daniel.mizyrycki@dotcloud.com> <mzdaniel@glidelink.net>
@@ -76,7 +58,7 @@ Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
<michael@docker.com> <michael@crosbymichael.com>
<michael@docker.com> <crosby.michael@gmail.com>
<michael@docker.com> <crosbymichael@gmail.com>
<github@developersupport.net> <github@metaliveblog.com>
<github@developersupport.net> <github@metaliveblog.com>
<brandon@ifup.org> <brandon@ifup.co>
<dano@spotify.com> <daniel.norberg@gmail.com>
<danny@codeaholics.org> <Danny.Yates@mailonline.co.uk>
@@ -92,6 +74,7 @@ Sven Dowideit <SvenDowideit@home.org.au> <SvenDowideit@docker.com>
Sven Dowideit <SvenDowideit@home.org.au> <¨SvenDowideit@home.org.au¨>
Sven Dowideit <SvenDowideit@home.org.au> <SvenDowideit@users.noreply.github.com>
Sven Dowideit <SvenDowideit@home.org.au> <sven@t440s.home.gateway>
unclejack <unclejacksons@gmail.com> <unclejack@users.noreply.github.com>
<alexl@redhat.com> <alexander.larsson@gmail.com>
Alexandr Morozov <lk4d4math@gmail.com>
<git.nivoc@neverbox.com> <kuehnle@online.de>
+57 -112
View File
@@ -12,46 +12,41 @@ Adam Singer <financeCoding@gmail.com>
Aditya <aditya@netroy.in>
Adrian Mouat <adrian.mouat@gmail.com>
Adrien Folie <folie.adrien@gmail.com>
Ahmed Kamal <email.ahmedkamal@googlemail.com>
Ahmet Alp Balkan <ahmetb@microsoft.com>
Aidan Hobson Sayers <aidanhs@cantab.net>
AJ Bowen <aj@gandi.net>
Al Tobey <al@ooyala.com>
alambike <alambike@gmail.com>
Alan Thompson <cloojure@gmail.com>
Albert Callarisa <shark234@gmail.com>
Albert Zhang <zhgwenming@gmail.com>
Aleksa Sarai <cyphar@cyphar.com>
Aleksandrs Fadins <aleks@s-ko.net>
Alex Gaynor <alex.gaynor@gmail.com>
Alex Warhawk <ax.warhawk@gmail.com>
Alexander Boyd <alex@opengroove.org>
Alexander Larsson <alexl@redhat.com>
Alexander Morozov <lk4d4@docker.com>
Alexander Shopov <ash@kambanaria.org>
Alexandr Morozov <lk4d4@docker.com>
Alexey Kotlyarov <alexey@infoxchange.net.au>
Alexey Shamrin <shamrin@gmail.com>
Alex Gaynor <alex.gaynor@gmail.com>
Alexis THOMAS <fr.alexisthomas@gmail.com>
Alex Warhawk <ax.warhawk@gmail.com>
almoehi <almoehi@users.noreply.github.com>
Al Tobey <al@ooyala.com>
Álvaro Lázaro <alvaro.lazaro.g@gmail.com>
amangoel <amangoel@gmail.com>
Amit Bakshi <ambakshi@gmail.com>
Anand Patil <anand.prabhakar.patil@gmail.com>
AnandkumarPatel <anandkumarpatel@gmail.com>
Andre Dublin <81dublin@gmail.com>
Anand Patil <anand.prabhakar.patil@gmail.com>
Andrea Luzzardi <aluzzardi@gmail.com>
Andrea Turli <andrea.turli@gmail.com>
Andreas Köhler <andi5.py@gmx.net>
Andreas Savvides <andreas@editd.com>
Andreas Tiefenthaler <at@an-ti.eu>
Andrew C. Bodine <acbodine@us.ibm.com>
Andrea Turli <andrea.turli@gmail.com>
Andre Dublin <81dublin@gmail.com>
Andrew Duckworth <grillopress@gmail.com>
Andrew France <andrew@avito.co.uk>
Andrew Macgregor <andrew.macgregor@agworld.com.au>
Andrew Munsell <andrew@wizardapps.net>
Andrews Medina <andrewsmedina@gmail.com>
Andrew Weiss <andrew.weiss@outlook.com>
Andrew Williams <williams.andrew@gmail.com>
Andrews Medina <andrewsmedina@gmail.com>
Andrey Petrov <andrey.petrov@shazow.net>
Andrey Stolbovsky <andrey.stolbovsky@gmail.com>
Andy Chambers <anchambers@paypal.com>
@@ -61,8 +56,6 @@ Andy Kipp <andy@rstudio.com>
Andy Rothfusz <github@developersupport.net>
Andy Smith <github@anarkystic.com>
Andy Wilson <wilson.andrew.j+github@gmail.com>
Ankush Agarwal <ankushagarwal11@gmail.com>
Anthony Baire <Anthony.Baire@irisa.fr>
Anthony Bishopric <git@anthonybishopric.com>
Anton Löfgren <anton.lofgren@gmail.com>
Anton Nikitin <anton.k.nikitin@gmail.com>
@@ -79,11 +72,11 @@ Barry Allard <barry.allard@gmail.com>
Bartłomiej Piotrowski <b@bpiotrowski.pl>
bdevloed <boris.de.vloed@gmail.com>
Ben Firshman <ben@firshman.co.uk>
Benjamin Atkin <ben@benatkin.com>
Benoit Chesneau <bchesneau@gmail.com>
Ben Sargent <ben@brokendigits.com>
Ben Toews <mastahyeti@gmail.com>
Ben Wiklund <ben@daisyowl.com>
Benjamin Atkin <ben@benatkin.com>
Benoit Chesneau <bchesneau@gmail.com>
Bernerd Schaefer <bj.schaefer@gmail.com>
Bert Goethals <bert@bertg.be>
Bhiraj Butala <abhiraj.butala@gmail.com>
@@ -120,22 +113,18 @@ Charles Hooper <charles.hooper@dotcloud.com>
Charles Lindsay <chaz@chazomatic.us>
Charles Merriam <charles.merriam@gmail.com>
Charlie Lewis <charliel@lab41.org>
Chen Chao <cc272309126@gmail.com>
Chewey <prosto-chewey@users.noreply.github.com>
Chia-liang Kao <clkao@clkao.org>
Chris Alfonso <calfonso@redhat.com>
Chris Armstrong <chris@opdemand.com>
chrismckinnel <chris.mckinnel@tangentlabs.co.uk>
Chris Snow <chsnow123@gmail.com>
Chris St. Pierre <chris.a.st.pierre@gmail.com>
chrismckinnel <chris.mckinnel@tangentlabs.co.uk>
Christian Berendt <berendt@b1-systems.de>
Christian Stefanescu <st.chris@gmail.com>
ChristoperBiscardi <biscarch@sketcht.com>
Christophe Troestler <christophe.Troestler@umons.ac.be>
Christopher Currie <codemonkey+github@gmail.com>
Christopher Latham <sudosurootdev@gmail.com>
Christopher Rigor <crigor@gmail.com>
Chun Chen <chenchun.feed@gmail.com>
Christophe Troestler <christophe.Troestler@umons.ac.be>
Ciro S. Costa <ciro.costa@usp.br>
Clayton Coleman <ccoleman@redhat.com>
Colin Dunklau <colin.dunklau@gmail.com>
@@ -143,20 +132,15 @@ Colin Rice <colin@daedrum.net>
Colin Walters <walters@verbum.org>
Cory Forsyth <cory.forsyth@gmail.com>
cressie176 <github@stephen-cresswell.net>
Cristian Staretu <cristian.staretu@gmail.com>
Cruceru Calin-Cristian <crucerucalincristian@gmail.com>
Daan van Berkel <daan.v.berkel.1980@gmail.com>
Daehyeok Mun <daehyeok@gmail.com>
Daehyeok.Mun <daehyeok@gmail.com>
Dafydd Crosby <dtcrsby@gmail.com>
Dan Buch <d.buch@modcloth.com>
Dan Cotora <dan@bluevision.ro>
Dan Griffin <dgriffin@peer1.com>
Dan Hirsch <thequux@upstandinghackers.com>
Dan Keder <dan.keder@gmail.com>
Dan McPherson <dmcphers@redhat.com>
Dan Stine <sw@stinemail.com>
Dan Walsh <dwalsh@redhat.com>
Dan Williams <me@deedubs.com>
Daniel, Dao Quang Minh <dqminh89@gmail.com>
Daniel Exner <dex@dragonslave.de>
Daniel Farrell <dfarrell@redhat.com>
Daniel Garcia <daniel@danielgarcia.info>
@@ -168,27 +152,29 @@ Daniel Nordberg <dnordberg@gmail.com>
Daniel Robinson <gottagetmac@gmail.com>
Daniel Von Fange <daniel@leancoder.com>
Daniel YC Lin <dlin.tw@gmail.com>
Daniel, Dao Quang Minh <dqminh89@gmail.com>
Dan Keder <dan.keder@gmail.com>
Dan McPherson <dmcphers@redhat.com>
Danny Berger <dpb587@gmail.com>
Danny Yates <danny@codeaholics.org>
Dan Stine <sw@stinemail.com>
Dan Walsh <dwalsh@redhat.com>
Dan Williams <me@deedubs.com>
Darren Coxall <darren@darrencoxall.com>
Darren Shepherd <darren.s.shepherd@gmail.com>
David Anderson <dave@natulte.net>
David Calavera <david.calavera@gmail.com>
David Corking <dmc-source@dcorking.com>
Davide Ceretti <davide.ceretti@hogarthww.com>
David Gageot <david@gageot.net>
David Gebler <davidgebler@gmail.com>
David Mat <david@davidmat.com>
David Mcanulty <github@hellspark.com>
David Pelaez <pelaez89@gmail.com>
David Röthlisberger <david@rothlis.net>
David Sissitka <me@dsissitka.com>
Davide Ceretti <davide.ceretti@hogarthww.com>
Dawn Chen <dawnchen@google.com>
decadent <decadent@users.noreply.github.com>
Deni Bertovic <deni@kset.org>
Derek <crq@kernel.org>
Derek <crquan@gmail.com>
Derek McGowan <derek@mcgstyle.net>
Deric Crago <deric.crago@gmail.com>
Deshi Xiao <dxiao@redhat.com>
@@ -196,16 +182,14 @@ Dinesh Subhraveti <dineshs@altiscale.com>
Djibril Koné <kone.djibril@gmail.com>
dkumor <daniel@dkumor.com>
Dmitry Demeshchuk <demeshchuk@gmail.com>
Dmitry V. Krivenok <krivenok.dmitry@gmail.com>
Dolph Mathews <dolph.mathews@gmail.com>
Dominik Honnef <dominik@honnef.co>
Don Kjer <don.kjer@gmail.com>
Don Spaulding <donspauldingii@gmail.com>
Doug Davis <dug@us.ibm.com>
doug tangren <d.tangren@gmail.com>
Dr Nic Williams <drnicwilliams@gmail.com>
dragon788 <dragon788@users.noreply.github.com>
Dražen Lučanin <kermit666@gmail.com>
Dr Nic Williams <drnicwilliams@gmail.com>
Dustin Sallings <dustin@spy.net>
Edmund Wagner <edmund-wagner@web.de>
Eiichi Tsukata <devel@etsukata.com>
@@ -213,22 +197,19 @@ Eike Herzbach <eike@herzbach.net>
Eivind Uggedal <eivind@uggedal.com>
Elias Probst <mail@eliasprobst.eu>
Emil Hernvall <emil@quench.at>
Emily Maier <emily@emilymaier.net>
Emily Rose <emily@contactvibe.com>
Eric Hanchrow <ehanchrow@ine.com>
Eric Lee <thenorthsecedes@gmail.com>
Eric Myhre <hash@exultant.us>
Eric Paris <eparis@redhat.com>
Eric Windisch <ewindisch@docker.com>
Erik Dubbelboer <erik@dubbelboer.com>
Erik Hollensbe <github@hollensbe.org>
Erik Inge Bolsø <knan@redpill-linpro.com>
Erik Kristensen <erik@erikkristensen.com>
Erno Hopearuoho <erno.hopearuoho@gmail.com>
Erwin van der Koogh <info@erronis.nl>
Eugene Yakubovich <eugene.yakubovich@coreos.com>
eugenkrizo <eugen.krizo@gmail.com>
Evan Carmi <carmi@users.noreply.github.com>
evanderkoogh <info@erronis.nl>
Evan Hazlett <ejhazlett@gmail.com>
Evan Krall <krall@yelp.com>
Evan Phoenix <evan@fallingsnow.net>
@@ -249,9 +230,9 @@ Francisco Carriedo <fcarriedo@gmail.com>
Francisco Souza <f@souza.cc>
Frank Macreery <frank@macreery.com>
Frank Rosquin <frank.rosquin+github@gmail.com>
Fred Lifton <fred.lifton@docker.com>
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
Frederik Loeffert <frederik@zitrusmedia.de>
Fred Lifton <fred.lifton@docker.com>
Freek Kalter <freek@kalteronline.org>
Gabe Rosenhouse <gabe@missionst.com>
Gabor Nagy <mail@aigeruth.hu>
@@ -285,15 +266,13 @@ Hector Castro <hectcastro@gmail.com>
Henning Sprang <henning.sprang@gmail.com>
Hobofan <goisser94@gmail.com>
Hollie Teal <hollie@docker.com>
Hu Keping <hukeping@huawei.com>
Hu Tao <hutao@cn.fujitsu.com>
Huayi Zhang <irachex@gmail.com>
Hugo Duncan <hugo@hugoduncan.org>
Hunter Blanks <hunter@twilio.com>
Hu Tao <hutao@cn.fujitsu.com>
Huu Nguyen <huu@prismskylabs.com>
hyeongkyu.lee <hyeongkyu.lee@navercorp.com>
Ian Babrou <ibobrik@gmail.com>
Ian Bishop <ianbishop@pace7.com>
Ian Bull <irbull@gmail.com>
Ian Main <imain@redhat.com>
Ian Truslove <ian.truslove@gmail.com>
@@ -305,10 +284,8 @@ Isabel Jimenez <contact.isabeljimenez@gmail.com>
Isao Jonas <isao.jonas@gmail.com>
Ivan Fraixedes <ifcdev@gmail.com>
Jack Danger Canty <jackdanger@squareup.com>
Jacob Atzen <jacob@jacobatzen.dk>
Jacob Edelman <edelman.jd@gmail.com>
Jake Moshenko <jake@devtable.com>
jakedt <jake@devtable.com>
Jake Moshenko <jake@devtable.com>
James Allen <jamesallen0108@gmail.com>
James Carr <james.r.carr@gmail.com>
James DeFelice <james.defelice@ishisystems.com>
@@ -329,52 +306,49 @@ Jason Plum <jplum@devonit.com>
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
Jean-Paul Calderone <exarkun@twistedmatrix.com>
Jean-Tiare Le Bigot <jt@yadutaf.fr>
Jeff Anderson <jeff@docker.com>
Jeff Lindsay <progrium@gmail.com>
Jeff Welch <whatthejeff@gmail.com>
Jeffrey Bolle <jeffreybolle@gmail.com>
Jeff Welch <whatthejeff@gmail.com>
Jeremy Grosser <jeremy@synack.me>
Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
Jesse Dubay <jesse@thefortytwo.net>
Jessica Frazelle <jess@docker.com>
Jezeniel Zapanta <jpzapanta22@gmail.com>
Jilles Oldenbeuving <ojilles@gmail.com>
Jim Alateras <jima@comware.com.au>
Jim Perrin <jperrin@centos.org>
Jimmy Cuadra <jimmy@jimmycuadra.com>
Jim Perrin <jperrin@centos.org>
Jiří Župka <jzupka@redhat.com>
Joe Beda <joe.github@bedafamily.com>
Joe Ferguson <joe@infosiftr.com>
Joel Handwell <joelhandwell@gmail.com>
Joe Shaw <joe@joeshaw.org>
Joe Van Dyk <joe@tanga.com>
Joel Friedly <joelfriedly@gmail.com>
Joel Handwell <joelhandwell@gmail.com>
Joffrey F <joffrey@docker.com>
Johan Euphrosine <proppy@google.com>
Johan Rydberg <johan.rydberg@gmail.com>
Johannes 'fish' Ziemke <github@freigeist.org>
Johan Rydberg <johan.rydberg@gmail.com>
John Costa <john.costa@gmail.com>
John Feminella <jxf@jxf.me>
John Gardiner Myers <jgmyers@proofpoint.com>
John Gossman <johngos@microsoft.com>
John OBrien III <jobrieniii@yahoo.com>
John Warwick <jwarwick@gmail.com>
Jon Wedaman <jweede@gmail.com>
Jonas Pfenniger <jonas@pfenniger.name>
Jonathan A. Sternberg <jonathansternberg@gmail.com>
Jonathan Boulle <jonathanboulle@gmail.com>
Jonathan Camp <jonathan@irondojo.com>
Jonathan McCrohan <jmccrohan@gmail.com>
Jonathan Mueller <j.mueller@apoveda.ch>
Jonathan Pares <jonathanpa@users.noreply.github.com>
Jonathan Rudenberg <jonathan@titanous.com>
Jon Wedaman <jweede@gmail.com>
Joost Cassee <joost@cassee.net>
Jordan Arentsen <blissdev@gmail.com>
Jordan Sissel <jls@semicomplete.com>
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
Joseph Hager <ajhager@gmail.com>
Josh <jokajak@gmail.com>
Josh Hawn <josh.hawn@docker.com>
Josh <jokajak@gmail.com>
Josh Poimboeuf <jpoimboe@redhat.com>
Josiah Kiehl <jkiehl@riotgames.com>
JP <jpellerin@leapfrogonline.com>
@@ -386,9 +360,6 @@ Justin Force <justin.force@gmail.com>
Justin Plock <jplock@users.noreply.github.com>
Justin Simonelis <justin.p.simonelis@gmail.com>
Jyrki Puttonen <jyrkiput@gmail.com>
Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
Jörg Thalheim <joerg@higgsboson.tk>
Kamil Domanski <kamil@domanski.co>
Karan Lyons <karan@karanlyons.com>
Karl Grzeszczak <karlgrz@gmail.com>
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
@@ -396,13 +367,14 @@ Kawsar Saiyeed <kawsar.saiyeed@projiris.com>
Keli Hu <dev@keli.hu>
Ken Cochrane <kencochrane@gmail.com>
Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com>
Kevin "qwazerty" Houdebert <kevin.houdebert@gmail.com>
Kevin Clark <kevin.clark@gmail.com>
Kevin J. Lynagh <kevin@keminglabs.com>
Kevin Menard <kevin@nirvdrum.com>
Kevin "qwazerty" Houdebert <kevin.houdebert@gmail.com>
Kevin Wallace <kevin@pentabarf.net>
Keyvan Fatehi <keyvanfatehi@gmail.com>
kies <lleelm@gmail.com>
kim0 <email.ahmedkamal@googlemail.com>
Kim BKC Carlbacker <kim.carlbacker@gmail.com>
Kimbro Staken <kstaken@kstaken.com>
Kiran Gangadharan <kiran.daredevil@gmail.com>
@@ -410,7 +382,6 @@ knappe <tyler.knappe@gmail.com>
Kohei Tsuruta <coheyxyz@gmail.com>
Konrad Kleine <konrad.wilhelm.kleine@gmail.com>
Konstantin Pelykh <kpelykh@zettaset.com>
Krasimir Georgiev <support@vip-consult.co.uk>
krrg <krrgithub@gmail.com>
Kyle Conroy <kyle.j.conroy@gmail.com>
kyu <leehk1227@gmail.com>
@@ -426,16 +397,13 @@ Lei Jitang <leijitang@huawei.com>
Len Weincier <len@cloudafrica.net>
Leszek Kowalski <github@leszekkowalski.pl>
Levi Gross <levi@levigross.com>
Lewis Marshall <lewis@lmars.net>
Lewis Peckover <lew+github@lew.io>
Liang-Chi Hsieh <viirya@gmail.com>
limsy <seongyeol37@gmail.com>
Lokesh Mandvekar <lsm5@fedoraproject.org>
Lorenz Leutgeb <lorenz.leutgeb@gmail.com>
Louis Opter <kalessin@kalessin.fr>
lukaspustina <lukas.pustina@centerdevice.com>
lukemarsden <luke@digital-crocus.com>
Lénaïc Huard <lhuard@amadeus.com>
Madhu Venugopal <madhu@socketplane.io>
Mahesh Tiyyagura <tmahesh@gmail.com>
Malte Janduda <mail@janduda.net>
@@ -444,13 +412,12 @@ Manuel Meurer <manuel@krautcomputing.com>
Manuel Woelker <github@manuel.woelker.org>
Marc Abramowitz <marc@marc-abramowitz.com>
Marc Kuo <kuomarc2@gmail.com>
Marc Tamsky <mtamsky@gmail.com>
Marco Hennings <marco.hennings@freiheit.com>
Marc Tamsky <mtamsky@gmail.com>
Marcus Farkas <toothlessgear@finitebox.com>
Marcus Linke <marcus.linke@gmx.de>
marcuslinke <marcus.linke@gmx.de>
Marcus Ramberg <marcus@nordaaker.com>
Marek Goldmann <marek.goldmann@gmail.com>
Marianna <mtesselh@gmail.com>
Marius Voila <marius.voila@gmail.com>
Mark Allen <mrallen1@yahoo.com>
Mark McGranaghan <mmcgrana@gmail.com>
@@ -458,9 +425,7 @@ Marko Mikulicic <mmikulicic@gmail.com>
Marko Tibold <marko@tibold.nl>
Markus Fix <lispmeister@gmail.com>
Martijn van Oosterhout <kleptog@svana.org>
Martin Honermeyer <maze@strahlungsfrei.de>
Martin Redmond <martin@tinychat.com>
Mary Anthony <moxieandmore@gmail.com>
Mason Malone <mason.malone@gmail.com>
Mateusz Sulima <sulima.mateusz@gmail.com>
Mathias Monnerville <mathias@monnerville.com>
@@ -470,14 +435,14 @@ Matt Bachmann <bachmann.matt@gmail.com>
Matt Haggard <haggardii@gmail.com>
Matthew Heon <mheon@redhat.com>
Matthew Mueller <mattmuelle@gmail.com>
Matthew Riley <mattdr@google.com>
Matthias Klumpp <matthias@tenstral.net>
Matthias Kühnle <git.nivoc@neverbox.com>
mattymo <raytrac3r@gmail.com>
mattyw <mattyw@me.com>
Max Shytikov <mshytikov@gmail.com>
Maxim Treskin <zerthurd@gmail.com>
Maxime Petazzoni <max@signalfuse.com>
Maxim Treskin <zerthurd@gmail.com>
Max Shytikov <mshytikov@gmail.com>
Médi-Rémi Hashim <medimatrix@users.noreply.github.com>
meejah <meejah@meejah.ca>
Mengdi Gao <usrgdd@gmail.com>
Mert Yazıcıoğlu <merty@users.noreply.github.com>
@@ -486,14 +451,12 @@ Michael Crosby <michael@docker.com>
Michael Gorsuch <gorsuch@github.com>
Michael Hudson-Doyle <michael.hudson@linaro.org>
Michael Neale <michael.neale@gmail.com>
Michaël Pailloncy <mpapo.dev@gmail.com>
Michael Prokop <github@michael-prokop.at>
Michael Scharf <github@scharf.gr>
Michael Stapelberg <michael+gh@stapelberg.de>
Michael Steinert <mike.steinert@gmail.com>
Michael Thies <michaelthies78@gmail.com>
Michal Jemala <michal.jemala@gmail.com>
Michal Minar <miminar@redhat.com>
Michaël Pailloncy <mpapo.dev@gmail.com>
Michiel@unhosted <michiel@unhosted.org>
Miguel Angel Fernández <elmendalerenda@gmail.com>
Mike Chelen <michael.chelen@gmail.com>
@@ -508,15 +471,12 @@ Morten Siebuhr <sbhr@sbhr.dk>
Mrunal Patel <mrunalp@gmail.com>
mschurenko <matt.schurenko@gmail.com>
Mustafa Akın <mustafa91@gmail.com>
Médi-Rémi Hashim <medimatrix@users.noreply.github.com>
Nan Monnand Deng <monnand@gmail.com>
Naoki Orii <norii@cs.cmu.edu>
Nate Eagleson <nate@nateeag.com>
Nate Jones <nate@endot.org>
Nathan Hsieh <hsieh.nathan@gmail.com>
Nathan Kleyn <nathan@nathankleyn.com>
Nathan LeClaire <nathan.leclaire@docker.com>
Neal McBurnett <neal@mcburnett.org>
Nelson Chen <crazysim@gmail.com>
Niall O'Higgins <niallo@unworkable.org>
Nicholas E. Rabenau <nerab@gmx.at>
@@ -531,21 +491,18 @@ NikolaMandic <mn080202@gmail.com>
noducks <onemannoducks@gmail.com>
Nolan Darilek <nolan@thewordnerd.info>
nzwsch <hi@nzwsch.com>
O.S. Tezer <ostezer@gmail.com>
OddBloke <daniel@daniel-watkins.co.uk>
odk- <github@odkurzacz.org>
Oguz Bilgic <fisyonet@gmail.com>
Oh Jinkyun <tintypemolly@gmail.com>
Ole Reifschneider <mail@ole-reifschneider.de>
Olivier Gambier <dmp42@users.noreply.github.com>
O.S. Tezer <ostezer@gmail.com>
pandrew <letters@paulnotcom.se>
panticz <mail@konczalski.de>
Pascal Borreli <pascal@borreli.com>
Pascal Hartig <phartig@rdrei.net>
Patrick Hemmer <patrick.hemmer@gmail.com>
Patrick Stapleton <github@gdi2290.com>
pattichen <craftsbear@gmail.com>
Paul <paul9869@gmail.com>
Paul Annesley <paul@annesley.cc>
Paul Bowsher <pbowsher@globalpersonals.co.uk>
Paul Hammond <paul@paulhammond.org>
@@ -553,6 +510,7 @@ Paul Jimenez <pj@place.org>
Paul Lietar <paul@lietar.net>
Paul Morie <pmorie@gmail.com>
Paul Nasrat <pnasrat@gmail.com>
Paul <paul9869@gmail.com>
Paul Weaver <pauweave@cisco.com>
Pavlos Ratis <dastergon@gentoo.org>
Peter Bourgon <peter@bourgon.org>
@@ -560,18 +518,16 @@ Peter Braden <peterbraden@peterbraden.co.uk>
Peter Ericson <pdericson@gmail.com>
Peter Salvatore <peter@psftw.com>
Peter Waller <p@pwaller.net>
Phil <underscorephil@gmail.com>
Phil Estes <estesp@linux.vnet.ibm.com>
Phil Spitler <pspitler@gmail.com>
Philipp Weissensteiner <mail@philippweissensteiner.com>
Phillip Alexander <git@phillipalexander.io>
Phil Spitler <pspitler@gmail.com>
Phil <underscorephil@gmail.com>
Piergiuliano Bossi <pgbossi@gmail.com>
Pierre <py@poujade.org>
Pierre Wacrenier <pierre.wacrenier@gmail.com>
Pierre-Alain RIVIERE <pariviere@ippon.fr>
Pierre <py@poujade.org>
Piotr Bogdan <ppbogdan@gmail.com>
pixelistik <pixelistik@users.noreply.github.com>
Porjo <porjo38@yahoo.com.au>
Prasanna Gautam <prasannagautam@gmail.com>
Przemek Hejman <przemyslaw.hejman@gmail.com>
pysqz <randomq@126.com>
@@ -591,7 +547,6 @@ Renato Riccieri Santos Zannon <renato.riccieri@gmail.com>
rgstephens <greg@udon.org>
Rhys Hiltner <rhys@twitch.tv>
Richard Harvey <richard@squarecows.com>
Richard Metzler <richard@paadee.com>
Richo Healey <richo@psych0tik.net>
Rick Bradley <rick@users.noreply.github.com>
Rick van de Loo <rickvandeloo@gmail.com>
@@ -617,26 +572,25 @@ Ryan Fowler <rwfowler@gmail.com>
Ryan O'Donnell <odonnellryanc@gmail.com>
Ryan Seto <ryanseto@yak.net>
Ryan Thomas <rthomas@atlassian.com>
Rémy Greinhofer <remy.greinhofer@livelovely.com>
Sam Alba <sam.alba@gmail.com>
Sam Bailey <cyprix@cyprix.com.au>
Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
Sam Reis <sreis@atlassian.com>
Sam Rijs <srijs@airpost.net>
Sami Wagiaalla <swagiaal@redhat.com>
Samuel Andaya <samuel@andaya.net>
Samuel PHAN <samuel-phan@users.noreply.github.com>
Satnam Singh <satnam@raintown.org>
satoru <satorulogic@gmail.com>
Satoshi Amemiya <satoshi_amemiya@voyagegroup.com>
Scott Bessler <scottbessler@gmail.com>
Scott Collier <emailscottcollier@gmail.com>
Scott Johnston <scott@docker.com>
Scott Stamp <scottstamp851@gmail.com>
Scott Walls <sawalls@umich.edu>
Sean Cronin <seancron@gmail.com>
Sean P. Kane <skane@newrelic.com>
Sebastiaan van Stijn <github@gone.nl>
Sébastien Luttringer <seblu@seblu.net>
Sébastien <sebastien@yoozio.com>
Sébastien Stormacq <sebsto@users.noreply.github.com>
Senthil Kumar Selvaraj <senthil.thecoder@gmail.com>
SeongJae Park <sj38.park@gmail.com>
Shane Canon <scanon@lbl.gov>
@@ -644,12 +598,12 @@ shaunol <shaunol@gmail.com>
Shawn Landden <shawn@churchofgit.com>
Shawn Siefkas <shawn.siefkas@meredith.com>
Shih-Yuan Lee <fourdollars@gmail.com>
Shishir Mahajan <shishir.mahajan@redhat.com>
shuai-z <zs.broccoli@gmail.com>
Silas Sewell <silas@sewell.org>
Simon Taranto <simon.taranto@gmail.com>
Sindhu S <sindhus@live.in>
Sjoerd Langkemper <sjoerd-github@linuxonly.nl>
s-ko <aleks@s-ko.net>
Solomon Hykes <solomon@docker.com>
Song Gao <song@gao.io>
Soulou <leo@unbekandt.eu>
@@ -657,23 +611,18 @@ soulshake <amy@gandi.net>
Sridatta Thatipamala <sthatipamala@gmail.com>
Sridhar Ratnakumar <sridharr@activestate.com>
Srini Brahmaroutu <sbrahma@us.ibm.com>
Srini Brahmaroutu <srbrahma@us.ibm.com>
Steeve Morin <steeve.morin@gmail.com>
Stefan Praszalowicz <stefan@greplin.com>
Stephen Crosby <stevecrozz@gmail.com>
Steven Burgess <steven.a.burgess@hotmail.com>
Steven Merrill <steven.merrill@gmail.com>
sudosurootdev <sudosurootdev@gmail.com>
Sven Dowideit <SvenDowideit@home.org.au>
Sylvain Bellemare <sylvain.bellemare@ezeep.com>
Sébastien <sebastien@yoozio.com>
Sébastien Luttringer <seblu@seblu.net>
Sébastien Stormacq <sebsto@users.noreply.github.com>
tang0th <tang0th@gmx.com>
Tatsuki Sugiura <sugi@nemui.org>
Tatsushi Inagaki <e29253@jp.ibm.com>
Ted M. Young <tedyoung@gmail.com>
Tehmasp Chaudhri <tehmasp@gmail.com>
Tejesh Mehta <tejesh.mehta@gmail.com>
Thatcher Peskens <thatcher@docker.com>
Thermionix <bond711@gmail.com>
Thijs Terlouw <thijsterlouw@gmail.com>
@@ -687,10 +636,11 @@ Tianon Gravi <admwiggin@gmail.com>
Tibor Vass <teabee89@gmail.com>
Tim Bosse <taim@bosboot.org>
Tim Hockin <thockin@google.com>
Timothy Hobbs <timothyhobbs@seznam.cz>
Tim Ruffles <oi@truffles.me.uk>
Tim Smith <timbot@google.com>
Tim Terhorst <mynamewastaken+git@gmail.com>
Timothy Hobbs <timothyhobbs@seznam.cz>
tjmehta <tj@init.me>
tjwebb123 <tjwebb123@users.noreply.github.com>
tobe <tobegit3hub@gmail.com>
Tobias Bieniek <Tobias.Bieniek@gmx.de>
@@ -698,12 +648,10 @@ Tobias Gesellchen <tobias@gesellix.de>
Tobias Schmidt <ts@soundcloud.com>
Tobias Schwab <tobias.schwab@dynport.de>
Todd Lunter <tlunter@gmail.com>
Tomasz Lipinski <tlipinski@users.noreply.github.com>
Tom Fotherby <tom+github@peopleperhour.com>
Tom Hulihan <hulihan.tom159@gmail.com>
Tom Maaswinkel <tom.maaswinkel@12wiki.eu>
Tomas Tomecek <ttomecek@redhat.com>
Tomasz Lipinski <tlipinski@users.noreply.github.com>
Tomasz Nurkiewicz <nurkiewicz@gmail.com>
Tommaso Visconti <tommaso.visconti@gmail.com>
Tonis Tiigi <tonistiigi@gmail.com>
Tony Daws <tony@daws.ca>
@@ -714,8 +662,7 @@ Trent Ogren <tedwardo2@gmail.com>
Tyler Brock <tyler.brock@gmail.com>
Tzu-Jung Lee <roylee17@gmail.com>
Ulysse Carion <ulyssecarion@gmail.com>
unknown <sebastiaan@ws-key-sebas3.dpi1.dpi>
Vaidas Jablonskis <jablonskis@gmail.com>
unclejack <unclejacksons@gmail.com>
vgeta <gopikannan.venugopalsamy@gmail.com>
Victor Coisne <victor.coisne@dotcloud.com>
Victor Lyuboslavsky <victor@victoreda.com>
@@ -744,15 +691,15 @@ Walter Leibbrandt <github@wrl.co.za>
Walter Stanish <walter@pratyeka.org>
Ward Vandewege <ward@jhvc.com>
WarheadsSE <max@warheads.net>
Wayne Chang <wayne@neverfear.org>
Wes Morgan <cap10morgan@gmail.com>
Will Dietz <w@wdtz.org>
Will Rouesnel <w.rouesnel@gmail.com>
Will Weaver <monkey@buildingbananas.com>
William Delanoue <william.delanoue@gmail.com>
William Henry <whenry@redhat.com>
William Riancho <wr.wllm@gmail.com>
William Thurston <thurstw@amazon.com>
Will Rouesnel <w.rouesnel@gmail.com>
Will Weaver <monkey@buildingbananas.com>
wyc <wayne@neverfear.org>
Xiuming Chen <cc@cxm.cc>
xuzhaokui <cynicholas@gmail.com>
Yang Bai <hamo.by@gmail.com>
@@ -768,6 +715,4 @@ Zilin Du <zilin.du@gmail.com>
zimbatm <zimbatm@zimbatm.com>
Zoltan Tombol <zoltan.tombol@gmail.com>
zqh <zqhxuyuan@gmail.com>
Álex González <agonzalezro@gmail.com>
Álvaro Lázaro <alvaro.lazaro.g@gmail.com>
尹吉峰 <jifeng.yin@gmail.com>
-1
View File
@@ -19,7 +19,6 @@
- Fixed contacting a private registry through a proxy
#### Remote API
+ A new endpoint will stream live container resource metrics and can be accessed with the `docker stats` command
+ Containers can be renamed using the new `rename` endpoint and the associated `docker rename` command
* Container `inspect` endpoint show the ID of `exec` commands running in this container
* Container `inspect` endpoint show the number of times Docker auto-restarted the container
+2 -8
View File
@@ -84,10 +84,8 @@ RUN cd /usr/local/go/src && ./make.bash --no-clean 2>&1
ENV DOCKER_CROSSPLATFORMS \
linux/386 linux/arm \
darwin/amd64 darwin/386 \
freebsd/amd64 freebsd/386 freebsd/arm
# TODO when https://jenkins.dockerproject.com/job/Windows/ is green, add windows back to the list above
# windows/amd64 windows/386
freebsd/amd64 freebsd/386 freebsd/arm \
windows/amd64 windows/386
# (set an explicit GOARM of 5 for maximum compatibility)
ENV GOARM 5
@@ -155,10 +153,6 @@ RUN set -x \
&& git clone -b v1.2 https://github.com/russross/blackfriday.git /go/src/github.com/russross/blackfriday \
&& go install -v github.com/cpuguy83/go-md2man
# install toml validator
RUN git clone -b v0.1.0 https://github.com/BurntSushi/toml.git /go/src/github.com/BurntSushi/toml \
&& go install -v github.com/BurntSushi/toml/cmd/tomlv
# Wrap all commands in the "docker-in-docker" script to allow nested containers
ENTRYPOINT ["hack/dind"]
+1 -1
View File
@@ -74,7 +74,7 @@ test-docker-py: build
$(DOCKER_RUN_DOCKER) hack/make.sh binary test-docker-py
validate: build
$(DOCKER_RUN_DOCKER) hack/make.sh validate-gofmt validate-dco validate-toml
$(DOCKER_RUN_DOCKER) hack/make.sh validate-gofmt validate-dco
shell: build
$(DOCKER_RUN_DOCKER) bash
+1 -1
View File
@@ -1 +1 @@
1.5.0-rc3
1.5.0
+4 -3
View File
@@ -17,6 +17,7 @@ import (
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/registry"
"github.com/docker/libtrust"
)
type DockerCli struct {
@@ -26,7 +27,7 @@ type DockerCli struct {
in io.ReadCloser
out io.Writer
err io.Writer
keyFile string
key libtrust.PrivateKey
tlsConfig *tls.Config
scheme string
// inFd holds file descriptor of the client's STDIN, if it's a valid file
@@ -121,7 +122,7 @@ func (cli *DockerCli) CheckTtyInput(attachStdin, ttyMode bool) error {
return nil
}
func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, addr string, tlsConfig *tls.Config) *DockerCli {
func NewDockerCli(in io.ReadCloser, out, err io.Writer, key libtrust.PrivateKey, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var (
inFd uintptr
outFd uintptr
@@ -176,7 +177,7 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, a
in: in,
out: out,
err: err,
keyFile: keyFile,
key: key,
inFd: inFd,
outFd: outFd,
isTerminalIn: isTerminalIn,
+55 -57
View File
@@ -39,7 +39,6 @@ import (
"github.com/docker/docker/pkg/parsers/filters"
"github.com/docker/docker/pkg/promise"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/pkg/timeutils"
"github.com/docker/docker/pkg/units"
@@ -47,6 +46,7 @@ import (
"github.com/docker/docker/registry"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/utils"
"github.com/docker/libtrust"
)
const (
@@ -148,36 +148,36 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
return err
}
filename := *dockerfileName // path to Dockerfile
var filename string // path to Dockerfile
var origDockerfile string // used for error msg
if *dockerfileName == "" {
// No -f/--file was specified so use the default
*dockerfileName = api.DefaultDockerfileName
origDockerfile = api.DefaultDockerfileName
*dockerfileName = origDockerfile
filename = path.Join(absRoot, *dockerfileName)
} else {
origDockerfile = *dockerfileName
if filename, err = filepath.Abs(*dockerfileName); err != nil {
return err
}
// Verify that 'filename' is within the build context
if !strings.HasSuffix(absRoot, string(os.PathSeparator)) {
absRoot += string(os.PathSeparator)
}
if !strings.HasPrefix(filename, absRoot) {
return fmt.Errorf("The Dockerfile (%s) must be within the build context (%s)", *dockerfileName, root)
}
// Now reset the dockerfileName to be relative to the build context
*dockerfileName = filename[len(absRoot):]
}
origDockerfile := *dockerfileName // used for error msg
if filename, err = filepath.Abs(filename); err != nil {
return err
if _, err = os.Stat(filename); os.IsNotExist(err) {
return fmt.Errorf("Can not locate Dockerfile: %s", origDockerfile)
}
// Verify that 'filename' is within the build context
filename, err = symlink.FollowSymlinkInScope(filename, absRoot)
if err != nil {
return fmt.Errorf("The Dockerfile (%s) must be within the build context (%s)", origDockerfile, root)
}
// Now reset the dockerfileName to be relative to the build context
*dockerfileName, err = filepath.Rel(absRoot, filename)
if err != nil {
return err
}
if _, err = os.Lstat(filename); os.IsNotExist(err) {
return fmt.Errorf("Cannot locate Dockerfile: %s", origDockerfile)
}
var includes = []string{"."}
var includes []string = []string{"."}
excludes, err := utils.ReadDockerIgnore(path.Join(root, ".dockerignore"))
if err != nil {
@@ -1216,6 +1216,25 @@ func (cli *DockerCli) CmdPush(args ...string) error {
v := url.Values{}
v.Set("tag", tag)
body, _, err := readBody(cli.call("GET", "/images/"+remote+"/manifest?"+v.Encode(), nil, false))
if err != nil {
return err
}
js, err := libtrust.NewJSONSignature(body)
if err != nil {
return err
}
err = js.Sign(cli.key)
if err != nil {
return err
}
signedBody, err := js.PrettySignature("signatures")
if err != nil {
return err
}
push := func(authConfig registry.AuthConfig) error {
buf, err := json.Marshal(authConfig)
if err != nil {
@@ -1225,7 +1244,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
base64.URLEncoding.EncodeToString(buf),
}
return cli.stream("POST", "/images/"+remote+"/push?"+v.Encode(), nil, cli.out, map[string][]string{
return cli.stream("POST", "/images/"+remote+"/push?"+v.Encode(), bytes.NewReader(signedBody), cli.out, map[string][]string{
"X-Registry-Auth": registryAuthHeader,
})
}
@@ -2615,12 +2634,7 @@ type containerStats struct {
err error
}
func (s *containerStats) Collect(cli *DockerCli) {
stream, _, err := cli.call("GET", "/containers/"+s.Name+"/stats", nil, false)
if err != nil {
s.err = err
return
}
func (s *containerStats) Collect(stream io.ReadCloser) {
defer stream.Close()
var (
previousCpu uint64
@@ -2700,44 +2714,28 @@ func (cli *DockerCli) CmdStats(args ...string) error {
names := cmd.Args()
sort.Strings(names)
var (
cStats []*containerStats
w = tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
)
printHeader := func() {
fmt.Fprint(cli.out, "\033[2J")
fmt.Fprint(cli.out, "\033[H")
fmt.Fprintln(w, "CONTAINER\tCPU %\tMEM USAGE/LIMIT\tMEM %\tNET I/O")
}
var cStats []*containerStats
for _, n := range names {
s := &containerStats{Name: n}
cStats = append(cStats, s)
go s.Collect(cli)
}
// do a quick pause so that any failed connections for containers that do not exist are able to be
// evicted before we display the initial or default values.
time.Sleep(500 * time.Millisecond)
var errs []string
for _, c := range cStats {
c.mu.Lock()
if c.err != nil {
errs = append(errs, fmt.Sprintf("%s: %s", c.Name, c.err.Error()))
stream, _, err := cli.call("GET", "/containers/"+n+"/stats", nil, false)
if err != nil {
return err
}
c.mu.Unlock()
}
if len(errs) > 0 {
return fmt.Errorf("%s", strings.Join(errs, ", "))
go s.Collect(stream)
}
w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
for _ = range time.Tick(500 * time.Millisecond) {
printHeader()
fmt.Fprint(cli.out, "\033[2J")
fmt.Fprint(cli.out, "\033[H")
fmt.Fprintln(w, "CONTAINER\tCPU %\tMEM USAGE/LIMIT\tMEM %\tNET I/O")
toRemove := []int{}
for i, s := range cStats {
if err := s.Display(w); err != nil {
toRemove = append(toRemove, i)
}
}
for j := len(toRemove) - 1; j >= 0; j-- {
i := toRemove[j]
for _, i := range toRemove {
cStats = append(cStats[:i], cStats[i+1:]...)
}
if len(cStats) == 0 {
-18
View File
@@ -72,15 +72,6 @@ func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Con
if err != nil {
return nil, err
}
// When we set up a TCP connection for hijack, there could be long periods
// of inactivity (a long running command with no output) that in certain
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
// state. Setting TCP KeepAlive on the socket connection will prohibit
// ECONNTIMEOUT unless the socket connection truly is broken
if tcpConn, ok := rawConn.(*net.TCPConn); ok {
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second)
}
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
@@ -149,15 +140,6 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
req.Host = cli.addr
dial, err := cli.dial()
// When we set up a TCP connection for hijack, there could be long periods
// of inactivity (a long running command with no output) that in certain
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
// state. Setting TCP KeepAlive on the socket connection will prohibit
// ECONNTIMEOUT unless the socket connection truly is broken
if tcpConn, ok := dial.(*net.TCPConn); ok {
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second)
}
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
+3 -3
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"mime"
"os"
"path/filepath"
"path"
"strings"
log "github.com/Sirupsen/logrus"
@@ -55,7 +55,7 @@ func MatchesContentType(contentType, expectedType string) bool {
// LoadOrCreateTrustKey attempts to load the libtrust key at the given path,
// otherwise generates a new one
func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
err := os.MkdirAll(filepath.Dir(trustKeyPath), 0700)
err := os.MkdirAll(path.Dir(trustKeyPath), 0700)
if err != nil {
return nil, err
}
@@ -69,7 +69,7 @@ func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
return nil, fmt.Errorf("Error saving key file: %s", err)
}
} else if err != nil {
return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err)
return nil, fmt.Errorf("Error loading key file: %s", err)
}
return trustKey, nil
}
+19
View File
@@ -621,6 +621,18 @@ func getImagesSearch(eng *engine.Engine, version version.Version, w http.Respons
return job.Run()
}
func getImageManifest(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := parseForm(r); err != nil {
return err
}
job := eng.Job("image_manifest", vars["name"])
job.Setenv("tag", r.Form.Get("tag"))
job.Stdout.Add(utils.NewWriteFlusher(w))
return job.Run()
}
func postImagesPush(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
@@ -652,9 +664,15 @@ func postImagesPush(eng *engine.Engine, version version.Version, w http.Response
}
}
manifest, err := ioutil.ReadAll(r.Body)
if err != nil {
return err
}
job := eng.Job("push", vars["name"])
job.SetenvJson("metaHeaders", metaHeaders)
job.SetenvJson("authConfig", authConfig)
job.Setenv("manifest", string(manifest))
job.Setenv("tag", r.Form.Get("tag"))
if version.GreaterThan("1.0") {
job.SetenvBool("json", true)
@@ -1307,6 +1325,7 @@ func createRouter(eng *engine.Engine, logging, enableCors bool, dockerVersion st
"/images/viz": getImagesViz,
"/images/search": getImagesSearch,
"/images/get": getImagesGet,
"/images/{name:.*}/manifest": getImageManifest,
"/images/{name:.*}/get": getImagesGet,
"/images/{name:.*}/history": getImagesHistory,
"/images/{name:.*}/json": getImagesByName,
+21 -21
View File
@@ -6,21 +6,21 @@ import "time"
type ThrottlingData struct {
// Number of periods with throttling active
Periods uint64 `json:"periods"`
Periods uint64 `json:"periods,omitempty"`
// Number of periods when the container hit its throttling limit.
ThrottledPeriods uint64 `json:"throttled_periods"`
ThrottledPeriods uint64 `json:"throttled_periods,omitempty"`
// Aggregate time the container was throttled for in nanoseconds.
ThrottledTime uint64 `json:"throttled_time"`
ThrottledTime uint64 `json:"throttled_time,omitempty"`
}
// All CPU stats are aggregated since container inception.
type CpuUsage struct {
// Total CPU time consumed.
// Units: nanoseconds.
TotalUsage uint64 `json:"total_usage"`
TotalUsage uint64 `json:"total_usage,omitempty"`
// Total CPU time consumed per core.
// Units: nanoseconds.
PercpuUsage []uint64 `json:"percpu_usage"`
PercpuUsage []uint64 `json:"percpu_usage,omitempty"`
// Time spent by tasks of the cgroup in kernel mode.
// Units: nanoseconds.
UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
@@ -30,41 +30,41 @@ type CpuUsage struct {
}
type CpuStats struct {
CpuUsage CpuUsage `json:"cpu_usage"`
CpuUsage CpuUsage `json:"cpu_usage,omitempty"`
SystemUsage uint64 `json:"system_cpu_usage"`
ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}
type MemoryStats struct {
// current res_counter usage for memory
Usage uint64 `json:"usage"`
Usage uint64 `json:"usage,omitempty"`
// maximum usage ever recorded.
MaxUsage uint64 `json:"max_usage"`
MaxUsage uint64 `json:"max_usage,omitempty"`
// TODO(vishh): Export these as stronger types.
// all the stats exported via memory.stat.
Stats map[string]uint64 `json:"stats"`
Stats map[string]uint64 `json:"stats,omitempty"`
// number of times memory usage hits limits.
Failcnt uint64 `json:"failcnt"`
Limit uint64 `json:"limit"`
}
type BlkioStatEntry struct {
Major uint64 `json:"major"`
Minor uint64 `json:"minor"`
Op string `json:"op"`
Value uint64 `json:"value"`
Major uint64 `json:"major,omitempty"`
Minor uint64 `json:"minor,omitempty"`
Op string `json:"op,omitempty"`
Value uint64 `json:"value,omitempty"`
}
type BlkioStats struct {
// number of bytes tranferred to and from the block device
IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive"`
IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive"`
IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive"`
IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive"`
IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive"`
IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive"`
SectorsRecursive []BlkioStatEntry `json:"sectors_recursive"`
IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive,omitempty"`
IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive,omitempty"`
IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive,omitempty"`
IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive,omitempty"`
SectorsRecursive []BlkioStatEntry `json:"sectors_recursive,omitempty"`
}
type Network struct {
+8 -12
View File
@@ -24,7 +24,7 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"path"
"strings"
log "github.com/Sirupsen/logrus"
@@ -32,7 +32,6 @@ import (
"github.com/docker/docker/daemon"
"github.com/docker/docker/engine"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/docker/pkg/tarsum"
"github.com/docker/docker/registry"
"github.com/docker/docker/runconfig"
@@ -170,15 +169,12 @@ func (b *Builder) Run(context io.Reader) (string, error) {
// Reads a Dockerfile from the current context. It assumes that the
// 'filename' is a relative path from the root of the context
func (b *Builder) readDockerfile(origFile string) error {
filename, err := symlink.FollowSymlinkInScope(filepath.Join(b.contextPath, origFile), b.contextPath)
if err != nil {
return fmt.Errorf("The Dockerfile (%s) must be within the build context", origFile)
}
func (b *Builder) readDockerfile(filename string) error {
filename = path.Join(b.contextPath, filename)
fi, err := os.Lstat(filename)
fi, err := os.Stat(filename)
if os.IsNotExist(err) {
return fmt.Errorf("Cannot locate specified Dockerfile: %s", origFile)
return fmt.Errorf("Cannot build a directory without a Dockerfile")
}
if fi.Size() == 0 {
return ErrDockerfileEmpty
@@ -205,13 +201,13 @@ func (b *Builder) readDockerfile(origFile string) error {
// Note that this assumes the Dockerfile has been read into memory and
// is now safe to be removed.
excludes, _ := utils.ReadDockerIgnore(filepath.Join(b.contextPath, ".dockerignore"))
excludes, _ := utils.ReadDockerIgnore(path.Join(b.contextPath, ".dockerignore"))
if rm, _ := fileutils.Matches(".dockerignore", excludes); rm == true {
os.Remove(filepath.Join(b.contextPath, ".dockerignore"))
os.Remove(path.Join(b.contextPath, ".dockerignore"))
b.context.(tarsum.BuilderContext).Remove(".dockerignore")
}
if rm, _ := fileutils.Matches(b.dockerfileName, excludes); rm == true {
os.Remove(filepath.Join(b.contextPath, b.dockerfileName))
os.Remove(path.Join(b.contextPath, b.dockerfileName))
b.context.(tarsum.BuilderContext).Remove(b.dockerfileName)
}
+1 -2
View File
@@ -25,7 +25,6 @@ import (
imagepkg "github.com/docker/docker/image"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/docker/pkg/system"
@@ -434,7 +433,7 @@ func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
job.SetenvBool("json", b.StreamFormatter.Json())
job.SetenvBool("parallel", true)
job.SetenvJson("authConfig", pullRegistryAuth)
job.Stdout.Add(ioutils.NopWriteCloser(b.OutOld))
job.Stdout.Add(b.OutOld)
if err := job.Run(); err != nil {
return nil, err
}
+5 -91
View File
@@ -104,22 +104,6 @@ __docker_pos_first_nonflag() {
echo $counter
}
# Transforms a multiline list of strings into a single line string
# with the words separated by "|".
# This is used to prepare arguments to __docker_pos_first_nonflag().
__docker_to_alternatives() {
local parts=( $1 )
local IFS='|'
echo "${parts[*]}"
}
# Transforms a multiline list of options into an extglob pattern
# suitable for use in case statements.
__docker_to_extglob() {
local extglob=$( __docker_to_alternatives "$1" )
echo "@($extglob)"
}
__docker_resolve_hostname() {
command -v host >/dev/null 2>&1 || return
COMPREPLY=( $(host 2>/dev/null "${cur%:}" | awk '/has address/ {print $4}') )
@@ -170,47 +154,15 @@ __docker_capabilities() {
}
_docker_docker() {
local boolean_options="
--api-enable-cors
--daemon -d
--debug -D
--help -h
--icc
--ip-forward
--ip-masq
--iptables
--ipv6
--selinux-enabled
--tls
--tlsverify
--version -v
"
case "$prev" in
--graph|-g)
_filedir -d
return
;;
--log-level|-l)
COMPREPLY=( $( compgen -W "debug info warn error fatal" -- "$cur" ) )
return
;;
--pidfile|-p|--tlscacert|--tlscert|--tlskey)
_filedir
return
;;
--storage-driver|-s)
COMPREPLY=( $( compgen -W "aufs devicemapper btrfs overlay" -- "$(echo $cur | tr '[:upper:]' '[:lower:]')" ) )
return
;;
$main_options_with_args_glob )
-H)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "$boolean_options $main_options_with_args" -- "$cur" ) )
COMPREPLY=( $( compgen -W "-H" -- "$cur" ) )
;;
*)
COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) )
@@ -609,8 +561,6 @@ _docker_run() {
--sig-proxy
"
local options_with_args_glob=$(__docker_to_extglob "$options_with_args")
case "$prev" in
--add-host)
case "$cur" in
@@ -727,7 +677,7 @@ _docker_run() {
__docker_containers_all
return
;;
$options_with_args_glob )
--cpuset|--cpu-shares|-c|--dns|--dns-search|--entrypoint|--expose|--hostname|-h|--lxc-conf|--mac-address|--memory|-m|--name|-n|--publish|-p|--user|-u|--workdir|-w)
return
;;
esac
@@ -737,7 +687,7 @@ _docker_run() {
COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) )
;;
*)
local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) )
local counter=$( __docker_pos_first_nonflag $( echo $options_with_args | tr -d "\n" | tr " " "|" ) )
if [ $cword -eq $counter ]; then
__docker_image_repos_and_tags_and_ids
@@ -789,10 +739,6 @@ _docker_start() {
esac
}
_docker_stats() {
__docker_containers_running
}
_docker_stop() {
case "$prev" in
--time|-t)
@@ -855,9 +801,6 @@ _docker_wait() {
}
_docker() {
local previous_extglob_setting=$(shopt -p extglob)
shopt -s extglob
local commands=(
attach
build
@@ -890,7 +833,6 @@ _docker() {
save
search
start
stats
stop
tag
top
@@ -899,33 +841,6 @@ _docker() {
wait
)
local main_options_with_args="
--bip
--bridge -b
--dns
--dns-search
--exec-driver -e
--fixed-cidr
--fixed-cidr-v6
--graph -g
--group -G
--host -H
--insecure-registry
--ip
--label
--log-level -l
--mtu
--pidfile -p
--registry-mirror
--storage-driver -s
--storage-opt
--tlscacert
--tlscert
--tlskey
"
local main_options_with_args_glob=$(__docker_to_extglob "$main_options_with_args")
COMPREPLY=()
local cur prev words cword
_get_comp_words_by_ref -n : cur prev words cword
@@ -934,7 +849,7 @@ _docker() {
local counter=1
while [ $counter -lt $cword ]; do
case "${words[$counter]}" in
$main_options_with_args_glob )
-H)
(( counter++ ))
;;
-*)
@@ -952,7 +867,6 @@ _docker() {
local completions_func=_docker_${command}
declare -F $completions_func >/dev/null && $completions_func
eval "$previous_extglob_setting"
return 0
}
+18 -76
View File
@@ -51,28 +51,23 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -s d -l daemon -d 'Enable
complete -c docker -f -n '__fish_docker_no_subcommand' -l dns -d 'Force Docker to use specific DNS servers'
complete -c docker -f -n '__fish_docker_no_subcommand' -l dns-search -d 'Force Docker to use specific DNS search domains'
complete -c docker -f -n '__fish_docker_no_subcommand' -s e -l exec-driver -d 'Force the Docker runtime to use a specific exec driver'
complete -c docker -f -n '__fish_docker_no_subcommand' -l fixed-cidr -d 'IPv4 subnet for fixed IPs (e.g. 10.20.0.0/16)'
complete -c docker -f -n '__fish_docker_no_subcommand' -l fixed-cidr-v6 -d 'IPv6 subnet for fixed IPs (e.g.: 2001:a02b/48)'
complete -c docker -f -n '__fish_docker_no_subcommand' -l fixed-cidr -d 'IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)'
complete -c docker -f -n '__fish_docker_no_subcommand' -s G -l group -d 'Group to assign the unix socket specified by -H when running in daemon mode'
complete -c docker -f -n '__fish_docker_no_subcommand' -s g -l graph -d 'Path to use as the root of the Docker runtime'
complete -c docker -f -n '__fish_docker_no_subcommand' -s H -l host -d 'The socket(s) to bind to in daemon mode or connect to in client mode, specified using one or more tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd.'
complete -c docker -f -n '__fish_docker_no_subcommand' -s h -l help -d 'Print usage'
complete -c docker -f -n '__fish_docker_no_subcommand' -l icc -d 'Allow unrestricted inter-container and Docker daemon host communication'
complete -c docker -f -n '__fish_docker_no_subcommand' -l icc -d 'Enable inter-container communication'
complete -c docker -f -n '__fish_docker_no_subcommand' -l insecure-registry -d 'Enable insecure communication with specified registries (no certificate verification for HTTPS and enable HTTP fallback) (e.g., localhost:5000 or 10.20.0.0/16)'
complete -c docker -f -n '__fish_docker_no_subcommand' -l ip -d 'Default IP address to use when binding container ports'
complete -c docker -f -n '__fish_docker_no_subcommand' -l ip-forward -d 'Enable net.ipv4.ip_forward and IPv6 forwarding if --fixed-cidr-v6 is defined. IPv6 forwarding may interfere with your existing IPv6 configuration when using Router Advertisement.'
complete -c docker -f -n '__fish_docker_no_subcommand' -l ip-forward -d 'Enable net.ipv4.ip_forward'
complete -c docker -f -n '__fish_docker_no_subcommand' -l ip-masq -d "Enable IP masquerading for bridge's IP range"
complete -c docker -f -n '__fish_docker_no_subcommand' -l iptables -d "Enable Docker's addition of iptables rules"
complete -c docker -f -n '__fish_docker_no_subcommand' -l ipv6 -d 'Enable IPv6 networking'
complete -c docker -f -n '__fish_docker_no_subcommand' -s l -l log-level -d 'Set the logging level (debug, info, warn, error, fatal)'
complete -c docker -f -n '__fish_docker_no_subcommand' -l label -d 'Set key=value labels to the daemon (displayed in `docker info`)'
complete -c docker -f -n '__fish_docker_no_subcommand' -l mtu -d 'Set the containers network MTU'
complete -c docker -f -n '__fish_docker_no_subcommand' -s p -l pidfile -d 'Path to use for daemon PID file'
complete -c docker -f -n '__fish_docker_no_subcommand' -l registry-mirror -d 'Specify a preferred Docker registry mirror'
complete -c docker -f -n '__fish_docker_no_subcommand' -s s -l storage-driver -d 'Force the Docker runtime to use a specific storage driver'
complete -c docker -f -n '__fish_docker_no_subcommand' -l selinux-enabled -d 'Enable selinux support. SELinux does not presently support the BTRFS storage driver'
complete -c docker -f -n '__fish_docker_no_subcommand' -l storage-opt -d 'Set storage driver options'
complete -c docker -f -n '__fish_docker_no_subcommand' -l tls -d 'Use TLS; implied by --tlsverify flag'
complete -c docker -f -n '__fish_docker_no_subcommand' -l tls -d 'Use TLS; implied by tls-verify flags'
complete -c docker -f -n '__fish_docker_no_subcommand' -l tlscacert -d 'Trust only remotes providing a certificate signed by the CA given here'
complete -c docker -f -n '__fish_docker_no_subcommand' -l tlscert -d 'Path to TLS certificate file'
complete -c docker -f -n '__fish_docker_no_subcommand' -l tlskey -d 'Path to TLS key file'
@@ -82,18 +77,14 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -s v -l version -d 'Print
# subcommands
# attach
complete -c docker -f -n '__fish_docker_no_subcommand' -a attach -d 'Attach to a running container'
complete -c docker -A -f -n '__fish_seen_subcommand_from attach' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from attach' -l no-stdin -d 'Do not attach STDIN'
complete -c docker -A -f -n '__fish_seen_subcommand_from attach' -l sig-proxy -d 'Proxy all received signals to the process (non-TTY mode only). SIGCHLD, SIGKILL, and SIGSTOP are not proxied.'
complete -c docker -A -f -n '__fish_seen_subcommand_from attach' -l sig-proxy -d 'Proxy all received signals to the process (even in non-TTY mode). SIGCHLD, SIGKILL, and SIGSTOP are not proxied.'
complete -c docker -A -f -n '__fish_seen_subcommand_from attach' -a '(__fish_print_docker_containers running)' -d "Container"
# build
complete -c docker -f -n '__fish_docker_no_subcommand' -a build -d 'Build an image from a Dockerfile'
complete -c docker -A -f -n '__fish_seen_subcommand_from build' -s f -l file -d "Name of the Dockerfile(Default is 'Dockerfile' at context root)"
complete -c docker -A -f -n '__fish_seen_subcommand_from build' -l force-rm -d 'Always remove intermediate containers, even after unsuccessful builds'
complete -c docker -A -f -n '__fish_seen_subcommand_from build' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from build' -l no-cache -d 'Do not use cache when building the image'
complete -c docker -A -f -n '__fish_seen_subcommand_from build' -l pull -d 'Always attempt to pull a newer version of the image'
complete -c docker -A -f -n '__fish_seen_subcommand_from build' -s q -l quiet -d 'Suppress the verbose output generated by the containers'
complete -c docker -A -f -n '__fish_seen_subcommand_from build' -l rm -d 'Remove intermediate containers after a successful build'
complete -c docker -A -f -n '__fish_seen_subcommand_from build' -s t -l tag -d 'Repository name (and optionally a tag) to be applied to the resulting image in case of success'
@@ -101,14 +92,12 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from build' -s t -l tag -d '
# commit
complete -c docker -f -n '__fish_docker_no_subcommand' -a commit -d "Create a new image from a container's changes"
complete -c docker -A -f -n '__fish_seen_subcommand_from commit' -s a -l author -d 'Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")'
complete -c docker -A -f -n '__fish_seen_subcommand_from commit' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from commit' -s m -l message -d 'Commit message'
complete -c docker -A -f -n '__fish_seen_subcommand_from commit' -s p -l pause -d 'Pause container during commit'
complete -c docker -A -f -n '__fish_seen_subcommand_from commit' -a '(__fish_print_docker_containers all)' -d "Container"
# cp
complete -c docker -f -n '__fish_docker_no_subcommand' -a cp -d "Copy files/folders from a container's filesystem to the host path"
complete -c docker -A -f -n '__fish_seen_subcommand_from cp' -l help -d 'Print usage'
# create
complete -c docker -f -n '__fish_docker_no_subcommand' -a create -d 'Create a new container'
@@ -119,29 +108,23 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cap-add -d '
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cap-drop -d 'Drop Linux capabilities'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cidfile -d 'Write the container ID to the file'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cpuset -d 'CPUs in which to allow execution (0-3, 0,1)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l dns -d 'Set custom DNS servers'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l dns-search -d "Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)"
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l dns-search -d 'Set custom DNS search domains'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s e -l env -d 'Set environment variables'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l entrypoint -d 'Overwrite the default ENTRYPOINT of the image'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l env-file -d 'Read in a line delimited file of environment variables'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l expose -d 'Expose a port or a range of ports (e.g. --expose=3300-3310) from the container without publishing it to your host'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l expose -d 'Expose a port from the container without publishing it to your host'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s h -l hostname -d 'Container host name'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s i -l interactive -d 'Keep STDIN open even if not attached'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l ipc -d 'Default is to create a private IPC namespace (POSIX SysV IPC) for the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l link -d 'Add link to another container in the form of <name|id>:alias'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l link -d 'Add link to another container in the form of name:alias'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l lxc-conf -d '(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s m -l memory -d 'Memory limit (format: <number><optional unit>, where unit = b, k, m or g)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l mac-address -d 'Container MAC address (e.g. 92:d0:c6:0a:29:33)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l memory-swap -d "Total memory usage (memory + swap), set '-1' to disable swap (format: <number><optional unit>, where unit = b, k, m or g)"
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l name -d 'Assign a name to the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l net -d 'Set the Network mode for the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s P -l publish-all -d 'Publish all exposed ports to random ports on the host interfaces'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s p -l publish -d "Publish a container's port to the host"
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l pid -d 'Default is to create a private PID namespace for the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l privileged -d 'Give extended privileges to this container'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l read-only -d "Mount the container's root filesystem as read only"
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l restart -d 'Restart policy to apply when a container exits (no, on-failure[:max-retry], always)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l security-opt -d 'Security Options'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s t -l tty -d 'Allocate a pseudo-TTY'
@@ -153,32 +136,26 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from create' -a '(__fish_pri
# diff
complete -c docker -f -n '__fish_docker_no_subcommand' -a diff -d "Inspect changes on a container's filesystem"
complete -c docker -A -f -n '__fish_seen_subcommand_from diff' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from diff' -a '(__fish_print_docker_containers all)' -d "Container"
# events
complete -c docker -f -n '__fish_docker_no_subcommand' -a events -d 'Get real time events from the server'
complete -c docker -A -f -n '__fish_seen_subcommand_from events' -s f -l filter -d "Provide filter values (i.e., 'event=stop')"
complete -c docker -A -f -n '__fish_seen_subcommand_from events' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from events' -l since -d 'Show all events created since timestamp'
complete -c docker -A -f -n '__fish_seen_subcommand_from events' -l until -d 'Stream events until this timestamp'
# exec
complete -c docker -f -n '__fish_docker_no_subcommand' -a exec -d 'Run a command in a running container'
complete -c docker -f -n '__fish_docker_no_subcommand' -a exec -d 'Run a command in an existing container'
complete -c docker -A -f -n '__fish_seen_subcommand_from exec' -s d -l detach -d 'Detached mode: run command in the background'
complete -c docker -A -f -n '__fish_seen_subcommand_from exec' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from exec' -s i -l interactive -d 'Keep STDIN open even if not attached'
complete -c docker -A -f -n '__fish_seen_subcommand_from exec' -s t -l tty -d 'Allocate a pseudo-TTY'
complete -c docker -A -f -n '__fish_seen_subcommand_from exec' -a '(__fish_print_docker_containers running)' -d "Container"
# export
complete -c docker -f -n '__fish_docker_no_subcommand' -a export -d 'Stream the contents of a container as a tar archive'
complete -c docker -A -f -n '__fish_seen_subcommand_from export' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from export' -a '(__fish_print_docker_containers all)' -d "Container"
# history
complete -c docker -f -n '__fish_docker_no_subcommand' -a history -d 'Show the history of an image'
complete -c docker -A -f -n '__fish_seen_subcommand_from history' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from history' -l no-trunc -d "Don't truncate output"
complete -c docker -A -f -n '__fish_seen_subcommand_from history' -s q -l quiet -d 'Only show numeric IDs'
complete -c docker -A -f -n '__fish_seen_subcommand_from history' -a '(__fish_print_docker_images)' -d "Image"
@@ -187,40 +164,34 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from history' -a '(__fish_pr
complete -c docker -f -n '__fish_docker_no_subcommand' -a images -d 'List images'
complete -c docker -A -f -n '__fish_seen_subcommand_from images' -s a -l all -d 'Show all images (by default filter out the intermediate image layers)'
complete -c docker -A -f -n '__fish_seen_subcommand_from images' -s f -l filter -d "Provide filter values (i.e., 'dangling=true')"
complete -c docker -A -f -n '__fish_seen_subcommand_from images' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from images' -l no-trunc -d "Don't truncate output"
complete -c docker -A -f -n '__fish_seen_subcommand_from images' -s q -l quiet -d 'Only show numeric IDs'
complete -c docker -A -f -n '__fish_seen_subcommand_from images' -a '(__fish_print_docker_repositories)' -d "Repository"
# import
complete -c docker -f -n '__fish_docker_no_subcommand' -a import -d 'Create a new filesystem image from the contents of a tarball'
complete -c docker -A -f -n '__fish_seen_subcommand_from import' -l help -d 'Print usage'
# info
complete -c docker -f -n '__fish_docker_no_subcommand' -a info -d 'Display system-wide information'
# inspect
complete -c docker -f -n '__fish_docker_no_subcommand' -a inspect -d 'Return low-level information on a container or image'
complete -c docker -f -n '__fish_docker_no_subcommand' -a inspect -d 'Return low-level information on a container'
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -s f -l format -d 'Format the output using the given go template.'
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_images)' -d "Image"
complete -c docker -A -f -n '__fish_seen_subcommand_from inspect' -a '(__fish_print_docker_containers all)' -d "Container"
# kill
complete -c docker -f -n '__fish_docker_no_subcommand' -a kill -d 'Kill a running container'
complete -c docker -A -f -n '__fish_seen_subcommand_from kill' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from kill' -s s -l signal -d 'Signal to send to the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from kill' -a '(__fish_print_docker_containers running)' -d "Container"
# load
complete -c docker -f -n '__fish_docker_no_subcommand' -a load -d 'Load an image from a tar archive'
complete -c docker -A -f -n '__fish_seen_subcommand_from load' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from load' -s i -l input -d 'Read from a tar archive file, instead of STDIN'
# login
complete -c docker -f -n '__fish_docker_no_subcommand' -a login -d 'Register or log in to a Docker registry server'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s e -l email -d 'Email'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s p -l password -d 'Password'
complete -c docker -A -f -n '__fish_seen_subcommand_from login' -s u -l username -d 'Username'
@@ -230,14 +201,12 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -a logout -d 'Log out fro
# logs
complete -c docker -f -n '__fish_docker_no_subcommand' -a logs -d 'Fetch the logs of a container'
complete -c docker -A -f -n '__fish_seen_subcommand_from logs' -s f -l follow -d 'Follow log output'
complete -c docker -A -f -n '__fish_seen_subcommand_from logs' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from logs' -s t -l timestamps -d 'Show timestamps'
complete -c docker -A -f -n '__fish_seen_subcommand_from logs' -l tail -d 'Output the specified number of lines at the end of logs (defaults to all logs)'
complete -c docker -A -f -n '__fish_seen_subcommand_from logs' -a '(__fish_print_docker_containers running)' -d "Container"
# port
complete -c docker -f -n '__fish_docker_no_subcommand' -a port -d 'Lookup the public-facing port that is NAT-ed to PRIVATE_PORT'
complete -c docker -A -f -n '__fish_seen_subcommand_from port' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from port' -a '(__fish_print_docker_containers running)' -d "Container"
# pause
@@ -249,40 +218,32 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -a ps -d 'List containers
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -s a -l all -d 'Show all containers. Only running containers are shown by default.'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -l before -d 'Show only container created before Id or Name, include non-running ones.'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -s f -l filter -d 'Provide filter values. Valid filters:'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -s l -l latest -d 'Show only the latest created container, include non-running ones.'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -s n -d 'Show n last created containers, include non-running ones.'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -l no-trunc -d "Don't truncate output"
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -s q -l quiet -d 'Only display numeric IDs'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -s s -l size -d 'Display total file sizes'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -s s -l size -d 'Display sizes'
complete -c docker -A -f -n '__fish_seen_subcommand_from ps' -l since -d 'Show only containers created since Id or Name, include non-running ones.'
# pull
complete -c docker -f -n '__fish_docker_no_subcommand' -a pull -d 'Pull an image or a repository from a Docker registry server'
complete -c docker -A -f -n '__fish_seen_subcommand_from pull' -s a -l all-tags -d 'Download all tagged images in the repository'
complete -c docker -A -f -n '__fish_seen_subcommand_from pull' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from pull' -a '(__fish_print_docker_images)' -d "Image"
complete -c docker -A -f -n '__fish_seen_subcommand_from pull' -a '(__fish_print_docker_repositories)' -d "Repository"
# push
complete -c docker -f -n '__fish_docker_no_subcommand' -a push -d 'Push an image or a repository to a Docker registry server'
complete -c docker -A -f -n '__fish_seen_subcommand_from push' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from push' -a '(__fish_print_docker_images)' -d "Image"
complete -c docker -A -f -n '__fish_seen_subcommand_from push' -a '(__fish_print_docker_repositories)' -d "Repository"
# rename
complete -c docker -f -n '__fish_docker_no_subcommand' -a rename -d 'Rename an existing container'
# restart
complete -c docker -f -n '__fish_docker_no_subcommand' -a restart -d 'Restart a running container'
complete -c docker -A -f -n '__fish_seen_subcommand_from restart' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from restart' -s t -l time -d 'Number of seconds to try to stop for before killing the container. Once killed it will then be restarted. Default is 10 seconds.'
complete -c docker -A -f -n '__fish_seen_subcommand_from restart' -a '(__fish_print_docker_containers running)' -d "Container"
# rm
complete -c docker -f -n '__fish_docker_no_subcommand' -a rm -d 'Remove one or more containers'
complete -c docker -A -f -n '__fish_seen_subcommand_from rm' -s f -l force -d 'Force the removal of a running container (uses SIGKILL)'
complete -c docker -A -f -n '__fish_seen_subcommand_from rm' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from rm' -s l -l link -d 'Remove the specified link and not the underlying container'
complete -c docker -A -f -n '__fish_seen_subcommand_from rm' -s v -l volumes -d 'Remove the volumes associated with the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from rm' -a '(__fish_print_docker_containers stopped)' -d "Container"
@@ -290,7 +251,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from rm' -a '(__fish_print_d
# rmi
complete -c docker -f -n '__fish_docker_no_subcommand' -a rmi -d 'Remove one or more images'
complete -c docker -A -f -n '__fish_seen_subcommand_from rmi' -s f -l force -d 'Force removal of the image'
complete -c docker -A -f -n '__fish_seen_subcommand_from rmi' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from rmi' -l no-prune -d 'Do not delete untagged parents'
complete -c docker -A -f -n '__fish_seen_subcommand_from rmi' -a '(__fish_print_docker_images)' -d "Image"
@@ -304,33 +264,27 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cap-drop -d 'Dr
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cidfile -d 'Write the container ID to the file'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l cpuset -d 'CPUs in which to allow execution (0-3, 0,1)'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s d -l detach -d 'Detached mode: run the container in the background and print the new container ID'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l device -d 'Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc)'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l dns -d 'Set custom DNS servers'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l dns-search -d "Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)"
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l dns-search -d 'Set custom DNS search domains'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s e -l env -d 'Set environment variables'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l entrypoint -d 'Overwrite the default ENTRYPOINT of the image'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l env-file -d 'Read in a line delimited file of environment variables'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l expose -d 'Expose a port or a range of ports (e.g. --expose=3300-3310) from the container without publishing it to your host'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l expose -d 'Expose a port from the container without publishing it to your host'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s h -l hostname -d 'Container host name'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s i -l interactive -d 'Keep STDIN open even if not attached'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l ipc -d 'Default is to create a private IPC namespace (POSIX SysV IPC) for the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l link -d 'Add link to another container in the form of <name|id>:alias'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l link -d 'Add link to another container in the form of name:alias'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l lxc-conf -d '(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s m -l memory -d 'Memory limit (format: <number><optional unit>, where unit = b, k, m or g)'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l mac-address -d 'Container MAC address (e.g. 92:d0:c6:0a:29:33)'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l memory-swap -d "Total memory usage (memory + swap), set '-1' to disable swap (format: <number><optional unit>, where unit = b, k, m or g)"
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l name -d 'Assign a name to the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l net -d 'Set the Network mode for the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s P -l publish-all -d 'Publish all exposed ports to random ports on the host interfaces'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s p -l publish -d "Publish a container's port to the host"
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l pid -d 'Default is to create a private PID namespace for the container'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l privileged -d 'Give extended privileges to this container'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l read-only -d "Mount the container's root filesystem as read only"
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l restart -d 'Restart policy to apply when a container exits (no, on-failure[:max-retry], always)'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l rm -d 'Automatically remove the container when it exits (incompatible with -d)'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l security-opt -d 'Security Options'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l sig-proxy -d 'Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied.'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l sig-proxy -d 'Proxy received signals to the process (even in non-TTY mode). SIGCHLD, SIGSTOP, and SIGKILL are not proxied.'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s t -l tty -d 'Allocate a pseudo-TTY'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s u -l user -d 'Username or UID'
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s v -l volume -d 'Bind mount a volume (e.g., from the host: -v /host:/container, from Docker: -v /container)'
@@ -340,43 +294,32 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from run' -a '(__fish_print_
# save
complete -c docker -f -n '__fish_docker_no_subcommand' -a save -d 'Save an image to a tar archive'
complete -c docker -A -f -n '__fish_seen_subcommand_from save' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from save' -s o -l output -d 'Write to an file, instead of STDOUT'
complete -c docker -A -f -n '__fish_seen_subcommand_from save' -s o -l output -d 'Write to a file, instead of STDOUT'
complete -c docker -A -f -n '__fish_seen_subcommand_from save' -a '(__fish_print_docker_images)' -d "Image"
# search
complete -c docker -f -n '__fish_docker_no_subcommand' -a search -d 'Search for an image on the Docker Hub'
complete -c docker -A -f -n '__fish_seen_subcommand_from search' -l automated -d 'Only show automated builds'
complete -c docker -A -f -n '__fish_seen_subcommand_from search' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from search' -l no-trunc -d "Don't truncate output"
complete -c docker -A -f -n '__fish_seen_subcommand_from search' -s s -l stars -d 'Only displays with at least x stars'
# start
complete -c docker -f -n '__fish_docker_no_subcommand' -a start -d 'Start a stopped container'
complete -c docker -A -f -n '__fish_seen_subcommand_from start' -s a -l attach -d "Attach container's STDOUT and STDERR and forward all signals to the process"
complete -c docker -A -f -n '__fish_seen_subcommand_from start' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from start' -s i -l interactive -d "Attach container's STDIN"
complete -c docker -A -f -n '__fish_seen_subcommand_from start' -a '(__fish_print_docker_containers stopped)' -d "Container"
# stats
complete -c docker -f -n '__fish_docker_no_subcommand' -a stats -d "Display a live stream of one or more containers' resource usage statistics"
complete -c docker -A -f -n '__fish_seen_subcommand_from stats' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from stats' -a '(__fish_print_docker_containers running)' -d "Container"
# stop
complete -c docker -f -n '__fish_docker_no_subcommand' -a stop -d 'Stop a running container'
complete -c docker -A -f -n '__fish_seen_subcommand_from stop' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from stop' -s t -l time -d 'Number of seconds to wait for the container to stop before killing it. Default is 10 seconds.'
complete -c docker -A -f -n '__fish_seen_subcommand_from stop' -a '(__fish_print_docker_containers running)' -d "Container"
# tag
complete -c docker -f -n '__fish_docker_no_subcommand' -a tag -d 'Tag an image into a repository'
complete -c docker -A -f -n '__fish_seen_subcommand_from tag' -s f -l force -d 'Force'
complete -c docker -A -f -n '__fish_seen_subcommand_from tag' -l help -d 'Print usage'
# top
complete -c docker -f -n '__fish_docker_no_subcommand' -a top -d 'Lookup the running processes of a container'
complete -c docker -A -f -n '__fish_seen_subcommand_from top' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from top' -a '(__fish_print_docker_containers running)' -d "Container"
# unpause
@@ -388,7 +331,6 @@ complete -c docker -f -n '__fish_docker_no_subcommand' -a version -d 'Show the D
# wait
complete -c docker -f -n '__fish_docker_no_subcommand' -a wait -d 'Block until a container stops, then print its exit code'
complete -c docker -A -f -n '__fish_seen_subcommand_from wait' -l help -d 'Print usage'
complete -c docker -A -f -n '__fish_seen_subcommand_from wait' -a '(__fish_print_docker_containers running)' -d "Container"
+6 -2
View File
@@ -820,7 +820,7 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error)
if os.Geteuid() != 0 {
return nil, fmt.Errorf("The Docker daemon needs to be run as root")
}
if err := checkKernel(); err != nil {
if err := checkKernelAndArch(); err != nil {
return nil, err
}
@@ -1205,7 +1205,11 @@ func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*i
return match, nil
}
func checkKernel() error {
func checkKernelAndArch() error {
// Check for unsupported architectures
if runtime.GOARCH != "amd64" {
return fmt.Errorf("The Docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH)
}
// Check for unsupported kernel versions
// FIXME: it would be cleaner to not test for specific versions, but rather
// test for specific functionalities.
+2 -2
View File
@@ -75,8 +75,8 @@ lxc.aa_profile = unconfined
# In non-privileged mode, lxc will automatically mount /proc and /sys in readonly mode
# for security. See: http://man7.org/linux/man-pages/man5/lxc.container.conf.5.html
lxc.mount.auto = proc sys
{{if .AppArmorProfile}}
lxc.aa_profile = {{.AppArmorProfile}}
{{if .AppArmor}}
lxc.aa_profile = .AppArmorProfile
{{end}}
{{end}}
@@ -248,8 +248,7 @@ func TestCustomLxcConfigMisc(t *testing.T) {
}
defer os.RemoveAll(root)
os.MkdirAll(path.Join(root, "containers", "1"), 0777)
driver, err := NewDriver(root, "", true)
driver, err := NewDriver(root, "", false)
if err != nil {
t.Fatal(err)
}
@@ -272,10 +271,9 @@ func TestCustomLxcConfigMisc(t *testing.T) {
Bridge: "docker0",
},
},
ProcessConfig: processConfig,
CapAdd: []string{"net_admin", "syslog"},
CapDrop: []string{"kill", "mknod"},
AppArmorProfile: "lxc-container-default-with-nesting",
ProcessConfig: processConfig,
CapAdd: []string{"net_admin", "syslog"},
CapDrop: []string{"kill", "mknod"},
}
p, err := driver.generateLXCConfig(command)
@@ -289,7 +287,7 @@ func TestCustomLxcConfigMisc(t *testing.T) {
grepFile(t, p, "lxc.network.ipv4 = 10.10.10.10/24")
grepFile(t, p, "lxc.network.ipv4.gateway = 10.10.10.1")
grepFile(t, p, "lxc.network.flags = up")
grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting")
// hostname
grepFile(t, p, "lxc.utsname = testhost")
grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
+15 -41
View File
@@ -150,21 +150,6 @@ func InitDriver(job *engine.Job) engine.Status {
}
}
// a bridge might exist but not have any IPv6 addr associated with it yet
// (for example, an existing Docker installation that has only been used
// with IPv4 and docker0 already is set up) In that case, we can perform
// the bridge init for IPv6 here, else we will error out below if --ipv6=true
if len(addrsv6) == 0 && enableIPv6 {
if err := setupIPv6Bridge(bridgeIPv6); err != nil {
return job.Error(err)
}
// recheck addresses now that IPv6 is setup on the bridge
addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface)
if err != nil {
return job.Error(err)
}
}
// TODO: Check if route to fixedCIDRv6 is set
}
@@ -188,6 +173,7 @@ func InitDriver(job *engine.Job) engine.Status {
networkv4 = addrv4.(*net.IPNet)
log.Infof("enableIPv6 = %t", enableIPv6)
if enableIPv6 {
if len(addrsv6) == 0 {
return job.Error(errors.New("IPv6 enabled but no IPv6 detected"))
@@ -410,14 +396,26 @@ func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error
return err
}
if err := netlink.NetworkLinkAddIp(iface, ipAddr, ipNet); err != nil {
if netlink.NetworkLinkAddIp(iface, ipAddr, ipNet); err != nil {
return fmt.Errorf("Unable to add private network: %s", err)
}
if enableIPv6 {
if err := setupIPv6Bridge(bridgeIPv6); err != nil {
// Enable IPv6 on the bridge
procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6"
if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
return fmt.Errorf("unable to enable IPv6 addresses on bridge: %s\n", err)
}
ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6)
if err != nil {
log.Errorf("BridgeIPv6 parsing failed")
return err
}
if netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
return fmt.Errorf("Unable to add private IPv6 network: %s", err)
}
}
if err := netlink.NetworkLinkUp(iface); err != nil {
@@ -426,30 +424,6 @@ func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error
return nil
}
func setupIPv6Bridge(bridgeIPv6 string) error {
iface, err := net.InterfaceByName(bridgeIface)
if err != nil {
return err
}
// Enable IPv6 on the bridge
procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6"
if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
}
ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6)
if err != nil {
return fmt.Errorf("Unable to parse bridge IPv6 address: %q, error: %v", bridgeIPv6, err)
}
if err := netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
return fmt.Errorf("Unable to add private IPv6 network: %v", err)
}
return nil
}
func createBridgeIface(name string) error {
kv, err := kernel.GetKernelVersion()
// only set the bridge's mac address if the kernel version is > 3.3
+1 -1
View File
@@ -74,7 +74,7 @@ func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
return netIP.Mask(network.Mask), net.IP(lastIP)
}
// Return the first IPv4 address and slice of IPv6 addresses for the specified network interface
// Return the IPv4 address of a network interface
func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
iface, err := net.InterfaceByName(name)
if err != nil {
+7 -2
View File
@@ -79,6 +79,11 @@ func main() {
}
protoAddrParts := strings.SplitN(flHosts[0], "://", 2)
trustKey, err := api.LoadOrCreateTrustKey(*flTrustKey)
if err != nil {
log.Fatal(err)
}
var (
cli *client.DockerCli
tlsConfig tls.Config
@@ -120,9 +125,9 @@ func main() {
}
if *flTls || *flTlsVerify {
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, trustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
} else {
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], nil)
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, trustKey, protoAddrParts[0], protoAddrParts[1], nil)
}
if err := cli.Cmd(flag.Args()...); err != nil {
+1 -1
View File
@@ -97,7 +97,7 @@ func init() {
{"images", "List images"},
{"import", "Create a new filesystem image from the contents of a tarball"},
{"info", "Display system-wide information"},
{"inspect", "Return low-level information on a container or image"},
{"inspect", "Return low-level information on a container"},
{"kill", "Kill a running container"},
{"load", "Load an image from a tar archive"},
{"login", "Register or log in to a Docker registry server"},
+2 -2
View File
@@ -59,7 +59,7 @@ as context.
# EXAMPLES
## Building an image using a Dockerfile located inside the current directory
## Building an image using a Dockefile located inside the current directory
Docker images can be built using the build command and a Dockerfile:
@@ -91,7 +91,7 @@ no hard rules here but it is best to give the names consideration.
The **-t**/**--tag** flag is used to rename an image. Here are some examples:
Though it is not a good practice, image names can be arbitrary:
Though it is not a good practice, image names can be arbtrary:
docker build -t myimage .
+1 -1
View File
@@ -144,7 +144,7 @@ unix://[/path/to/socket] to use.
Display system-wide information
**docker-inspect(1)**
Return low-level information on a container or image
Return low-level information on a container
**docker-kill(1)**
Kill a running container (which includes the wrapper process and everything
-6
View File
@@ -69,11 +69,6 @@ pages:
- ['docker-hub/builds.md', 'Docker Hub', 'Automated Builds']
- ['docker-hub/official_repos.md', 'Docker Hub', 'Official Repo Guidelines']
# Docker Hub Enterprise
- ['docker-hub-enterprise/index.md', '**HIDDEN**' ]
- ['docker-hub-enterprise/install-config.md', 'Docker Hub Enterprise', 'Installation and Configuration' ]
- ['docker-hub-enterprise/usage.md', 'Docker Hub Enterprise', 'User Guide' ]
# Examples:
- ['examples/index.md', '**HIDDEN**']
- ['examples/nodejs_web_app.md', 'Examples', 'Dockerizing a Node.js web application']
@@ -91,7 +86,6 @@ pages:
- ['articles/networking.md', 'Articles', 'Advanced networking']
- ['articles/security.md', 'Articles', 'Security']
- ['articles/https.md', 'Articles', 'Running Docker with HTTPS']
- ['articles/registry_mirror.md', 'Articles', 'Run a local registry mirror']
- ['articles/host_integration.md', 'Articles', 'Automatically starting containers']
- ['articles/baseimages.md', 'Articles', 'Creating a base image']
- ['articles/dockerfile_best-practices.md', 'Articles', 'Best practices for writing Dockerfiles']
+2 -6
View File
@@ -72,9 +72,6 @@ setup_s3() {
build_current_documentation() {
mkdocs build
cd site/
gzip -9k -f search_content.json
cd ..
}
upload_current_documentation() {
@@ -90,6 +87,8 @@ upload_current_documentation() {
echo "Uploading $src"
echo " to $dst"
echo
#s3cmd --recursive --follow-symlinks --preserve --acl-public sync "$src" "$dst"
#aws s3 cp --profile $BUCKET --cache-control "max-age=3600" --acl public-read "site/search_content.json" "$dst"
# a really complicated way to send only the files we want
# if there are too many in any one set, aws s3 sync seems to fall over with 2 files to go
@@ -101,9 +100,6 @@ upload_current_documentation() {
echo "$run"
echo "======================="
$run
# Make sure the search_content.json.gz file has the right content-encoding
aws s3 cp --profile $BUCKET --cache-control $cache --content-encoding="gzip" --acl public-read "site/search_content.json.gz" "$dst"
}
invalidate_cache() {
+15
View File
@@ -0,0 +1,15 @@
# Articles
- [Docker Basics](basics/)
- [Docker Security](security/)
- [Running the Docker daemon with HTTPS](https/)
- [Configure Networking](networking/)
- [Using Supervisor with Docker](using_supervisord/)
- [Process Management with CFEngine](cfengine_process_management/)
- [Using Puppet](puppet/)
- [Create a Base Image](baseimages/)
- [Runtime Metrics](runmetrics/)
- [Automatically Start Containers](host_integration/)
- [Link via an Ambassador Container](ambassador_pattern_linking/)
- [Increase a Boot2Docker Volume](b2d_volume_resize/)
- [Run a Local Registry Mirror](registry_mirror/)
+29 -44
View File
@@ -26,7 +26,7 @@ it will only connect to servers with a certificate signed by that CA.
## Create a CA, server and client keys with OpenSSL
> **Note**: replace all instances of `$HOST` in the following example with the
> **Note:** replace all instances of `$HOST` in the following example with the
> DNS name of your Docker daemon's host.
First generate CA private and public keys:
@@ -40,26 +40,26 @@ First generate CA private and public keys:
Verifying - Enter pass phrase for ca-key.pem:
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
Enter pass phrase for ca-key.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:Queensland
Locality Name (eg, city) []:Brisbane
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc
Organizational Unit Name (eg, section) []:Boot2Docker
Common Name (e.g. server FQDN or YOUR name) []:$HOST
Email Address []:Sven@home.org.au
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:Queensland
Locality Name (eg, city) []:Brisbane
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc
Organizational Unit Name (eg, section) []:Boot2Docker
Common Name (e.g. server FQDN or YOUR name) []:$HOST
Email Address []:Sven@home.org.au
Now that we have a CA, you can create a server key and certificate
signing request (CSR). Make sure that "Common Name" (i.e., server FQDN or YOUR
name) matches the hostname you will use to connect to Docker:
> **Note**: replace all instances of `$HOST` in the following example with the
> **Note:** replace all instances of `$HOST` in the following example with the
> DNS name of your Docker daemon's host.
$ openssl genrsa -out server-key.pem 2048
@@ -69,7 +69,7 @@ name) matches the hostname you will use to connect to Docker:
e is 65537 (0x10001)
$ openssl req -subj "/CN=$HOST" -new -key server-key.pem -out server.csr
Next, we're going to sign the public key with our CA:
Next, we're going to sign the key with our CA:
$ openssl x509 -req -days 365 -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem
@@ -93,7 +93,7 @@ config file:
$ echo extendedKeyUsage = clientAuth > extfile.cnf
Now sign the public key:
Now sign the key:
$ openssl x509 -req -days 365 -in client.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out cert.pem -extfile extfile.cnf
@@ -102,24 +102,6 @@ Now sign the public key:
Getting CA Private Key
Enter pass phrase for ca-key.pem:
After generating `cert.pem` and `server-cert.pem` you can safely remove the
two certificate signing requests:
$ rm -v client.csr server.csr
With a default `umask` of 022, your secret keys will be *world-readable* and
writable for you and your group.
In order to protect your keys from accidental damage, you will want to remove their
write permissions. To make them only readable by you, change file modes as follows:
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
Certificates can be world-readable, but you might want to remove write access to
prevent accidental damage:
$ chmod -v 0444 ca.pem server-cert.pem cert.pem
Now you can make the Docker daemon only accept connections from clients
providing a certificate trusted by our CA:
@@ -129,7 +111,7 @@ providing a certificate trusted by our CA:
To be able to connect to Docker and validate its certificate, you now
need to provide your client keys, certificates and trusted CA:
> **Note**: replace all instances of `$HOST` in the following example with the
> **Note:** replace all instances of `$HOST` in the following example with the
> DNS name of your Docker daemon's host.
$ docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem \
@@ -148,13 +130,16 @@ need to provide your client keys, certificates and trusted CA:
## Secure by default
If you want to secure your Docker client connections by default, you can move
the files to the `.docker` directory in your home directory -- and set the
the files to the `.docker` directory in your home directory - and set the
`DOCKER_HOST` and `DOCKER_TLS_VERIFY` variables as well (instead of passing
`-H=tcp://$HOST:2376` and `--tlsverify` on every call).
`-H=tcp://:2376` and `--tlsverify` on every call).
$ mkdir -pv ~/.docker
$ cp -v {ca,cert,key}.pem ~/.docker
$ export DOCKER_HOST=tcp://$HOST:2376 DOCKER_TLS_VERIFY=1
$ mkdir -p ~/.docker
$ cp ca.pem ~/.docker/ca.pem
$ cp cert.pem ~/.docker/cert.pem
$ cp key.pem ~/.docker/key.pem
$ export DOCKER_HOST=tcp://:2376
$ export DOCKER_TLS_VERIFY=1
Docker will now connect securely by default:
@@ -180,11 +165,11 @@ Docker in various other modes by mixing the flags.
certificate and authenticate server based on given CA
If found, the client will send its client certificate, so you just need
to drop your keys into `~/.docker/{ca,cert,key}.pem`. Alternatively,
to drop your keys into `~/.docker/<ca, cert or key>.pem`. Alternatively,
if you want to store your keys in another location, you can specify that
location using the environment variable `DOCKER_CERT_PATH`.
$ export DOCKER_CERT_PATH=~/.docker/zone1/
$ export DOCKER_CERT_PATH=${HOME}/.docker/zone1/
$ docker --tlsverify ps
### Connecting to the Secure Docker port using `curl`
+3 -4
View File
@@ -13,12 +13,11 @@ cert: build
certs: cert
run:
sudo docker -d -D --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=0.0.0.0:6666 --pidfile=$(pwd)/docker.pid --graph=$(pwd)/graph
docker -d -D --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=0.0.0.0:6666 --pidfile=$(pwd)/docker.pid --graph=$(pwd)/graph
client:
sudo docker --tls --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=$(HOST):6666 version
sudo docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=$(HOST):6666 info
sudo curl https://$(HOST):6666/images/json --cert cert.pem --key key.pem --cacert ca.pem
docker --tls --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=$(HOST):6666 version
docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=$(HOST):6666 info
clean:
rm ca-key.pem ca.pem ca.srl cert.pem client.csr extfile.cnf key.pem server-cert.pem server-key.pem server.csr
+1 -7
View File
@@ -1,10 +1,4 @@
#!/bin/sh
echo "#!/bin/sh"
cat ../https.md | awk '{if (sub(/\\$/,"")) printf "%s", $0; else print $0}' \
| grep ' $ ' \
| sed 's/ $ //g' \
| sed 's/2375/7777/g' \
| sed 's/2376/7778/g' \
| sed 's/^docker/# docker/g' \
| sed 's/^curl/# curl/g'
cat ../https.md | awk '{if (sub(/\\$/,"")) printf "%s", $0; else print $0}' | grep ' $ ' | sed 's/ $ //g' | sed 's/2375/7777/g' | sed 's/2376/7778/g'
-10
View File
@@ -687,7 +687,6 @@ stopping the service and removing the interface:
$ sudo service docker stop
$ sudo ip link set dev docker0 down
$ sudo brctl delbr docker0
$ sudo iptables -t nat -F POSTROUTING
Then, before starting the Docker service, create your own bridge and
give it whatever configuration you want. Here we will create a simple
@@ -714,15 +713,6 @@ illustrate the technique.
$ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker
$ sudo service docker start
# Confirming new outgoing NAT masquerade is set up
$ sudo iptables -t nat -L -n
...
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 192.168.5.0/24 0.0.0.0/0
The result should be that the Docker server starts successfully and is
now prepared to bind containers to the new bridge. After pausing to
verify the bridge's configuration, try creating a container — you will
+1 -1
View File
@@ -39,7 +39,7 @@ our container.
Here we're installing the `openssh-server`,
`apache2` and `supervisor`
(which provides the Supervisor daemon) packages. We're also creating four
(which provides the Supervisor daemon) packages. We're also creating two
new directories that are needed to run our SSH daemon and Supervisor.
## Adding Supervisor's configuration file
+12 -18
View File
@@ -10,12 +10,6 @@ used for all tests, builds and releases. The standard development
environment defines all build dependencies: system libraries and
binaries, go environment, go dependencies, etc.
**Things you need:**
* Docker
* git
* make
## Install Docker
Docker's build environment itself is a Docker container, so the first
@@ -49,18 +43,18 @@ with the name of branch or revision number.
This following command builds a development environment using the
`Dockerfile` in the current directory. Essentially, it installs all
the build and runtime dependencies necessary to build and test Docker.
Your first build will take some time to complete. On Linux systems and on Mac
OS X from within the `boot2docker` shell:
Your first build will take some time to complete. On Linux systems:
$ sudo make build
On Mac OS X, from within the `boot2docker` shell:
$ make build
> **Note**:
> On Mac OS X, the Docker make targets such as `build`, `binary`, and `test`
> should **not** be built by the 'root' user. Therefore, you shouldn't use `sudo` when
> running these commands on OS X.
> On Linux, we suggest you add your current user to the `docker` group via
> [these
> instructions](http://docs.docker.com/installation/ubuntulinux/#giving-non-root-access).
> running these commands on OS X.
If the build is successful, congratulations! You have produced a clean
build of docker, neatly encapsulated in a standard build environment.
@@ -70,13 +64,13 @@ build of docker, neatly encapsulated in a standard build environment.
To create the Docker binary, run this command:
$ make binary
$ sudo make binary
This will create the Docker binary in `./bundles/<version>-dev/binary/`. If you
do not see files in the `./bundles` directory in your host, your `BINDDIR`
setting is not set quite right. You want to run the following command:
$ make BINDDIR=. binary
$ sudo make BINDDIR=. binary
If you are on a non-Linux platform, e.g., OSX, you'll want to run `make cross`
or `make BINDDIR=. cross`.
@@ -97,7 +91,7 @@ on ubuntu:
To execute the test cases, run this command:
$ make test
$ sudo make test
If the test are successful then the tail of the output should look
something like this
@@ -144,7 +138,7 @@ is recommended.
You can run an interactive session in the newly built container:
$ make shell
$ sudo make shell
# type 'exit' or Ctrl-D to exit
@@ -154,7 +148,7 @@ If you want to read the documentation from a local website, or are
making changes to it, you can build the documentation and then serve it
by:
$ make docs
$ sudo make docs
# when its done, you can point your browser to http://yourdockerhost:8000
# type Ctrl-C to exit
@@ -1,8 +0,0 @@
page_title: Using Docker Hub Enterprise Installation
page_description: Docker Hub Enterprise Installation
page_keywords: docker hub enterprise
# Docker Hub Enterprise Installation
Documenation coming soon.
@@ -1,9 +0,0 @@
page_title: Using Docker Hub Enterprise
page_description: Docker Hub Enterprise
page_keywords: docker hub enterprise
# Docker Hub Enterprise
Documenation coming soon.
-4
View File
@@ -278,10 +278,6 @@ Webhooks are available under the Settings menu of each Repository.
> **Note:** If you want to test your webhook out we recommend using
> a tool like [requestb.in](http://requestb.in/).
> **Note**: The Docker Hub servers are currently in the IP range
> `162.242.195.64 - 162.242.195.127`, so you can restrict your webhooks to
> accept webhook requests from that set of IP addresses.
### Webhook chains
Webhook chains allow you to chain calls to multiple services. For example,
+3 -7
View File
@@ -105,6 +105,9 @@ Settings page. A webhook is called only after a successful `push` is
made. The webhook calls are HTTP POST requests with a JSON payload
similar to the example shown below.
> **Note:** For testing, you can try an HTTP request tool like
> [requestb.in](http://requestb.in/).
*Example webhook JSON payload:*
```
@@ -138,13 +141,6 @@ new updates to your images and repositories. To get started adding webhooks,
go to the desired repo in the Hub, and click "Webhooks" under the "Settings"
box.
> **Note:** For testing, you can try an HTTP request tool like
> [requestb.in](http://requestb.in/).
> **Note**: The Docker Hub servers are currently in the IP range
> `162.242.195.64 - 162.242.195.127`, so you can restrict your webhooks to
> accept webhook requests from that set of IP addresses.
### Webhook chains
Webhook chains allow you to chain calls to multiple services. For example,
@@ -385,41 +385,6 @@ Status Codes:
- **404** no such container
- **500** server error
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -385,41 +385,6 @@ Status Codes:
- **404** no such container
- **500** server error
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -35,7 +35,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -45,7 +45,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -55,7 +55,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -65,7 +65,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -119,7 +119,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"ubuntu",
"Image":"base",
"Volumes":{
"/tmp": {}
},
@@ -194,7 +194,7 @@ Return low-level information on the container `id`
"Cmd": [
"date"
],
"Image": "ubuntu",
"Image": "base",
"Volumes": {},
"WorkingDir":""
@@ -539,41 +539,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1)
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -702,7 +667,7 @@ Create an image, either by pull it from the registry or by importing
**Example request**:
POST /images/create?fromImage=ubuntu HTTP/1.1
POST /images/create?fromImage=base HTTP/1.1
**Example response**:
@@ -774,7 +739,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/ubuntu/json HTTP/1.1
GET /images/base/json HTTP/1.1
**Example response**:
@@ -801,7 +766,7 @@ Return low-level information on the image `name`
"StdinOnce":false,
"Env":null,
"Cmd": ["/bin/bash"]
"Image":"ubuntu",
"Image":"base",
"Volumes":null,
"WorkingDir":""
},
@@ -822,7 +787,7 @@ Return the history of the image `name`
**Example request**:
GET /images/ubuntu/history HTTP/1.1
GET /images/base/history HTTP/1.1
**Example response**:
@@ -1229,10 +1194,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
{"status": "create", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "base:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "base:latest", "time":1374067970}
Query Parameters:
@@ -35,7 +35,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -45,7 +45,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -55,7 +55,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -65,7 +65,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -119,7 +119,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"ubuntu",
"Image":"base",
"Volumes":{
"/tmp": {}
},
@@ -195,7 +195,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -574,41 +574,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1)
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -736,7 +701,7 @@ Create an image, either by pull it from the registry or by importing i
**Example request**:
POST /images/create?fromImage=ubuntu HTTP/1.1
POST /images/create?fromImage=base HTTP/1.1
**Example response**:
@@ -777,7 +742,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/ubuntu/json HTTP/1.1
GET /images/base/json HTTP/1.1
**Example response**:
@@ -805,7 +770,7 @@ Return low-level information on the image `name`
"Env":null,
"Cmd": ["/bin/bash"],
"Dns":null,
"Image":"ubuntu",
"Image":"base",
"Volumes":null,
"VolumesFrom":"",
"WorkingDir":""
@@ -827,7 +792,7 @@ Return the history of the image `name`
**Example request**:
GET /images/ubuntu/history HTTP/1.1
GET /images/base/history HTTP/1.1
**Example response**:
@@ -1259,10 +1224,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
{"status": "create", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "base:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "base:latest", "time":1374067970}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -127,7 +127,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"ubuntu",
"Image":"base",
"Volumes":{
"/tmp": {}
},
@@ -204,7 +204,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -622,41 +622,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -795,7 +760,7 @@ Create an image, either by pull it from the registry or by importing i
**Example request**:
POST /images/create?fromImage=ubuntu HTTP/1.1
POST /images/create?fromImage=base HTTP/1.1
**Example response**:
@@ -838,7 +803,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/ubuntu/json HTTP/1.1
GET /images/base/json HTTP/1.1
**Example response**:
@@ -864,7 +829,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -888,7 +853,7 @@ Return the history of the image `name`
**Example request**:
GET /images/ubuntu/history HTTP/1.1
GET /images/base/history HTTP/1.1
**Example response**:
@@ -1325,10 +1290,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
{"status": "create", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "base:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "base:latest", "time":1374067970}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -121,7 +121,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"ubuntu",
"Image":"base",
"Volumes":{
"/tmp": {}
},
@@ -198,7 +198,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -615,41 +615,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -784,7 +749,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=ubuntu HTTP/1.1
POST /images/create?fromImage=base HTTP/1.1
**Example response**:
@@ -827,7 +792,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/ubuntu/json HTTP/1.1
GET /images/base/json HTTP/1.1
**Example response**:
@@ -853,7 +818,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -877,7 +842,7 @@ Return the history of the image `name`
**Example request**:
GET /images/ubuntu/history HTTP/1.1
GET /images/base/history HTTP/1.1
**Example response**:
@@ -1314,10 +1279,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
{"status": "create", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "base:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "base:latest", "time":1374067970}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -124,7 +124,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"ubuntu",
"Image":"base",
"Volumes":{
"/tmp": {}
},
@@ -207,7 +207,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -625,41 +625,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -794,7 +759,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=ubuntu HTTP/1.1
POST /images/create?fromImage=base HTTP/1.1
**Example response**:
@@ -837,7 +802,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/ubuntu/json HTTP/1.1
GET /images/base/json HTTP/1.1
**Example response**:
@@ -863,7 +828,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -887,7 +852,7 @@ Return the history of the image `name`
**Example request**:
GET /images/ubuntu/history HTTP/1.1
GET /images/base/history HTTP/1.1
**Example response**:
@@ -1324,10 +1289,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
{"status": "create", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "base:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "base:latest", "time":1374067970}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -128,7 +128,7 @@ Create a container
"date"
],
"Entrypoint": "",
"Image": "ubuntu",
"Image": "base",
"Volumes": {
"/tmp": {}
},
@@ -148,7 +148,6 @@ Create a container
"Privileged": false,
"Dns": ["8.8.8.8"],
"DnsSearch": [""],
"ExtraHosts": null,
"VolumesFrom": ["parent", "other:ro"],
"CapAdd": ["NET_ADMIN"],
"CapDrop": ["MKNOD"],
@@ -221,8 +220,6 @@ Json Parameters:
a boolean value.
- **Dns** - A list of dns servers for the container to use.
- **DnsSearch** - A list of DNS search domains
- **ExtraHosts** - A list of hostnames/IP mappings to be added to the
container's `/etc/hosts` file. Specified in the form `["hostname:IP"]`.
- **VolumesFrom** - A list of volumes to inherit from another container.
Specified in the form `<container name>[:<ro|rw>]`
- **CapAdd** - A list of kernel capabilties to add to the container.
@@ -291,7 +288,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -770,41 +767,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -939,7 +901,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=ubuntu HTTP/1.1
POST /images/create?fromImage=base HTTP/1.1
**Example response**:
@@ -983,7 +945,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/ubuntu/json HTTP/1.1
GET /images/base/json HTTP/1.1
**Example response**:
@@ -1009,7 +971,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -1033,7 +995,7 @@ Return the history of the image `name`
**Example request**:
GET /images/ubuntu/history HTTP/1.1
GET /images/base/history HTTP/1.1
**Example response**:
@@ -1471,10 +1433,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
{"status": "create", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "base:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "base:latest", "time":1374067970}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -128,7 +128,7 @@ Create a container
"date"
],
"Entrypoint": "",
"Image": "ubuntu",
"Image": "base",
"Volumes": {
"/tmp": {}
},
@@ -148,7 +148,6 @@ Create a container
"Privileged": false,
"Dns": ["8.8.8.8"],
"DnsSearch": [""],
"ExtraHosts": null,
"VolumesFrom": ["parent", "other:ro"],
"CapAdd": ["NET_ADMIN"],
"CapDrop": ["MKNOD"],
@@ -221,8 +220,6 @@ Json Parameters:
a boolean value.
- **Dns** - A list of dns servers for the container to use.
- **DnsSearch** - A list of DNS search domains
- **ExtraHosts** - A list of hostnames/IP mappings to be added to the
container's `/etc/hosts` file. Specified in the form `["hostname:IP"]`.
- **VolumesFrom** - A list of volumes to inherit from another container.
Specified in the form `<container name>[:<ro|rw>]`
- **CapAdd** - A list of kernel capabilties to add to the container.
@@ -291,7 +288,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -716,41 +713,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -885,7 +847,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=ubuntu HTTP/1.1
POST /images/create?fromImage=base HTTP/1.1
**Example response**:
@@ -929,7 +891,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/ubuntu/json HTTP/1.1
GET /images/base/json HTTP/1.1
**Example response**:
@@ -955,7 +917,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -979,7 +941,7 @@ Return the history of the image `name`
**Example request**:
GET /images/ubuntu/history HTTP/1.1
GET /images/base/history HTTP/1.1
**Example response**:
@@ -1427,10 +1389,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
{"status": "create", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "base:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "base:latest", "time":1374067970}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "ubuntu:latest",
"Image": "base:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -128,7 +128,7 @@ Create a container
"date"
],
"Entrypoint": "",
"Image": "ubuntu",
"Image": "base",
"Volumes": {
"/tmp": {}
},
@@ -149,7 +149,6 @@ Create a container
"ReadonlyRootfs": false,
"Dns": ["8.8.8.8"],
"DnsSearch": [""],
"ExtraHosts": null,
"VolumesFrom": ["parent", "other:ro"],
"CapAdd": ["NET_ADMIN"],
"CapDrop": ["MKNOD"],
@@ -224,8 +223,6 @@ Json Parameters:
Specified as a boolean value.
- **Dns** - A list of dns servers for the container to use.
- **DnsSearch** - A list of DNS search domains
- **ExtraHosts** - A list of hostnames/IP mappings to be added to the
container's `/etc/hosts` file. Specified in the form `["hostname:IP"]`.
- **VolumesFrom** - A list of volumes to inherit from another container.
Specified in the form `<container name>[:<ro|rw>]`
- **CapAdd** - A list of kernel capabilties to add to the container.
@@ -873,41 +870,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -1096,7 +1058,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=ubuntu HTTP/1.1
POST /images/create?fromImage=base HTTP/1.1
**Example response**:
@@ -1140,7 +1102,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/ubuntu/json HTTP/1.1
GET /images/base/json HTTP/1.1
**Example response**:
@@ -1166,7 +1128,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "ubuntu",
"Image": "base",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -1190,7 +1152,7 @@ Return the history of the image `name`
**Example request**:
GET /images/ubuntu/history HTTP/1.1
GET /images/base/history HTTP/1.1
**Example response**:
@@ -1589,10 +1551,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "create", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "ubuntu:latest", "time":1374067970}
{"status": "create", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "start", "id": "dfdf82bd3881","from": "base:latest", "time":1374067924}
{"status": "stop", "id": "dfdf82bd3881","from": "base:latest", "time":1374067966}
{"status": "destroy", "id": "dfdf82bd3881","from": "base:latest", "time":1374067970}
Query Parameters:
@@ -397,41 +397,6 @@ Status Codes:
- **404** no such container
- **500** server error
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -445,41 +445,6 @@ Status Codes:
- **404** no such container
- **500** server error
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -460,41 +460,6 @@ Status Codes:
- **404** no such container
- **500** server error
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -458,41 +458,6 @@ Status Codes:
- **404** no such container
- **500** server error
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -564,41 +564,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1)
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -509,41 +509,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1)
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -557,41 +557,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1)
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
@@ -561,41 +561,6 @@ Status Codes:
4. Read the extracted size and output it on the correct output
5. Goto 1)
### Attach to a container (websocket)
`GET /containers/(id)/attach/ws`
Attach to the container `id` via websocket
Implements websocket protocol handshake according to [RFC 6455](http://tools.ietf.org/html/rfc6455)
**Example request**
GET /containers/e90e34656806/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
**Example response**
{{ STREAM }}
Query Parameters:
- **logs** 1/True/true or 0/False/false, return logs. Default false
- **stream** 1/True/true or 0/False/false, return stream.
Default false
- **stdin** 1/True/true or 0/False/false, if stream=true, attach
to stdin. Default false
- **stdout** 1/True/true or 0/False/false, if logs=true, return
stdout log, if stream=true, attach to stdout. Default false
- **stderr** 1/True/true or 0/False/false, if logs=true, return
stderr log, if stream=true, attach to stderr. Default false
Status Codes:
- **200** no error
- **400** bad parameter
- **404** no such container
- **500** server error
### Wait a container
`POST /containers/(id)/wait`
+1 -1
View File
@@ -64,7 +64,7 @@ This will mount the host directory, `/src/webapp`, into the container at
`/opt/webapp`.
> **Note:**
> If the path `/opt/webapp` already exists inside the container's image, its
> If the path `/opt/webapp` already exists inside the container's image, it's
> contents will be replaced by the contents of `/src/webapp` on the host to stay
> consistent with the expected behavior of `mount`
+2 -3
View File
@@ -167,9 +167,8 @@ host. You might be asking about now: why wouldn't we just want to always
use 1:1 port mappings in Docker containers rather than mapping to high
ports? Well 1:1 mappings have the constraint of only being able to map
one of each port on your local host. Let's say you want to test two
Python applications: both bound to port 5000 inside their own containers.
Without Docker's port mapping you could only access one at a time on the
Docker host.
Python applications: both bound to port 5000 inside your container.
Without Docker's port mapping you could only access one at a time.
So let's now browse to port 49155 in a web browser to
see the application.
-1
View File
@@ -60,7 +60,6 @@ pre {
/* Main Navigation */
#nav_menu > #docsnav {
max-width: 940px;
width: 940px;
margin: 0 auto;
}
#nav_menu > #docsnav > #nav_search {
+4
View File
@@ -801,6 +801,10 @@ div + .form-inline {
transition: box-shadow linear 0.2s, background linear 0.3s, width linear 0.3s;
width: 140px;
}
#topmostnav .navbar-index-search .search-query:focus,
#topmostnav .navbar-index-search .search-query.focused {
width: 200px;
}
#topmostnav.public {
border-bottom: none;
height: 80px;
+8 -10
View File
@@ -1,14 +1,13 @@
<div id="topmostnav" class="topmostnav_loggedout navbar navbar-static-top">
<div id="topmostnav" class="topmostnav_loggedout navbar navbar-static-top public">
<div class="container">
<a href="/" title="Docker Docs Home"><div class="brand logo"><img src="/img/nav/docker-logo-loggedin.png"> </div></a>
<form id="nav_search" class="navbar-index-search pull-right" action="/jsearch/">
<span role="status" aria-live="polite" class="ui-helper-hidden-accessible"></span>
<input name="q" id="tipue_search_input" type="text" class="search_input search-query ui-autocomplete-input" placeholder="Search the Docs" autocomplete="off">
</form>
<a href="http://www.docker.com/" title="Homepage">
<div class="brand logo"><img src="/img/nav/docker-logo-loggedout.png"> </div>
</a>
<ul class="nav">
<li class=""><a href="http://www.docker.com/whatisdocker/" title="What is Docker">What is Docker?</a></li>
<li class=""><a href="http://www.docker.com/resources/usecases/" title="Use Cases">Use Cases</a></li>
<li class=""><a href="http://www.docker.com/tryit/" title="Try It!">Try It!</a></li>
<li class="active"><a href="https://docs.docker.com" title="Install &amp; Docs">Install &amp; Docs</a></li>
<li><a href="https://registry.hub.docker.com" title="Browse">Browse</a></li>
</ul>
<div id="usernav" class="pull-right">
@@ -19,10 +18,9 @@
</div>
<div id="topmostnav" class="topmostnav_loggedin navbar navbar-static-top">
<div class="container">
<a href="/" title="Docker Docs Home"><div class="brand logo"><img src="/img/nav/docker-logo-loggedin.png"> </div></a>
<form id="nav_search" class="navbar-index-search pull-right" action="/jsearch/">
<span role="status" aria-live="polite" class="ui-helper-hidden-accessible"></span>
<input name="q" id="tipue_search_input" type="text" class="search_input search-query ui-autocomplete-input" placeholder="Search the Docs" autocomplete="off">
<a href="http://www.docker.com/" title="Docker Docs Home"><div class="brand logo"><img src="/img/nav/docker-logo-loggedin.png"> </div></a>
<form id="search_box_header" class="navbar-index-search pull-right" action="https://registry.hub.docker.com/search">
<span role="status" aria-live="polite" class="ui-helper-hidden-accessible"></span><input type="text" class="search-query ui-autocomplete-input" placeholder="Search..." name="q" value="" autocomplete="off">
</form>
<ul class="nav">
<li><a href="https://registry.hub.docker.com" title="Browse Repos">Browse Repos</a></li>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 20 KiB

+7 -13
View File
@@ -1,6 +1,12 @@
$(document).ready(function ()
{
// Tipue Search activation
$('#tipue_search_input').tipuesearch({
'mode': 'json',
'contentLocation': '/search_content.json'
});
prettyPrint();
// Resizing
@@ -45,18 +51,6 @@ $(document).ready(function ()
},
});
function getURLP(name)
{
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20')) || null;
}
if (getURLP("q")) {
// Tipue Search activation
$('#tipue_search_input').tipuesearch({
'mode': 'json',
'contentLocation': '/search_content.json.gz'
});
}
});
function resizeMenuDropdown ()
@@ -98,4 +92,4 @@ function getCookie(cname) {
if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
}
return "";
}
}
+4
View File
@@ -18,5 +18,9 @@
{% endif %}
{% endfor %}
</ul>
<form id="nav_search" class="pull-right" action="/jsearch/">
<span role="status" aria-live="polite" class="ui-helper-hidden-accessible"></span>
<input name="q" id="tipue_search_input" type="text" class="search_input search-query ui-autocomplete-input" placeholder="Search the Docs" autocomplete="off">
</form>
</div>
</nav>
-84
View File
@@ -4,8 +4,6 @@ import (
"bytes"
"strings"
"testing"
"github.com/docker/docker/pkg/ioutils"
)
func TestRegister(t *testing.T) {
@@ -152,85 +150,3 @@ func TestCatchallEmptyName(t *testing.T) {
t.Fatalf("Engine.Job(\"\").Run() should return an error")
}
}
// Ensure that a job within a job both using the same underlying standard
// output writer does not close the output of the outer job when the inner
// job's stdout is wrapped with a NopCloser. When not wrapped, it should
// close the outer job's output.
func TestNestedJobSharedOutput(t *testing.T) {
var (
outerHandler Handler
innerHandler Handler
wrapOutput bool
)
outerHandler = func(job *Job) Status {
job.Stdout.Write([]byte("outer1"))
innerJob := job.Eng.Job("innerJob")
if wrapOutput {
innerJob.Stdout.Add(ioutils.NopWriteCloser(job.Stdout))
} else {
innerJob.Stdout.Add(job.Stdout)
}
if err := innerJob.Run(); err != nil {
t.Fatal(err)
}
// If wrapOutput was *false* this write will do nothing.
// FIXME (jlhawn): It should cause an error to write to
// closed output.
job.Stdout.Write([]byte(" outer2"))
return StatusOK
}
innerHandler = func(job *Job) Status {
job.Stdout.Write([]byte(" inner"))
return StatusOK
}
eng := New()
eng.Register("outerJob", outerHandler)
eng.Register("innerJob", innerHandler)
// wrapOutput starts *false* so the expected
// output of running the outer job will be:
//
// "outer1 inner"
//
outBuf := new(bytes.Buffer)
outerJob := eng.Job("outerJob")
outerJob.Stdout.Add(outBuf)
if err := outerJob.Run(); err != nil {
t.Fatal(err)
}
expectedOutput := "outer1 inner"
if outBuf.String() != expectedOutput {
t.Fatalf("expected job output to be %q, got %q", expectedOutput, outBuf.String())
}
// Set wrapOutput to true so that the expected
// output of running the outer job will be:
//
// "outer1 inner outer2"
//
wrapOutput = true
outBuf.Reset()
outerJob = eng.Job("outerJob")
outerJob.Stdout.Add(outBuf)
if err := outerJob.Run(); err != nil {
t.Fatal(err)
}
expectedOutput = "outer1 inner outer2"
if outBuf.String() != expectedOutput {
t.Fatalf("expected job output to be %q, got %q", expectedOutput, outBuf.String())
}
}
-22
View File
@@ -223,28 +223,6 @@ func (graph *Graph) Mktemp(id string) (string, error) {
return dir, nil
}
func (graph *Graph) newTempFile() (*os.File, error) {
tmp, err := graph.Mktemp("")
if err != nil {
return nil, err
}
return ioutil.TempFile(tmp, "")
}
func bufferToFile(f *os.File, src io.Reader) (int64, error) {
n, err := io.Copy(f, src)
if err != nil {
return n, err
}
if err = f.Sync(); err != nil {
return n, err
}
if _, err := f.Seek(0, 0); err != nil {
return n, err
}
return n, nil
}
// setupInitLayer populates a directory with mountpoints suitable
// for bind-mounting dockerinit into the container. The mountpoint is simply an
// empty file at /.dockerinit
+52 -38
View File
@@ -3,9 +3,11 @@ package graph
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"path"
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/engine"
@@ -15,6 +17,35 @@ import (
"github.com/docker/libtrust"
)
func (s *TagStore) CmdManifest(job *engine.Job) engine.Status {
if len(job.Args) != 1 {
return job.Errorf("usage: %s NAME", job.Name)
}
name := job.Args[0]
tag := job.Getenv("tag")
if tag == "" {
tag = "latest"
}
// Resolve the Repository name from fqn to endpoint + name
repoInfo, err := registry.ParseRepositoryInfo(name)
if err != nil {
return job.Error(err)
}
manifestBytes, err := s.newManifest(name, repoInfo.RemoteName, tag)
if err != nil {
return job.Error(err)
}
_, err = job.Stdout.Write(manifestBytes)
if err != nil {
return job.Error(err)
}
return engine.StatusOK
}
func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error) {
manifest := &registry.ManifestData{
Name: remoteName,
@@ -40,13 +71,14 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
if err != nil {
return nil, err
}
if layer.Config == nil {
return nil, errors.New("Missing layer configuration")
}
manifest.Architecture = layer.Architecture
manifest.FSLayers = make([]*registry.FSLayer, 0, 4)
manifest.History = make([]*registry.ManifestHistory, 0, 4)
var metadata runconfig.Config
if layer.Config != nil {
metadata = *layer.Config
}
metadata = *layer.Config
for ; layer != nil; layer, err = layer.GetParent() {
if err != nil {
@@ -63,41 +95,28 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
}
}
checksum, err := layer.GetCheckSum(s.graph.ImageRoot(layer.ID))
archive, err := layer.TarLayer()
if err != nil {
return nil, fmt.Errorf("Error getting image checksum: %s", err)
}
if tarsum.VersionLabelForChecksum(checksum) != tarsum.Version1.String() {
archive, err := layer.TarLayer()
if err != nil {
return nil, err
}
tarSum, err := tarsum.NewTarSum(archive, true, tarsum.Version1)
if err != nil {
return nil, err
}
if _, err := io.Copy(ioutil.Discard, tarSum); err != nil {
return nil, err
}
checksum = tarSum.Sum(nil)
// Save checksum value
if err := layer.SaveCheckSum(s.graph.ImageRoot(layer.ID), checksum); err != nil {
return nil, err
}
return nil, err
}
jsonData, err := layer.RawJson()
tarSum, err := tarsum.NewTarSum(archive, true, tarsum.Version1)
if err != nil {
return nil, err
}
if _, err := io.Copy(ioutil.Discard, tarSum); err != nil {
return nil, err
}
tarId := tarSum.Sum(nil)
manifest.FSLayers = append(manifest.FSLayers, &registry.FSLayer{BlobSum: tarId})
layersSeen[layer.ID] = true
jsonData, err := ioutil.ReadFile(path.Join(s.graph.Root, layer.ID, "json"))
if err != nil {
return nil, fmt.Errorf("Cannot retrieve the path for {%s}: %s", layer.ID, err)
}
manifest.FSLayers = append(manifest.FSLayers, &registry.FSLayer{BlobSum: checksum})
layersSeen[layer.ID] = true
manifest.History = append(manifest.History, &registry.ManifestHistory{V1Compatibility: string(jsonData)})
}
@@ -109,12 +128,7 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
return manifestBytes, nil
}
// loadManifest loads a manifest from a byte array and verifies its content.
// The signature must be verified or an error is returned. If the manifest
// contains no signatures by a trusted key for the name in the manifest, the
// image is not considered verified. The parsed manifest object and a boolean
// for whether the manifest is verified is returned.
func (s *TagStore) loadManifest(eng *engine.Engine, manifestBytes []byte) (*registry.ManifestData, bool, error) {
func (s *TagStore) verifyManifest(eng *engine.Engine, manifestBytes []byte) (*registry.ManifestData, bool, error) {
sig, err := libtrust.ParsePrettySignature(manifestBytes, "signatures")
if err != nil {
return nil, false, fmt.Errorf("error parsing payload: %s", err)
-82
View File
@@ -1,82 +0,0 @@
package graph
import (
"encoding/json"
"os"
"testing"
"github.com/docker/docker/image"
"github.com/docker/docker/registry"
"github.com/docker/docker/utils"
)
const (
testManifestImageName = "testapp"
testManifestImageID = "d821b739e8834ec89ac4469266c3d11515da88fdcbcbdddcbcddb636f54fdde9"
testManifestImageIDShort = "d821b739e883"
testManifestTag = "manifesttest"
)
func TestManifestTarsumCache(t *testing.T) {
tmp, err := utils.TestDirectory("")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
store := mkTestTagStore(tmp, t)
defer store.graph.driver.Cleanup()
archive, err := fakeTar()
if err != nil {
t.Fatal(err)
}
img := &image.Image{ID: testManifestImageID}
if err := store.graph.Register(img, archive); err != nil {
t.Fatal(err)
}
if err := store.Set(testManifestImageName, testManifestTag, testManifestImageID, false); err != nil {
t.Fatal(err)
}
if cs, err := img.GetCheckSum(store.graph.ImageRoot(testManifestImageID)); err != nil {
t.Fatal(err)
} else if cs != "" {
t.Fatalf("Non-empty checksum file after register")
}
// Generate manifest
payload, err := store.newManifest(testManifestImageName, testManifestImageName, testManifestTag)
if err != nil {
t.Fatal(err)
}
manifestChecksum, err := img.GetCheckSum(store.graph.ImageRoot(testManifestImageID))
if err != nil {
t.Fatal(err)
}
var manifest registry.ManifestData
if err := json.Unmarshal(payload, &manifest); err != nil {
t.Fatalf("error unmarshalling manifest: %s", err)
}
if len(manifest.FSLayers) != 1 {
t.Fatalf("Unexpected number of layers, expecting 1: %d", len(manifest.FSLayers))
}
if manifest.FSLayers[0].BlobSum != manifestChecksum {
t.Fatalf("Unexpected blob sum, expecting %q, got %q", manifestChecksum, manifest.FSLayers[0].BlobSum)
}
if len(manifest.History) != 1 {
t.Fatalf("Unexpected number of layer history, expecting 1: %d", len(manifest.History))
}
v1compat, err := img.RawJson()
if err != nil {
t.Fatal(err)
}
if manifest.History[0].V1Compatibility != string(v1compat) {
t.Fatalf("Unexpected json value\nExpected:\n%s\nActual:\n%s", v1compat, manifest.History[0].V1Compatibility)
}
}
+2 -4
View File
@@ -153,6 +153,7 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, repoInfo *
for _, image := range repoData.ImgList {
downloadImage := func(img *registry.ImgData) {
if askedTag != "" && img.Tag != askedTag {
log.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID)
if parallel {
errors <- nil
}
@@ -387,9 +388,6 @@ func (s *TagStore) pullV2Repository(eng *engine.Engine, r *registry.Session, out
if err != nil {
return err
}
if len(tags) == 0 {
return registry.ErrDoesNotExist
}
for _, t := range tags {
if downloaded, err := s.pullV2Tag(eng, r, out, endpoint, repoInfo, t, sf, parallel, auth); err != nil {
return err
@@ -420,7 +418,7 @@ func (s *TagStore) pullV2Tag(eng *engine.Engine, r *registry.Session, out io.Wri
return false, err
}
manifest, verified, err := s.loadManifest(eng, manifestBytes)
manifest, verified, err := s.verifyManifest(eng, manifestBytes)
if err != nil {
return false, fmt.Errorf("error verifying manifest: %s", err)
}
+66 -118
View File
@@ -2,7 +2,6 @@ package graph
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
@@ -19,8 +18,6 @@ import (
"github.com/docker/libtrust"
)
var ErrV2RegistryUnavailable = errors.New("error v2 registry unavailable")
// Retrieve the all the images to be uploaded in the correct order
func (s *TagStore) getImageList(localRepo map[string]string, requestedTag string) ([]string, map[string][]string, error) {
var (
@@ -68,25 +65,6 @@ func (s *TagStore) getImageList(localRepo map[string]string, requestedTag string
return imageList, tagsByImage, nil
}
func (s *TagStore) getImageTags(localName, askedTag string) ([]string, error) {
localRepo, err := s.Get(localName)
if err != nil {
return nil, err
}
log.Debugf("Checking %s against %#v", askedTag, localRepo)
if len(askedTag) > 0 {
if _, ok := localRepo[askedTag]; !ok {
return nil, fmt.Errorf("Tag does not exist for %s:%s", localName, askedTag)
}
return []string{askedTag}, nil
}
var tags []string
for tag := range localRepo {
tags = append(tags, tag)
}
return tags, nil
}
// createImageIndex returns an index of an image's layer IDs and tags.
func (s *TagStore) createImageIndex(images []string, tags map[string][]string) []*registry.ImgData {
var imageIndex []*registry.ImgData
@@ -258,7 +236,10 @@ func (s *TagStore) pushImage(r *registry.Session, out io.Writer, imgID, ep strin
// Send the layer
log.Debugf("rendered layer for %s of [%d] size", imgData.ID, layerData.Size)
checksum, checksumPayload, err := r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf, false, utils.TruncateID(imgData.ID), "Pushing"), ep, token, jsonRaw)
prgRd := utils.ProgressReader(layerData, int(layerData.Size), out, sf, false, utils.TruncateID(imgData.ID), "Pushing")
defer prgRd.Close()
checksum, checksumPayload, err := r.PushImageLayerRegistry(imgData.ID, prgRd, ep, token, jsonRaw)
if err != nil {
return "", err
}
@@ -273,7 +254,7 @@ func (s *TagStore) pushImage(r *registry.Session, out io.Writer, imgID, ep strin
return imgData.Checksum, nil
}
func (s *TagStore) pushV2Repository(r *registry.Session, eng *engine.Engine, out io.Writer, repoInfo *registry.RepositoryInfo, tag string, sf *utils.StreamFormatter) error {
func (s *TagStore) pushV2Repository(r *registry.Session, eng *engine.Engine, out io.Writer, repoInfo *registry.RepositoryInfo, manifestBytes, tag string, sf *utils.StreamFormatter) error {
if repoInfo.Official {
j := eng.Job("trust_update_base")
if err := j.Run(); err != nil {
@@ -283,28 +264,15 @@ func (s *TagStore) pushV2Repository(r *registry.Session, eng *engine.Engine, out
endpoint, err := r.V2RegistryEndpoint(repoInfo.Index)
if err != nil {
if repoInfo.Index.Official {
log.Infof("Unable to push to V2 registry, falling back to v1: %s", err)
return ErrV2RegistryUnavailable
}
return fmt.Errorf("error getting registry endpoint: %s", err)
}
tags, err := s.getImageTags(repoInfo.LocalName, tag)
if err != nil {
return err
}
if len(tags) == 0 {
return fmt.Errorf("No tags to push for %s", repoInfo.LocalName)
}
auth, err := r.GetV2Authorization(endpoint, repoInfo.RemoteName, false)
if err != nil {
return fmt.Errorf("error getting authorization: %s", err)
}
for _, tag := range tags {
log.Debugf("Pushing %s:%s to v2 repository", repoInfo.LocalName, tag)
// if no manifest is given, generate and sign with the key associated with the local tag store
if len(manifestBytes) == 0 {
mBytes, err := s.newManifest(repoInfo.LocalName, repoInfo.RemoteName, tag)
if err != nil {
return err
@@ -322,99 +290,75 @@ func (s *TagStore) pushV2Repository(r *registry.Session, eng *engine.Engine, out
if err != nil {
return err
}
log.Infof("Signed manifest for %s:%s using daemon's key: %s", repoInfo.LocalName, tag, s.trustKey.KeyID())
log.Infof("Signed manifest using daemon's key: %s", s.trustKey.KeyID())
manifestBytes := string(signedBody)
manifestBytes = string(signedBody)
}
manifest, verified, err := s.loadManifest(eng, signedBody)
manifest, verified, err := s.verifyManifest(eng, []byte(manifestBytes))
if err != nil {
return fmt.Errorf("error verifying manifest: %s", err)
}
if err := checkValidManifest(manifest); err != nil {
return fmt.Errorf("invalid manifest: %s", err)
}
if !verified {
log.Debugf("Pushing unverified image")
}
for i := len(manifest.FSLayers) - 1; i >= 0; i-- {
var (
sumStr = manifest.FSLayers[i].BlobSum
imgJSON = []byte(manifest.History[i].V1Compatibility)
)
sumParts := strings.SplitN(sumStr, ":", 2)
if len(sumParts) < 2 {
return fmt.Errorf("Invalid checksum: %s", sumStr)
}
manifestSum := sumParts[1]
img, err := image.NewImgJSON(imgJSON)
if err != nil {
return fmt.Errorf("error verifying manifest: %s", err)
return fmt.Errorf("Failed to parse json: %s", err)
}
if err := checkValidManifest(manifest); err != nil {
return fmt.Errorf("invalid manifest: %s", err)
img, err = s.graph.Get(img.ID)
if err != nil {
return err
}
if verified {
log.Infof("Pushing verified image, key %s is registered for %q", s.trustKey.KeyID(), repoInfo.RemoteName)
arch, err := img.TarLayer()
if err != nil {
return fmt.Errorf("Could not get tar layer: %s", err)
}
for i := len(manifest.FSLayers) - 1; i >= 0; i-- {
var (
sumStr = manifest.FSLayers[i].BlobSum
imgJSON = []byte(manifest.History[i].V1Compatibility)
)
// Call mount blob
exists, err := r.HeadV2ImageBlob(endpoint, repoInfo.RemoteName, sumParts[0], manifestSum, auth)
if err != nil {
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Image push failed", nil))
return err
}
sumParts := strings.SplitN(sumStr, ":", 2)
if len(sumParts) < 2 {
return fmt.Errorf("Invalid checksum: %s", sumStr)
}
manifestSum := sumParts[1]
if !exists {
prgRd := utils.ProgressReader(arch, int(img.Size), out, sf, false, utils.TruncateID(img.ID), "Pushing")
defer prgRd.Close()
img, err := image.NewImgJSON(imgJSON)
if err != nil {
return fmt.Errorf("Failed to parse json: %s", err)
}
// Call mount blob
exists, err := r.HeadV2ImageBlob(endpoint, repoInfo.RemoteName, sumParts[0], manifestSum, auth)
err = r.PutV2ImageBlob(endpoint, repoInfo.RemoteName, sumParts[0], manifestSum, prgRd, auth)
if err != nil {
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Image push failed", nil))
return err
}
if !exists {
if err := s.pushV2Image(r, img, endpoint, repoInfo.RemoteName, sumParts[0], manifestSum, sf, out, auth); err != nil {
return err
}
} else {
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Image already exists", nil))
}
}
// push the manifest
if err := r.PutV2ImageManifest(endpoint, repoInfo.RemoteName, tag, bytes.NewReader([]byte(manifestBytes)), auth); err != nil {
return err
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Image successfully pushed", nil))
} else {
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Image already exists", nil))
}
}
return nil
}
// PushV2Image pushes the image content to the v2 registry, first buffering the contents to disk
func (s *TagStore) pushV2Image(r *registry.Session, img *image.Image, endpoint *registry.Endpoint, imageName, sumType, sumStr string, sf *utils.StreamFormatter, out io.Writer, auth *registry.RequestAuthorization) error {
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Buffering to Disk", nil))
image, err := s.graph.Get(img.ID)
if err != nil {
return err
}
arch, err := image.TarLayer()
if err != nil {
return err
}
tf, err := s.graph.newTempFile()
if err != nil {
return err
}
defer func() {
tf.Close()
os.Remove(tf.Name())
}()
size, err := bufferToFile(tf, arch)
if err != nil {
return err
}
// Send the layer
log.Debugf("rendered layer for %s of [%d] size", img.ID, size)
if err := r.PutV2ImageBlob(endpoint, imageName, sumType, sumStr, utils.ProgressReader(tf, int(size), out, sf, false, utils.TruncateID(img.ID), "Pushing"), auth); err != nil {
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Image push failed", nil))
return err
}
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Image successfully pushed", nil))
return nil
// push the manifest
return r.PutV2ImageManifest(endpoint, repoInfo.RemoteName, tag, bytes.NewReader([]byte(manifestBytes)), auth)
}
// FIXME: Allow to interrupt current push when new push of same image is done.
@@ -436,6 +380,7 @@ func (s *TagStore) CmdPush(job *engine.Job) engine.Status {
}
tag := job.Getenv("tag")
manifestBytes := job.Getenv("manifest")
job.GetenvJson("authConfig", authConfig)
job.GetenvJson("metaHeaders", &metaHeaders)
@@ -455,15 +400,18 @@ func (s *TagStore) CmdPush(job *engine.Job) engine.Status {
return job.Error(err2)
}
if len(tag) == 0 {
tag = DEFAULTTAG
}
if repoInfo.Index.Official || endpoint.Version == registry.APIVersion2 {
err := s.pushV2Repository(r, job.Eng, job.Stdout, repoInfo, tag, sf)
err := s.pushV2Repository(r, job.Eng, job.Stdout, repoInfo, manifestBytes, tag, sf)
if err == nil {
return engine.StatusOK
}
if err != ErrV2RegistryUnavailable {
return job.Errorf("Error pushing to registry: %s", err)
}
// error out, no fallback to V1
return job.Error(err)
}
if err != nil {
+2
View File
@@ -25,6 +25,7 @@ func (s *TagStore) Install(eng *engine.Engine) error {
"import": s.CmdImport,
"pull": s.CmdPull,
"push": s.CmdPush,
"image_manifest": s.CmdManifest,
} {
if err := eng.Register(name, handler); err != nil {
return fmt.Errorf("Could not register %q: %v", name, err)
@@ -150,6 +151,7 @@ func (s *TagStore) CmdLookup(job *engine.Job) engine.Status {
out.Set("Os", image.OS)
out.SetInt64("Size", image.Size)
out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size)
out.Set("Checksum", image.Checksum)
if _, err = out.WriteTo(job.Stdout); err != nil {
return job.Error(err)
}
+38 -22
View File
@@ -9,7 +9,9 @@ import (
"strconv"
"time"
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/tarsum"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/utils"
)
@@ -31,6 +33,7 @@ type Image struct {
Config *runconfig.Config `json:"config,omitempty"`
Architecture string `json:"architecture,omitempty"`
OS string `json:"os,omitempty"`
Checksum string `json:"checksum"`
Size int64
graph Graph
@@ -78,15 +81,45 @@ func LoadImage(root string) (*Image, error) {
// StoreImage stores file system layer data for the given image to the
// image's registered storage driver. Image metadata is stored in a file
// at the specified root directory.
func StoreImage(img *Image, layerData archive.ArchiveReader, root string) (err error) {
// Store the layer. If layerData is not nil, unpack it into the new layer
// at the specified root directory. This function also computes the TarSum
// of `layerData` (currently using tarsum.dev).
func StoreImage(img *Image, layerData archive.ArchiveReader, root string) error {
// Store the layer
var (
size int64
err error
driver = img.graph.Driver()
layerTarSum tarsum.TarSum
)
// If layerData is not nil, unpack it into the new layer
if layerData != nil {
if img.Size, err = img.graph.Driver().ApplyDiff(img.ID, img.Parent, layerData); err != nil {
// If the image doesn't have a checksum, we should add it. The layer
// checksums are verified when they are pulled from a remote, but when
// a container is committed it should be added here.
if img.Checksum == "" {
layerDataDecompressed, err := archive.DecompressStream(layerData)
if err != nil {
return err
}
defer layerDataDecompressed.Close()
if layerTarSum, err = tarsum.NewTarSum(layerDataDecompressed, true, tarsum.VersionDev); err != nil {
return err
}
if size, err = driver.ApplyDiff(img.ID, img.Parent, layerTarSum); err != nil {
return err
}
img.Checksum = layerTarSum.Sum(nil)
} else if size, err = driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil {
return err
}
}
img.Size = size
if err := img.SaveSize(root); err != nil {
return err
}
@@ -113,24 +146,6 @@ func (img *Image) SaveSize(root string) error {
return nil
}
func (img *Image) SaveCheckSum(root, checksum string) error {
if err := ioutil.WriteFile(path.Join(root, "checksum"), []byte(checksum), 0600); err != nil {
return fmt.Errorf("Error storing checksum in %s/checksum: %s", root, err)
}
return nil
}
func (img *Image) GetCheckSum(root string) (string, error) {
cs, err := ioutil.ReadFile(path.Join(root, "checksum"))
if err != nil {
if os.IsNotExist(err) {
return "", nil
}
return "", err
}
return string(cs), err
}
func jsonPath(root string) string {
return path.Join(root, "json")
}
@@ -259,6 +274,7 @@ func (img *Image) CheckDepth() error {
func NewImgJSON(src []byte) (*Image, error) {
ret := &Image{}
log.Debugf("Json string: {%s}", src)
// FIXME: Is there a cleaner way to "purify" the input json?
if err := json.Unmarshal(src, ret); err != nil {
return nil, err
@@ -299,70 +299,3 @@ func TestGetContainerStats(t *testing.T) {
}
logDone("container REST API - check GET containers/stats")
}
func TestBuildApiDockerfilePath(t *testing.T) {
// Test to make sure we stop people from trying to leave the
// build context when specifying the path to the dockerfile
buffer := new(bytes.Buffer)
tw := tar.NewWriter(buffer)
defer tw.Close()
dockerfile := []byte("FROM busybox")
if err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Size: int64(len(dockerfile)),
}); err != nil {
t.Fatalf("failed to write tar file header: %v", err)
}
if _, err := tw.Write(dockerfile); err != nil {
t.Fatalf("failed to write tar file content: %v", err)
}
if err := tw.Close(); err != nil {
t.Fatalf("failed to close tar archive: %v", err)
}
out, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar")
if err == nil {
t.Fatalf("Build was supposed to fail: %s", out)
}
if !strings.Contains(string(out), "must be within the build context") {
t.Fatalf("Didn't complain about leaving build context: %s", out)
}
logDone("container REST API - check build w/bad Dockerfile path")
}
func TestBuildApiDockerfileSymlink(t *testing.T) {
// Test to make sure we stop people from trying to leave the
// build context when specifying a symlink as the path to the dockerfile
buffer := new(bytes.Buffer)
tw := tar.NewWriter(buffer)
defer tw.Close()
if err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Typeflag: tar.TypeSymlink,
Linkname: "/etc/passwd",
}); err != nil {
t.Fatalf("failed to write tar file header: %v", err)
}
if err := tw.Close(); err != nil {
t.Fatalf("failed to close tar archive: %v", err)
}
out, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
if err == nil {
t.Fatalf("Build was supposed to fail: %s", out)
}
// The reason the error is "Cannot locate specified Dockerfile" is because
// in the builder, the symlink is resolved within the context, therefore
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
// a nonexistent file.
if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") {
t.Fatalf("Didn't complain about leaving build context: %s", out)
}
logDone("container REST API - check build w/bad Dockerfile symlink path")
}
@@ -81,9 +81,6 @@ func TestAttachAfterDetach(t *testing.T) {
}()
time.Sleep(500 * time.Millisecond)
if err := waitRun(name); err != nil {
t.Fatal(err)
}
cpty.Write([]byte{16})
time.Sleep(100 * time.Millisecond)
cpty.Write([]byte{17})
-64
View File
@@ -4592,67 +4592,3 @@ func TestBuildFromOfficialNames(t *testing.T) {
}
logDone("build - from official names")
}
func TestBuildDockerfileOutsideContext(t *testing.T) {
name := "testbuilddockerfileoutsidecontext"
tmpdir, err := ioutil.TempDir("", name)
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
ctx := filepath.Join(tmpdir, "context")
if err := os.MkdirAll(ctx, 0755); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM busybox"), 0644); err != nil {
t.Fatal(err)
}
wd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
defer os.Chdir(wd)
if err := os.Chdir(ctx); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM busbox"), 0644); err != nil {
t.Fatal(err)
}
if err := os.Symlink("../outsideDockerfile", filepath.Join(ctx, "dockerfile1")); err != nil {
t.Fatal(err)
}
if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
t.Fatal(err)
}
if err := os.Link("../outsideDockerfile", filepath.Join(ctx, "dockerfile3")); err != nil {
t.Fatal(err)
}
if err := os.Link(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile4")); err != nil {
t.Fatal(err)
}
for _, dockerfilePath := range []string{
"../outsideDockerfile",
filepath.Join(ctx, "dockerfile1"),
filepath.Join(ctx, "dockerfile2"),
filepath.Join(ctx, "dockerfile3"),
filepath.Join(ctx, "dockerfile4"),
} {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", dockerfilePath, "."))
if err == nil {
t.Fatalf("Expected error with %s. Out: %s", dockerfilePath, out)
}
deleteImages(name)
}
os.Chdir(tmpdir)
// Path to Dockerfile should be resolved relative to working directory, not relative to context.
// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx))
if err == nil {
t.Fatalf("Expected error. Out: %s", out)
}
deleteImages(name)
logDone("build - Dockerfile outside context")
}
-77
View File
@@ -383,9 +383,6 @@ func TestDaemonKeyMigration(t *testing.T) {
if err != nil {
t.Fatalf("Error generating private key: %s", err)
}
if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil {
t.Fatalf("Error creating .docker directory: %s", err)
}
if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil {
t.Fatalf("Error saving private key: %s", err)
}
@@ -406,77 +403,3 @@ func TestDaemonKeyMigration(t *testing.T) {
logDone("daemon - key migration")
}
// Simulate an older daemon (pre 1.3) coming up with volumes specified in containers
// without corrosponding volume json
func TestDaemonUpgradeWithVolumes(t *testing.T) {
d := NewDaemon(t)
graphDir := filepath.Join(os.TempDir(), "docker-test")
defer os.RemoveAll(graphDir)
if err := d.StartWithBusybox("-g", graphDir); err != nil {
t.Fatal(err)
}
tmpDir := filepath.Join(os.TempDir(), "test")
defer os.RemoveAll(tmpDir)
if out, err := d.Cmd("create", "-v", tmpDir+":/foo", "--name=test", "busybox"); err != nil {
t.Fatal(err, out)
}
if err := d.Stop(); err != nil {
t.Fatal(err)
}
// Remove this since we're expecting the daemon to re-create it too
if err := os.RemoveAll(tmpDir); err != nil {
t.Fatal(err)
}
configDir := filepath.Join(graphDir, "volumes")
if err := os.RemoveAll(configDir); err != nil {
t.Fatal(err)
}
if err := d.Start("-g", graphDir); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
t.Fatalf("expected volume path %s to exist but it does not", tmpDir)
}
dir, err := ioutil.ReadDir(configDir)
if err != nil {
t.Fatal(err)
}
if len(dir) == 0 {
t.Fatalf("expected volumes config dir to contain data for new volume")
}
// Now with just removing the volume config and not the volume data
if err := d.Stop(); err != nil {
t.Fatal(err)
}
if err := os.RemoveAll(configDir); err != nil {
t.Fatal(err)
}
if err := d.Start("-g", graphDir); err != nil {
t.Fatal(err)
}
dir, err = ioutil.ReadDir(configDir)
if err != nil {
t.Fatal(err)
}
if len(dir) == 0 {
t.Fatalf("expected volumes config dir to contain data for new volume")
}
logDone("daemon - volumes from old(pre 1.3) daemon work")
}
+1 -1
View File
@@ -24,7 +24,6 @@ func TestPullImageWithAliases(t *testing.T) {
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "tag", "busybox", repo)); err != nil {
t.Fatalf("Failed to tag image %v: error %v, output %q", repos, err, out)
}
defer deleteImages(repo)
if out, err := exec.Command(dockerBinary, "push", repo).CombinedOutput(); err != nil {
t.Fatalf("Failed to push image %v: error %v, output %q", err, string(out))
}
@@ -41,6 +40,7 @@ func TestPullImageWithAliases(t *testing.T) {
if out, _, err := runCommandWithOutput(pullCmd); err != nil {
t.Fatalf("Failed to pull %v: error %v, output %q", repoName, err, out)
}
defer deleteImages(repos[0])
if err := exec.Command(dockerBinary, "inspect", repos[0]).Run(); err != nil {
t.Fatalf("Image %v was not pulled down", repos[0])
}
+1 -77
View File
@@ -2,14 +2,10 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"
"testing"
"time"
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
)
// pulling an image from the central registry should work
@@ -45,21 +41,6 @@ func TestPushUntagged(t *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
expected := "No tags to push"
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err == nil {
t.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
} else if !strings.Contains(out, expected) {
t.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
}
logDone("push - untagged image")
}
func TestPushBadTag(t *testing.T) {
defer setupRegistry(t)()
repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL)
expected := "does not exist"
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err == nil {
@@ -67,32 +48,7 @@ func TestPushBadTag(t *testing.T) {
} else if !strings.Contains(out, expected) {
t.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
}
logDone("push - image with bad tag")
}
func TestPushMultipleTags(t *testing.T) {
defer setupRegistry(t)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL)
repoTag2 := fmt.Sprintf("%v/dockercli/busybox:t2", privateRegistryURL)
// tag the image to upload it tot he private registry
tagCmd1 := exec.Command(dockerBinary, "tag", "busybox", repoTag1)
if out, _, err := runCommandWithOutput(tagCmd1); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoTag1)
tagCmd2 := exec.Command(dockerBinary, "tag", "busybox", repoTag2)
if out, _, err := runCommandWithOutput(tagCmd2); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoTag2)
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err != nil {
t.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
}
logDone("push - multiple tags to private registry")
logDone("push - untagged image")
}
func TestPushInterrupt(t *testing.T) {
@@ -124,35 +80,3 @@ func TestPushInterrupt(t *testing.T) {
logDone("push - interrupted")
}
func TestPushEmptyLayer(t *testing.T) {
defer setupRegistry(t)()
repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL)
emptyTarball, err := ioutil.TempFile("", "empty_tarball")
if err != nil {
t.Fatalf("Unable to create test file: %v", err)
}
tw := tar.NewWriter(emptyTarball)
err = tw.Close()
if err != nil {
t.Fatalf("Error creating empty tarball: %v", err)
}
freader, err := os.Open(emptyTarball.Name())
if err != nil {
t.Fatalf("Could not open test tarball: %v", err)
}
importCmd := exec.Command(dockerBinary, "import", "-", repoName)
importCmd.Stdin = freader
out, _, err := runCommandWithOutput(importCmd)
if err != nil {
t.Errorf("import failed with errors: %v, output: %q", err, out)
}
// Now verify we can push it
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err != nil {
t.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
}
logDone("push - empty layer config to private registry")
}
+7 -28
View File
@@ -274,15 +274,6 @@ func daemonHost() string {
}
func sockRequest(method, endpoint string, data interface{}) ([]byte, error) {
jsonData := bytes.NewBuffer(nil)
if err := json.NewEncoder(jsonData).Encode(data); err != nil {
return nil, err
}
return sockRequestRaw(method, endpoint, jsonData, "application/json")
}
func sockRequestRaw(method, endpoint string, data io.Reader, ct string) ([]byte, error) {
daemon := daemonHost()
daemonUrl, err := url.Parse(daemon)
if err != nil {
@@ -305,16 +296,17 @@ func sockRequestRaw(method, endpoint string, data io.Reader, ct string) ([]byte,
client := httputil.NewClientConn(c, nil)
defer client.Close()
req, err := http.NewRequest(method, endpoint, data)
jsonData := bytes.NewBuffer(nil)
if err := json.NewEncoder(jsonData).Encode(data); err != nil {
return nil, err
}
req, err := http.NewRequest(method, endpoint, jsonData)
req.Header.Set("Content-Type", "application/json")
if err != nil {
return nil, fmt.Errorf("could not create new request: %v", err)
}
if ct == "" {
ct = "application/json"
}
req.Header.Set("Content-Type", ct)
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("could not perform request: %v", err)
@@ -878,18 +870,5 @@ func setupRegistry(t *testing.T) func() {
if err != nil {
t.Fatal(err)
}
// Wait for registry to be ready to serve requests.
for i := 0; i != 5; i++ {
if err = reg.Ping(); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
if err != nil {
t.Fatal("Timeout waiting for test registry to become available")
}
return func() { reg.Close() }
}
-13
View File
@@ -3,7 +3,6 @@ package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
@@ -53,18 +52,6 @@ http:
}, nil
}
func (t *testRegistryV2) Ping() error {
// We always ping through HTTP for our test registry.
resp, err := http.Get(fmt.Sprintf("http://%s/v2/", privateRegistryURL))
if err != nil {
return err
}
if resp.StatusCode != 200 {
return fmt.Errorf("registry ping replied with an unexpected status code %s", resp.StatusCode)
}
return nil
}
func (r *testRegistryV2) Close() {
r.cmd.Process.Kill()
os.RemoveAll(r.dir)
+32 -8
View File
@@ -14,6 +14,7 @@ import (
"github.com/docker/docker/daemon"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/utils"
"github.com/docker/libtrust"
"github.com/kr/pty"
)
@@ -121,7 +122,12 @@ func TestRunDetach(t *testing.T) {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@@ -171,7 +177,12 @@ func TestAttachDetach(t *testing.T) {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@@ -208,7 +219,7 @@ func TestAttachDetach(t *testing.T) {
t.Fatal(err)
}
cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
ch = make(chan struct{})
go func() {
@@ -259,7 +270,12 @@ func TestAttachDetachTruncatedID(t *testing.T) {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
// Discard the CmdRun output
@@ -281,7 +297,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
t.Fatal(err)
}
cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
ch := make(chan struct{})
go func() {
@@ -331,7 +347,12 @@ func TestAttachDisconnect(t *testing.T) {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
go func() {
@@ -400,8 +421,11 @@ func TestAttachDisconnect(t *testing.T) {
func TestRunAutoRemove(t *testing.T) {
t.Skip("Fixme. Skipping test for now, race condition")
stdout, stdoutPipe := io.Pipe()
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
+16 -3
View File
@@ -9,6 +9,7 @@ import (
"time"
"github.com/docker/docker/api/client"
"github.com/docker/libtrust"
)
const (
@@ -37,7 +38,11 @@ func getTlsConfig(certFile, keyFile string, t *testing.T) *tls.Config {
// TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint
func TestHttpsInfo(t *testing.T) {
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, "", testDaemonProto,
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
testDaemonHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
@@ -50,7 +55,11 @@ func TestHttpsInfo(t *testing.T) {
// TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint
// by using a rogue client certificate and checks that it fails with the expected error.
func TestHttpsInfoRogueCert(t *testing.T) {
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, "", testDaemonProto,
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
testDaemonHttpsAddr, getTlsConfig("client-rogue-cert.pem", "client-rogue-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
@@ -67,7 +76,11 @@ func TestHttpsInfoRogueCert(t *testing.T) {
// TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint
// which provides a rogue server certificate and checks that it fails with the expected error
func TestHttpsInfoRogueServerCert(t *testing.T) {
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, "", testDaemonProto,
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
testDaemonRogueHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
+1
View File
@@ -101,6 +101,7 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
if err != nil {
return nil, err
}
log.Debugf("[tar autodetect] n: %v", bs)
compression := DetectCompression(bs)
switch compression {
-1
View File
@@ -122,7 +122,6 @@ type tHashConfig struct {
}
var (
// NOTE: DO NOT include MD5 or SHA1, which are considered insecure.
standardHashConfigs = map[string]tHashConfig{
"sha256": {name: "sha256", hash: crypto.SHA256},
"sha512": {name: "sha512", hash: crypto.SHA512},
-12
View File
@@ -22,18 +22,6 @@ const (
VersionDev
)
// VersionLabelForChecksum returns the label for the given tarsum
// checksum, i.e., everything before the first `+` character in
// the string or an empty string if no label separator is found.
func VersionLabelForChecksum(checksum string) string {
// Checksums are in the form: {versionLabel}+{hashID}:{hex}
sepIndex := strings.Index(checksum, "+")
if sepIndex < 0 {
return ""
}
return checksum[:sepIndex]
}
// Get a list of all known tarsum Version
func GetVersions() []Version {
v := []Version{}
+1 -1
View File
@@ -11,5 +11,5 @@ cd "$(dirname "$(readlink -f "$BASH_SOURCE")")/.."
# For how it is generated, see `project/generate-authors.sh`.
EOH
echo
git log --format='%aN <%aE>' | LC_ALL=C.UTF-8 sort -uf
git log --format='%aN <%aE>' | sort -uf
} > AUTHORS
-1
View File
@@ -44,7 +44,6 @@ echo
DEFAULT_BUNDLES=(
validate-dco
validate-gofmt
validate-toml
binary
+5 -20
View File
@@ -2,26 +2,11 @@
DEST=$1
PKGVERSION="${VERSION//-/'~'}"
# if we have a "-dev" suffix or have change in Git, let's make this package version more complex so it works better
if [[ "$VERSION" == *-dev ]] || [ -n "$(git status --porcelain)" ]; then
GIT_UNIX="$(git log -1 --pretty='%at')"
GIT_DATE="$(date --date "@$GIT_UNIX" +'%Y%m%d.%H%M%S')"
GIT_COMMIT="$(git log -1 --pretty='%h')"
GIT_VERSION="git${GIT_DATE}.0.${GIT_COMMIT}"
# GIT_VERSION is now something like 'git20150128.112847.0.17e840a'
PKGVERSION="$PKGVERSION~$GIT_VERSION"
PKGVERSION="$VERSION"
if [ -n "$(git status --porcelain)" ]; then
PKGVERSION="$PKGVERSION-$(date +%Y%m%d%H%M%S)-$GITCOMMIT"
fi
# $ dpkg --compare-versions 1.5.0 gt 1.5.0~rc1 && echo true || echo false
# true
# $ dpkg --compare-versions 1.5.0~rc1 gt 1.5.0~git20150128.112847.17e840a && echo true || echo false
# true
# $ dpkg --compare-versions 1.5.0~git20150128.112847.17e840a gt 1.5.0~dev~git20150128.112847.17e840a && echo true || echo false
# true
# ie, 1.5.0 > 1.5.0~rc1 > 1.5.0~git20150128.112847.17e840a > 1.5.0~dev~git20150128.112847.17e840a
PACKAGE_ARCHITECTURE="$(dpkg-architecture -qDEB_HOST_ARCH)"
PACKAGE_URL="http://www.docker.com/"
PACKAGE_MAINTAINER="support@docker.com"
@@ -139,7 +124,7 @@ EOF
# create lxc-docker-VERSION package
fpm -s dir -C $DIR \
--name lxc-docker-$VERSION --version "$PKGVERSION" \
--name lxc-docker-$VERSION --version $PKGVERSION \
--after-install $DEST/postinst \
--before-remove $DEST/prerm \
--after-remove $DEST/postrm \
@@ -172,7 +157,7 @@ EOF
# create empty lxc-docker wrapper package
fpm -s empty \
--name lxc-docker --version "$PKGVERSION" \
--name lxc-docker --version $PKGVERSION \
--architecture "$PACKAGE_ARCHITECTURE" \
--depends lxc-docker-$VERSION \
--description "$PACKAGE_DESCRIPTION" \
-30
View File
@@ -1,30 +0,0 @@
#!/bin/bash
source "$(dirname "$BASH_SOURCE")/.validate"
IFS=$'\n'
files=( $(validate_diff --diff-filter=ACMR --name-only -- 'MAINTAINERS' || true) )
unset IFS
badFiles=()
for f in "${files[@]}"; do
# we use "git show" here to validate that what's committed is formatted
if [ "$(git show "$VALIDATE_HEAD:$f" | tomlv)" ]; then
badFiles+=( "$f" )
fi
done
if [ ${#badFiles[@]} -eq 0 ]; then
echo 'Congratulations! All toml source files have valid syntax.'
else
{
echo "These files are not valid toml:"
for f in "${badFiles[@]}"; do
echo " - $f"
done
echo
echo 'Please reformat the above files as valid toml'
echo
} >&2
false
fi
+4 -7
View File
@@ -231,13 +231,10 @@ func (e *Endpoint) pingV2() (RegistryInfo, error) {
// Ensure it supports the v2 Registry API.
var supportsV2 bool
HeaderLoop:
for _, supportedVersions := range resp.Header[http.CanonicalHeaderKey("Docker-Distribution-API-Version")] {
for _, versionName := range strings.Fields(supportedVersions) {
if versionName == "registry/2.0" {
supportsV2 = true
break HeaderLoop
}
for _, versionName := range resp.Header[http.CanonicalHeaderKey("Docker-Distribution-API-Version")] {
if versionName == "registry/2.0" {
supportsV2 = true
break
}
}
+1 -3
View File
@@ -42,9 +42,7 @@ func TestValidateEndpointAmbiguousAPIVersion(t *testing.T) {
})
requireBasicAuthHandlerV2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// This mock server supports v2.0, v2.1, v42.0, and v100.0
w.Header().Add("Docker-Distribution-API-Version", "registry/100.0 registry/42.0")
w.Header().Add("Docker-Distribution-API-Version", "registry/2.0 registry/2.1")
w.Header().Add("Docker-Distribution-API-Version", "registry/2.0")
requireBasicAuthHandler.ServeHTTP(w, r)
})
+10 -23
View File
@@ -124,18 +124,15 @@ func (r *Session) HeadV2ImageBlob(ep *Endpoint, imageName, sumType, sum string,
return false, err
}
res.Body.Close() // close early, since we're not needing a body on this call .. yet?
switch {
case res.StatusCode >= 200 && res.StatusCode < 400:
switch res.StatusCode {
case 200:
// return something indicating no push needed
return true, nil
case res.StatusCode == 401:
return false, errLoginRequired
case res.StatusCode == 404:
case 404:
// return something indicating blob push needed
return false, nil
}
return false, utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying head request for %s - %s:%s", res.StatusCode, imageName, sumType, sum), res)
return false, fmt.Errorf("Failed to mount %q - %s:%s : %d", imageName, sumType, sum, res.StatusCode)
}
func (r *Session) GetV2ImageBlob(ep *Endpoint, imageName, sumType, sum string, blobWrtr io.Writer, auth *RequestAuthorization) error {
@@ -192,7 +189,7 @@ func (r *Session) GetV2ImageBlobReader(ep *Endpoint, imageName, sumType, sum str
if res.StatusCode == 401 {
return nil, 0, errLoginRequired
}
return nil, 0, utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to pull %s blob - %s:%s", res.StatusCode, imageName, sumType, sum), res)
return nil, 0, utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to pull %s blob", res.StatusCode, imageName), res)
}
lenStr := res.Header.Get("Content-Length")
l, err := strconv.ParseInt(lenStr, 10, 64)
@@ -249,12 +246,7 @@ func (r *Session) PutV2ImageBlob(ep *Endpoint, imageName, sumType, sumStr string
if res.StatusCode == 401 {
return errLoginRequired
}
errBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
log.Debugf("Unexpected response from server: %q %#v", errBody, res.Header)
return utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s blob - %s:%s", res.StatusCode, imageName, sumType, sumStr), res)
return utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s blob", res.StatusCode, imageName), res)
}
return nil
@@ -280,18 +272,13 @@ func (r *Session) PutV2ImageManifest(ep *Endpoint, imageName, tagName string, ma
if err != nil {
return err
}
defer res.Body.Close()
// All 2xx and 3xx responses can be accepted for a put.
if res.StatusCode >= 400 {
b, _ := ioutil.ReadAll(res.Body)
res.Body.Close()
if res.StatusCode != 200 {
if res.StatusCode == 401 {
return errLoginRequired
}
errBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
log.Debugf("Unexpected response from server: %q %#v", errBody, res.Header)
log.Debugf("Unexpected response from server: %q %#v", b, res.Header)
return utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s:%s manifest", res.StatusCode, imageName, tagName), res)
}
+2 -4
View File
@@ -51,12 +51,10 @@ func getToken(username, password string, params map[string]string, registryEndpo
reqParams.Add("scope", scopeField)
}
if username != "" {
reqParams.Add("account", username)
req.SetBasicAuth(username, password)
}
reqParams.Add("account", username)
req.URL.RawQuery = reqParams.Encode()
req.SetBasicAuth(username, password)
resp, err := client.Do(req)
if err != nil {
+4 -19
View File
@@ -128,28 +128,13 @@ func (ub *URLBuilder) BuildBlobUploadChunkURL(name, uuid string, values ...url.V
// clondedRoute returns a clone of the named route from the router. Routes
// must be cloned to avoid modifying them during url generation.
func (ub *URLBuilder) cloneRoute(name string) clonedRoute {
func (ub *URLBuilder) cloneRoute(name string) *mux.Route {
route := new(mux.Route)
root := new(url.URL)
*route = *ub.router.GetRoute(name) // clone the route
*root = *ub.root
return clonedRoute{Route: route, root: root}
}
type clonedRoute struct {
*mux.Route
root *url.URL
}
func (cr clonedRoute) URL(pairs ...string) (*url.URL, error) {
routeURL, err := cr.Route.URL(pairs...)
if err != nil {
return nil, err
}
return cr.root.ResolveReference(routeURL), nil
return route.
Schemes(ub.root.Scheme).
Host(ub.root.Host)
}
// appendValuesURL appends the parameters to the url.
+37 -50
View File
@@ -6,58 +6,62 @@ import (
)
type urlBuilderTestCase struct {
description string
expectedPath string
build func() (string, error)
description string
expected string
build func() (string, error)
}
// TestURLBuilder tests the various url building functions, ensuring they are
// returning the expected values.
func TestURLBuilder(t *testing.T) {
var (
urlBuilder *URLBuilder
err error
)
testCases := []urlBuilderTestCase{
root := "http://localhost:5000/"
urlBuilder, err := NewURLBuilderFromString(root)
if err != nil {
t.Fatalf("unexpected error creating urlbuilder: %v", err)
}
for _, testcase := range []struct {
description string
expected string
build func() (string, error)
}{
{
description: "test base url",
expectedPath: "/v2/",
build: func() (string, error) {
return urlBuilder.BuildBaseURL()
},
description: "test base url",
expected: "http://localhost:5000/v2/",
build: urlBuilder.BuildBaseURL,
},
{
description: "test tags url",
expectedPath: "/v2/foo/bar/tags/list",
description: "test tags url",
expected: "http://localhost:5000/v2/foo/bar/tags/list",
build: func() (string, error) {
return urlBuilder.BuildTagsURL("foo/bar")
},
},
{
description: "test manifest url",
expectedPath: "/v2/foo/bar/manifests/tag",
description: "test manifest url",
expected: "http://localhost:5000/v2/foo/bar/manifests/tag",
build: func() (string, error) {
return urlBuilder.BuildManifestURL("foo/bar", "tag")
},
},
{
description: "build blob url",
expectedPath: "/v2/foo/bar/blobs/tarsum.v1+sha256:abcdef0123456789",
description: "build blob url",
expected: "http://localhost:5000/v2/foo/bar/blobs/tarsum.v1+sha256:abcdef0123456789",
build: func() (string, error) {
return urlBuilder.BuildBlobURL("foo/bar", "tarsum.v1+sha256:abcdef0123456789")
},
},
{
description: "build blob upload url",
expectedPath: "/v2/foo/bar/blobs/uploads/",
description: "build blob upload url",
expected: "http://localhost:5000/v2/foo/bar/blobs/uploads/",
build: func() (string, error) {
return urlBuilder.BuildBlobUploadURL("foo/bar")
},
},
{
description: "build blob upload url with digest and size",
expectedPath: "/v2/foo/bar/blobs/uploads/?digest=tarsum.v1%2Bsha256%3Aabcdef0123456789&size=10000",
description: "build blob upload url with digest and size",
expected: "http://localhost:5000/v2/foo/bar/blobs/uploads/?digest=tarsum.v1%2Bsha256%3Aabcdef0123456789&size=10000",
build: func() (string, error) {
return urlBuilder.BuildBlobUploadURL("foo/bar", url.Values{
"size": []string{"10000"},
@@ -66,15 +70,15 @@ func TestURLBuilder(t *testing.T) {
},
},
{
description: "build blob upload chunk url",
expectedPath: "/v2/foo/bar/blobs/uploads/uuid-part",
description: "build blob upload chunk url",
expected: "http://localhost:5000/v2/foo/bar/blobs/uploads/uuid-part",
build: func() (string, error) {
return urlBuilder.BuildBlobUploadChunkURL("foo/bar", "uuid-part")
},
},
{
description: "build blob upload chunk url with digest and size",
expectedPath: "/v2/foo/bar/blobs/uploads/uuid-part?digest=tarsum.v1%2Bsha256%3Aabcdef0123456789&size=10000",
description: "build blob upload chunk url with digest and size",
expected: "http://localhost:5000/v2/foo/bar/blobs/uploads/uuid-part?digest=tarsum.v1%2Bsha256%3Aabcdef0123456789&size=10000",
build: func() (string, error) {
return urlBuilder.BuildBlobUploadChunkURL("foo/bar", "uuid-part", url.Values{
"size": []string{"10000"},
@@ -82,32 +86,15 @@ func TestURLBuilder(t *testing.T) {
})
},
},
}
roots := []string{
"http://example.com",
"https://example.com",
"http://localhost:5000",
"https://localhost:5443",
}
for _, root := range roots {
urlBuilder, err = NewURLBuilderFromString(root)
} {
u, err := testcase.build()
if err != nil {
t.Fatalf("unexpected error creating urlbuilder: %v", err)
t.Fatalf("%s: error building url: %v", testcase.description, err)
}
for _, testCase := range testCases {
url, err := testCase.build()
if err != nil {
t.Fatalf("%s: error building url: %v", testCase.description, err)
}
expectedURL := root + testCase.expectedPath
if url != expectedURL {
t.Fatalf("%s: %q != %q", testCase.description, url, expectedURL)
}
if u != testcase.expected {
t.Fatalf("%s: %q != %q", testcase.description, u, testcase.expected)
}
}
}
+10 -9
View File
@@ -57,10 +57,9 @@ func (r *Repository) newVolume(path string, writable bool) (*Volume, error) {
}
path = filepath.Clean(path)
// Ignore the error here since the path may not exist
// Really just want to make sure the path we are using is real(or non-existant)
if cleanPath, err := filepath.EvalSymlinks(path); err == nil {
path = cleanPath
path, err = filepath.EvalSymlinks(path)
if err != nil {
return nil, err
}
v := &Volume{
@@ -170,11 +169,13 @@ func (r *Repository) Delete(path string) error {
return err
}
if !volume.IsBindMount {
if err := r.driver.Remove(volume.ID); err != nil {
if !os.IsNotExist(err) {
return err
}
if volume.IsBindMount {
return nil
}
if err := r.driver.Remove(volume.ID); err != nil {
if !os.IsNotExist(err) {
return err
}
}