Compare commits

..

28 Commits

Author SHA1 Message Date
Arnaud Porterie a1cae772c4 Bump to version v1.5.0
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2015-02-04 10:07:14 -08:00
Derek McGowan d4c731ecd6 Limit push and pull to v2 official registry
No longer push to the official v2 registry when it is available. This allows pulling images from the v2 registry without defaulting push. Only pull official images from the v2 official registry.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2015-02-04 10:05:16 -08:00
Arnaud Porterie 2dba4e1386 Fix client-side validation of Dockerfile path
Arguments to `filepath.Rel` were reversed, making all builder tests to
fail.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2015-02-03 09:07:17 -08:00
Tibor Vass 06a7f471e0 builder: prevent Dockerfile to leave build context
Signed-off-by: Tibor Vass <teabee89@gmail.com>
2015-02-03 09:07:17 -08:00
Doug Davis 4683d01691 Add an API test for docker build -f Dockerfile
I noticed that while we have tests to make sure that people don't
specify a Dockerfile (via -f) that's outside of the build context
when using the docker cli, we don't check on the server side to make
sure that API users have the same check done. This would be a security
risk.

While in there I had to add a new util func for the tests to allow us to
send content to the server that isn't json encoded - in this case a tarball

Signed-off-by: Doug Davis <dug@us.ibm.com>
2015-02-03 09:07:17 -08:00
Michael Crosby 6020a06399 Print zeros for initial stats collection on stopped container
When calling stats on stopped container's print out zeros for all of the
values to populate the initial table.  This signals to the user that the
operations completed and will not block.

Closes #10504

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2015-02-03 08:50:47 -08:00
Sebastiaan van Stijn cc0bfccdf4 Replace "base" with "ubuntu" in documentation
The API documentation uses the "base" image in various
places. The "base" image is deprecated and it is no longer
possible to download this image.

This changes the API documentation to use "ubuntu" in stead.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2015-02-02 13:34:12 -08:00
Chen Hanxiao 0c18ec62f3 docs: fix another typo in docker-build man page
s/arbtrary/arbitrary

Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
2015-02-02 13:30:11 -08:00
John Tims a9825c9bd8 Fix documentation typo
Signed-off-by: John Tims <john.k.tims@gmail.com>
2015-02-02 13:30:11 -08:00
Josh Hawn 908be50c44 Handle gorilla/mux route url bug
When getting the URL from a v2 registry url builder, it does not
honor the scheme from the endpoint object and will cause an https
endpoint to return urls starting with http.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
2015-02-02 13:30:11 -08:00
Josh Hawn 2a82dba34d Fix token basic auth header issue
When requesting a token, the basic auth header is always being set even
if there is no username value. This patch corrects this and does not set
the basic auth header if the username is empty.

Also fixes an issue where pulling all tags from a v2 registry succeeds
when the image does not actually exist on the registry.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
2015-02-02 13:30:11 -08:00
Erik Hollensbe 13fd2a908c Remove "OMG IPV6" log message
Signed-off-by: Erik Hollensbe <erik+github@hollensbe.org>
2015-02-02 13:30:11 -08:00
Arnaud Porterie 464891aaf8 Fix race in test registry setup
Wait for the local registry-v2 test instance to become available to
avoid random tests failures.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2015-02-02 13:30:10 -08:00
Phil Estes 9974663ed7 Add missing $HOST in a couple places in HTTPS/TLS setup docs
Fix typos in setup docs where tcp://:2376 is used without the $HOST
parameter.

Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com>
2015-02-02 13:30:10 -08:00
Derek McGowan 76269e5c9d Add push fallback to v1 for the official registry
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2015-02-02 13:30:10 -08:00
Jessica Frazelle 1121d7c4fd Validate toml
Docker-DCO-1.1-Signed-off-by: Jessie Frazelle <princess@docker.com> (github: jfrazelle)

Docker-DCO-1.1-Signed-off-by: Jessie Frazelle <hugs@docker.com> (github: jfrazelle)
2015-02-02 13:30:10 -08:00
Josh Hawn 7e197575a2 Remove Checksum field from image.Image struct
The checksum is now being stored in a separate file beside the image
JSON file.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
2015-02-02 13:30:10 -08:00
Derek McGowan 3dc3059d94 Store tar checksum in separate file
Fixes #10432

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2015-02-02 13:30:10 -08:00
Derek McGowan 7b6de74c9a Revert client signature
Supports multiple tag push with daemon signature

Fixes #10444

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2015-02-02 13:30:10 -08:00
Phil Estes cad8adacb8 Setup TCP keep-alive on hijacked HTTP(S) client <--> daemon sessions
Fixes #10387

Without TCP keep-alive set on socket connections to the daemon, any
long-running container with std{out,err,in} attached that doesn't
read/write for a minute or longer will end in ECONNTIMEDOUT (depending
on network settings/OS defaults, etc.), leaving the docker client side
believing it is still waiting on data with no actual underlying socket
connection.

This patch turns on TCP keep-alive for the underlying TCP connection
for both TLS and standard HTTP hijacked daemon connections from the
docker client, with a keep-alive timeout of 30 seconds.

Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com>
2015-02-02 13:30:10 -08:00
Srini Brahmaroutu 6226deeaf4 Removing the check on Architecture to build and run Docker on IBM Power and Z platforms
Signed-off-by: Srini Brahmaroutu <srbrahma@us.ibm.com>
2015-02-02 13:30:10 -08:00
gdi2290 3ec19f56cf Update AUTHORS file and .mailmap
added `LC_ALL=C.UTF-8` due to osx
http://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searche
s-with-lc-all

Signed-off-by: Patrick Stapleton <github@gdi2290.com>
2015-02-02 13:30:10 -08:00
Josh Hawn 48c71787ed No longer compute checksum when installing images.
While checksums are verified when a layer is pulled from v2 registries,
there are known issues where the checksum may change when the layer diff
is computed again. To avoid these issues, the checksum should no longer
be computed and stored until after it has been extracted to the docker
storage driver. The checksums are instead computed lazily before they
are pushed to a v2 registry.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
2015-02-02 13:30:10 -08:00
Jessica Frazelle 604731a930 Some small updates to the dev env docs.
Docker-DCO-1.1-Signed-off-by: Jessica Frazelle <jess@docker.com> (github: jfrazelle)
2015-02-02 13:30:09 -08:00
Derek McGowan e8650e01f8 Defer creation of trust key file until needed
Fixes #10442

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2015-02-02 13:30:09 -08:00
Sven Dowideit 817d04d992 DHE documentation placeholder and Navbar changes
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-02 13:30:09 -08:00
Sven Dowideit cdff91a01c comment out the docker and curl lines we'll run later
Docker-DCO-1.1-Signed-off-by: Sven Dowideit <SvenDowideit@docker.com> (github: SvenDowideit)
2015-02-02 13:30:09 -08:00
Mehul Kar 6f26bd0e16 Improve explanation of port mapping from containers
Signed-off-by: Mehul Kar <mehul.kar@gmail.com>
2015-02-02 13:30:09 -08:00
58 changed files with 968 additions and 549 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
- hack/make.sh validate-dco validate-gofmt validate-toml
- hack/make.sh binary cross test-unit test-integration-cli test-integration test-docker-py
+19 -2
View File
@@ -6,6 +6,24 @@
#
# 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>
@@ -58,7 +76,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>
@@ -74,7 +92,6 @@ 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>
+113 -58
View File
@@ -12,41 +12,46 @@ 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>
AnandkumarPatel <anandkumarpatel@gmail.com>
Anand Patil <anand.prabhakar.patil@gmail.com>
AnandkumarPatel <anandkumarpatel@gmail.com>
Andre Dublin <81dublin@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>
Andrea Turli <andrea.turli@gmail.com>
Andre Dublin <81dublin@gmail.com>
Andrew C. Bodine <acbodine@us.ibm.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>
@@ -56,6 +61,8 @@ 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>
@@ -72,11 +79,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>
@@ -113,18 +120,22 @@ 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>
Christopher Currie <codemonkey+github@gmail.com>
Christopher Rigor <crigor@gmail.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>
Ciro S. Costa <ciro.costa@usp.br>
Clayton Coleman <ccoleman@redhat.com>
Colin Dunklau <colin.dunklau@gmail.com>
@@ -132,15 +143,20 @@ 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>
Daniel, Dao Quang Minh <dqminh89@gmail.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 Exner <dex@dragonslave.de>
Daniel Farrell <dfarrell@redhat.com>
Daniel Garcia <daniel@danielgarcia.info>
@@ -152,29 +168,27 @@ Daniel Nordberg <dnordberg@gmail.com>
Daniel Robinson <gottagetmac@gmail.com>
Daniel Von Fange <daniel@leancoder.com>
Daniel YC Lin <dlin.tw@gmail.com>
Dan Keder <dan.keder@gmail.com>
Dan McPherson <dmcphers@redhat.com>
Daniel, Dao Quang Minh <dqminh89@gmail.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>
@@ -182,14 +196,16 @@ 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>
@@ -197,19 +213,22 @@ 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>
evanderkoogh <info@erronis.nl>
Evan Carmi <carmi@users.noreply.github.com>
Evan Hazlett <ejhazlett@gmail.com>
Evan Krall <krall@yelp.com>
Evan Phoenix <evan@fallingsnow.net>
@@ -230,9 +249,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>
@@ -266,13 +285,15 @@ 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>
@@ -284,8 +305,10 @@ Isabel Jimenez <contact.isabeljimenez@gmail.com>
Isao Jonas <isao.jonas@gmail.com>
Ivan Fraixedes <ifcdev@gmail.com>
Jack Danger Canty <jackdanger@squareup.com>
jakedt <jake@devtable.com>
Jacob Atzen <jacob@jacobatzen.dk>
Jacob Edelman <edelman.jd@gmail.com>
Jake Moshenko <jake@devtable.com>
jakedt <jake@devtable.com>
James Allen <jamesallen0108@gmail.com>
James Carr <james.r.carr@gmail.com>
James DeFelice <james.defelice@ishisystems.com>
@@ -306,49 +329,52 @@ 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>
Jeffrey Bolle <jeffreybolle@gmail.com>
Jeff Welch <whatthejeff@gmail.com>
Jeffrey Bolle <jeffreybolle@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>
Jimmy Cuadra <jimmy@jimmycuadra.com>
Jim Perrin <jperrin@centos.org>
Jimmy Cuadra <jimmy@jimmycuadra.com>
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>
Johannes 'fish' Ziemke <github@freigeist.org>
Johan Rydberg <johan.rydberg@gmail.com>
Johannes 'fish' Ziemke <github@freigeist.org>
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 Hawn <josh.hawn@docker.com>
Josh <jokajak@gmail.com>
Josh Hawn <josh.hawn@docker.com>
Josh Poimboeuf <jpoimboe@redhat.com>
Josiah Kiehl <jkiehl@riotgames.com>
JP <jpellerin@leapfrogonline.com>
@@ -360,6 +386,9 @@ 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>
@@ -367,14 +396,13 @@ 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>
@@ -382,6 +410,7 @@ 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>
@@ -397,13 +426,16 @@ 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>
@@ -412,12 +444,13 @@ Manuel Meurer <manuel@krautcomputing.com>
Manuel Woelker <github@manuel.woelker.org>
Marc Abramowitz <marc@marc-abramowitz.com>
Marc Kuo <kuomarc2@gmail.com>
Marco Hennings <marco.hennings@freiheit.com>
Marc Tamsky <mtamsky@gmail.com>
Marco Hennings <marco.hennings@freiheit.com>
Marcus Farkas <toothlessgear@finitebox.com>
marcuslinke <marcus.linke@gmx.de>
Marcus Linke <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>
@@ -425,7 +458,9 @@ 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>
@@ -435,14 +470,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>
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>
Maxim Treskin <zerthurd@gmail.com>
Maxime Petazzoni <max@signalfuse.com>
meejah <meejah@meejah.ca>
Mengdi Gao <usrgdd@gmail.com>
Mert Yazıcıoğlu <merty@users.noreply.github.com>
@@ -451,12 +486,14 @@ 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>
@@ -471,12 +508,15 @@ 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>
@@ -491,18 +531,21 @@ 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>
@@ -510,7 +553,6 @@ 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>
@@ -518,16 +560,18 @@ 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-Alain RIVIERE <pariviere@ippon.fr>
Pierre <py@poujade.org>
Pierre Wacrenier <pierre.wacrenier@gmail.com>
Pierre-Alain RIVIERE <pariviere@ippon.fr>
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>
@@ -547,6 +591,7 @@ 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>
@@ -572,25 +617,26 @@ 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>
@@ -598,12 +644,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>
@@ -611,18 +657,23 @@ 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>
@@ -636,11 +687,10 @@ 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>
tjmehta <tj@init.me>
Timothy Hobbs <timothyhobbs@seznam.cz>
tjwebb123 <tjwebb123@users.noreply.github.com>
tobe <tobegit3hub@gmail.com>
Tobias Bieniek <Tobias.Bieniek@gmx.de>
@@ -648,10 +698,12 @@ 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>
@@ -662,7 +714,8 @@ Trent Ogren <tedwardo2@gmail.com>
Tyler Brock <tyler.brock@gmail.com>
Tzu-Jung Lee <roylee17@gmail.com>
Ulysse Carion <ulyssecarion@gmail.com>
unclejack <unclejacksons@gmail.com>
unknown <sebastiaan@ws-key-sebas3.dpi1.dpi>
Vaidas Jablonskis <jablonskis@gmail.com>
vgeta <gopikannan.venugopalsamy@gmail.com>
Victor Coisne <victor.coisne@dotcloud.com>
Victor Lyuboslavsky <victor@victoreda.com>
@@ -691,15 +744,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>
@@ -715,4 +768,6 @@ 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>
+4
View File
@@ -155,6 +155,10 @@ 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
$(DOCKER_RUN_DOCKER) hack/make.sh validate-gofmt validate-dco validate-toml
shell: build
$(DOCKER_RUN_DOCKER) bash
+1 -1
View File
@@ -1 +1 @@
1.5.0-rc2
1.5.0-rc4
+3 -4
View File
@@ -17,7 +17,6 @@ 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 {
@@ -27,7 +26,7 @@ type DockerCli struct {
in io.ReadCloser
out io.Writer
err io.Writer
key libtrust.PrivateKey
keyFile string
tlsConfig *tls.Config
scheme string
// inFd holds file descriptor of the client's STDIN, if it's a valid file
@@ -122,7 +121,7 @@ func (cli *DockerCli) CheckTtyInput(attachStdin, ttyMode bool) error {
return nil
}
func NewDockerCli(in io.ReadCloser, out, err io.Writer, key libtrust.PrivateKey, proto, addr string, tlsConfig *tls.Config) *DockerCli {
func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var (
inFd uintptr
outFd uintptr
@@ -177,7 +176,7 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, key libtrust.PrivateKey,
in: in,
out: out,
err: err,
key: key,
keyFile: keyFile,
inFd: inFd,
outFd: outFd,
isTerminalIn: isTerminalIn,
+60 -58
View File
@@ -39,6 +39,7 @@ 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"
@@ -46,7 +47,6 @@ 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
}
var filename string // path to Dockerfile
var origDockerfile string // used for error msg
filename := *dockerfileName // path to Dockerfile
if *dockerfileName == "" {
// No -f/--file was specified so use the default
origDockerfile = api.DefaultDockerfileName
*dockerfileName = origDockerfile
*dockerfileName = api.DefaultDockerfileName
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):]
}
if _, err = os.Stat(filename); os.IsNotExist(err) {
return fmt.Errorf("Can not locate Dockerfile: %s", origDockerfile)
origDockerfile := *dockerfileName // used for error msg
if filename, err = filepath.Abs(filename); err != nil {
return err
}
var includes []string = []string{"."}
// 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{"."}
excludes, err := utils.ReadDockerIgnore(path.Join(root, ".dockerignore"))
if err != nil {
@@ -1216,25 +1216,6 @@ 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 {
@@ -1244,7 +1225,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
base64.URLEncoding.EncodeToString(buf),
}
return cli.stream("POST", "/images/"+remote+"/push?"+v.Encode(), bytes.NewReader(signedBody), cli.out, map[string][]string{
return cli.stream("POST", "/images/"+remote+"/push?"+v.Encode(), nil, cli.out, map[string][]string{
"X-Registry-Auth": registryAuthHeader,
})
}
@@ -2634,7 +2615,12 @@ type containerStats struct {
err error
}
func (s *containerStats) Collect(stream io.ReadCloser) {
func (s *containerStats) Collect(cli *DockerCli) {
stream, _, err := cli.call("GET", "/containers/"+s.Name+"/stats", nil, false)
if err != nil {
s.err = err
return
}
defer stream.Close()
var (
previousCpu uint64
@@ -2714,28 +2700,44 @@ func (cli *DockerCli) CmdStats(args ...string) error {
names := cmd.Args()
sort.Strings(names)
var cStats []*containerStats
for _, n := range names {
s := &containerStats{Name: n}
cStats = append(cStats, s)
stream, _, err := cli.call("GET", "/containers/"+n+"/stats", nil, false)
if err != nil {
return err
}
go s.Collect(stream)
}
w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
for _ = range time.Tick(500 * time.Millisecond) {
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")
}
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()))
}
c.mu.Unlock()
}
if len(errs) > 0 {
return fmt.Errorf("%s", strings.Join(errs, ", "))
}
for _ = range time.Tick(500 * time.Millisecond) {
printHeader()
toRemove := []int{}
for i, s := range cStats {
if err := s.Display(w); err != nil {
toRemove = append(toRemove, i)
}
}
for _, i := range toRemove {
for j := len(toRemove) - 1; j >= 0; j-- {
i := toRemove[j]
cStats = append(cStats[:i], cStats[i+1:]...)
}
if len(cStats) == 0 {
+18
View File
@@ -72,6 +72,15 @@ 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 {
@@ -140,6 +149,15 @@ 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?")
-19
View File
@@ -621,18 +621,6 @@ 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")
@@ -664,15 +652,9 @@ 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)
@@ -1325,7 +1307,6 @@ 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,
+12 -8
View File
@@ -24,7 +24,7 @@ import (
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
log "github.com/Sirupsen/logrus"
@@ -32,6 +32,7 @@ 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"
@@ -169,12 +170,15 @@ 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(filename string) error {
filename = path.Join(b.contextPath, filename)
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)
}
fi, err := os.Stat(filename)
fi, err := os.Lstat(filename)
if os.IsNotExist(err) {
return fmt.Errorf("Cannot build a directory without a Dockerfile")
return fmt.Errorf("Cannot locate specified Dockerfile: %s", origFile)
}
if fi.Size() == 0 {
return ErrDockerfileEmpty
@@ -201,13 +205,13 @@ func (b *Builder) readDockerfile(filename string) error {
// Note that this assumes the Dockerfile has been read into memory and
// is now safe to be removed.
excludes, _ := utils.ReadDockerIgnore(path.Join(b.contextPath, ".dockerignore"))
excludes, _ := utils.ReadDockerIgnore(filepath.Join(b.contextPath, ".dockerignore"))
if rm, _ := fileutils.Matches(".dockerignore", excludes); rm == true {
os.Remove(path.Join(b.contextPath, ".dockerignore"))
os.Remove(filepath.Join(b.contextPath, ".dockerignore"))
b.context.(tarsum.BuilderContext).Remove(".dockerignore")
}
if rm, _ := fileutils.Matches(b.dockerfileName, excludes); rm == true {
os.Remove(path.Join(b.contextPath, b.dockerfileName))
os.Remove(filepath.Join(b.contextPath, b.dockerfileName))
b.context.(tarsum.BuilderContext).Remove(b.dockerfileName)
}
+2 -6
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 := checkKernelAndArch(); err != nil {
if err := checkKernel(); err != nil {
return nil, err
}
@@ -1205,11 +1205,7 @@ func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*i
return match, nil
}
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)
}
func checkKernel() error {
// Check for unsupported kernel versions
// FIXME: it would be cleaner to not test for specific versions, but rather
// test for specific functionalities.
-1
View File
@@ -188,7 +188,6 @@ 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"))
+2 -7
View File
@@ -79,11 +79,6 @@ 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
@@ -125,9 +120,9 @@ func main() {
}
if *flTls || *flTlsVerify {
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, trustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
} else {
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, trustKey, protoAddrParts[0], protoAddrParts[1], nil)
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, *flTrustKey, protoAddrParts[0], protoAddrParts[1], nil)
}
if err := cli.Cmd(flag.Args()...); err != nil {
+1 -1
View File
@@ -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 arbtrary:
Though it is not a good practice, image names can be arbitrary:
docker build -t myimage .
+5
View File
@@ -69,6 +69,11 @@ 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']
+2 -2
View File
@@ -150,11 +150,11 @@ need to provide your client keys, certificates and trusted CA:
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
`DOCKER_HOST` and `DOCKER_TLS_VERIFY` variables as well (instead of passing
`-H=tcp://:2376` and `--tlsverify` on every call).
`-H=tcp://$HOST:2376` and `--tlsverify` on every call).
$ mkdir -pv ~/.docker
$ cp -v {ca,cert,key}.pem ~/.docker
$ export DOCKER_HOST=tcp://:2376 DOCKER_TLS_VERIFY=1
$ export DOCKER_HOST=tcp://$HOST:2376 DOCKER_TLS_VERIFY=1
Docker will now connect securely by default:
+4 -3
View File
@@ -13,11 +13,12 @@ cert: build
certs: cert
run:
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
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
client:
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
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
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
+7 -1
View File
@@ -1,4 +1,10 @@
#!/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'
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'
+18 -12
View File
@@ -10,6 +10,12 @@ 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
@@ -43,18 +49,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:
$ sudo make build
On Mac OS X, from within the `boot2docker` shell:
Your first build will take some time to complete. On Linux systems and 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.
> 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).
If the build is successful, congratulations! You have produced a clean
build of docker, neatly encapsulated in a standard build environment.
@@ -64,13 +70,13 @@ build of docker, neatly encapsulated in a standard build environment.
To create the Docker binary, run this command:
$ sudo make binary
$ 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:
$ sudo make BINDDIR=. binary
$ 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`.
@@ -91,7 +97,7 @@ on ubuntu:
To execute the test cases, run this command:
$ sudo make test
$ make test
If the test are successful then the tail of the output should look
something like this
@@ -138,7 +144,7 @@ is recommended.
You can run an interactive session in the newly built container:
$ sudo make shell
$ make shell
# type 'exit' or Ctrl-D to exit
@@ -148,7 +154,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:
$ sudo make docs
$ make docs
# when its done, you can point your browser to http://yourdockerhost:8000
# type Ctrl-C to exit
@@ -0,0 +1,8 @@
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.
@@ -0,0 +1,9 @@
page_title: Using Docker Hub Enterprise
page_description: Docker Hub Enterprise
page_keywords: docker hub enterprise
# Docker Hub Enterprise
Documenation coming soon.
@@ -35,7 +35,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -45,7 +45,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -55,7 +55,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -65,7 +65,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -119,7 +119,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"base",
"Image":"ubuntu",
"Volumes":{
"/tmp": {}
},
@@ -194,7 +194,7 @@ Return low-level information on the container `id`
"Cmd": [
"date"
],
"Image": "base",
"Image": "ubuntu",
"Volumes": {},
"WorkingDir":""
@@ -702,7 +702,7 @@ Create an image, either by pull it from the registry or by importing
**Example request**:
POST /images/create?fromImage=base HTTP/1.1
POST /images/create?fromImage=ubuntu HTTP/1.1
**Example response**:
@@ -774,7 +774,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/base/json HTTP/1.1
GET /images/ubuntu/json HTTP/1.1
**Example response**:
@@ -801,7 +801,7 @@ Return low-level information on the image `name`
"StdinOnce":false,
"Env":null,
"Cmd": ["/bin/bash"]
"Image":"base",
"Image":"ubuntu",
"Volumes":null,
"WorkingDir":""
},
@@ -822,7 +822,7 @@ Return the history of the image `name`
**Example request**:
GET /images/base/history HTTP/1.1
GET /images/ubuntu/history HTTP/1.1
**Example response**:
@@ -1229,10 +1229,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"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}
{"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}
Query Parameters:
@@ -35,7 +35,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -45,7 +45,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -55,7 +55,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -65,7 +65,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -119,7 +119,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"base",
"Image":"ubuntu",
"Volumes":{
"/tmp": {}
},
@@ -195,7 +195,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -736,7 +736,7 @@ Create an image, either by pull it from the registry or by importing i
**Example request**:
POST /images/create?fromImage=base HTTP/1.1
POST /images/create?fromImage=ubuntu HTTP/1.1
**Example response**:
@@ -777,7 +777,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/base/json HTTP/1.1
GET /images/ubuntu/json HTTP/1.1
**Example response**:
@@ -805,7 +805,7 @@ Return low-level information on the image `name`
"Env":null,
"Cmd": ["/bin/bash"],
"Dns":null,
"Image":"base",
"Image":"ubuntu",
"Volumes":null,
"VolumesFrom":"",
"WorkingDir":""
@@ -827,7 +827,7 @@ Return the history of the image `name`
**Example request**:
GET /images/base/history HTTP/1.1
GET /images/ubuntu/history HTTP/1.1
**Example response**:
@@ -1259,10 +1259,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"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}
{"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}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -127,7 +127,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"base",
"Image":"ubuntu",
"Volumes":{
"/tmp": {}
},
@@ -204,7 +204,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -795,7 +795,7 @@ Create an image, either by pull it from the registry or by importing i
**Example request**:
POST /images/create?fromImage=base HTTP/1.1
POST /images/create?fromImage=ubuntu HTTP/1.1
**Example response**:
@@ -838,7 +838,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/base/json HTTP/1.1
GET /images/ubuntu/json HTTP/1.1
**Example response**:
@@ -864,7 +864,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -888,7 +888,7 @@ Return the history of the image `name`
**Example request**:
GET /images/base/history HTTP/1.1
GET /images/ubuntu/history HTTP/1.1
**Example response**:
@@ -1325,10 +1325,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"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}
{"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}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -121,7 +121,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"base",
"Image":"ubuntu",
"Volumes":{
"/tmp": {}
},
@@ -198,7 +198,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -784,7 +784,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=base HTTP/1.1
POST /images/create?fromImage=ubuntu HTTP/1.1
**Example response**:
@@ -827,7 +827,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/base/json HTTP/1.1
GET /images/ubuntu/json HTTP/1.1
**Example response**:
@@ -853,7 +853,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -877,7 +877,7 @@ Return the history of the image `name`
**Example request**:
GET /images/base/history HTTP/1.1
GET /images/ubuntu/history HTTP/1.1
**Example response**:
@@ -1314,10 +1314,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"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}
{"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}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -124,7 +124,7 @@ Create a container
"Cmd":[
"date"
],
"Image":"base",
"Image":"ubuntu",
"Volumes":{
"/tmp": {}
},
@@ -207,7 +207,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -794,7 +794,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=base HTTP/1.1
POST /images/create?fromImage=ubuntu HTTP/1.1
**Example response**:
@@ -837,7 +837,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/base/json HTTP/1.1
GET /images/ubuntu/json HTTP/1.1
**Example response**:
@@ -863,7 +863,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -887,7 +887,7 @@ Return the history of the image `name`
**Example request**:
GET /images/base/history HTTP/1.1
GET /images/ubuntu/history HTTP/1.1
**Example response**:
@@ -1324,10 +1324,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"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}
{"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}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -128,7 +128,7 @@ Create a container
"date"
],
"Entrypoint": "",
"Image": "base",
"Image": "ubuntu",
"Volumes": {
"/tmp": {}
},
@@ -291,7 +291,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -939,7 +939,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=base HTTP/1.1
POST /images/create?fromImage=ubuntu HTTP/1.1
**Example response**:
@@ -983,7 +983,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/base/json HTTP/1.1
GET /images/ubuntu/json HTTP/1.1
**Example response**:
@@ -1009,7 +1009,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -1033,7 +1033,7 @@ Return the history of the image `name`
**Example request**:
GET /images/base/history HTTP/1.1
GET /images/ubuntu/history HTTP/1.1
**Example response**:
@@ -1471,10 +1471,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"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}
{"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}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -128,7 +128,7 @@ Create a container
"date"
],
"Entrypoint": "",
"Image": "base",
"Image": "ubuntu",
"Volumes": {
"/tmp": {}
},
@@ -291,7 +291,7 @@ Return low-level information on the container `id`
"date"
],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": {},
"VolumesFrom": "",
"WorkingDir": ""
@@ -885,7 +885,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=base HTTP/1.1
POST /images/create?fromImage=ubuntu HTTP/1.1
**Example response**:
@@ -929,7 +929,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/base/json HTTP/1.1
GET /images/ubuntu/json HTTP/1.1
**Example response**:
@@ -955,7 +955,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -979,7 +979,7 @@ Return the history of the image `name`
**Example request**:
GET /images/base/history HTTP/1.1
GET /images/ubuntu/history HTTP/1.1
**Example response**:
@@ -1427,10 +1427,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"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}
{"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}
Query Parameters:
@@ -36,7 +36,7 @@ List containers
[
{
"Id": "8dfafdbc3a40",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 1",
"Created": 1367854155,
"Status": "Exit 0",
@@ -46,7 +46,7 @@ List containers
},
{
"Id": "9cd87474be90",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 222222",
"Created": 1367854155,
"Status": "Exit 0",
@@ -56,7 +56,7 @@ List containers
},
{
"Id": "3176a2479c92",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 3333333333333333",
"Created": 1367854154,
"Status": "Exit 0",
@@ -66,7 +66,7 @@ List containers
},
{
"Id": "4cb07b47f9fb",
"Image": "base:latest",
"Image": "ubuntu:latest",
"Command": "echo 444444444444444444444444444444444",
"Created": 1367854152,
"Status": "Exit 0",
@@ -128,7 +128,7 @@ Create a container
"date"
],
"Entrypoint": "",
"Image": "base",
"Image": "ubuntu",
"Volumes": {
"/tmp": {}
},
@@ -1096,7 +1096,7 @@ Create an image, either by pulling it from the registry or by importing it
**Example request**:
POST /images/create?fromImage=base HTTP/1.1
POST /images/create?fromImage=ubuntu HTTP/1.1
**Example response**:
@@ -1140,7 +1140,7 @@ Return low-level information on the image `name`
**Example request**:
GET /images/base/json HTTP/1.1
GET /images/ubuntu/json HTTP/1.1
**Example response**:
@@ -1166,7 +1166,7 @@ Return low-level information on the image `name`
"Env": null,
"Cmd": ["/bin/bash"],
"Dns": null,
"Image": "base",
"Image": "ubuntu",
"Volumes": null,
"VolumesFrom": "",
"WorkingDir": ""
@@ -1190,7 +1190,7 @@ Return the history of the image `name`
**Example request**:
GET /images/base/history HTTP/1.1
GET /images/ubuntu/history HTTP/1.1
**Example response**:
@@ -1589,10 +1589,10 @@ and Docker images will report:
HTTP/1.1 200 OK
Content-Type: application/json
{"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}
{"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}
Query Parameters:
+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, it's
> If the path `/opt/webapp` already exists inside the container's image, its
> contents will be replaced by the contents of `/src/webapp` on the host to stay
> consistent with the expected behavior of `mount`
+3 -2
View File
@@ -167,8 +167,9 @@ 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 your container.
Without Docker's port mapping you could only access one at a time.
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.
So let's now browse to port 49155 in a web browser to
see the application.
+1
View File
@@ -60,6 +60,7 @@ pre {
/* Main Navigation */
#nav_menu > #docsnav {
max-width: 940px;
width: 940px;
margin: 0 auto;
}
#nav_menu > #docsnav > #nav_search {
-4
View File
@@ -801,10 +801,6 @@ 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;
+10 -8
View File
@@ -1,13 +1,14 @@
<div id="topmostnav" class="topmostnav_loggedout navbar navbar-static-top public">
<div id="topmostnav" class="topmostnav_loggedout navbar navbar-static-top">
<div class="container">
<a href="http://www.docker.com/" title="Homepage">
<div class="brand logo"><img src="/img/nav/docker-logo-loggedout.png"> </div>
</a>
<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>
<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">
@@ -18,9 +19,10 @@
</div>
<div id="topmostnav" class="topmostnav_loggedin navbar navbar-static-top">
<div class="container">
<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">
<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>
<ul class="nav">
<li><a href="https://registry.hub.docker.com" title="Browse Repos">Browse Repos</a></li>
-4
View File
@@ -18,9 +18,5 @@
{% 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>
+15 -31
View File
@@ -15,35 +15,6 @@ 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,
@@ -92,7 +63,10 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
}
}
checksum := layer.Checksum
checksum, err := layer.GetCheckSum(s.graph.ImageRoot(layer.ID))
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 {
@@ -108,6 +82,11 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
}
checksum = tarSum.Sum(nil)
// Save checksum value
if err := layer.SaveCheckSum(s.graph.ImageRoot(layer.ID), checksum); err != nil {
return nil, err
}
}
jsonData, err := layer.RawJson()
@@ -130,7 +109,12 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
return manifestBytes, nil
}
func (s *TagStore) verifyManifest(eng *engine.Engine, manifestBytes []byte) (*registry.ManifestData, bool, error) {
// 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) {
sig, err := libtrust.ParsePrettySignature(manifestBytes, "signatures")
if err != nil {
return nil, false, fmt.Errorf("error parsing payload: %s", err)
+82
View File
@@ -0,0 +1,82 @@
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)
}
}
+5 -2
View File
@@ -72,7 +72,7 @@ func (s *TagStore) CmdPull(job *engine.Job) engine.Status {
logName += ":" + tag
}
if len(repoInfo.Index.Mirrors) == 0 && (repoInfo.Index.Official || endpoint.Version == registry.APIVersion2) {
if len(repoInfo.Index.Mirrors) == 0 && ((repoInfo.Official && repoInfo.Index.Official) || endpoint.Version == registry.APIVersion2) {
j := job.Eng.Job("trust_update_base")
if err = j.Run(); err != nil {
log.Errorf("error updating trust base graph: %s", err)
@@ -387,6 +387,9 @@ 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
@@ -417,7 +420,7 @@ func (s *TagStore) pullV2Tag(eng *engine.Engine, r *registry.Session, out io.Wri
return false, err
}
manifest, verified, err := s.verifyManifest(eng, manifestBytes)
manifest, verified, err := s.loadManifest(eng, manifestBytes)
if err != nil {
return false, fmt.Errorf("error verifying manifest: %s", err)
}
+89 -55
View File
@@ -2,6 +2,7 @@ package graph
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
@@ -18,6 +19,8 @@ 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 (
@@ -65,6 +68,25 @@ 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
@@ -251,7 +273,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, manifestBytes, tag string, sf *utils.StreamFormatter) error {
func (s *TagStore) pushV2Repository(r *registry.Session, eng *engine.Engine, out io.Writer, repoInfo *registry.RepositoryInfo, tag string, sf *utils.StreamFormatter) error {
if repoInfo.Official {
j := eng.Job("trust_update_base")
if err := j.Run(); err != nil {
@@ -261,15 +283,28 @@ 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)
}
// if no manifest is given, generate and sign with the key associated with the local tag store
if len(manifestBytes) == 0 {
for _, tag := range tags {
log.Debugf("Pushing %s:%s to v2 repository", repoInfo.LocalName, tag)
mBytes, err := s.newManifest(repoInfo.LocalName, repoInfo.RemoteName, tag)
if err != nil {
return err
@@ -287,63 +322,66 @@ func (s *TagStore) pushV2Repository(r *registry.Session, eng *engine.Engine, out
if err != nil {
return err
}
log.Infof("Signed manifest using daemon's key: %s", s.trustKey.KeyID())
log.Infof("Signed manifest for %s:%s using daemon's key: %s", repoInfo.LocalName, tag, s.trustKey.KeyID())
manifestBytes = string(signedBody)
}
manifestBytes := string(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)
manifest, verified, err := s.loadManifest(eng, signedBody)
if err != nil {
return fmt.Errorf("Failed to parse json: %s", err)
return fmt.Errorf("error verifying manifest: %s", err)
}
// 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
if err := checkValidManifest(manifest); err != nil {
return fmt.Errorf("invalid manifest: %s", err)
}
if !exists {
if err := s.PushV2Image(r, img, endpoint, repoInfo.RemoteName, sumParts[0], manifestSum, sf, out, auth); err != nil {
if verified {
log.Infof("Pushing verified image, key %s is registered for %q", s.trustKey.KeyID(), repoInfo.RemoteName)
}
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("Failed to parse json: %s", err)
}
// 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
}
} else {
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Image already exists", nil))
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
}
}
// push the manifest
return r.PutV2ImageManifest(endpoint, repoInfo.RemoteName, tag, bytes.NewReader([]byte(manifestBytes)), auth)
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 {
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)
@@ -398,7 +436,6 @@ 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)
@@ -418,18 +455,15 @@ 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, manifestBytes, tag, sf)
if endpoint.Version == registry.APIVersion2 {
err := s.pushV2Repository(r, job.Eng, job.Stdout, repoInfo, tag, sf)
if err == nil {
return engine.StatusOK
}
// error out, no fallback to V1
return job.Errorf("Error pushing to registry: %s", err)
if err != ErrV2RegistryUnavailable {
return job.Errorf("Error pushing to registry: %s", err)
}
}
if err != nil {
-2
View File
@@ -25,7 +25,6 @@ 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)
@@ -151,7 +150,6 @@ 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)
}
+22 -39
View File
@@ -10,7 +10,6 @@ import (
"time"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/tarsum"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/utils"
)
@@ -32,7 +31,6 @@ 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
@@ -80,48 +78,15 @@ 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. This function also computes a checksum
// of `layerData` if the image does not have one already.
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
// 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
if layerData != 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. Also ensure that
// the stored checksum has the latest version of tarsum (assuming we
// are using tarsum).
if tarsum.VersionLabelForChecksum(img.Checksum) != tarsum.Version1.String() {
// Either there was no checksum or it's not a tarsum.v1
layerDataDecompressed, err := archive.DecompressStream(layerData)
if err != nil {
return err
}
defer layerDataDecompressed.Close()
if layerTarSum, err = tarsum.NewTarSum(layerDataDecompressed, true, tarsum.Version1); 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 {
if img.Size, err = img.graph.Driver().ApplyDiff(img.ID, img.Parent, layerData); err != nil {
return err
}
}
img.Size = size
if err := img.SaveSize(root); err != nil {
return err
}
@@ -148,6 +113,24 @@ 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")
}
@@ -299,3 +299,70 @@ 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")
}
+64
View File
@@ -4592,3 +4592,67 @@ 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")
}
@@ -383,6 +383,9 @@ 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)
}
+1 -1
View File
@@ -24,6 +24,7 @@ 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))
}
@@ -40,7 +41,6 @@ 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])
}
+41 -1
View File
@@ -45,7 +45,7 @@ func TestPushUntagged(t *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
expected := "does not exist"
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)
@@ -55,6 +55,46 @@ func TestPushUntagged(t *testing.T) {
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 {
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 - 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")
}
func TestPushInterrupt(t *testing.T) {
defer setupRegistry(t)()
+28 -7
View File
@@ -274,6 +274,15 @@ 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 {
@@ -296,17 +305,16 @@ func sockRequest(method, endpoint string, data interface{}) ([]byte, error) {
client := httputil.NewClientConn(c, nil)
defer client.Close()
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")
req, err := http.NewRequest(method, endpoint, data)
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)
@@ -870,5 +878,18 @@ 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,6 +3,7 @@ package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
@@ -52,6 +53,18 @@ 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)
+8 -32
View File
@@ -14,7 +14,6 @@ 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"
)
@@ -122,12 +121,7 @@ func TestRunDetach(t *testing.T) {
t.Fatal(err)
}
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@@ -177,12 +171,7 @@ func TestAttachDetach(t *testing.T) {
t.Fatal(err)
}
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@@ -219,7 +208,7 @@ func TestAttachDetach(t *testing.T) {
t.Fatal(err)
}
cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
ch = make(chan struct{})
go func() {
@@ -270,12 +259,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
t.Fatal(err)
}
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
// Discard the CmdRun output
@@ -297,7 +281,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
t.Fatal(err)
}
cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
ch := make(chan struct{})
go func() {
@@ -347,12 +331,7 @@ func TestAttachDisconnect(t *testing.T) {
t.Fatal(err)
}
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(tty, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
go func() {
@@ -421,11 +400,8 @@ func TestAttachDisconnect(t *testing.T) {
func TestRunAutoRemove(t *testing.T) {
t.Skip("Fixme. Skipping test for now, race condition")
stdout, stdoutPipe := io.Pipe()
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, key, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, "", testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
+3 -16
View File
@@ -9,7 +9,6 @@ import (
"time"
"github.com/docker/docker/api/client"
"github.com/docker/libtrust"
)
const (
@@ -38,11 +37,7 @@ 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) {
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, "", testDaemonProto,
testDaemonHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
@@ -55,11 +50,7 @@ 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) {
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, "", testDaemonProto,
testDaemonHttpsAddr, getTlsConfig("client-rogue-cert.pem", "client-rogue-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
@@ -76,11 +67,7 @@ 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) {
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatal(err)
}
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, key, testDaemonProto,
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, "", testDaemonProto,
testDaemonRogueHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
+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>' | sort -uf
git log --format='%aN <%aE>' | LC_ALL=C.UTF-8 sort -uf
} > AUTHORS
+1
View File
@@ -44,6 +44,7 @@ echo
DEFAULT_BUNDLES=(
validate-dco
validate-gofmt
validate-toml
binary
+30
View File
@@ -0,0 +1,30 @@
#!/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
+2
View File
@@ -128,6 +128,8 @@ func (r *Session) HeadV2ImageBlob(ep *Endpoint, imageName, sumType, sum string,
case res.StatusCode >= 200 && res.StatusCode < 400:
// return something indicating no push needed
return true, nil
case res.StatusCode == 401:
return false, errLoginRequired
case res.StatusCode == 404:
// return something indicating blob push needed
return false, nil
+4 -2
View File
@@ -51,10 +51,12 @@ func getToken(username, password string, params map[string]string, registryEndpo
reqParams.Add("scope", scopeField)
}
reqParams.Add("account", username)
if username != "" {
reqParams.Add("account", username)
req.SetBasicAuth(username, password)
}
req.URL.RawQuery = reqParams.Encode()
req.SetBasicAuth(username, password)
resp, err := client.Do(req)
if err != nil {
+20 -5
View File
@@ -128,13 +128,28 @@ 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) *mux.Route {
func (ub *URLBuilder) cloneRoute(name string) clonedRoute {
route := new(mux.Route)
*route = *ub.router.GetRoute(name) // clone the route
root := new(url.URL)
return route.
Schemes(ub.root.Scheme).
Host(ub.root.Host)
*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
}
// appendValuesURL appends the parameters to the url.
+53 -40
View File
@@ -6,62 +6,58 @@ import (
)
type urlBuilderTestCase struct {
description string
expected string
build func() (string, error)
description string
expectedPath 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
)
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)
}{
testCases := []urlBuilderTestCase{
{
description: "test base url",
expected: "http://localhost:5000/v2/",
build: urlBuilder.BuildBaseURL,
description: "test base url",
expectedPath: "/v2/",
build: func() (string, error) {
return urlBuilder.BuildBaseURL()
},
},
{
description: "test tags url",
expected: "http://localhost:5000/v2/foo/bar/tags/list",
description: "test tags url",
expectedPath: "/v2/foo/bar/tags/list",
build: func() (string, error) {
return urlBuilder.BuildTagsURL("foo/bar")
},
},
{
description: "test manifest url",
expected: "http://localhost:5000/v2/foo/bar/manifests/tag",
description: "test manifest url",
expectedPath: "/v2/foo/bar/manifests/tag",
build: func() (string, error) {
return urlBuilder.BuildManifestURL("foo/bar", "tag")
},
},
{
description: "build blob url",
expected: "http://localhost:5000/v2/foo/bar/blobs/tarsum.v1+sha256:abcdef0123456789",
description: "build blob url",
expectedPath: "/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",
expected: "http://localhost:5000/v2/foo/bar/blobs/uploads/",
description: "build blob upload url",
expectedPath: "/v2/foo/bar/blobs/uploads/",
build: func() (string, error) {
return urlBuilder.BuildBlobUploadURL("foo/bar")
},
},
{
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",
description: "build blob upload url with digest and size",
expectedPath: "/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"},
@@ -70,15 +66,15 @@ func TestURLBuilder(t *testing.T) {
},
},
{
description: "build blob upload chunk url",
expected: "http://localhost:5000/v2/foo/bar/blobs/uploads/uuid-part",
description: "build blob upload chunk url",
expectedPath: "/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",
expected: "http://localhost:5000/v2/foo/bar/blobs/uploads/uuid-part?digest=tarsum.v1%2Bsha256%3Aabcdef0123456789&size=10000",
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",
build: func() (string, error) {
return urlBuilder.BuildBlobUploadChunkURL("foo/bar", "uuid-part", url.Values{
"size": []string{"10000"},
@@ -86,15 +82,32 @@ func TestURLBuilder(t *testing.T) {
})
},
},
} {
u, err := testcase.build()
if err != nil {
t.Fatalf("%s: error building url: %v", testcase.description, err)
}
if u != testcase.expected {
t.Fatalf("%s: %q != %q", testcase.description, u, testcase.expected)
}
}
roots := []string{
"http://example.com",
"https://example.com",
"http://localhost:5000",
"https://localhost:5443",
}
for _, root := range roots {
urlBuilder, err = NewURLBuilderFromString(root)
if err != nil {
t.Fatalf("unexpected error creating urlbuilder: %v", 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)
}
}
}
}