Compare commits

...

75 Commits

Author SHA1 Message Date
Arnaud Porterie a8a31eff10 Bump to version v1.5.0
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2015-02-10 08:14:37 -08:00
Sven Dowideit 68a8fd5c4e updates from review
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-10 08:14:37 -08:00
unclejack 8387c5ab65 update kernel reqs doc; recommend updates on RHEL
Signed-off-by: Cristian Staretu <cristian.staretu@gmail.com>
2015-02-10 08:14:37 -08:00
Sven Dowideit 69498943c3 remove the text-indent and increase the font size
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-10 08:14:37 -08:00
Sven Dowideit 1aeb78c2ae Simplfy the sidebar html and css, and then allow the text to wrap
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-10 08:14:36 -08:00
Tibor Vass 331d37f35d Minor nits
Signed-off-by: Tibor Vass <tibor@docker.com>
2015-02-10 08:14:36 -08:00
Tibor Vass edf3bf7f33 Clarify docs review role
Signed-off-by: Tibor Vass <teabee89@gmail.com>
2015-02-10 08:14:36 -08:00
Tibor Vass 9ee8dca246 A few fixes
Signed-off-by: Tibor Vass <teabee89@gmail.com>
2015-02-10 08:14:36 -08:00
Tibor Vass aa98bb6c13 New pull request workflow
Signed-off-by: Tibor Vass <teabee89@gmail.com>
2015-02-10 08:14:36 -08:00
Zhang Wei 2aba3c69f9 docs: fix a typo in registry_mirror.md
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
2015-02-10 08:14:36 -08:00
Steve Koch 71a44c769e Add link to user guide to end of 14.04 section
Adding instructions to exit the test shell and a link to the user guide (as is done in the following sections for 12.04 and 13.04/10

Signed-off-by: Steven Koch <sjkoch@unm.edu>
2015-02-10 08:14:36 -08:00
Wei-Ting Kuo d8381fad2b Update certificates.md
`openssl req -new -x509 -text -key client.key -out client.cert` creates a self-sign certificate but not a certificate request.

Signed-off-by: Wei-Ting Kuo <waitingkuo0527@gmail.com>
2015-02-09 08:49:05 -08:00
Chen Hanxiao be379580d0 docs: fix a typo in Dockerfile.5.md
s/Mutliple/Multiple

Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
2015-02-09 08:49:05 -08:00
Alexander Morozov 7ea8513479 Fix example about ps and linked containers
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
2015-02-09 08:49:05 -08:00
Sven Dowideit 3b2fe01c78 Documentation on boolean flags is wrong #10517
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:05 -08:00
Sven Dowideit e8afc22b1f Do some major rearranging of the fedora/centos/rhel installation docs
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:05 -08:00
Lokesh Mandvekar 4e407e6b77 update fedora docs to reflect latest rpm changes
Signed-off-by: Lokesh Mandvekar <lsm5@fedoraproject.org>
2015-02-09 08:49:05 -08:00
unclejack 23f1c2ea9e docs/articles/systemd: correct --storage-driver
Signed-off-by: Cristian Staretu <cristian.staretu@gmail.com>
2015-02-09 08:49:05 -08:00
Katie McLaughlin 788047cafb Format awsconfig sample config correctly
Reflow change in commit 195f3a3f removed newlines in the config format.

This change reverts the sample config to the original formatting, which
matches the actual config format of a `awsconfig` file.

Signed-off-by: Katie McLaughlin <katie@glasnt.com>
2015-02-09 08:49:05 -08:00
Sven Dowideit 0c0e7b1b60 Fix a small spelling error in the dm.blkdiscard docs
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:05 -08:00
Sven Dowideit 09d41529a0 Add an initial list of new features in Docker Engine 1.5.0
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:04 -08:00
Sven Dowideit cb288fefee remove swarm, machine and compose from the 1.5.0 release docs
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:04 -08:00
Sven Dowideit f7636796c5 The DHE documentation will not be published with 1.5.0
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:04 -08:00
Sven Dowideit cb5af83444 For now, docker stats appears to be libcontainer only
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:04 -08:00
Mihai Borobocea 96feaf1920 docs: fix typo
There are 2 not 3 RUN instructions in the userguide's Dockerfile.

Signed-off-by: Mihai Borobocea <MihaiBorobocea@gmail.com>
2015-02-09 08:49:04 -08:00
Vincent Giersch 1f03944950 Documents build API "remote" parameter
Introduced in Docker v0.4.5 / Remove API v1.1 (#848), the remote
parameter of the API method POST /build allows to specify a buildable
remote URL (HTTPS, HTTP or Git).

Signed-off-by: Vincent Giersch <vincent.giersch@ovh.net>
2015-02-09 08:49:04 -08:00
Sven Dowideit 6060eedf9c The Hub build webhooks now list the images that have been built
And fix some spelling - repo isn't really a word :)

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:04 -08:00
Sven Dowideit d217da854a Spelling mistake in dockerlinks
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:04 -08:00
Victor Vieux d74d6d981b add crosbymichael and Github -> GitHub
Signed-off-by: Victor Vieux <vieux@docker.com>
2015-02-09 08:49:04 -08:00
Victor Vieux 0205ac33d2 update MAINTAINERS file
Signed-off-by: Victor Vieux <vieux@docker.com>
2015-02-09 08:49:04 -08:00
Sven Dowideit dbb9d47bdc The reference menu is too big to list more than the latest API docs, so the others can be hidden - they're still linked from the API summary
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:03 -08:00
Sven Dowideit ddd1d081d7 use the same paths as in the swarm repo, so that their links magically work
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:03 -08:00
Sven Dowideit d6ac36d929 Docker attach documentation didn't make sense to me
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-02-09 08:49:03 -08:00
Michael A. Smith 715b94f664 Distinguish ENV from setting environment inline
It's ambiguous to say that `ENV` is _functionally equivalent to prefixing the command with `<key>=<value>`_. `ENV` sets the environment for all future commands, but `RUN` can take chained commands like `RUN foo=bar bash -c 'echo $foo' && bash -c 'echo $foo $bar'`. Users with a solid understanding of `exec` may grok this without confusion, but less experienced users may need this distinction.

Signed-off-by: Michael A. Smith <msmith3@ebay.com>

Improve Environment Handling Descriptions

- Link `ENV` and `Environment Replacement`
- Improve side-effects of `ENV` text
- Rearrange avoiding side effects text

Signed-off-by: Michael A. Smith <msmith3@ebay.com>
2015-02-09 08:49:03 -08:00
Chen Hanxiao 16baca9277 docs: change events --since to fit RFC3339Nano
PR6931 changed time format to RFC3339Nano.
But the example in cli.md does not changed.

Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
2015-02-09 08:49:03 -08:00
J Bruni 627f8a6cd5 Remove File List
This list is outdated. It could be updated instead of removed... but why should it be maintained? I do not see a reason.

Signed-off-by: João Bruni <contato@jbruni.com.br>
2015-02-09 08:49:03 -08:00
Sebastiaan van Stijn a8a7df203a Fix broken link to project/MAINTAINERS.md
The link to project/MAINTAINERS.md was broken, in
addition, /MAINTAINERS containers more relevant
information on the LGTM process and contains info
about maintainers of all subsystems.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2015-02-09 08:49:03 -08:00
Thell 'Bo' Fowler 580cbcefd3 Update dockerfile_best-practices.md
Signed-off-by: Thell Fowler <Thell@tbfowler.name>
2015-02-09 08:49:03 -08:00
Yihang Ho d9c5ce6e97 Fix a tiny typo.
'saving', not 'saveing'

Signed-off-by: Yihang Ho <hoyihang5@gmail.com>
2015-02-09 08:49:03 -08:00
Bradley Cicenas 0fe9b95415 fix project url in readme to point to the correct location,
https://github.com/docker/docker/tree/master/project

Signed-off-by: Bradley Cicenas <bradley.cicenas@gmail.com>
2015-02-09 08:49:03 -08:00
Alexandr Morozov 41d0e4293e Update events format in man page
Signed-off-by: Alexandr Morozov <lk4d4@docker.com>
2015-02-09 08:49:03 -08:00
Doug Davis 26fe640da1 Add builder folks to the top-level maintainers file
Signed-off-by: Doug Davis <dug@us.ibm.com>
2015-02-09 08:49:02 -08:00
Jessica Frazelle 198ca26969 Added tianon's info and changed a typo.
Docker-DCO-1.1-Signed-off-by: Jessica Frazelle <jess@docker.com> (github: jfrazelle)
2015-02-09 08:49:02 -08:00
Phil Estes d5365f6fc4 Fix incorrect IPv6 addresses/subnet notations in docs
Fixes a few typos in IPv6 addresses. Will make it easier for users who
actually try and copy/paste or use the example addresses directly.

Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com> (github: estesp)
2015-02-09 08:49:02 -08:00
Brian Goff 5f7e814ee7 Update go-md2man
Update fixes some rendering issues, including improperly escaping '$' in
blocks, and actual parsing of blockcode.

`ID=$(sudo docker run -d fedora /usr/bin/top -b)` was being converted to
`ID=do docker run -d fedora/usr/bin/top -b)`

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2015-02-09 08:49:02 -08:00
Doug Davis a84aca0985 Fix docs so WORKDIR mentions it works for COPY and ADD too
The docs around COPY/ADD already mentioned that it will do a relative
copy/add based on WORKDIR, so that part is already ok.  Just needed to
tweak the WORKDIR section since w/o mentioning COPY/ADD it can be misleading.

Noticed by @phemmer

Signed-off-by: Doug Davis <dug@us.ibm.com>
2015-02-09 08:49:02 -08:00
Solomon Hykes 68ec22876a Proposal for an improved project structure.
Note: this deprecates the fine-grained, high-overlap cascading MAINTAINERS files,
and replaces them with a single top-level file, using a new structure:

* More coarse grained subsystems with dedicated teams of maintainers
* Core maintainers with a better-defined role and a wider scope (if it's
not in a subsystem, it's up to the core maintainers to figure it out)
* Architects
* Operators

This is work in progress, the goal is to start a conversation

Signed-off-by: Solomon Hykes <solomon@docker.com>
Signed-off-by: Erik Hollensbe <github@hollensbe.org>
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
Signed-off-by: Tibor Vass <teabee89@gmail.com>
Signed-off-by: Victor Vieux <vieux@docker.com>
Signed-off-by: Vincent Batts <vbatts@redhat.com>
2015-02-09 08:49:02 -08:00
Josh Hawn 0dcc3559e9 Updated image spec docs to clarify image JSON
The title `Image JSON Schema` was used as a header in the section
which describes the layout and fields of the image metadata JSON
file. It was pointed out that `JSON Schema` is its own term for
describing JSON in a machine-and-human-readable format, while the
word "Schema" in this context was used more generically to say that
the section is meant to be an example and outline of the Image JSON.

http://spacetelescope.github.io/understanding-json-schema/

This section now has the title `Image JSON Description` in order
to not cause this confusion.

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
2015-02-09 08:49:02 -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
100 changed files with 2060 additions and 1071 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>
+39
View File
@@ -1,5 +1,44 @@
# Changelog
## 1.5.0 (2015-02-10)
#### Builder
+ Dockerfile to use for a given `docker build` can be specified with the `-f` flag
* Dockerfile and .dockerignore files can be themselves excluded as part of the .dockerignore file, thus preventing modifications to these files invalidating ADD or COPY instructions cache
* ADD and COPY instructions accept relative paths
* Dockerfile `FROM scratch` instruction is now interpreted as a no-base specifier
* Improve performance when exposing a large number of ports
#### Hack
+ Allow client-side only integration tests for Windows
* Include docker-py integration tests against Docker daemon as part of our test suites
#### Packaging
+ Support for the new version of the registry HTTP API
* Speed up `docker push` for images with a majority of already existing layers
- Fixed contacting a private registry through a proxy
#### Remote API
+ A new endpoint will stream live container resource metrics and can be accessed with the `docker stats` command
+ Containers can be renamed using the new `rename` endpoint and the associated `docker rename` command
* Container `inspect` endpoint show the ID of `exec` commands running in this container
* Container `inspect` endpoint show the number of times Docker auto-restarted the container
* New types of event can be streamed by the `events` endpoint: OOM (container died with out of memory), exec_create, and exec_start'
- Fixed returned string fields which hold numeric characters incorrectly omitting surrounding double quotes
#### Runtime
+ Docker daemon has full IPv6 support
+ The `docker run` command can take the `--pid=host` flag to use the host PID namespace, which makes it possible for example to debug host processes using containerized debugging tools
+ The `docker run` command can take the `--read-only` flag to make the containers root filesystem mounted as readonly, which can be used in combination with volumes to force a containers processes to only write to locations that will be persisted
+ Container total memory usage can be limited for `docker run` using the `—memory-swap` flag
* Major stability improvements for devicemapper storage driver
* Better integration with host system: containers will reflect changes to the host's `/etc/resolv.conf` file when restarted
* Better integration with host system: per-container iptable rules are moved to the DOCKER chain
- Fixed container exiting on out of memory to return an invalid exit code
#### Other
* The HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables are properly taken into account by the client when connecting to the Docker daemon
## 1.4.1 (2014-12-15)
#### Runtime
+1 -1
View File
@@ -211,7 +211,7 @@ component affected. For example, if a change affects `docs/` and `registry/`, it
needs an absolute majority from the maintainers of `docs/` AND, separately, an
absolute majority of the maintainers of `registry/`.
For more details see [MAINTAINERS.md](project/MAINTAINERS.md)
For more details see [MAINTAINERS](MAINTAINERS)
### Sign your work
+5 -1
View File
@@ -151,10 +151,14 @@ ENV DOCKER_BUILDTAGS apparmor selinux btrfs_noversion
COPY vendor /go/src/github.com/docker/docker/vendor
# (copy vendor/ because go-md2man needs golang.org/x/net)
RUN set -x \
&& git clone -b v1 https://github.com/cpuguy83/go-md2man.git /go/src/github.com/cpuguy83/go-md2man \
&& git clone -b v1.0.1 https://github.com/cpuguy83/go-md2man.git /go/src/github.com/cpuguy83/go-md2man \
&& 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"]
+590 -9
View File
@@ -1,9 +1,590 @@
Solomon Hykes <solomon@docker.com> (@shykes)
Victor Vieux <vieux@docker.com> (@vieux)
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
.mailmap: Tianon Gravi <admwiggin@gmail.com> (@tianon)
.travis.yml: Tianon Gravi <admwiggin@gmail.com> (@tianon)
AUTHORS: Tianon Gravi <admwiggin@gmail.com> (@tianon)
Dockerfile: Tianon Gravi <admwiggin@gmail.com> (@tianon)
Makefile: Tianon Gravi <admwiggin@gmail.com> (@tianon)
.dockerignore: Tianon Gravi <admwiggin@gmail.com> (@tianon)
# Docker maintainers file
#
# This file describes who runs the Docker project and how.
# This is a living document - if you see something out of date or missing,
# speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant
# parser.
[Rules]
[Rules.maintainers]
title = "What is a maintainer?"
text = """
There are different types of maintainers, with different responsibilities, but
all maintainers have 3 things in common:
1) They share responsibility in the project's success.
2) They have made a long-term, recurring time investment to improve the project.
3) They spend that time doing whatever needs to be done, not necessarily what
is the most interesting or fun.
Maintainers are often under-appreciated, because their work is harder to appreciate.
It's easy to appreciate a really cool and technically advanced feature. It's harder
to appreciate the absence of bugs, the slow but steady improvement in stability,
or the reliability of a release process. But those things distinguish a good
project from a great one.
"""
[Rules.bdfl]
title = "The Benevolent dictator for life (BDFL)"
text = """
Docker follows the timeless, highly efficient and totally unfair system
known as [Benevolent dictator for
life](http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life), with
yours truly, Solomon Hykes, in the role of BDFL. This means that all
decisions are made, by default, by Solomon. Since making every decision
myself would be highly un-scalable, in practice decisions are spread
across multiple maintainers.
Ideally, the BDFL role is like the Queen of England: awesome crown, but not
an actual operational role day-to-day. The real job of a BDFL is to NEVER GO AWAY.
Every other rule can change, perhaps drastically so, but the BDFL will always
be there, preserving the philosophy and principles of the project, and keeping
ultimate authority over its fate. This gives us great flexibility in experimenting
with various governance models, knowing that we can always press the "reset" button
without fear of fragmentation or deadlock. See the US congress for a counter-example.
BDFL daily routine:
* Is the project governance stuck in a deadlock or irreversibly fragmented?
* If yes: refactor the project governance
* Are there issues or conflicts escalated by core?
* If yes: resolve them
* Go back to polishing that crown.
"""
[Rules.decisions]
title = "How are decisions made?"
text = """
Short answer: EVERYTHING IS A PULL REQUEST.
Docker is an open-source project with an open design philosophy. This
means that the repository is the source of truth for EVERY aspect of the
project, including its philosophy, design, road map, and APIs. *If it's
part of the project, it's in the repo. If it's in the repo, it's part of
the project.*
As a result, all decisions can be expressed as changes to the
repository. An implementation change is a change to the source code. An
API change is a change to the API specification. A philosophy change is
a change to the philosophy manifesto, and so on.
All decisions affecting Docker, big and small, follow the same 3 steps:
* Step 1: Open a pull request. Anyone can do this.
* Step 2: Discuss the pull request. Anyone can do this.
* Step 3: Merge or refuse the pull request. Who does this depends on the nature
of the pull request and which areas of the project it affects. See *review flow*
for details.
Because Docker is such a large and active project, it's important for everyone to know
who is responsible for deciding what. That is determined by a precise set of rules.
* For every *decision* in the project, the rules should designate, in a deterministic way,
who should *decide*.
* For every *problem* in the project, the rules should designate, in a deterministic way,
who should be responsible for *fixing* it.
* For every *question* in the project, the rules should designate, in a deterministic way,
who should be expected to have the *answer*.
"""
[Rules.review]
title = "Review flow"
text = """
Pull requests should be processed according to the following flow:
* For each subsystem affected by the change, the maintainers of the subsystem must approve or refuse it.
It is the responsibility of the subsystem maintainers to process patches affecting them in a timely
manner.
* If the change affects areas of the code which are not part of a subsystem,
or if subsystem maintainers are unable to reach a timely decision, it must be approved by
the core maintainers.
* If the change affects the UI or public APIs, or if it represents a major change in architecture,
the architects must approve or refuse it.
* If the change affects the operations of the project, it must be approved or rejected by
the relevant operators.
* If the change affects the governance, philosophy, goals or principles of the project,
it must be approved by BDFL.
* A pull request can be in 1 of 5 distinct states, for each of which there is a corresponding label
that needs to be applied. `Rules.review.states` contains the list of states with possible targets
for each.
"""
# Triage
[Rules.review.states.0-triage]
# Maintainers are expected to triage new incoming pull requests by removing
# the `0-triage` label and adding the correct labels (e.g. `1-design-review`)
# potentially skipping some steps depending on the kind of pull request.
# Use common sense for judging.
#
# Checking for DCO should be done at this stage.
#
# If an owner, responsible for closing or merging, can be assigned to the PR,
# the better.
close = "e.g. unresponsive contributor without DCO"
3-docs-review = "non-proposal documentation-only change"
2-code-review = "e.g. trivial bugfix"
1-design-review = "general case"
# Design review
[Rules.review.states.1-design-review]
# Maintainers are expected to comment on the design of the pull request.
# Review of documentation is expected only in the context of design validation,
# not for stylistic changes.
#
# Ideally, documentation should reflect the expected behavior of the code.
# No code review should take place in this step.
#
# Once design is approved, a maintainer should make sure to remove this label
# and add the next one.
close = "design rejected"
3-docs-review = "proposals with only documentation changes"
2-code-review = "general case"
# Code review
[Rules.review.states.2-code-review]
# Maintainers are expected to review the code and ensure that it is good
# quality and in accordance with the documentation in the PR.
#
# If documentation is absent but expected, maintainers should ask for documentation.
#
# All tests should pass.
#
# Once code is approved according to the rules of the subsystem, a maintainer
# should make sure to remove this label and add the next one.
close = ""
1-design-review = "raises design concerns"
4-merge = "trivial change not impacting documentation"
3-docs-review = "general case"
# Docs review
[Rules.review.states.3-docs-review]
# Maintainers are expected to review the documentation in its bigger context,
# ensuring consistency, completeness, validity, and breadth of coverage across
# all extent and new documentation.
#
# They should ask for any editorial change that makes the documentation more
# consistent and easier to understand.
#
# Once documentation is approved, a maintainer should make sure to remove this
# label and add the next one.
close = ""
2-code-review = "requires more code changes"
1-design-review = "raises design concerns"
4-merge = "general case"
# Merge
[Rules.review.states.4-merge]
# Maintainers are expected to merge this pull request as soon as possible.
# They can ask for a rebase, or carry the pull request themselves.
# These should be the easy PRs to merge.
close = "carry PR"
merge = ""
[Rules.DCO]
title = "Helping contributors with the DCO"
text = """
The [DCO or `Sign your work`](
https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work)
requirement is not intended as a roadblock or speed bump.
Some Docker contributors are not as familiar with `git`, or have used a web based
editor, and thus asking them to `git commit --amend -s` is not the best way forward.
In this case, maintainers can update the commits based on clause (c) of the DCO. The
most trivial way for a contributor to allow the maintainer to do this, is to add
a DCO signature in a Pull Requests's comment, or a maintainer can simply note that
the change is sufficiently trivial that it does not substantivly change the existing
contribution - i.e., a spelling change.
When you add someone's DCO, please also add your own to keep a log.
"""
[Rules.holiday]
title = "I'm a maintainer, and I'm going on holiday"
text = """
Please let your co-maintainers and other contributors know by raising a pull
request that comments out your `MAINTAINERS` file entry using a `#`.
"""
[Rules."no direct push"]
title = "I'm a maintainer. Should I make pull requests too?"
text = """
Yes. Nobody should ever push to master directly. All changes should be
made through a pull request.
"""
[Rules.meta]
title = "How is this process changed?"
text = "Just like everything else: by making a pull request :)"
# Current project organization
[Org]
bdfl = "shykes"
# The chief architect is responsible for the overall integrity of the technical architecture
# across all subsystems, and the consistency of APIs and UI.
#
# Changes to UI, public APIs and overall architecture (for example a plugin system) must
# be approved by the chief architect.
"Chief Architect" = "shykes"
# The Chief Operator is responsible for the day-to-day operations of the project including:
# - facilitating communications amongst all the contributors;
# - tracking release schedules;
# - managing the relationship with downstream distributions and upstream dependencies;
# - helping new contributors to get involved and become successful contributors and maintainers
#
# The role is also responsible for managing and measuring the success of the overall project
# and ensuring it is governed properly working in concert with the Docker Governance Advisory Board (DGAB).
"Chief Operator" = "spf13"
[Org.Operators]
# The operators make sure the trains run on time. They are responsible for overall operations
# of the project. This includes facilitating communication between all the participants; helping
# newcomers get involved and become successful contributors and maintainers; tracking the schedule
# of releases; managing the relationship with downstream distributions and upstream dependencies;
# define measures of success for the project and measure progress; Devise and implement tools and
# processes which make contributors and maintainers happier and more efficient.
[Org.Operators.security]
people = [
"erw"
]
[Org.Operators."monthly meetings"]
people = [
"sven",
"tianon"
]
[Org.Operators.infrastructure]
people = [
"jfrazelle",
"crosbymichael"
]
# The chief maintainer is responsible for all aspects of quality for the project including
# code reviews, usability, stability, security, performance, etc.
# The most important function of the chief maintainer is to lead by example. On the first
# day of a new maintainer, the best advice should be "follow the C.M.'s example and you'll
# be fine".
"Chief Maintainer" = "crosbymichael"
[Org."Core maintainers"]
# The Core maintainers are the ghostbusters of the project: when there's a problem others
# can't solve, they show up and fix it with bizarre devices and weaponry.
# They have final say on technical implementation and coding style.
# They are ultimately responsible for quality in all its forms: usability polish,
# bugfixes, performance, stability, etc. When ownership can cleanly be passed to
# a subsystem, they are responsible for doing so and holding the
# subsystem maintainers accountable. If ownership is unclear, they are the de facto owners.
# For each release (including minor releases), a "release captain" is assigned from the
# pool of core maintainers. Rotation is encouraged across all maintainers, to ensure
# the release process is clear and up-to-date.
#
# It is common for core maintainers to "branch out" to join or start a subsystem.
people = [
"unclejack",
"crosbymichael",
"erikh",
"icecrime",
"jfrazelle",
"lk4d4",
"tibor",
"vbatts",
"vieux",
"vish"
]
[Org.Subsystems]
# As the project grows, it gets separated into well-defined subsystems. Each subsystem
# has a dedicated group of maintainers, which are dedicated to that subsytem and responsible
# for its quality.
# This "cellular division" is the primary mechanism for scaling maintenance of the project as it grows.
#
# The maintainers of each subsytem are responsible for:
#
# 1. Exposing a clear road map for improving their subsystem.
# 2. Deliver prompt feedback and decisions on pull requests affecting their subsystem.
# 3. Be available to anyone with questions, bug reports, criticism etc.
# on their component. This includes IRC, GitHub requests and the mailing
# list.
# 4. Make sure their subsystem respects the philosophy, design and
# road map of the project.
#
# #### How to review patches to your subsystem
#
# Accepting pull requests:
#
# - If the pull request appears to be ready to merge, give it a `LGTM`, which
# stands for "Looks Good To Me".
# - If the pull request has some small problems that need to be changed, make
# a comment adressing the issues.
# - If the changes needed to a PR are small, you can add a "LGTM once the
# following comments are adressed..." this will reduce needless back and
# forth.
# - If the PR only needs a few changes before being merged, any MAINTAINER can
# make a replacement PR that incorporates the existing commits and fixes the
# problems before a fast track merge.
#
# Closing pull requests:
#
# - If a PR appears to be abandoned, after having attempted to contact the
# original contributor, then a replacement PR may be made. Once the
# replacement PR is made, any contributor may close the original one.
# - If you are not sure if the pull request implements a good feature or you
# do not understand the purpose of the PR, ask the contributor to provide
# more documentation. If the contributor is not able to adequately explain
# the purpose of the PR, the PR may be closed by any MAINTAINER.
# - If a MAINTAINER feels that the pull request is sufficiently architecturally
# flawed, or if the pull request needs significantly more design discussion
# before being considered, the MAINTAINER should close the pull request with
# a short explanation of what discussion still needs to be had. It is
# important not to leave such pull requests open, as this will waste both the
# MAINTAINER's time and the contributor's time. It is not good to string a
# contributor on for weeks or months, having them make many changes to a PR
# that will eventually be rejected.
[Org.Subsystems.Documentation]
people = [
"fredlf",
"james",
"sven",
]
[Org.Subsystems.libcontainer]
people = [
"crosbymichael",
"vmarmol",
"mpatel",
"jnagal",
"lk4d4"
]
[Org.Subsystems.registry]
people = [
"dmp42",
"vbatts",
"joffrey",
"samalba"
]
[Org.Subsystems."build tools"]
people = [
"shykes",
"tianon"
]
[Org.Subsystem."remote api"]
people = [
"vieux"
]
[Org.Subsystem.swarm]
people = [
"aluzzardi",
"vieux"
]
[Org.Subsystem.machine]
people = [
"bfirsh",
"ehazlett"
]
[Org.Subsystem.compose]
people = [
"aanand"
]
[Org.Subsystem.builder]
people = [
"erikh",
"tibor",
"duglin"
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.aanand]
Name = "Aanand Prasad"
Email = "aanand@docker.com"
GitHub = "aanand"
[people.aluzzardi]
Name = "Andrea Luzzardi"
Email = "aluzzardi@docker.com"
GitHub = "aluzzardi"
[people.bfirsh]
Name = "Ben Firshman"
Email = "ben@firshman.co.uk"
GitHub = "bfirsh"
[people.crosbymichael]
Name = "Michael Crosby"
Email = "crosbymichael@gmail.com"
GitHub = "crosbymichael"
[people.duglin]
Name = "Doug Davis"
Email = "dug@us.ibm.com"
GitHub = "duglin"
[people.ehazlett]
Name = "Evan Hazlett"
Email = "ejhazlett@gmail.com"
GitHub = "ehazlett"
[people.erikh]
Name = "Erik Hollensbe"
Email = "erik@docker.com"
GitHub = "erikh"
[people.erw]
Name = "Eric Windisch"
Email = "eric@windisch.us"
GitHub = "ewindisch"
[people.icecrime]
Name = "Arnaud Porterie"
Email = "arnaud@docker.com"
GitHub = "icecrime"
[people.jfrazelle]
Name = "Jessie Frazelle"
Email = "jess@docker.com"
GitHub = "jfrazelle"
[people.lk4d4]
Name = "Alexander Morozov"
Email = "lk4d4@docker.com"
GitHub = "lk4d4"
[people.shykes]
Name = "Solomon Hykes"
Email = "solomon@docker.com"
GitHub = "shykes"
[people.spf13]
Name = "Steve Francia"
Email = "steve.francia@gmail.com"
GitHub = "spf13"
[people.sven]
Name = "Sven Dowideit"
Email = "SvenDowideit@home.org.au"
GitHub = "SvenDowideit"
[people.tianon]
Name = "Tianon Gravi"
Email = "admwiggin@gmail.com"
GitHub = "tianon"
[people.tibor]
Name = "Tibor Vass"
Email = "tibor@docker.com"
GitHub = "tiborvass"
[people.vbatts]
Name = "Vincent Batts"
Email = "vbatts@redhat.com"
GitHub = "vbatts"
[people.vieux]
Name = "Victor Vieux"
Email = "vieux@docker.com"
GitHub = "vieux"
[people.vmarmol]
Name = "Victor Marmol"
Email = "vmarmol@google.com"
GitHub = "vmarmol"
[people.jnagal]
Name = "Rohit Jnagal"
Email = "jnagal@google.com"
GitHub = "rjnagal"
[people.mpatel]
Name = "Mrunal Patel"
Email = "mpatel@redhat.com"
GitHub = "mrunalp"
[people.unclejack]
Name = "Cristian Staretu"
Email = "cristian.staretu@gmail.com"
GitHub = "unclejack"
[people.vish]
Name = "Vishnu Kannan"
Email = "vishnuk@google.com"
GitHub = "vishh"
+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
+8
View File
@@ -195,6 +195,14 @@ Don't know how to use that super cool new feature in the master build? Check
out the master docs at
[docs.master.dockerproject.com](http://docs.master.dockerproject.com).
How the project is run
======================
Docker is a very, very active project. If you want to learn more about how it is run,
or want to get more involved, the best place to start is [the project directory](https://github.com/docker/docker/tree/master/project).
We are always open to suggestions on process improvements, and are always looking for more maintainers.
### Legal
*Brought to you courtesy of our legal counsel. For more context,
+1 -1
View File
@@ -1 +1 @@
1.4.1-dev
1.5.0
+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 -1
View File
@@ -201,7 +201,7 @@ Here is the list of supported options:
Enables or disables the use of blkdiscard when removing
devicemapper devices. This is enabled by default (only) if using
loopback devices and is required to res-parsify the loopback file
loopback devices and is required to resparsify the loopback file
on image/container removal.
Disabling this on loopback can lead to *much* faster container
-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 {
+12 -12
View File
@@ -64,23 +64,23 @@ CMD ["mkdocs", "serve"]
# Sven plans to move each Dockerfile into the respective repository
# Docker Swarm
ADD https://raw.githubusercontent.com/docker/swarm/master/logo.png /docs/sources/swarm/logo.png
ADD https://raw.githubusercontent.com/docker/swarm/master/README.md /docs/sources/swarm/README.md
ADD https://raw.githubusercontent.com/docker/swarm/master/discovery/README.md /docs/sources/swarm/discovery.md
ADD https://raw.githubusercontent.com/docker/swarm/master/api/README.md /docs/sources/swarm/API.md
ADD https://raw.githubusercontent.com/docker/swarm/master/scheduler/filter/README.md /docs/sources/swarm/filters.md
#ADD https://raw.githubusercontent.com/docker/swarm/master/userguide.md /docs/sources/swarm/README.md
#ADD https://raw.githubusercontent.com/docker/swarm/master/discovery/README.md /docs/sources/swarm/discovery.md
#ADD https://raw.githubusercontent.com/docker/swarm/master/api/README.md /docs/sources/swarm/API.md
#ADD https://raw.githubusercontent.com/docker/swarm/master/scheduler/filter/README.md /docs/sources/swarm/scheduler/filter.md
#ADD https://raw.githubusercontent.com/docker/swarm/master/scheduler/strategy/README.md /docs/sources/swarm/scheduler/strategy.md
# Docker Machine
ADD https://raw.githubusercontent.com/docker/machine/master/docs/dockermachine.md /docs/sources/machine/userguide.md
# ADD https://raw.githubusercontent.com/docker/machine/master/docs/dockermachine.md /docs/sources/machine/userguide.md
# Docker Compose
ADD https://raw.githubusercontent.com/docker/fig/master/docs/index.md /docs/sources/compose/userguide.md
ADD https://raw.githubusercontent.com/docker/fig/master/docs/install.md /docs/sources/compose/install.md
ADD https://raw.githubusercontent.com/docker/fig/master/docs/cli.md /docs/sources/compose/cli.md
ADD https://raw.githubusercontent.com/docker/fig/master/docs/yml.md /docs/sources/compose/yml.md
# ADD https://raw.githubusercontent.com/docker/fig/master/docs/index.md /docs/sources/compose/userguide.md
# ADD https://raw.githubusercontent.com/docker/fig/master/docs/install.md /docs/sources/compose/install.md
# ADD https://raw.githubusercontent.com/docker/fig/master/docs/cli.md /docs/sources/compose/cli.md
# ADD https://raw.githubusercontent.com/docker/fig/master/docs/yml.md /docs/sources/compose/yml.md
# add the project docs from the `mkdocs-<project>.yml` files
RUN cd /docs && ./build.sh
# RUN cd /docs && ./build.sh
# remove `^---*` lines from md's
RUN cd /docs/sources && find . -name "*.md" | xargs sed -i~ -n '/^---*/!p'
# RUN cd /docs/sources && find . -name "*.md" | xargs sed -i~ -n '/^---*/!p'
+4 -2
View File
@@ -89,8 +89,10 @@ you need to access the AWS bucket you'll be deploying to.
The release script will create an s3 if needed, and will then push the files to it.
[profile dowideit-docs] aws_access_key_id = IHOIUAHSIDH234rwf....
aws_secret_access_key = OIUYSADJHLKUHQWIUHE...... region = ap-southeast-2
[profile dowideit-docs]
aws_access_key_id = IHOIUAHSIDH234rwf....
aws_secret_access_key = OIUYSADJHLKUHQWIUHE......
region = ap-southeast-2
The `profile` name must be the same as the name of the bucket you are deploying
to - which you call from the `docker` directory:
+2 -2
View File
@@ -138,7 +138,7 @@ or
whitespace.
The ADD instruction copies new files, directories
or remote file URLs to the filesystem of the container at path <dest>.
Mutliple <src> resources may be specified but if they are files or directories
Multiple <src> resources may be specified but if they are files or directories
then they must be relative to the source directory that is being built
(the context of the build). The <dest> is the absolute path, or path relative
to `WORKDIR`, into which the source is copied inside the target container.
@@ -195,7 +195,7 @@ or
**WORKDIR**
-- **WORKDIR /path/to/workdir**
The WORKDIR instruction sets the working directory for the **RUN**, **CMD**, and **ENTRYPOINT** Dockerfile commands that follow it.
The WORKDIR instruction sets the working directory for the **RUN**, **CMD**, **ENTRYPOINT**, **COPY** and **ADD** Dockerfile commands that follow it.
It can be used multiple times in a single Dockerfile. Relative paths are defined relative to the path of the previous **WORKDIR** instruction. For example:
**WORKDIR /a WORKDIR b WORKDIR c RUN pwd**
In the above example, the output of the **pwd** command is **a/b/c**.
-37
View File
@@ -5,43 +5,6 @@ This directory contains the Docker user manual in the Markdown format.
Do *not* edit the man pages in the man1 directory. Instead, amend the
Markdown (*.md) files.
# File List
docker.md
docker-attach.md
docker-build.md
docker-commit.md
docker-cp.md
docker-diff.md
docker-events.md
docker-export.md
docker-history.md
docker-images.md
docker-import.md
docker-info.md
docker-inspect.md
docker-kill.md
docker-load.md
docker-login.md
docker-logs.md
docker-port.md
docker-ps.md
docker-pull.md
docker-push.md
docker-restart.md
docker-rmi.md
docker-rm.md
docker-run.md
docker-save.md
docker-search.md
docker-start.md
docker-stop.md
docker-tag.md
docker-top.md
docker-wait.md
Dockerfile
md2man-all.sh
# Generating man pages from the Markdown files
The recommended approach for generating the man pages is via a Docker
+11 -9
View File
@@ -12,17 +12,19 @@ docker-attach - Attach to a running container
CONTAINER
# DESCRIPTION
If you **docker run** a container in detached mode (**-d**), you can reattach to
the detached container with **docker attach** using the container's ID or name.
The **docker attach** command allows you to attach to a running container using
the container's ID or name, either to view its ongoing output or to control it
interactively. You can attach to the same contained process multiple times
simultaneously, screen sharing style, or quickly view the progress of your
daemonized process.
You can detach from the container again (and leave it running) with `CTRL-p
CTRL-q` (for a quiet exit), or `CTRL-c` which will send a SIGKILL to the
container, or `CTRL-\` to get a stacktrace of the Docker client when it quits.
When you detach from a container the exit code will be returned to
the client.
You can detach from the container (and leave it running) with `CTRL-p CTRL-q`
(for a quiet exit) or `CTRL-c` which will send a `SIGKILL` to the container.
When you are attached to a container, and exit its main process, the process's
exit code will be returned to the client.
It is forbidden to redirect the standard input of a docker attach command while
attaching to a tty-enabled container (i.e.: launched with -t`).
It is forbidden to redirect the standard input of a `docker attach` command while
attaching to a tty-enabled container (i.e.: launched with `-t`).
# OPTIONS
**--help**
+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 .
+13 -13
View File
@@ -45,23 +45,23 @@ After running docker events a container 786d698004576 is started and stopped
(The container name has been shortened in the output below):
# docker events
[2014-04-12 18:23:04 -0400 EDT] 786d69800457: (from whenry/testimage:latest) start
[2014-04-12 18:23:13 -0400 EDT] 786d69800457: (from whenry/testimage:latest) die
[2014-04-12 18:23:13 -0400 EDT] 786d69800457: (from whenry/testimage:latest) stop
2015-01-28T20:21:31.000000000-08:00 59211849bc10: (from whenry/testimage:latest) start
2015-01-28T20:21:31.000000000-08:00 59211849bc10: (from whenry/testimage:latest) die
2015-01-28T20:21:32.000000000-08:00 59211849bc10: (from whenry/testimage:latest) stop
## Listening for events since a given date
Again the output container IDs have been shortened for the purposes of this document:
# docker events --since '2014-04-12'
[2014-04-12 18:11:28 -0400 EDT] c655dbf640dc: (from whenry/testimage:latest) create
[2014-04-12 18:11:28 -0400 EDT] c655dbf640dc: (from whenry/testimage:latest) start
[2014-04-12 18:14:13 -0400 EDT] 786d69800457: (from whenry/testimage:latest) create
[2014-04-12 18:14:13 -0400 EDT] 786d69800457: (from whenry/testimage:latest) start
[2014-04-12 18:22:44 -0400 EDT] 786d69800457: (from whenry/testimage:latest) die
[2014-04-12 18:22:44 -0400 EDT] 786d69800457: (from whenry/testimage:latest) stop
[2014-04-12 18:23:04 -0400 EDT] 786d69800457: (from whenry/testimage:latest) start
[2014-04-12 18:23:13 -0400 EDT] 786d69800457: (from whenry/testimage:latest) die
[2014-04-12 18:23:13 -0400 EDT] 786d69800457: (from whenry/testimage:latest) stop
# docker events --since '2015-01-28'
2015-01-28T20:25:38.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) create
2015-01-28T20:25:38.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) start
2015-01-28T20:25:39.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) create
2015-01-28T20:25:39.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) start
2015-01-28T20:25:40.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) die
2015-01-28T20:25:42.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) stop
2015-01-28T20:25:45.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) start
2015-01-28T20:25:45.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) die
2015-01-28T20:25:46.000000000-08:00 c21f6c22ba27: (from whenry/testimage:latest) stop
# HISTORY
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
+2
View File
@@ -13,6 +13,8 @@ docker-stats - Display a live stream of one or more containers' resource usage s
Display a live stream of one or more containers' resource usage statistics
Note: this functionality currently only works when using the *libcontainer* exec-driver.
# OPTIONS
**--help**
Print usage statement
+1 -1
View File
@@ -277,7 +277,7 @@ is 64K.
#### dm.blkdiscard
Enables or disables the use of blkdiscard when removing devicemapper devices.
This is enabled by default (only) if using loopback devices and is required to
res-parsify the loopback file on image/container removal.
resparsify the loopback file on image/container removal.
Disabling this on loopback can lead to *much* faster container removal times,
but will prevent the space used in `/var/lib/docker` directory from being returned to
+1 -1
View File
@@ -2,4 +2,4 @@
- ['swarm/README.md', 'User Guide', 'Docker Swarm' ]
- ['swarm/discovery.md', 'Reference', 'Swarm discovery']
- ['swarm/API.md', 'Reference', 'Swarm API']
- ['swarm/filters.md', 'Reference', 'Swarm filters']
- ['swarm/scheduler/filter.md', 'Reference', 'Swarm filters']
+10 -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']
@@ -116,11 +121,11 @@ pages:
- ['reference/api/docker_remote_api.md', 'Reference', 'Docker Remote API']
- ['reference/api/docker_remote_api_v1.17.md', 'Reference', 'Docker Remote API v1.17']
- ['reference/api/docker_remote_api_v1.16.md', 'Reference', 'Docker Remote API v1.16']
- ['reference/api/docker_remote_api_v1.15.md', 'Reference', 'Docker Remote API v1.15']
- ['reference/api/docker_remote_api_v1.14.md', 'Reference', 'Docker Remote API v1.14']
- ['reference/api/docker_remote_api_v1.13.md', 'Reference', 'Docker Remote API v1.13']
- ['reference/api/docker_remote_api_v1.12.md', 'Reference', 'Docker Remote API v1.12']
- ['reference/api/docker_remote_api_v1.11.md', 'Reference', 'Docker Remote API v1.11']
- ['reference/api/docker_remote_api_v1.15.md', '**HIDDEN**']
- ['reference/api/docker_remote_api_v1.14.md', '**HIDDEN**']
- ['reference/api/docker_remote_api_v1.13.md', '**HIDDEN**']
- ['reference/api/docker_remote_api_v1.12.md', '**HIDDEN**']
- ['reference/api/docker_remote_api_v1.11.md', '**HIDDEN**']
- ['reference/api/docker_remote_api_v1.10.md', '**HIDDEN**']
- ['reference/api/docker_remote_api_v1.9.md', '**HIDDEN**']
- ['reference/api/docker_remote_api_v1.8.md', '**HIDDEN**']
+1 -1
View File
@@ -45,7 +45,7 @@ Our example is set up like this:
## Creating the client certificates
You will use OpenSSL's `genrsa` and `req` commands to first generate an RSA
key and then use the key to create the certificate request.
key and then use the key to create the certificate.
$ openssl genrsa -out client.key 1024
$ openssl req -new -x509 -text -key client.key -out client.cert
@@ -359,7 +359,7 @@ like `RUN groupadd -r postgres && useradd -r -g postgres postgres`.
> rebuilds. So, if its critical, you should assign an explicit UID/GID.
You should avoid installing or using `sudo` since it has unpredictable TTY and
signal-forwarding behavior that can cause more more problems than it solves. If
signal-forwarding behavior that can cause more problems than it solves. If
you absolutely need functionality similar to `sudo` (e.g., initializing the
daemon as root but running it as non-root), you may be able to use
[“gosu”](https://github.com/tianon/gosu).
+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'
+3 -3
View File
@@ -433,7 +433,7 @@ To assign globally routable IPv6 addresses to your containers you have to
specify an IPv6 subnet to pick the addresses from. Set the IPv6 subnet via the
`--fixed-cidr-v6` parameter when starting Docker daemon:
docker -d --ipv6 --fixed-cidr-v6="2001:db8:0:2:/64"
docker -d --ipv6 --fixed-cidr-v6="2001:db8:0:2::/64"
The subnet for Docker containers should at least have a size of `/80`. This way
an IPv6 address can end with the container's MAC address and you prevent NDP
@@ -443,11 +443,11 @@ With the `--fixed-cidr-v6` parameter set Docker will add a new route to the
routing table. Further IPv6 routing will be enabled (you may prevent this by
starting Docker daemon with `--ip-forward=false`):
$ route -A inet6 add 2001:db8:0:2/64 dev docker0
$ route -A inet6 add 2001:db8:0:2::/64 dev docker0
$ echo 1 > /proc/sys/net/ipv6/conf/default/forwarding
$ echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
All traffic to the subnet `2001:db8:0:2/64` will now be routed
All traffic to the subnet `2001:db8:0:2::/64` will now be routed
via the `docker0` interface.
Be aware that IPv6 forwarding may interfere with your existing IPv6
+1 -1
View File
@@ -38,7 +38,7 @@ For example, if your mirror is serving on `http://10.0.0.2:5000`, you would run:
**NOTE:**
Depending on your local host setup, you may be able to add the
`--registry-mirror` options to the `DOCKER_OPTS` variable in
`/etc/defaults/docker`.
`/etc/default/docker`.
### Step 2: Run the local registry mirror
+1 -1
View File
@@ -59,7 +59,7 @@ In this example, we'll assume that your `docker.service` file looks something li
This will allow us to add extra flags to the `/etc/sysconfig/docker` file by
setting `OPTIONS`:
OPTIONS="--graph /mnt/docker-data --storage btrfs"
OPTIONS="--graph /mnt/docker-data --storage-driver btrfs"
You can also set other environment variables in this file, for example, the
`HTTP_PROXY` environment variables described below.
+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.
+12 -8
View File
@@ -8,7 +8,7 @@ page_keywords: Docker, docker, registry, accounts, plans, Dockerfile, Docker Hub
*Automated Builds* are a special feature of Docker Hub which allow you to
use [Docker Hub's](https://hub.docker.com) build clusters to automatically
create images from a specified `Dockerfile` and a GitHub or Bitbucket repo
create images from a specified `Dockerfile` and a GitHub or Bitbucket repository
(or "context"). The system will clone your repository and build the image
described by the `Dockerfile` using the repository as the context. The
resulting automated image will then be uploaded to the Docker Hub registry
@@ -148,7 +148,7 @@ https://registry.hub.docker.com/associate/bitbucket/).
Then follow the onscreen instructions to authorize and link your
Bitbucket account to Docker Hub. Once it is linked, you'll be able
to choose a repo from which to create the Automatic Build.
to choose a repository from which to create the Automatic Build.
### Creating an Automated Build
@@ -159,7 +159,7 @@ public or private Bitbucket repositories with a `Dockerfile`.
### Adding a Hook
When you link your Docker Hub account, a `POST` hook should get automatically
added to your Bitbucket repo. Follow the steps below to confirm or modify the
added to your Bitbucket repository. Follow the steps below to confirm or modify the
Bitbucket hooks for your Automated Build:
<table class="table table-bordered">
@@ -195,8 +195,8 @@ Bitbucket hooks for your Automated Build:
During the build process, Docker will copy the contents of your `Dockerfile`.
It will also add it to the [Docker Hub](https://hub.docker.com) for the Docker
community (for public repos) or approved team members/orgs (for private repos)
to see on the repository page.
community (for public repositories) or approved team members/orgs (for private
repositories) to see on the repository page.
### README.md
@@ -217,7 +217,7 @@ Automated Build, it will give you a URL to which you can send POST requests.
This will trigger the Automated Build, much as with a GitHub webhook.
Build triggers are available under the Settings menu of each Automated Build
repo on the Docker Hub.
repository on the Docker Hub.
![Build trigger screen](/docker-hub/hub-images/build-trigger.png)
@@ -249,7 +249,11 @@ payload:
{
"callback_url": "https://registry.hub.docker.com/u/svendowideit/testhook/hook/2141b5bi5i5b02bec211i4eeih0242eg11000a/",
"push_data": {
"images": [],
"images": [
"27d47432a69bca5f2700e4dff7de0388ed65f9d3fb1ec645e2bc24c223dc1cc3",
"51a9c7c1f8bb2fa19bcd09789a34e63f35abb80044bc10196e304f6634cc582c",
...
],
"pushed_at": 1.417566161e+09,
"pusher": "trustedbuilder"
},
@@ -336,7 +340,7 @@ another. If one gets updated,the linking system triggers a rebuild
for the other Automated Build. This makes it easy to keep all your
Automated Builds up to date.
To add a link, go to the repo for the Automated Build you want to
To add a link, go to the repository for the Automated Build you want to
link to and click on *Repository Links* under the Settings menu at
right. Then, enter the name of the repository that you want have linked.
+6 -2
View File
@@ -111,7 +111,11 @@ similar to the example shown below.
{
"callback_url": "https://registry.hub.docker.com/u/svendowideit/busybox/hook/2141bc0cdec4hebec411i4c1g40242eg110020/",
"push_data": {
"images": [],
"images": [
"27d47432a69bca5f2700e4dff7de0388ed65f9d3fb1ec645e2bc24c223dc1cc3",
"51a9c7c1f8bb2fa19bcd09789a34e63f35abb80044bc10196e304f6634cc582c",
...
],
"pushed_at": 1.417566822e+09,
"pusher": "svendowideit"
},
@@ -135,7 +139,7 @@ similar to the example shown below.
Webhooks allow you to notify people, services and other applications of
new updates to your images and repositories. To get started adding webhooks,
go to the desired repo in the Hub, and click "Webhooks" under the "Settings"
go to the desired repository in the Hub, and click "Webhooks" under the "Settings"
box.
> **Note:** For testing, you can try an HTTP request tool like
+38 -4
View File
@@ -32,18 +32,52 @@ runtime:
Docker in daemon mode has specific kernel requirements. For details,
check your distribution in [*Installation*](../#installation-list).
In general, a 3.8 Linux kernel is the minimum requirement for Docker, as
some of the prior versions have known issues that are triggered by Docker.
Linux kernel versions older than 3.8 are known to cause kernel panics and
to break Docker.
A 3.10 Linux kernel is the minimum requirement for Docker.
Kernels older than 3.10 lack some of the features required to run Docker
containers. These older versions are known to have bugs which cause data loss
and frequently panic under certain conditions.
The latest minor version (3.x.y) of the 3.10 (or a newer maintained version)
Linux kernel is recommended. Keeping the kernel up to date with the latest
minor version will ensure critical kernel bugs get fixed.
> **Warning**:
> Installing custom kernels and kernel packages is probably not
> supported by your Linux distribution's vendor. Please make sure to
> ask your vendor about Docker support first before attempting to
> install custom kernels on your distribution.
> **Warning**:
> Installing a newer kernel might not be enough for some distributions
> which provide packages which are too old or incompatible with
> newer kernels.
Note that Docker also has a client mode, which can run on virtually any
Linux kernel (it even builds on OS X!).
## Enable AppArmor and SELinux when possible
Please use AppArmor or SELinux if your Linux distribution supports
either of the two. This helps improve security and blocks certain
types of exploits. Your distribution's documentation should provide
detailed steps on how to enable the recommended security mechanism.
Some Linux distributions enable AppArmor or SELinux by default and
they run a kernel which doesn't meet the minimum requirements (3.10
or newer). Updating the kernel to 3.10 or newer on such a system
might not be enough to start Docker and run containers.
Incompatibilities between the version of AppArmor/SELinux user
space utilities provided by the system and the kernel could prevent
Docker from running, from starting containers or, cause containers to
exhibit unexpected behaviour.
> **Warning**:
> If either of the security mechanisms is enabled, it should not be
> disabled to make Docker or its containers run. This will reduce
> security in that environment, lose support from the distribution's
> vendor for the system, and might break regulations and security
> policies in heavily regulated environments.
## Get the docker binary:
$ wget https://get.docker.com/builds/Linux/x86_64/docker-latest -O docker
+51 -48
View File
@@ -4,48 +4,34 @@ page_keywords: Docker, Docker documentation, requirements, linux, centos, epel,
# CentOS
While the Docker package is provided by default as part of CentOS-7,
it is provided by the EPEL repository for CentOS-6. Please note that
this changes the installation instructions slightly between versions. If you
need the latest version, you can always use the latest binary which works on
kernel 3.8 and above.
Docker is supported on the following versions of CentOS:
These instructions work for CentOS 6 and later. They will likely work for
other binary compatible EL6 distributions such as Scientific Linux, but
they haven't been tested.
- [*CentOS 7 (64-bit)*](#installing-docker---centos-7)
- [*CentOS 6.5 (64-bit)*](#installing-docker---centos-6.5) or later
These instructions are likely work for other binary compatible EL6/EL7 distributions
such as Scientific Linux, but they haven't been tested.
Please note that due to the current Docker limitations, Docker is able to
run only on the **64 bit** architecture.
To run Docker, you will need [CentOS6](http://www.centos.org) or higher,
with a kernel version 2.6.32-431 or higher as this has specific kernel
fixes to allow Docker to run.
## Kernel support
Currently the CentOS project will only support Docker when running on kernels
shipped by the distribution. There are kernel changes which will cause issues
if one decides to step outside that box and run non-distribution kernel packages.
To run Docker on [CentOS-6.5](http://www.centos.org) or later, you will need
kernel version 2.6.32-431 or higher as this has specific kernel fixes to allow
Docker to run.
## Installing Docker - CentOS-7
Docker is included by default in the CentOS-Extras repository. To install
simply run the following command.
run the following command:
$ sudo yum install docker
## Kernel support
Currently the CentOS project will only support Docker via the EPEL package when
running on kernels shipped by the distribution. There are things like namespace
changes which will cause issues if one decides to step outside that box and run
non-distro kernel packages.
### Manual installation of latest version
While using a package is the recommended way of installing Docker,
the above package might not be the latest version. If you need the latest
version, [you can install the binary directly](
https://docs.docker.com/installation/binaries/).
When installing the binary without a package, you may want
to integrate Docker with systemd. For this, simply install the two unit files
(service and socket) from [the github
repository](https://github.com/docker/docker/tree/master/contrib/init/systemd)
to `/etc/systemd/system`.
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
### FirewallD
@@ -55,32 +41,49 @@ conflict with Docker.
When `firewalld` is started or restarted it will remove the `DOCKER` chain
from iptables, preventing Docker from working properly.
When using systemd, `firewalld` is started before Docker, but if you
When using Systemd, `firewalld` is started before Docker, but if you
start or restart `firewalld` after Docker, you will have to restart the Docker daemon.
## Installing Docker - CentOS-6
Please note that this for CentOS-6, this package is part of [Extra Packages
for Enterprise Linux (EPEL)](https://fedoraproject.org/wiki/EPEL), a community effort
to create and maintain additional packages for the RHEL distribution.
## Installing Docker - CentOS-6.5
For Centos-6.5, the Docker package is part of [Extra Packages
for Enterprise Linux (EPEL)](https://fedoraproject.org/wiki/EPEL) repository,
a community effort to create and maintain additional packages for the RHEL distribution.
Firstly, you need to ensure you have the EPEL repository enabled. Please
follow the [EPEL installation instructions](
https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F).
The `docker-io` package provides Docker on EPEL.
For CentOS-6, there is a package name conflict with a system tray application
and its executable, so the Docker RPM package was called `docker-io`.
If you already have the (unrelated) `docker` package
installed, it will conflict with `docker-io`.
There's a [bug report](
https://bugzilla.redhat.com/show_bug.cgi?id=1043676) filed for it.
To proceed with `docker-io` installation, please remove `docker` first.
To proceed with `docker-io` installation on CentOS-6, you may need to remove the
`docker` package first.
Next, let's install the `docker-io` package which
will install Docker on our host.
$ sudo yum -y remove docker
Next, let's install the `docker-io` package which will install Docker on our host.
$ sudo yum install docker-io
## Using Docker
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
## Manual installation of latest Docker release
While using a package is the recommended way of installing Docker,
the above package might not be the current release version. If you need the latest
version, [you can install the binary directly](
https://docs.docker.com/installation/binaries/).
When installing the binary without a package, you may want
to integrate Docker with Systemd. For this, install the two unit files
(service and socket) from [the GitHub
repository](https://github.com/docker/docker/tree/master/contrib/init/systemd)
to `/etc/systemd/system`.
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
## Starting the Docker daemon
Once Docker is installed, you will need to start the docker daemon.
@@ -115,13 +118,13 @@ If everything is working properly, you'll get a simple bash prompt. Type
## Custom daemon options
If you need to add an HTTP Proxy, set a different directory or partition for the
Docker runtime files, or make other customizations, read our systemd article to
learn how to [customize your systemd Docker daemon options](/articles/systemd/).
Docker runtime files, or make other customizations, read our Systemd article to
learn how to [customize your Systemd Docker daemon options](/articles/systemd/).
## Dockerfiles
The CentOS Project provides a number of sample Dockerfiles which you may use
either as templates or to familiarize yourself with docker. These templates
are available on github at [https://github.com/CentOS/CentOS-Dockerfiles](
are available on GitHub at [https://github.com/CentOS/CentOS-Dockerfiles](
https://github.com/CentOS/CentOS-Dockerfiles)
**Done!** You can either continue with the [Docker User
+41 -36
View File
@@ -1,41 +1,49 @@
page_title: Installation on Fedora
page_description: Installation instructions for Docker on Fedora.
page_keywords: Docker, Docker documentation, Fedora, requirements, virtualbox, vagrant, git, ssh, putty, cygwin, linux
page_description: Instructions for installing Docker on Fedora.
page_keywords: Docker, Docker documentation, Fedora, requirements, linux
# Fedora
Docker is available in **Fedora 19 and later**. Please note that due to
the current Docker limitations Docker is able to run only on the **64
bit** architecture.
Docker is supported on the following versions of Fedora:
## Installation
- [*Fedora 20 (64-bit)*](#fedora-20-installation)
- [*Fedora 21 and later (64-bit)*](#fedora-21-and-later-installation)
The `docker-io` package provides Docker on Fedora.
Currently the Fedora project will only support Docker when running on kernels
shipped by the distribution. There are kernel changes which will cause issues
if one decides to step outside that box and run non-distribution kernel packages.
If you have the (unrelated) `docker` package installed already, it will
conflict with `docker-io`. There's a [bug
report](https://bugzilla.redhat.com/show_bug.cgi?id=1043676) filed for
it. To proceed with `docker-io` installation on Fedora 19, please remove
`docker` first.
## Fedora 21 and later installation
Install the `docker` package which will install Docker on our host.
$ sudo yum -y install docker
To update the `docker` package:
$ sudo yum -y update docker
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
## Fedora 20 installation
For `Fedora 20`, there is a package name conflict with a system tray application
and its executable, so the Docker RPM package was called `docker-io`.
To proceed with `docker-io` installation on Fedora 20, please remove the `docker`
package first.
$ sudo yum -y remove docker
For Fedora 21 and later, the `wmdocker` package will
provide the same functionality as `docker` and will
also not conflict with `docker-io`.
$ sudo yum -y install wmdocker
$ sudo yum -y remove docker
Install the `docker-io` package which will install
Docker on our host.
$ sudo yum -y install docker-io
To update the `docker-io` package:
To update the `docker` package:
$ sudo yum -y update docker-io
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
## Starting the Docker daemon
Now that it's installed, let's start the Docker daemon.
$ sudo systemctl start docker
@@ -54,24 +62,21 @@ Now let's verify that Docker is working.
## Granting rights to users to use Docker
Fedora 19 and 20 shipped with Docker 0.11. The package has already been updated
to 1.0 in Fedora 20. If you are still using the 0.11 version you will need to
grant rights to users of Docker.
The `docker` command line tool contacts the `docker` daemon process via a
socket file `/var/run/docker.sock` owned by group `docker`. One must be
member of that group in order to contact the `docker -d` process.
socket file `/var/run/docker.sock` owned by `root:root`. Though it's
[recommended](https://lists.projectatomic.io/projectatomic-archives/atomic-devel/2015-January/msg00034.html)
to use `sudo` for docker commands, if users wish to avoid it, an administrator can
create a `docker` group, have it own `/var/run/docker.sock`, and add users to this group.
$ usermod -a -G docker login_name
Adding users to the `docker` group is *not* necessary for Docker versions 1.0
and above.
$ sudo groupadd docker
$ sudo chown root:docker /var/run/docker.sock
$ sudo usermod -a -G docker $USERNAME
## Custom daemon options
If you need to add an HTTP Proxy, set a different directory or partition for the
Docker runtime files, or make other customizations, read our systemd article to
learn how to [customize your systemd Docker daemon options](/articles/systemd/).
Docker runtime files, or make other customizations, read our Systemd article to
learn how to [customize your Systemd Docker daemon options](/articles/systemd/).
## What next?
+48 -26
View File
@@ -1,10 +1,24 @@
page_title: Installation on Red Hat Enterprise Linux
page_description: Installation instructions for Docker on Red Hat Enterprise Linux.
page_keywords: Docker, Docker documentation, requirements, linux, rhel, centos
page_description: Instructions for installing Docker on Red Hat Enterprise Linux.
page_keywords: Docker, Docker documentation, requirements, linux, rhel
# Red Hat Enterprise Linux 7
# Red Hat Enterprise Linux
**Red Hat Enterprise Linux 7** has [shipped with
Docker is supported on the following versions of RHEL:
- [*Red Hat Enterprise Linux 7 (64-bit)*](#red-hat-enterprise-linux-7-installation)
- [*Red Hat Enterprise Linux 6.5 (64-bit)*](#red-hat-enterprise-linux-6.5-installation) or later
## Kernel support
RHEL will only support Docker via the *extras* channel or EPEL package when
running on kernels shipped by the distribution. There are kernel changes which
will cause issues if one decides to step outside that box and run
non-distribution kernel packages.
## Red Hat Enterprise Linux 7 Installation
**Red Hat Enterprise Linux 7 (64 bit)** has [shipped with
Docker](https://access.redhat.com/site/products/red-hat-enterprise-linux/docker-and-containers).
An overview and some guidance can be found in the [Release
Notes](https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/7.0_Release_Notes/chap-Red_Hat_Enterprise_Linux-7.0_Release_Notes-Linux_Containers_with_Docker_Format.html).
@@ -25,51 +39,59 @@ Enterprise Linux 7](https://access.redhat.com/site/articles/881893)
guide, can be found by Red Hat customers on the [Red Hat Customer
Portal](https://access.redhat.com/).
# Red Hat Enterprise Linux 6
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
Docker is available for **RHEL** on EPEL. Please note that
## Red Hat Enterprise Linux 6.5 Installation
You will need **64 bit** [RHEL
6.5](https://access.redhat.com/site/articles/3078#RHEL6) or later, with
a RHEL 6 kernel version 2.6.32-431 or higher as this has specific kernel
fixes to allow Docker to work.
Docker is available for **RHEL6.5** on EPEL. Please note that
this package is part of [Extra Packages for Enterprise Linux
(EPEL)](https://fedoraproject.org/wiki/EPEL), a community effort to
create and maintain additional packages for the RHEL distribution.
Also note that due to the current Docker limitations, Docker is able to
run only on the **64 bit** architecture.
You will need [RHEL
6.5](https://access.redhat.com/site/articles/3078#RHEL6) or higher, with
a RHEL 6 kernel version 2.6.32-431 or higher as this has specific kernel
fixes to allow Docker to work.
## Kernel support
### Kernel support
RHEL will only support Docker via the *extras* channel or EPEL package when
running on kernels shipped by the distribution. There are things like namespace
changes which will cause issues if one decides to step outside that box and run
non-distro kernel packages.
> **Warning**:
> Please keep your system up to date using `yum update` and rebooting
> your system. Keeping your system updated ensures critical security
> vulnerabilities and severe bugs (such as those found in kernel 2.6.32)
> are fixed.
## Installation
Firstly, you need to install the EPEL repository. Please follow the
[EPEL installation
instructions](https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F).
The `docker-io` package provides Docker on EPEL.
There is a package name conflict with a system tray application
and its executable, so the Docker RPM package was called `docker-io`.
If you already have the (unrelated) `docker` package
installed, it will conflict with `docker-io`.
There's a [bug report](
https://bugzilla.redhat.com/show_bug.cgi?id=1043676) filed for it.
To proceed with `docker-io` installation, please remove `docker` first.
To proceed with `docker-io` installation, you may need to remove the
`docker` package first.
Next, let's install the `docker-io` package which
will install Docker on our host.
$ sudo yum -y remove docker
$ sudo yum -y install docker-io
Next, let's install the `docker-io` package which will install Docker on our host.
$ sudo yum install docker-io
To update the `docker-io` package
$ sudo yum -y update docker-io
Please continue with the [Starting the Docker daemon](#starting-the-docker-daemon).
## Starting the Docker daemon
Now that it's installed, let's start the Docker daemon.
$ sudo service docker start
@@ -93,8 +115,8 @@ Continue with the [User Guide](/userguide/).
## Custom daemon options
If you need to add an HTTP Proxy, set a different directory or partition for the
Docker runtime files, or make other customizations, read our systemd article to
learn how to [customize your systemd Docker daemon options](/articles/systemd/).
Docker runtime files, or make other customizations, read our Systemd article to
learn how to [customize your Systemd Docker daemon options](/articles/systemd/).
## Issues?
+22 -10
View File
@@ -80,21 +80,33 @@ To verify that everything has worked as expected:
Which should download the `ubuntu` image, and then start `bash` in a container.
Type `exit` to exit
**Done!**, continue with the [User Guide](/userguide/).
## Ubuntu Precise 12.04 (LTS) (64-bit)
This installation path should work at all times.
### Dependencies
**Linux kernel 3.8**
**Linux kernel 3.13**
Due to a bug in LXC, Docker works best on the 3.8 kernel. Precise comes
with a 3.2 kernel, so we need to upgrade it. The kernel you'll install
when following these steps comes with AUFS built in. We also include the
generic headers to enable packages that depend on them, like ZFS and the
VirtualBox guest additions. If you didn't install the headers for your
"precise" kernel, then you can skip these headers for the "raring"
kernel. But it is safer to include them if you're not sure.
For Ubuntu Precise, the currently recommended kernel version is 3.13.
Ubuntu Precise installations with older kernels must be upgraded. The
kernel you'll install when following these steps has AUFS built in.
We also include the generic headers to enable packages that depend on them,
like ZFS and the VirtualBox guest additions. If you didn't install the
headers for your "precise" kernel, then you can skip these headers for the
"trusty" kernel. If you're unsure, you should include the headers for safety.
> **Warning**:
> Kernels 3.8 and 3.11 are no longer supported by Canonical. Systems
> running these kernels need to be updated using the instructions below.
> Running Docker on these unsupported systems isn't supported either.
> These old kernels are no longer patched for security vulnerabilities
> and severe bugs which lead to data loss.
Please read the installation instructions for backported kernels at
Ubuntu.org to understand why you also need to install the Xorg packages
@@ -104,10 +116,10 @@ each version.
# install the backported kernel
$ sudo apt-get update
$ sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring
$ sudo apt-get install linux-image-generic-lts-trusty linux-headers-generic-lts-trusty
# install the backported kernel and xorg if using Unity/Xorg
$ sudo apt-get install --install-recommends linux-generic-lts-raring xserver-xorg-lts-raring libgl1-mesa-glx-lts-raring
$ sudo apt-get install --install-recommends linux-generic-lts-trusty xserver-xorg-lts-trusty libgl1-mesa-glx-lts-trusty
# reboot
$ sudo reboot
@@ -73,6 +73,8 @@ root filesystem as read only.
**New!**
This endpoint returns a live stream of a container's resource usage statistics.
> **Note**: this functionality currently only works when using the *libcontainer* exec-driver.
## v1.16
@@ -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**:
@@ -1039,6 +1039,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** git or HTTP/HTTPS URI build source
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **rm** - remove intermediate containers after a successful build
@@ -1229,10 +1230,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**:
@@ -1045,6 +1045,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** git or HTTP/HTTPS URI build source
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **rm** - remove intermediate containers after a successful build
@@ -1259,10 +1260,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**:
@@ -1106,6 +1106,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** git or HTTP/HTTPS URI build source
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **rm** - remove intermediate containers after a successful build (default behavior)
@@ -1325,10 +1326,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**:
@@ -1095,6 +1095,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** git or HTTP/HTTPS URI build source
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **rm** - remove intermediate containers after a successful build (default behavior)
@@ -1314,10 +1315,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**:
@@ -1105,6 +1105,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** git or HTTP/HTTPS URI build source
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **rm** - remove intermediate containers after a successful build (default behavior)
@@ -1324,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",
@@ -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**:
@@ -1252,6 +1252,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** git or HTTP/HTTPS URI build source
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **rm** - remove intermediate containers after a successful build (default behavior)
@@ -1471,10 +1472,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**:
@@ -1198,6 +1198,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** git or HTTP/HTTPS URI build source
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **pull** - attempt to pull the image even if an older image exists locally
@@ -1427,10 +1428,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": {}
},
@@ -523,6 +523,8 @@ Status Codes:
This endpoint returns a live stream of a container's resource usage statistics.
> **Note**: this functionality currently only works when using the *libcontainer* exec-driver.
**Example request**:
GET /containers/redis1/stats HTTP/1.1
@@ -1072,6 +1074,7 @@ Query Parameters:
- **dockerfile** - path within the build context to the Dockerfile
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** git or HTTP/HTTPS URI build source
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **pull** - attempt to pull the image even if an older image exists locally
@@ -1096,7 +1099,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 +1143,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 +1169,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 +1193,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 +1592,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:
@@ -898,6 +898,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** build source URI (git or HTTPS/HTTP)
- **q** suppress verbose build output
Status Codes:
@@ -940,6 +940,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** build source URI (git or HTTPS/HTTP)
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
@@ -951,6 +951,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** build source URI (git or HTTPS/HTTP)
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **rm** remove intermediate containers after a successful build
@@ -1049,6 +1049,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** build source URI (git or HTTPS/HTTP)
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
@@ -991,6 +991,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** build source URI (git or HTTPS/HTTP)
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
@@ -1041,6 +1041,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** build source URI (git or HTTPS/HTTP)
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
@@ -1044,6 +1044,7 @@ Query Parameters:
- **t** repository name (and optionally a tag) to be applied to
the resulting image in case of success
- **remote** build source URI (git or HTTPS/HTTP)
- **q** suppress verbose build output
- **nocache** do not use the cache when building the image
- **rm** Remove intermediate containers after a successful build
+9 -9
View File
@@ -113,7 +113,7 @@ was no formal definition on as to which instructions handled environment
replacement at the time. After 1.3 this behavior will be preserved and
canonical.
Environment variables (declared with the `ENV` statement) can also be used in
Environment variables (declared with [the `ENV` statement](#env)) can also be used in
certain instructions as variables to be interpreted by the `Dockerfile`. Escapes
are also handled for including variable-like syntax into a statement literally.
@@ -349,9 +349,8 @@ accessible from the host by default. To expose ports to the host, at runtime,
ENV <key>=<value> ...
The `ENV` instruction sets the environment variable `<key>` to the value
`<value>`. This value will be passed to all future
`RUN`, `ENTRYPOINT`, and `CMD` instructions. This is
functionally equivalent to prefixing the command with `<key>=<value>`
`<value>`. This value will be in the environment of all "descendent" `Dockerfile`
commands and can be [replaced inline](#environment-replacement) in many as well.
The `ENV` instruction has two forms. The first form, `ENV <key> <value>`,
will set a single variable to a value. The entire string after the first
@@ -382,9 +381,10 @@ from the resulting image. You can view the values using `docker inspect`, and
change them using `docker run --env <key>=<value>`.
> **Note**:
> One example where this can cause unexpected consequences, is setting
> `ENV DEBIAN_FRONTEND noninteractive`. Which will persist when the container
> is run interactively; for example: `docker run -t -i image bash`
> Environment persistence can cause unexpected effects. For example,
> setting `ENV DEBIAN_FRONTEND noninteractive` may confuse apt-get
> users on a Debian-based image. To set a value for a single command, use
> `RUN <key>=<value> <command>`.
## ADD
@@ -801,8 +801,8 @@ and for any `RUN`, `CMD` and `ENTRYPOINT` instructions that follow it in the
WORKDIR /path/to/workdir
The `WORKDIR` instruction sets the working directory for any `RUN`, `CMD` and
`ENTRYPOINT` instructions that follow it in the `Dockerfile`.
The `WORKDIR` instruction sets the working directory for any `RUN`, `CMD`,
`ENTRYPOINT`, `COPY` and `ADD` instructions that follow it in the `Dockerfile`.
It can be used multiple times in the one `Dockerfile`. If a relative path
is provided, it will be relative to the path of the previous `WORKDIR`
+65 -34
View File
@@ -32,19 +32,24 @@ To list the help on any command just execute the command, followed by the `--hel
## Option types
Single character commandline options can be combined, so rather than
Single character command line options can be combined, so rather than
typing `docker run -t -i --name test busybox sh`,
you can write `docker run -ti --name test busybox sh`.
### Boolean
Boolean options look like `-d=false`. The value you
see is the default value which gets set if you do **not** use the
boolean flag. If you do call `run -d`, that sets the
opposite boolean value, so in this case, `true`, and
so `docker run -d` **will** run in "detached" mode,
in the background. Other boolean options are similar specifying them
will set the value to the opposite of the default value.
Boolean options take the form `-d=false`. The value you see in the help text is the
default value which is set if you do **not** specify that flag. If you specify
a Boolean flag without a value, this will set the flag to `true`, irrespective
of the default value.
For example, running `docker run -d` will set the value to `true`, so
your container **will** run in "detached" mode, in the background.
Options which default to `true` (e.g., `docker build --rm=true`) can only
be set to the non-default value by explicitly setting them to `false`:
$ docker build --rm=false .
### Multi
@@ -139,7 +144,7 @@ for un-encrypted, and port `2376` for encrypted communication with the daemon.
> for security reasons.
On Systemd based systems, you can communicate with the daemon via
[systemd socket activation](http://0pointer.de/blog/projects/socket-activation.html), use
[Systemd socket activation](http://0pointer.de/blog/projects/socket-activation.html), use
`docker -d -H fd://`. Using `fd://` will work perfectly for most setups but
you can also specify individual sockets: `docker -d -H fd://3`. If the
specified socket activated files aren't found, then Docker will exit. You
@@ -329,7 +334,7 @@ Currently supported options are:
Enables or disables the use of blkdiscard when removing devicemapper
devices. This is enabled by default (only) if using loopback devices and is
required to res-parsify the loopback file on image/container removal.
required to resparsify the loopback file on image/container removal.
Disabling this on loopback can lead to *much* faster container removal
times, but will make the space used in `/var/lib/docker` directory not be
@@ -430,29 +435,24 @@ Docker supports softlinks for the Docker data directory
--no-stdin=false Do not attach STDIN
--sig-proxy=true Proxy all received signals to the process (non-TTY mode only). SIGCHLD, SIGKILL, and SIGSTOP are not proxied.
The `attach` command lets you view or interact with any running container's
primary process (`pid 1`).
The `docker attach` command allows you to attach to a running container using
the container's ID or name, either to view its ongoing output or to control it
interactively. You can attach to the same contained process multiple times
simultaneously, screen sharing style, or quickly view the progress of your
daemonized process.
You can attach to the same contained process multiple times simultaneously, screen
sharing style, or quickly view the progress of your daemonized process.
You can detach from the container (and leave it running) with `CTRL-p CTRL-q`
(for a quiet exit) or `CTRL-c` which will send a `SIGKILL` to the container.
When you are attached to a container, and exit its main process, the process's
exit code will be returned to the client.
> **Note:** This command is not for running a new process in a container.
> See: [`docker exec`](#exec).
You can detach from the container again (and leave it running) with
`CTRL-p CTRL-q` (for a quiet exit), or `CTRL-c` which will send a
SIGKILL to the container, or `CTRL-\` to get a stacktrace of the
Docker client when it quits. When you detach from the container's
process the exit code will be returned to the client.
To stop a container, use `docker stop`.
To kill the container, use `docker kill`.
It is forbidden to redirect the standard input of a `docker attach` command while
attaching to a tty-enabled container (i.e.: launched with `-t`).
#### Examples
$ ID=$(sudo docker run -d ubuntu /usr/bin/top -b)
$ sudo docker attach $ID
$ sudo docker run -d --name topdemo ubuntu /usr/bin/top -b)
$ sudo docker attach topdemo
top - 02:05:52 up 3:05, 0 users, load average: 0.01, 0.02, 0.05
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
@@ -481,7 +481,23 @@ To kill the container, use `docker kill`.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 17208 1144 932 R 0 0.3 0:00.03 top
^C$
$ sudo docker stop $ID
$ echo $?
0
$ docker ps -a | grep topdemo
7998ac8581f9 ubuntu:14.04 "/usr/bin/top -b" 38 seconds ago Exited (0) 21 seconds ago topdemo
And in this second example, you can see the exit code returned by the `bash` process
is returned by the `docker attach` command to its caller too:
$ sudo docker run --name test -d -it debian
275c44472aebd77c926d4527885bb09f2f6db21d878c75f0a1c212c03d3bcfab
$ sudo docker attach test
$$ exit 13
exit
$ echo $?
13
$ sudo docker ps -a | grep test
275c44472aeb debian:7 "/bin/bash" 26 seconds ago Exited (13) 17 seconds ago test
## build
@@ -926,7 +942,7 @@ You'll need two shells for this example.
2014-05-10T17:42:14.999999999Z07:00 7805c1d35632: (from redis:2.8) die
2014-09-03T17:42:14.999999999Z07:00 7805c1d35632: (from redis:2.8) stop
$ sudo docker events --since '2013-09-03 15:49:29 +0200 CEST'
$ sudo docker events --since '2013-09-03T15:49:29'
2014-09-03T15:49:29.999999999Z07:00 4386fb97867d: (from ubuntu-1:14.04) die
2014-05-10T17:42:14.999999999Z07:00 4386fb97867d: (from ubuntu-1:14.04) stop
2014-05-10T17:42:14.999999999Z07:00 7805c1d35632: (from redis:2.8) die
@@ -1430,12 +1446,12 @@ The `docker rename` command allows the container to be renamed to a different na
-s, --size=false Display total file sizes
--since="" Show only containers created since Id or Name, include non-running ones.
Running `docker ps` showing 2 linked containers.
Running `docker ps --no-trunc` showing 2 linked containers.
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c01db0b339c ubuntu:12.04 bash 17 seconds ago Up 16 seconds webapp
d7886598dbe2 crosbymichael/redis:latest /redis-server --dir 33 minutes ago Up 33 minutes 6379/tcp redis,webapp/db
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f7ee772232194fcc088c6bdec6ea09f7b3f6c54d53934658164b8602d7cd4744 ubuntu:12.04 bash 17 seconds ago Up 16 seconds webapp
d0963715a061c7c7b7cc80b2646da913a959fbf13e80a971d4a60f6997a2f595 crosbymichael/redis:latest /redis-server --dir 33 minutes ago Up 33 minutes 6379/tcp redis,webapp/db
`docker ps` will show only running containers by default. To see all containers:
`docker ps -a`
@@ -1659,6 +1675,19 @@ and linking containers.
#### Examples
$ sudo docker run --name test -it debian
$$ exit 13
exit
$ echo $?
13
$ sudo docker ps -a | grep test
275c44472aeb debian:7 "/bin/bash" 26 seconds ago Exited (13) 17 seconds ago test
In this example, we are running `bash` interactively in the `debian:latest` image, and giving
the container the name `test`. We then quit `bash` by running `exit 13`, which means `bash`
will have an exit code of `13`. This is then passed on to the caller of `docker run`, and
is recorded in the `test` container metadata.
$ sudo docker run --cidfile /tmp/docker_test.cid ubuntu echo "test"
This will create a container and print `test` to the console. The `cidfile`
@@ -2012,6 +2041,8 @@ more details on finding shared images from the command line.
--help=false Print usage
> **Note**: this functionality currently only works when using the *libcontainer* exec-driver.
Running `docker stats` on multiple containers
$ sudo docker stats redis1 redis2
+38 -65
View File
@@ -2,78 +2,44 @@ page_title: Docker 1.x Series Release Notes
page_description: Release Notes for Docker 1.x.
page_keywords: docker, documentation, about, technology, understanding, release
#Release Notes
# Release Notes
You can view release notes for earlier version of Docker by selecting the
desired version from the drop-down list at the top right of this page.
##Version 1.4.1
(2014-12-17)
This release fixes an issue related to mounting volumes on `create`. Details available in the [Github milestone](https://github.com/docker/docker/issues?q=milestone%3A1.4.1+is%3Aclosed).
## Version 1.5.0
(2015-02-03)
##Version 1.4.0
(2014-12-11)
This release provides a number of new features, but is mainly focused on bug
fixes and improvements to platform stability and security.
For a complete list of patches, fixes, and other improvements, see the
[merge PR on GitHub](https://github.com/docker/docker/pull/10286).
For a complete list of patches, fixes, and other improvements, see the [merge PR on GitHub](https://github.com/docker/docker/pull/9345).
*New Features*
* You can now add labels to the Docker daemon using key=value pairs defined with
the new `--label` flag. The labels are displayed by running `docker info`. In
addition, `docker info` also now returns an ID and hostname field. For more
information, see the
[command line reference](http://docs.docker.com/reference/commandline/cli/#daemon).
* The `ENV` instruction in the `Dockerfile` now supports arguments in the form
of `ENV name=value name2=value2..`. For more information, see the
[command line reference](http://docs.docker.com/reference/builder/#env)
* Introducing a new, still
[experimental, overlayfs storage driver](https://github.com/docker/docker/pull/7619/).
* You can now add filters to `docker events` to filter events by event name,
container, or image. For more information, see the
[command line reference](http://docs.docker.com/reference/commandline/cli/#events).
* The `docker cp` command now supports copying files from the filesystem of a
container's volumes. For more information, see the
[remote API reference](http://docs.docker.com/reference/api/docker_remote_api/).
* The `docker tag` command has been fixed so that it correctly honors `--force`
when overriding a tag for existing image. For more information, see
the [command line reference](http://docs.docker.com/reference/commandline/cli/#tag).
* Container volumes are now initialized during `docker create`. For more information, see
the [command line reference](http://docs.docker.com/reference/commandline/cli/#create).
*Security Fixes*
Patches and changes were made to address the following vulnerabilities:
* CVE-2014-9356: Path traversal during processing of absolute symlinks.
Absolute symlinks were not adequately checked for traversal which created a
vulnerability via image extraction and/or volume mounts.
* CVE-2014-9357: Escalation of privileges during decompression of LZMA (.xz)
archives. Docker 1.3.2 added `chroot` for archive extraction. This created a
vulnerability that could allow malicious images or builds to write files to the
host system and escape containerization, leading to privilege escalation.
* CVE-2014-9358: Path traversal and spoofing opportunities via image
identifiers. Image IDs passed either via `docker load` or registry communications
were not sufficiently validated. This created a vulnerability to path traversal
attacks wherein malicious images or repository spoofing could lead to graph
corruption and manipulation.
> **Note:** the above CVEs are also patched in Docker 1.3.3, which was released
> concurrently with 1.4.0.
*Runtime fixes*
* Fixed an issue that caused image archives to be read slowly.
*Client fixes*
* Fixed a regression related to STDIN redirection.
* Fixed a regression involving `docker cp` when the current directory is the
destination.
* The Docker daemon has now supports for IPv6 networking between containers
and on the `docker0` bridge. For more information see the
[IPv6 networking reference](/articles/networking/#ipv6).
* Docker container filesystems can now be set to`--read-only`, restricting your
container to writing to volumes [PR# 10093](https://github.com/docker/docker/pull/10093).
* A new `docker stats CONTAINERID` command has been added to allow users to view a
continuously updating stream of container resource usage statistics. See the
[`stats` command line reference](/reference/commandline/cli/#stats) and the
[container `stats` API reference](/reference/api/docker_remote_api_v1.17/#get-container-stats-based-on-resource-usage).
**Note**: this feature is only enabled for the `libcontainer` exec-driver at this point.
* Users can now specify the file to use as the `Dockerfile` by running
`docker build -f alternate.dockerfile .`. This will allow the definition of multiple
`Dockerfile`s for a single project. See the [`docker build` command reference](
/reference/commandline/cli/#build) for more information.
* The v1 Open Image specification has been created to document the current Docker image
format and metadata. Please see [the Open Image specification document](
https://github.com/docker/docker/blob/master/image/spec/v1.md) for more details.
* This release also includes a number of significant performance improvements in
build and image management ([PR #9720](https://github.com/docker/docker/pull/9720),
[PR #8827](https://github.com/docker/docker/pull/8827))
* The `docker inspect` command now lists ExecIDs generated for each `docker exec` process.
See [PR #9800](https://github.com/docker/docker/pull/9800)) for more details.
* The `docker inspect` command now shows the number of container restarts when there
is a restart policy ([PR #9621](https://github.com/docker/docker/pull/9621))
* This version of Docker is built using Go 1.4
> **Note:**
> Development history prior to version 1.0 can be found by
@@ -89,4 +55,11 @@ impact on users. This list will be updated as issues are resolved.
An idiosyncrasy in AUFS prevents permissions from propagating predictably
between upper and lower layers. This can cause issues with accessing private
keys, database instances, etc. For complete information and workarounds see
[Github Issue 783](https://github.com/docker/docker/issues/783).
[Github Issue 783](https://github.com/docker/docker/issues/783).
* **Docker Hub incompatible with Safari 8**
Docker Hub has multiple issues displaying on Safari 8, the default browser
for OS X 10.10 (Yosemite). Users should access the hub using a different
browser. Most notably, changes in the way Safari handles cookies means that the
user is repeatedly logged out. For more information, see the [Docker
forum post](https://forums.docker.com/t/new-safari-in-yosemite-issue/300).
+1 -1
View File
@@ -263,7 +263,7 @@ this case we're basing our new image on an Ubuntu 14.04 image.
Next we use the `MAINTAINER` instruction to specify who maintains our new image.
Lastly, we've specified three `RUN` instructions. A `RUN` instruction executes
Lastly, we've specified two `RUN` instructions. A `RUN` instruction executes
a command inside the image, for example installing a package. Here we're
updating our APT cache, installing Ruby and RubyGems and then installing the
Sinatra gem.
+1 -1
View File
@@ -233,7 +233,7 @@ command to list the specified container's environment variables.
> will scrub them when spawning shells for connection.
> **Note**:
> Unlike host entries in the [`/ets/hosts` file](#updating-the-etchosts-file),
> Unlike host entries in the [`/etc/hosts` file](#updating-the-etchosts-file),
> IP addresses stored in the environment variables are not automatically updated
> if the source container is restarted. We recommend using the host entries in
> `/etc/hosts` to resolve the IP address of linked containers.
+2 -2
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`
@@ -115,7 +115,7 @@ it.
Let's create a new named container with a volume to share.
While this container doesn't run an application, it reuses the `training/postgres`
image so that all containers are using layers in common, saveing disk space.
image so that all containers are using layers in common, saving disk space.
$ sudo docker create -v /dbdata --name dbdata training/postgres
+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.
+34 -23
View File
@@ -22,22 +22,39 @@
#leftnav {
height: 100%;
}
#leftnav h3 {
font-size: 10px;
font-weight: 700;
color: #394d54;
line-height: 1;
margin: 10px 0 10px 0;
padding-left: 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#leftnav li.active {
margin-bottom: 10px;
#leftnav .nav ul {
line-height: 1;
margin: 10px 10px 0px 16px;
padding: 0;
list-style: none;
}
#leftnav .nav li ul a,
#leftnav .nav li ul a:hover {
margin: 0 !important;
padding: 0 !important;
font-size: 13px;
font-weight: 400;
color: #394d54;
}
#leftnav .nav li ul a:hover {
color: #24b8eb;
}
#leftnav .nav.nav-tabs li a,
#leftnav .nav.nav-tabs li li {
line-height: 1.1 !important;
}
#leftnav li {
margin-top: 20px;
// text-indent: -16px;
padding-left: 10px;
}
#leftnav .nav-tabs.nav ul li {
margin-top: 5px;
}
.content-body {
@@ -60,6 +77,7 @@ pre {
/* Main Navigation */
#nav_menu > #docsnav {
max-width: 940px;
width: 940px;
margin: 0 auto;
}
#nav_menu > #docsnav > #nav_search {
@@ -112,7 +130,7 @@ pre {
box-sizing: border-box;
}
#nav_menu #docsnav #main-nav > li {
font-size: 14px;
font-size: 15px;
font-weight: 400;
color: #253237;
line-height: 2em;
@@ -177,13 +195,13 @@ pre {
display: block;
}
.dd_menu li a {
font-size: 14px;
font-size: 15px;
font-weight: 400;
color: #005976;
}
.dd_menu li a:hover {
text-decoration: none;
font-size: 14px;
font-size: 15px;
font-weight: 400;
color: #24b8eb;
}
@@ -321,13 +339,6 @@ pre {
font-weight: bold;
}
#leftnav .nav.nav-tabs li a {
line-height: 20px !important;
padding-top: 15px !important;
padding-right: 8px;
padding-bottom: 15px !important;
}
/* Logged-in/out header */
.topmostnav_loggedin {
display: none;
+3 -7
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;
@@ -995,7 +991,7 @@ div + .form-inline {
#leftnav .nav.nav-tabs.nav-stacked > li > a {
border: 0;
}
#leftnav .nav.nav-tabs li.active a {
Killwithfire #leftnav .nav.nav-tabs li.active a {
font-size: 16px;
font-weight: 500;
color: #394d54;
@@ -1005,14 +1001,14 @@ div + .form-inline {
border-left: 10px solid #ade5f9;
padding-left: 9px;
}
#leftnav .nav.nav-tabs li.active a:hover {
Killwithfire #leftnav .nav.nav-tabs li.active a:hover {
font-size: 16px;
font-weight: 500;
color: #24b8eb;
text-decoration: none;
cursor: pointer;
}
#leftnav .nav.nav-tabs li.active a:focus {
Killwithfire #leftnav .nav.nav-tabs li.active a:focus {
outline: none;
}
#leftnav .nav.nav-tabs > li > a {
+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>
+5 -2
View File
@@ -1,8 +1,11 @@
{% for toc_item in toc %}
{% for toc_h2_item in toc_item.children %}
<li class=""><a href="{{ toc_h2_item.url }}">{{ toc_h2_item.title }}</a></li>
<li class=""><a href="{{ toc_h2_item.url }}">{{ toc_h2_item.title }}</a>
<ul>
{% for toc_h3_item in toc_h2_item.children %}
<h3><a href="{{ toc_h3_item.url }}">{{ toc_h3_item.title }}</a></h3>
<li><a href="{{ toc_h3_item.url }}">{{ toc_h3_item.title }}</a></li>
{% endfor %}
</ul>
</li>
{% endfor %}
{% endfor %}
+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")
}
+1 -1
View File
@@ -114,7 +114,7 @@ This specification uses the following terms:
</dd>
</dl>
## Image JSON Schema
## Image JSON Description
Here is an example image JSON file:
@@ -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() {
-147
View File
@@ -1,147 +0,0 @@
# The Docker Maintainer manual
## Introduction
Dear maintainer. Thank you for investing the time and energy to help
make Docker as useful as possible. Maintaining a project is difficult,
sometimes unrewarding work. Sure, you will get to contribute cool
features to the project. But most of your time will be spent reviewing,
cleaning up, documenting, answering questions, and justifying design
decisions - while everyone has all the fun! But remember - the quality
of the maintainers' work is what distinguishes the good projects from
the great. So please be proud of your work, even the unglamourous parts,
and encourage a culture of appreciation and respect for *every* aspect
of improving the project - not just the hot new features.
This document is a manual for maintainers old and new. It explains what
is expected of maintainers, how they should work, and what tools are
available to them.
This is a living document - if you see something out of date or missing,
speak up!
## What is a maintainer's responsibility?
It is every maintainer's responsibility to:
1. Expose a clear road map for improving their component.
2. Deliver prompt feedback and decisions on pull requests.
3. Be available to anyone with questions, bug reports, criticism etc.
on their component. This includes IRC, GitHub requests and the mailing
list.
4. Make sure their component respects the philosophy, design and
road map of the project.
## How are decisions made?
Short answer: with pull requests to the Docker repository.
Docker is an open-source project with an open design philosophy. This
means that the repository is the source of truth for EVERY aspect of the
project, including its philosophy, design, road map, and APIs. *If it's
part of the project, it's in the repo. If it's in the repo, it's part of
the project.*
As a result, all decisions can be expressed as changes to the
repository. An implementation change is a change to the source code. An
API change is a change to the API specification. A philosophy change is
a change to the philosophy manifesto, and so on.
All decisions affecting Docker, big and small, follow the same 3 steps:
* Step 1: Open a pull request. Anyone can do this.
* Step 2: Discuss the pull request. Anyone can do this.
* Step 3: Accept (`LGTM`) or refuse a pull request. The relevant maintainers do
this (see below "Who decides what?")
+ Accepting pull requests
- If the pull request appears to be ready to merge, give it a `LGTM`, which
stands for "Looks Good To Me".
- If the pull request has some small problems that need to be changed, make
a comment adressing the issues.
- If the changes needed to a PR are small, you can add a "LGTM once the
following comments are adressed..." this will reduce needless back and
forth.
- If the PR only needs a few changes before being merged, any MAINTAINER can
make a replacement PR that incorporates the existing commits and fixes the
problems before a fast track merge.
+ Closing pull requests
- If a PR appears to be abandoned, after having attempted to contact the
original contributor, then a replacement PR may be made. Once the
replacement PR is made, any contributor may close the original one.
- If you are not sure if the pull request implements a good feature or you
do not understand the purpose of the PR, ask the contributor to provide
more documentation. If the contributor is not able to adequately explain
the purpose of the PR, the PR may be closed by any MAINTAINER.
- If a MAINTAINER feels that the pull request is sufficiently architecturally
flawed, or if the pull request needs significantly more design discussion
before being considered, the MAINTAINER should close the pull request with
a short explanation of what discussion still needs to be had. It is
important not to leave such pull requests open, as this will waste both the
MAINTAINER's time and the contributor's time. It is not good to string a
contributor on for weeks or months, having them make many changes to a PR
that will eventually be rejected.
## Who decides what?
All decisions are pull requests, and the relevant maintainers make
decisions by accepting or refusing pull requests. Review and acceptance
by anyone is denoted by adding a comment in the pull request: `LGTM`.
However, only currently listed `MAINTAINERS` are counted towards the
required majority.
Docker follows the timeless, highly efficient and totally unfair system
known as [Benevolent dictator for
life](http://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life), with
yours truly, Solomon Hykes, in the role of BDFL. This means that all
decisions are made, by default, by Solomon. Since making every decision
myself would be highly un-scalable, in practice decisions are spread
across multiple maintainers.
The relevant maintainers for a pull request can be worked out in 2 steps:
* Step 1: Determine the subdirectories affected by the pull request. This
might be `src/registry`, `docs/source/api`, or any other part of the repo.
* Step 2: Find the `MAINTAINERS` file which affects this directory. If the
directory itself does not have a `MAINTAINERS` file, work your way up
the repo hierarchy until you find one.
There is also a `hacks/getmaintainers.sh` script that will print out the
maintainers for a specified directory.
### I'm a maintainer, and I'm going on holiday
Please let your co-maintainers and other contributors know by raising a pull
request that comments out your `MAINTAINERS` file entry using a `#`.
### I'm a maintainer. Should I make pull requests too?
Yes. Nobody should ever push to master directly. All changes should be
made through a pull request.
### Helping contributors with the DCO
The [DCO or `Sign your work`](
https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work)
requirement is not intended as a roadblock or speed bump.
Some Docker contributors are not as familiar with `git`, or have used a web based
editor, and thus asking them to `git commit --amend -s` is not the best way forward.
In this case, maintainers can update the commits based on clause (c) of the DCO. The
most trivial way for a contributor to allow the maintainer to do this, is to add
a DCO signature in a Pull Requests's comment, or a maintainer can simply note that
the change is sufficiently trivial that it does not substantivly change the existing
contribution - i.e., a spelling change.
When you add someone's DCO, please also add your own to keep a log.
### Who assigns maintainers?
Solomon has final `LGTM` approval for all pull requests to `MAINTAINERS` files.
### How is this process changed?
Just like everything else: by making a pull request :)
+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)
}
}
}
}