Compare commits

..

170 Commits

Author SHA1 Message Date
Tibor Vass
6b8415bd0e Bump version to v1.10.0
Signed-off-by: Tibor Vass <tibor@docker.com>
2016-02-03 17:31:25 -05:00
Jessica Frazelle
58410c2d77 fix opensuse rpm
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2016-02-03 17:31:25 -05:00
Arnaud Porterie
e7efe99042 Remove unnecessary call to /info
Avoid using the `/info` endpoint in the `login` and `logout` workflows
when the Registry endpoint is overriden by the user through the command
line.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2016-02-03 17:31:25 -05:00
Aaron Lehmann
0438c9bd3a Introduce a client-side version of resolveAuthConfig
This is similar to the version in the registry package, but uses the
daemon's default index (as opposed to the default for the client's
platform) if using the "official index".

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-02-03 17:31:24 -05:00
Arnaud Porterie
08fc87ab80 Enable cross-platforms logout from Registry
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2016-02-03 17:31:24 -05:00
Aaron Lehmann
6708e2305c Revert "Set idle timeouts for HTTP reads and writes in communications with the registry"
This reverts commit 84b2162c1a.

The intent of this commit was to set an idle timeout on a HTTP
connection. If a read took more than 60 seconds to complete, or a write
took more than 60 seconds to complete, the connection would be
considered dead.

This doesn't work properly, because the HTTP internals apparently read
from the connection concurrently while writing. An upload that doesn't
complete in 60 seconds leads to a timeout.

Fixes #19967

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-02-03 17:31:24 -05:00
Florian Maier
fbd96e09c3 Fix formatting in breaking changes doc
Signed-off-by: Florian Maier <contact@marsmenschen.com>
2016-02-03 17:31:24 -05:00
Lei Jitang
6f72190b7d Check nil before set resource.OomKillDisable
Signed-off-by: Lei Jitang <leijitang@huawei.com>
2016-02-03 17:31:24 -05:00
Alessandro Boch
fa0856e0e4 Store endpoint config on network connect to a stopped container
Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-02-03 17:31:24 -05:00
Ben Firshman
a315a5acec Add 1.10 migration docs
Originally from https://blog.docker.com/2016/01/docker-1-10-rc/

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-02-03 16:27:49 -05:00
Victor Vieux
c7725242b9 fix error message on version too low
Signed-off-by: Victor Vieux <vieux@docker.com>
2016-02-03 16:27:49 -05:00
David Calavera
4a6436223e Make sure flat options are not parsed as config structures.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-02-02 15:37:14 -05:00
Arnaud Porterie
4750819a79 Delegation is not experimental
Change wording that described user delegation as an experimental
feature.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2016-02-02 15:17:44 -05:00
Mary Anthony
72bf64601d Changing menu label from Engine > Docker Engine
Signed-off-by: Mary Anthony <mary@docker.com>
2016-02-02 13:46:16 -05:00
Sebastiaan van Stijn
c040d956d3 Add note about legacy links
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2016-02-02 13:46:15 -05:00
Arnaud Porterie
534d69d38a Add doc page for breaking changes
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2016-02-02 13:46:15 -05:00
Madhu Venugopal
7a6536c546 Docs cleanup for networking features added in v1.10
Signed-off-by: Madhu Venugopal <madhu@docker.com>
2016-02-02 13:46:15 -05:00
Sebastiaan van Stijn
1f6c3c72b4 Fix memory-swap description in older API versions
A value of -1 disables the *limit* so enables unlimited swap

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2016-02-02 13:46:15 -05:00
Qiang Huang
8051540de9 Fix comment about swap limit of docker update
The description "set `-1` to disable swap" is wrong, `build`,
`create` and `run` already fixed, we need to fix `update` as well.

Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
2016-02-02 13:46:15 -05:00
Arnaud Porterie
220adb320b Enable cross-platforms login to Registry
Use a daemon-defined Registry URL for `docker login`. This allows a
Windows client interacting with a Linux daemon to properly use the
default Registry endpoint instead of the Windows specific one.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
2016-02-02 13:46:14 -05:00
Kai Qiang Wu(Kennan)
9750ba3494 Correct old virtual size
In new content addressable model, image no longer
have virtual size column, it is now 'size'. So we
need to update related docs about them.

Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
2016-02-02 13:46:14 -05:00
Tibor Vass
6da35a288f Skip Close()-ing stdin on Darwin. The Return.
This was accidentally removed in https://github.com/docker/docker/pull/16289
Now adding it back.

Signed-off-by: Tibor Vass <tibor@docker.com>
2016-02-02 13:46:14 -05:00
Alessandro Boch
b2c04e941b Vendoring libnetwork 0.6.0-rc7
Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-02-02 13:46:14 -05:00
Brian Goff
cd9879744f handle debug mode for clients
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-02-02 13:46:14 -05:00
Joel Wurtz
b3307d9e84 Update docker-php library from stage1
Signed-off-by: Joel Wurtz <joel.wurtz@gmail.com>
2016-02-02 13:46:14 -05:00
Aditi Rajagopal
b03c57a726 Update Instructions for Docker Remote API access
Update the location of cert.pem and key.pem to use within the
~/.docker folder
Resolves: #18778

Signed-off-by: Aditi Rajagopal <arajagopal@us.ibm.com>
2016-02-02 13:46:13 -05:00
Alessandro Boch
9c0c32f701 Vendoring libnetwork 0.6.0-rc6
Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-02-02 13:46:13 -05:00
Weiyang Zhu
5d8585fc4b Fix upgrade command
Signed-off-by: Weiyang Zhu <cnresonant@gmail.com>
2016-02-02 13:46:13 -05:00
Aaron Lehmann
a0861479dc Fix panic on network timeout during push
`Upload` already closes the reader returned by `compress` and the
progressreader passed into it, before returning. But even so, the
io.Copy inside compress' goroutine needs to attempt a read from the
progressreader to notice that it's closed, and this read has a side
effect of outputting a progress message. If this happens after `Upload`
returns, it can result in a write to a closed channel. Change `compress`
to return a channel that allows the caller to wait for its goroutine to
finish before freeing any resources connected to the reader that was
passed to it.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-02-02 13:46:13 -05:00
Vincent Demeester
70326ef54a Add docker-volume-ipfs plugin to the list.
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-02-02 13:46:13 -05:00
Felix Hupfeld
797a92d0b2 Added link to Quobyte's volume plugin.
Signed-off-by: Felix Hupfeld <felix@quobyte.com>
2016-02-02 13:46:13 -05:00
qg
a22c9f551b change 'host:port' to host:port
Signed-off-by: Gang Qiao <qiaohai8866@gmail.com>
2016-02-02 13:46:12 -05:00
Wen Cheng Ma
72eb04e7b2 Change container name to id as actual results
Signed-off-by: Wen Cheng Ma <wenchma@cn.ibm.com>
2016-02-02 13:46:12 -05:00
Prayag Verma
d38ed8e5ac Fix typo
Signed-off-by: Prayag Verma <prayag.verma@gmail.com>
2016-02-02 13:46:12 -05:00
Nigel
c7436a4ff8 Updating for CAS changes and new select a driver section
Adding changes requested by @jamtur01 and wrapping to 80 chars
Adding typo fixes and replacing tabs with 4xspaces
Closes and fixes #19240
Updating with content addressable storage model changes

Signed-off-by: Nigel <nigelpoulton@hotmail.com>
2016-02-02 13:46:12 -05:00
Joffrey F
8230753ebf Update example request for container update in docs.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-02 13:46:12 -05:00
Nishant Totla
c2119a9c00 Adding SystemStatus field for /info endpoint
Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
2016-02-02 13:46:11 -05:00
Tibor Vass
192011e178 vendor engine-api 0.2.3 to add SystemStatus in Info type
Signed-off-by: Tibor Vass <tibor@docker.com>
2016-02-02 13:46:11 -05:00
Jessica Frazelle
0d875a262b update bash completions for push and pull
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2016-02-02 12:20:13 -05:00
John Howard
b6d406fe19 Improvements to ANSI emulation in conemu
Signed-off-by: John Howard <jhoward@microsoft.com>
2016-02-02 12:20:13 -05:00
David Calavera
d37f5ad62e Always prompt for a password when asking for credentials.
There is a weird behavior where we don't ask for a password
when the user you type in the prompt is the same you have configured
in the config file.

This is the source of many frustrations and also a bug.
If the authentication with a registry fails because the password
is incorrect, we won't ask for the password again with the current logic.

With this change, we also stop calling `CmdLogin` directly when
authentication fails. We don't need to parse flags from the cli or
setting up input destriptiors again, like the current behavior is doing.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-02-02 12:20:13 -05:00
David Calavera
dc2f5d0f4b Respond with 401 when there is an unauthorized error from the registry.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-02-02 12:20:13 -05:00
Wen Cheng Ma
79f0588009 docs: document options for default network driver
Fixes issue #18410

Signed-off-by: Wen Cheng Ma <wenchma@cn.ibm.com>
2016-02-02 12:20:12 -05:00
cyli
16ba075162 Include a new version of notary with less verbose INFO+ logging
Signed-off-by: cyli <cyli@twistedmatrix.com>
2016-02-02 12:20:12 -05:00
cyli
a8bf0dad6f Update integration tests with new error messages, and to use different repos per test.
This way we won't encounter any problems with one test using cached data from a different
test.

Signed-off-by: cyli <cyli@twistedmatrix.com>
2016-02-02 12:20:12 -05:00
cyli
63e57bcc22 Re-vendor notary, as well as change jfrazelle/go to docker/go.
Signed-off-by: cyli <cyli@twistedmatrix.com>
2016-02-02 12:20:12 -05:00
Sebastiaan van Stijn
fe8647bc06 Update notary to 1.10-3 in all Dockerfiles
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2016-02-02 12:20:12 -05:00
Jessica Frazelle
66afedbbce way better apparmor docs
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2016-02-02 12:20:11 -05:00
Bryan Boreham
cffaf6725b Improve wording about re-assigning IP addresses
Signed-off-by: Bryan Boreham <bjboreham@gmail.com>
2016-02-02 12:20:11 -05:00
Tomasz Kopczynski
1974ccd122 FAQ: add docker daemon unavailable note
Signed-off-by: Tomasz Kopczynski <tomek@kopczynski.net.pl>
2016-02-02 12:20:11 -05:00
Aaron Lehmann
556314ad14 Set idle timeouts for HTTP reads and writes in communications with the registry
Otherwise, some operations can get stuck indefinitely when the remote
side is unresponsive.

Fixes #12823

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-27 10:29:57 -08:00
Harald Albers
dc41fad580 bash completion for docker ps --filter status=dead
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-27 10:29:56 -08:00
Zhang Wei
ec60923688 Forbid exec a restarting container
Currently if we exec a restarting container, client will fail silently,
and daemon will print error that container can't be found which is not a
very meaningful prompt to user.

This commit will stop user from exec a restarting container and gives
more explicit error message.

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
2016-01-27 10:29:56 -08:00
Pei Su
5dd0e5acb0 fix dead lock in volume store dereference
Signed-off-by: Pei Su <sillyousu@gmail.com>
2016-01-27 10:29:56 -08:00
Harald Albers
b6ea29fad3 Improve bash completion for docker volume ls -f dangling
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-27 10:29:56 -08:00
David Calavera
0f90db8c33 Fix bash completion for docker volume ls --dangling=false.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-01-27 10:29:56 -08:00
David Calavera
823d7ce150 Make volume dangling filter return only used volumes with dangling=false.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-01-27 10:29:56 -08:00
Kai Qiang Wu(Kennan)
0cd60bcf47 Fix volume filter validation
Fixes: #18890
This fix add same filter validation logic as images. We should
add such check to make sure filters work make sense to end-users

Right now, we keep old use 1 as filter, but in long term, it should
be have same interface checking as images, it could be improved in
other patches.

Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
2016-01-27 10:29:55 -08:00
Sebastiaan van Stijn
c9417fac95 Fix docs for tmpfs (pr 19688)
Underlying files are no longer copied to the tmpfs.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2016-01-27 10:29:55 -08:00
Michael Crosby
7d749fbd48 Update libcontainer to 3d8a20bb772defc28c355534d83
Fixes #14203

This bump fixes the issue of having the container's pipes connection
reset by peer because of using the json.Encoder and having a \n added to
the output.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2016-01-27 10:29:55 -08:00
David Calavera
745158f033 Remove cluster storage advertise from reload.
Because libnetwork won't really send container information to the new
storage anyways.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-01-27 10:29:55 -08:00
Michael Crosby
cd5c2575c1 Move tar copy-up for tmpfs mounts
We cannot rely on the tar command for this type of operation because tar
versions, flags, and functionality can very from distro to distro.
Since this is in the container execution path it is not safe to have
this as a dependency from dockers POV where the user cannot change the
fact that docker is adding these pre and post mount commands.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2016-01-27 10:29:55 -08:00
Mary Anthony
828c8ba83d Creating Engine specific menu
Fixing the links
Updating with Seb's comments
Adding weight
Fixing the engine aliases
Updating after Arun pushed
Removing empty file

Signed-off-by: Mary Anthony <mary@docker.com>
2016-01-27 10:29:54 -08:00
Sebastiaan van Stijn
794b2bcc89 Fix remove API order in menu
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2016-01-27 10:29:54 -08:00
Mike Dougherty
7dc109e727 Adjust version string processing for RPM build
This will only trim off the last '-' separated token to be checked for
RC status. This allows including a 'cs#' token in the version string.

Signed-off-by: Mike Dougherty <mike.dougherty@docker.com>
2016-01-27 10:29:54 -08:00
Kai Qiang Wu(Kennan)
dd7b0abc01 Refine the volume mount example
The path here should be absolute, else it would
deem it as volume name.

Also link to release page to contain static binary,
the old link not work, because it is just used to
install docker in os distro, it can not be used
as static binary directly.

Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
2016-01-27 10:29:54 -08:00
Kai Qiang Wu(Kennan)
a145ec47e0 Fix the typo in ps
Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
2016-01-27 10:29:54 -08:00
Morton Fox
8934612d69 cgroups documentation moved
Signed-off-by: Morton Fox <github@qslw.com>
2016-01-27 10:29:54 -08:00
Kai Qiang Wu(Kennan)
f01ff1db7f Fix commit wrong repository example
The old name is invalid in new repository name spec.
So we need to fix them.

Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
2016-01-27 10:29:53 -08:00
Dave Barboza
36809b4726 Fix minor doc grammar issues
Signed-off-by: Dave Barboza <dxbarboza@gmail.com>
2016-01-27 10:29:53 -08:00
Kai Qiang Wu(Kennan)
517628120c Fix the privileged example
Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
2016-01-27 10:29:53 -08:00
Kai Qiang Wu(Kennan)
ea4ee1e4ea Fix ulimit command form
The ulimit is builtin, so we need shell form to execute it.

Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
2016-01-27 10:29:53 -08:00
Tianon Gravi
fdaa6d0c7e Change the way we install from backports in the deb builder (to force deps too)
Also, add "libsystemd-journal-dev" to the explicit list (which is what prompted the change in how we install).

Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
2016-01-27 10:29:53 -08:00
Jana Radhakrishnan
d4497e74f5 Vendoring libnetwork v0.6.0-rc5
- Cleanup stale overlay sandboxes

Fixes #19694

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
2016-01-27 10:29:53 -08:00
Victor Costan
debe687d55 Add missing words in selectadriver.md
Signed-off-by: Victor Costan <costan@gmail.com>
2016-01-27 10:29:52 -08:00
Brian Goff
fcad2d9384 Use imageStore.Children instead of whole the Map
daemon cache was getting the whole image map and then iterating through
it to find children. This information is already stored in the image
store.

Prior to this change building the docker repo with a full cache took 30
seconds.
After it takes between 15 seconds or less (As low as 9 seconds).
This is an improvement on docker 1.9.1 which hovered around 17 seconds.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-27 10:29:52 -08:00
Brian Goff
b04d424bf8 Add note about mount propagation on systemd
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-27 10:29:52 -08:00
Aidan Hobson Sayers
364967e39e Permit OPTIONS request against any url, fixes #19398
Signed-off-by: Aidan Hobson Sayers <aidanhs@cantab.net>
2016-01-27 10:29:52 -08:00
Harald Albers
4632701fe2 bash completion for docker daemon --userns-remap
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-27 10:29:52 -08:00
Madhu Venugopal
59915f15bd Move port-mapping ownership closer to Sandbox (from Endpoint)
https://github.com/docker/libnetwork/pull/810 provides the more complete
solution for moving the Port-mapping ownership away from endpoint and
into Sandbox. But, this PR makes the best use of existing libnetwork
design and get a step closer to the gaol.

Signed-off-by: Madhu Venugopal <madhu@docker.com>
2016-01-26 12:59:00 -08:00
Madhu Venugopal
3b2cbc2325 Vendor libnetwork v0.6.0-rc4
- Add Endpoints() API to Sandbox interface
- Fixes #19677

Signed-off-by: Madhu Venugopal <madhu@docker.com>
2016-01-26 12:59:00 -08:00
Qiang Huang
6934594ae0 Verify cgroup-parent name for systemd cgroup
Fixes: #17126

Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
2016-01-26 12:59:00 -08:00
Aaron Lehmann
a5fc987d2e Remove temporary layer download file on error
Currently, the temporary file storing downloaded layer data is only
removed after a successful download or a digest verification error. A
transport-level error does not cause it to be removed. This is a
regression from 1.9 that could cause disk usage to grow until the Docker
daemon is restarted.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-26 12:59:00 -08:00
David Calavera
c446fd2099 Allow network configuration via daemon config file.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-01-26 12:59:00 -08:00
Tianon Gravi
949255c010 Add a note to /etc/default/docker noting that it does not apply to systemd
Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
2016-01-26 12:58:59 -08:00
Brian Goff
be311fba7b On container rm, don't remove named mountpoints
This makes it so when calling `docker run --rm`, or `docker rm -v`, only
volumes specified without a name, e.g. `docker run -v /foo` instead of
`docker run -v awesome:/foo` are removed.

Note that all volumes are named, some are named by the user, some get a
generated name. This is specifically about how the volume was specified
on `run`, assuming that if the user specified it with a name they expect
it to persist after the container is cleaned up.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-26 12:58:59 -08:00
Alessandro Boch
61943d54aa Save endpoint config only if endpoint creation succeeds
- Currently it is being save upfront...

Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-01-26 12:58:59 -08:00
Brian Goff
08ca18b59d Fix removing mountpoints on container rm fail
Ensure that the the container's mountpoints are cleaned up if the
container is force removed.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-26 12:58:59 -08:00
Madhu Venugopal
46ea20fb18 Vendor libnetwork v0.6.0-rc3
- Fixes docker/docker#19576
- Fixed embedded DNS to listen in TCP as well
- Fixed a race-condition in IPAM to choose non-overlapping subnet for concurrent requests

Signed-off-by: Madhu Venugopal <madhu@docker.com>
2016-01-26 12:58:59 -08:00
Arun Gupta
fe82e7fb2f adding docs for Dockerizing Couchbase service
cleaning up instructions, removing redundant output

Signed-off-by: Arun Gupta <arun.gupta@gmail.com>

adding the latest feedback

Signed-off-by: Arun Gupta <arun.gupta@gmail.com>
2016-01-26 12:58:59 -08:00
Aaron Lehmann
1fd7b0881e Fix watching a released transfer
Things could go wrong if Watch was called after the last existing
watcher was released. The call to Watch would succeed even though it was
not really adding a watcher, and the corresponding call to Release would
close hasWatchers a second time.

The fix for this is twofold:

1. We allow transfers to gain new watchers after the watcher count has
touched zero. This means that the channel returned by Released should
not be closed until all watchers have been released AND the transfer is
no longer tracked by the transfer manager, meaning it won't be possible
for additional calls to Watch to race with closing the channel returned
by Released.

The Transfer interface has a new method called Close so the transfer can
know when the transfer manager no longer references it.

Remove the Cancel method. It's not used and should not be exported.

2. Even though (1) makes it possible to add watchers after all the
previous watchers have been released, we want to avoid doing this in
practice. A transfer that has had all its watchers released is in the
process of being cancelled, and attaching to one of these will never be
the correct behavior. Add a check if a watcher is attaching to a
cancelled transfer.  In this case, wait for the transfer to be removed
from the map and try again. This will ensure correct behavior when a
watcher tries to attach during the race window.

Either (1) or (2) should be sufficient to fix the race involved here,
but the combination is the most correct approach. (1) fixes the
low-level plumbing to be resilient to the race condition, and (2) avoids
using it in a racy way.

Fixes #19606

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-26 12:58:58 -08:00
Alessandro Boch
36efc47844 Reject multiple networks on container creation
Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-01-26 12:58:58 -08:00
Tonis Tiigi
5bb832e024 Fix error message in container creation
Error message was different if image was specified with the full ID.

Fixes #19652

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2016-01-26 12:58:58 -08:00
Brian Goff
fb6eda91c2 Add back compat for volume drivers Get and Ls
Use a back-compat struct to handle listing volumes for volumes we know
about (because, presumably, they are being used by a container) for
volume drivers which don't yet support `List`.

Adds a fall-back for the volume driver `Get` call, which will use
`Create` when the driver returns a `404` for `Get`. The old behavior was
to always use `Create` to get a volume reference.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-26 12:58:58 -08:00
Mary Anthony
3fbb69073f Fixing missing certs article; consolidating security material
Entering comments from reviewers
Updating with Derek's comments
Fixing bad links reported by build

Signed-off-by: Mary Anthony <mary@docker.com>
2016-01-26 12:58:58 -08:00
Steve Durrheimer
41c6bf4fdd Add zsh completion for 'docker cp -L --follow-link'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:57 -08:00
Steve Durrheimer
66e6eff020 Add zsh completion for new 'docker daemon --log-opt syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify' options
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:57 -08:00
Steve Durrheimer
abfe273447 Add zsh completion for new 'docker daemon --cluster-store-opt discovery.heartbeat discovery.ttl kv.path' options
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:57 -08:00
Harald Albers
e68d32f1e7 fix minor bash completion issue on OSX (compopt)
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:57 -08:00
scaleoutsean
29423cb6e9 Add GPFS
Signed-off-by: Sean Lee <seanlee@tw.ibm.com>
2016-01-26 12:58:57 -08:00
Harald Albers
a22b9c5bdf bash completion for syslog over TLS log driver
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:57 -08:00
Harald Albers
f2fb744453 remove zsh completion for docker tag -f
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:56 -08:00
Harald Albers
88d4ce135b bash completion for --cluster-store-opt kv.path discovery.{heartbeat,ttl}
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:56 -08:00
Harald Albers
f292f12f00 bash completion for docker cp --follow-link
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:56 -08:00
Harald Albers
5dc40351af bash completion for docker images -f dangling=false
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:56 -08:00
Jasmine Hegman
e778dc919b Correcting overlay -> bridge driver in run.md
Correcting `overlay` -> `bridge` driver in run.md to match the preceding paragraph.

Signed-off-by: Jasmine Hegman <jasmine@jhegman.com>
2016-01-26 12:58:56 -08:00
Tianon Gravi
7138dedf6a Add pkg-config to our Debian build environment
This is used in `hack/make.sh` for detecting various dependencies such as `libsystemd-journal` -- without this, our packages don't support pulling logs back out of journald. 😢

Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
2016-01-26 12:58:56 -08:00
Doug Davis
09ff96bace Add some helper text for magical ADD
Closes: #15777

Signed-off-by: Doug Davis <dug@us.ibm.com>
2016-01-26 12:58:55 -08:00
Avi Miller
789a10de60 Updated Oracle Linux install documentation to be more accurate.
Signed-off-by: Avi Miller <avi.miller@oracle.com>
2016-01-26 12:58:55 -08:00
Nalin Dahyabhai
3a9ebcb7f7 Add pkg-config to our RPM build environment
While hack/make.sh checks for systemd headers using pkg-config, we
forgot to ensure that they were there in the images that we use for
building binaries for RPM-based distributions.  Add the right packages
to the generate.sh that we use for them, and update the copies of the
generated files that we carry in the source tree.

Notes: Fedora, CentOS, and Oracle Linux put the pkg-config command in
the "pkgconfig" package, while OpenSUSE calls the package "pkg-config".
The systemd-devel package, like systemd, is not in Oracle Linux 6.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2016-01-26 12:58:55 -08:00
Aleksa Sarai
2bc762e6c8 integration-cli: add bad --cgroup-parent tests
To ensure we don't regress on bad --cgroup-parent paths, add some
integration tests that check that the host hasn't toppled (or suddently
started to create files in the host).

Signed-off-by: Aleksa Sarai <asarai@suse.com>
2016-01-26 12:58:55 -08:00
Aleksa Sarai
7fa92c23d5 vendor: *: update libcontainer
This fixes a security vulnerability in Docker, which can cause a DoS
under certain circumstances. This is from the hotfix branch, so the
vendored commit is actually bf899fef451956be4abd63de6d6141d9f9096a02 in
runc master.

Signed-off-by: Aleksa Sarai <asarai@suse.com>
2016-01-26 12:58:55 -08:00
Michael Crosby
187a9a154c Update libcontainer to 47e3f834d73e76bc2a6a585b48d
This adds a fix for the resource struct in the cgroups type and seccomp
IsEnabled function

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2016-01-26 12:58:55 -08:00
Aaron Lehmann
6649716949 Vendor updated distribution package
Another day, another revendor.

This revision of distribution is more tolerant of incorrect Content-Type
headers when fetching manifests.

Fixes #19526

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-26 12:58:54 -08:00
Santhosh Manohar
5e36b8cf81 IT for service/network name with '.', corrected libnetwork flag for DNS
Signed-off-by: Santhosh Manohar <santhosh@docker.com>
2016-01-26 12:58:54 -08:00
Santhosh Manohar
fc7f291b9b Vendor in libnetwork v0.6.0-rc2
Signed-off-by: Santhosh Manohar <santhosh@docker.com>
2016-01-26 12:58:54 -08:00
David Calavera
c62c9636c5 Extract container store from the daemon.
- Generalize in an interface.
- Stop abusing of List for everything.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-01-26 12:58:54 -08:00
Alessandro Boch
56a982afb0 Move ErrUnsupportedNetwork* checks to updateNetworkConfig() func
Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-01-26 12:58:53 -08:00
Stephen Rust
e91c8a9aa0 Allow external volume drivers to host anonymous volumes and copy existing data from image.
Signed-off-by: Stephen Rust <srust@blockbridge.com>
2016-01-26 12:58:53 -08:00
David Calavera
f999cd3d4e Make TLSOptions and LogConfig embedded structs.
That way the configuration file becomes flag, without extra keys.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-01-26 12:58:53 -08:00
David Calavera
231eeca2b0 Verify that the configuration keys in the file are valid.
- Return an error if any of the keys don't match valid flags.
- Fix an issue ignoring merged values as named values.
- Fix tlsverify configuration key.
- Fix bug in mflag to avoid panics when one of the flag set doesn't have any flag.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-01-26 12:58:53 -08:00
David Calavera
ba01d9f9d6 Fix post config verification without flags.
- Set the daemon log level to what's set in the configuration.
- Enable TLS when TLSVerify is enabled.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-01-26 12:58:53 -08:00
Brian Bland
97d84623cf Fixes layer MediaTypes in manifests created from a cross-repository push
Signed-off-by: Brian Bland <brian.bland@docker.com>
2016-01-26 12:58:53 -08:00
Brian Goff
aad22c7801 Bump plugin API version
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-26 12:58:52 -08:00
Anton Polonskiy
233cc865b5 fixed typo
Signed-off-by: Anton Polonskiy <anton.polonskiy@gmail.com>
2016-01-26 12:58:52 -08:00
Aaron Lehmann
d550cf0bee Clarify error message when a .cert file is missing a corresponding key
The daemon uses two similar filename extensions to identify different
kinds of certificates. ".crt" files are interpreted as CA certificates,
and ".cert" files are interprted as client certificates. If a CA
certificate is accidentally given the extension ".cert", it will lead to
the following error message:

    Missing key ca.key for certificate ca.cert

To make this slightly less confusing, clarify the error message with a
note that CA certificates should use the extension ".crt".

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-26 12:58:52 -08:00
Kareem Khazem
5a65aac15c Added dead to docs for docker ps -f status=...
It is possible to invoke `docker ps -f status=dead`, but the
documentation for docker-ps does not mention `dead` as a valid option.
This commit fixes that.

Signed-off-by: Kareem Khazem <karkhaz@karkhaz.com>
2016-01-26 12:58:52 -08:00
Aaron Lehmann
2d678f5120 Don't retry downloads when disk is full
There was already a check that prevented protocol-level fallback in this
situation, but retries within a specific protocol will still happen.
This makes it take a long time for the pull to finally error out.

This fixes slowness in TestDaemonNoSpaceleftOnDeviceError, which used to
take a long time due to the backoff between retry attempts:

PASS: docker_cli_daemon_test.go:1868: DockerDaemonSuite.TestDaemonNoSpaceleftOnDeviceError	5.882s

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-26 12:58:52 -08:00
Derek McGowan
e08cf4fd80 Unwrap URL errors on retry
When authorization errors are returned by the token process the error will be wrapped in url.Error.
In order to check the underlying error for retry this error message should be unwrapped.
Unwrapping this error allows failure to push due to an unauthorized response to keep from retrying, possibly resulting in later 429 responses.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2016-01-26 12:58:52 -08:00
Tonis Tiigi
084a60e8e1 Revert "Copy aufs hardlinks to top layer"
This reverts commit ef05b83417.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2016-01-26 12:58:51 -08:00
Jessica Frazelle
43267aa225 add warning if upgrading via script to migrate
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2016-01-26 12:58:51 -08:00
Harald Albers
1fe410e173 Refactor handling of key specific subcompletions
The currently used idiom for handling key specific subcompletions
did not work here: behind `docker event -f type=network `, the completion
of networks triggered. The expected behaviour is not to complete
anything here.

In order to limit the scope of the corresponding PR, the new idiom is
currently only used in `docker events --filter`.

Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:51 -08:00
Harald Albers
821b40d1ef Support new events in bash completion
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:51 -08:00
Jessica Frazelle
4d331573ff disable install of docker-engine for 1.10, try to get ready for 1.11
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2016-01-26 12:58:51 -08:00
Azat Khuyiyakhmetov
3aa4d3e936 Fixed typo in "/etc/subUid"
Signed-off-by: Azat Khuziyakhmetov <shadow_uz@mail.ru>
2016-01-26 12:58:51 -08:00
Aaron Lehmann
6514690023 Vendor updated distribution
The only changes are https://github.com/docker/distribution/pull/1379
and https://github.com/docker/distribution/pull/1380.

Fixes #19476

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-26 12:58:50 -08:00
Brian Goff
d1043f654c Use fine-grained locks for plugin loading.
This helps ensure that only one thing is trying to intialize a plugin at
once while also keeping the global lock free during initialization.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-26 12:58:50 -08:00
Brian Goff
360d59662f Fix loading of containerized plugins
During daemon startup, all containers are registered before any are
started.
During container registration it was calling out to initialize volumes.
If the volume uses a plugin that is running in a container, this will
cause the restart of that container to fail since the plugin is not yet
running.
This also slowed down daemon startup since volume initialization was
happening sequentially, which can be slow (and is flat out slow since
initialization would fail but take 8 seconds for each volume to do it).

This fix holds off on volume initialization until after containers are
restarted and does the initialization in parallel.

The containers that are restarted will have thier volumes initialized
because they are being started. If any of these containers are using a
plugin they will just keep retrying to reach the plugin (up to the
timeout, which is 8seconds) until the container with the plugin is up
and running.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-26 12:58:50 -08:00
Lei Jitang
326de12d8f Fix #19477, clean up the ports when release network
Signed-off-by: Lei Jitang <leijitang@huawei.com>
2016-01-26 12:58:50 -08:00
Koichi Shiraishi
528ebe6ed1 Add ARG instruction syntax for vim
Signed-off-by: Koichi Shiraishi <k@zchee.io>
2016-01-26 12:58:50 -08:00
Steve Durrheimer
6820877d65 Add zsh completion for 'docker network connect --link'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:50 -08:00
Steve Durrheimer
bea0dca3d4 Add zsh completion for 'docker {network connect, create, run} --ip --ip6'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:49 -08:00
Steve Durrheimer
57833e5fb6 Add zsh completion for 'docker network connect --alias' and 'docker {create, run} --net-alias'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:49 -08:00
Aaron Lehmann
d37f25f0d7 Revert reporting of multiple pull errors
Revert the portions of #17617 that report all errors when a pull
falls back, and go back to just reporting the last error. This was nice
to have, but causes some UX issues because nonexistent images show
additional "unauthorized" errors.

Keep the part of the PR that handled ENOSPC, as this appears to work
even without tracking multiple errors.

Fixes #19419

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-26 12:58:49 -08:00
Brian Goff
77e92cfb13 Don't error out when link name in use.
This preserves old behavior from sqlite links/names.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-26 12:58:49 -08:00
Michael Crosby
3b5b116d43 Move tty set and restore to caller
Fixes #19506

This fixes the issue of errors on create and the tty not being able to
be restored to its previous state because of a race where it was
in the hijack goroutine.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2016-01-26 12:58:49 -08:00
Pei Su
ac382473d9 Fix race condition in execCommandGC
`daemon.execCommandGC`
The daemon object (grep execCommandGC) iterate over a map
(grep execCommands.Commands) in a goroutine.
Lock can't protect concurrency access in this case.
Exec command storage object should return a copy of commands instead.

Signed-off-by: Pei Su <sillyousu@gmail.com>
2016-01-26 12:58:49 -08:00
Wenyu You
64c6593a36 fix a spelling error of 'dnsmasq'
Signed-off-by: Wenyu You <21551128@zju.edu.cn>
2016-01-26 12:58:48 -08:00
Steve Durrheimer
37a51e452a Add zsh completion for 'docker {attach,exec,run,start} --detach-keys'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:48 -08:00
Steve Durrheimer
78ece35f2b Add zsh completion for 'docker network create --ipam-opt' + Reordering for better maintainability
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:48 -08:00
Madhu Venugopal
c2443596bf IT for remote network driver & ungraceful restart
Signed-off-by: Madhu Venugopal <madhu@docker.com>
2016-01-26 12:58:48 -08:00
Madhu Venugopal
c9b16010a6 Vendor libnetwork v0.6.0-rc1
- Fixes docker/docker#19404
- Fixes ungraceful daemon restart issue in systemd with remote
  network plugin (https://github.com/docker/libnetwork/issues/813)

Signed-off-by: Madhu Venugopal <madhu@docker.com>
2016-01-26 12:58:48 -08:00
Aaron Lehmann
98ccb46f3d Vendor updated docker/distribution package
Fixes #19400

Note that this introduces an incompatibility with Docker 1.10-rc1,
because the media type used for schema1 manifests has been corrected in
the upstream distribution code. Docker 1.10-rc1 won't be able to pull
old manifests from Registry 2.3-rc0 and up, but because of this vendor
update, Docker 1.10-rc2 won't have this problem.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
2016-01-26 12:58:48 -08:00
Derek McGowan
c51c1caab7 Add more robust error handling on layer store creation
Add continue when layer fails on store creation
Trim whitespace from layerstore files to keep trailing space from failing a layer load

Fixes #19449

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
2016-01-26 12:58:47 -08:00
Antonio Murdaca
aa8641d504 api: client: build: do not fall through if git isn't installed
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
2016-01-26 12:58:47 -08:00
Jessica Frazelle
e75305e5f3 add send, recv, and x32 so we can install i386 pkgs on amd64
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2016-01-26 12:58:47 -08:00
Santhosh Manohar
3e54117f4a Vendoring miekg/dns @ 75e6e86cc601825c5dbcd4e0c209eab180997cd7
- Fixes the issue of Shutdown() not working, resulting in hung
  goroutines

Signed-off-by: Santhosh Manohar <santhosh@docker.com>
2016-01-26 12:58:47 -08:00
Kai Qiang Wu(Kennan)
ebc02ee93b Fix add host device example
The example is not right in parameter, and also
one command is same as first one, it should be typo
before, we should use 'rw' as example for that.

Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
2016-01-26 12:58:47 -08:00
Madhu Venugopal
f175dc5fb4 nil ptr check for endpointsettings when used with older clients
Signed-off-by: Madhu Venugopal <madhu@docker.com>
2016-01-26 12:58:47 -08:00
Zhang Wei
d9217acb11 bugfix: prevent creating network 'default'
Default is predefined network and is reserved, so we should stop user
from creating network with name `default`

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
2016-01-26 12:58:46 -08:00
Christy Perez
35ca3304ff Move closeNotify to fix panic with newer golang
This is happening now due to improvements in net/http:
99fb19194c

To test, change the go version in the Dockerfile:
-ENV GO_VERSION 1.5.3
+ENV GO_VERSION 1.6beta2

More info here: https://github.com/golang/go/issues/14001

Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com>
2016-01-26 12:58:46 -08:00
Daniel Dao
bfa80edf4b only close LogDriver after LogCopier is done
this prevents the copier from sending messages in the buffer to the closed
driver. If the copied took longer than the timeout to drain the buffer, this
aborts the copier read loop and return back so we can cleanup resources
properly.

Signed-off-by: Daniel Dao <dqminh@cloudflare.com>
2016-01-26 12:58:46 -08:00
Candid Dauth
2af5574795 Set TasksMax in addition to LimitNPROC in systemd service files
systemd sets an additional limit on processes and threads that defaults to 512 when run under Linux >= 4.3.
See more information here: http://unix.stackexchange.com/a/255603/59955

Signed-off-by: Candid Dauth <cdauth@cdauth.eu>
2016-01-26 12:58:46 -08:00
Harald Albers
c78eb02bb1 bash completion for docker network create --internal, --ipam-opt
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:46 -08:00
Harald Albers
91ddf04563 bash completion for container linking and aliasing
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-26 12:58:46 -08:00
Avi Miller
2bffeb8a70 Add missing ? to specfile variable.
Signed-off-by: Avi Miller <avi.miller@oracle.com>
2016-01-26 12:58:45 -08:00
Avi Miller
245b1facb8 Restoring the RPM build process for Oracle Linux 6 and updating the docker-engine.spec
file to require the Unbreakable Enterprise Kernel Release 4 on both Oracle Linux 6
and Oracle Linux 7.

The UEK R4 provides the required kernel functionality for VxLAN support
required by Docker 1.9 and user namespace support required for 1.10+.

The build of Docker on Oracle Linux 6 requires some manipulation of the build
environment so that the CGO compiler uses the UEK R4 headers instead of the old
default kernel headers.

Signed-off-by: Avi Miller <avi.miller@oracle.com>
2016-01-26 12:58:45 -08:00
Steve Durrheimer
0e7fbdd62f Modify zsh completion for connecting/disconnecting non-running containers to networks
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:45 -08:00
Steve Durrheimer
0b8eafefd5 Add zsh completion for 'docker network create --internal'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-26 12:58:45 -08:00
Brian Goff
81cd580d68 Fix panic on starting exec more than once
Issue was caused when exec is tarted, exits, then stated again.
In this case, `Close` is called twice, which closes a channel twice.

Changes execConfig.ExitCode to a pointer so we can test if the it has
been set or not.
This allows us to return early when the exec has already been run.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-01-26 12:58:45 -08:00
1510 changed files with 45099 additions and 90363 deletions

View File

@@ -1,51 +0,0 @@
<!--
If you are reporting a new issue, make sure that we do not have any duplicates
already open. You can ensure this by searching the issue list for this
repository. If there is a duplicate, please close your issue and add a comment
to the existing issue instead.
If you suspect your issue is a bug, please edit your issue description to
include the BUG REPORT INFORMATION shown below. If you fail to provide this
information within 7 days, we cannot debug your issue and will close it. We
will, however, reopen it if you later provide the information.
For more information about reporting issues, see
https://github.com/docker/docker/blob/master/CONTRIBUTING.md#reporting-other-issues
---------------------------------------------------
BUG REPORT INFORMATION
---------------------------------------------------
Use the commands below to provide key information from your environment:
You do NOT have to include this information if this is a FEATURE REQUEST
-->
**Output of `docker version`:**
```
(paste your output here)
```
**Output of `docker info`:**
```
(paste your output here)
```
**Additional environment details (AWS, VirtualBox, physical, etc.):**
**Steps to reproduce the issue:**
1.
2.
3.
**Describe the results you received:**
**Describe the results you expected:**
**Additional information you deem important (e.g. issue happens only occasionally):**

View File

@@ -1,23 +0,0 @@
<!--
Please make sure you've read and understood our contributing guidelines;
https://github.com/docker/docker/blob/master/CONTRIBUTING.md
** Make sure all your commits include a signature generated with `git commit -s` **
For additional information on our contributing process, read our contributing
guide https://docs.docker.com/opensource/code/
If this is a bug fix, make sure your description includes "fixes #xxxx", or
"closes #xxxx"
Please provide the following information:
-->
**- What I did**
**- How I did it**
**- How to verify it**
**- A picture of a cute animal (not mandatory but encouraged)**

11
.gitignore vendored
View File

@@ -7,8 +7,18 @@
*.test
.*.swp
.DS_Store
.bashrc
.dotcloud
.flymake*
.git/
.gopath/
.hg/
.vagrant*
Vagrantfile
a.out
autogen/
bin
build_src
bundles/
docker/docker
dockerversion/version_autogen.go
@@ -24,4 +34,5 @@ docs/changed-files
man/man1
man/man5
man/man8
pyenv
vendor/pkg/

View File

@@ -93,8 +93,7 @@ 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>
<alexl@redhat.com> <alexander.larsson@gmail.com>
Alexander Morozov <lk4d4@docker.com> <lk4d4math@gmail.com>
Alexander Morozov <lk4d4@docker.com>
Alexandr Morozov <lk4d4math@gmail.com>
<git.nivoc@neverbox.com> <kuehnle@online.de>
O.S. Tezer <ostezer@gmail.com>
<ostezer@gmail.com> <ostezer@users.noreply.github.com>
@@ -107,9 +106,7 @@ Roberto G. Hashioka <roberto.hashioka@docker.com> <roberto_hashioka@hotmail.com>
Sridhar Ratnakumar <sridharr@activestate.com>
Sridhar Ratnakumar <sridharr@activestate.com> <github@srid.name>
Liang-Chi Hsieh <viirya@gmail.com>
Aleksa Sarai <asarai@suse.de>
Aleksa Sarai <asarai@suse.de> <asarai@suse.com>
Aleksa Sarai <asarai@suse.de> <cyphar@cyphar.com>
Aleksa Sarai <cyphar@cyphar.com>
Will Weaver <monkey@buildingbananas.com>
Timothy Hobbs <timothyhobbs@seznam.cz>
Nathan LeClaire <nathan.leclaire@docker.com> <nathan.leclaire@gmail.com>
@@ -120,27 +117,24 @@ Nathan LeClaire <nathan.leclaire@docker.com> <nathanleclaire@gmail.com>
<marc@marc-abramowitz.com> <msabramo@gmail.com>
Matthew Heon <mheon@redhat.com> <mheon@mheonlaptop.redhat.com>
<bernat@luffy.cx> <vincent@bernat.im>
<bernat@luffy.cx> <Vincent.Bernat@exoscale.ch>
<p@pwaller.net> <peter@scraperwiki.com>
<andrew.weiss@outlook.com> <andrew.weiss@microsoft.com>
Francisco Carriedo <fcarriedo@gmail.com>
<julienbordellier@gmail.com> <git@julienbordellier.com>
<ahmetb@microsoft.com> <ahmetalpbalkan@gmail.com>
<lk4d4@docker.com> <lk4d4math@gmail.com>
<arnaud.porterie@docker.com> <icecrime@gmail.com>
<baloo@gandi.net> <superbaloo+registrations.github@superbaloo.net>
Brian Goff <cpuguy83@gmail.com>
<cpuguy83@gmail.com> <bgoff@cpuguy83-mbp.home>
<eric@windisch.us> <ewindisch@docker.com>
<ewindisch@docker.com> <eric@windisch.us>
<frank.rosquin+github@gmail.com> <frank.rosquin@gmail.com>
Hollie Teal <hollie@docker.com>
<hollie@docker.com> <hollie.teal@docker.com>
<hollie@docker.com> <hollietealok@users.noreply.github.com>
<huu@prismskylabs.com> <whoshuu@gmail.com>
Jessica Frazelle <jess@mesosphere.com>
Jessica Frazelle <jess@mesosphere.com> <jfrazelle@users.noreply.github.com>
Jessica Frazelle <jess@mesosphere.com> <acidburn@docker.com>
Jessica Frazelle <jess@mesosphere.com> <jess@docker.com>
Jessica Frazelle <jess@mesosphere.com> <princess@docker.com>
Jessica Frazelle <jess@docker.com> Jessie Frazelle <jfrazelle@users.noreply.github.com>
<jess@docker.com> <jfrazelle@users.noreply.github.com>
<konrad.wilhelm.kleine@gmail.com> <kwk@users.noreply.github.com>
<tintypemolly@gmail.com> <tintypemolly@Ohui-MacBook-Pro.local>
<estesp@linux.vnet.ibm.com> <estesp@gmail.com>
@@ -148,8 +142,6 @@ Jessica Frazelle <jess@mesosphere.com> <princess@docker.com>
Thomas LEVEIL <thomasleveil@gmail.com> Thomas LÉVEIL <thomasleveil@users.noreply.github.com>
<oi@truffles.me.uk> <timruffles@googlemail.com>
<Vincent.Bernat@exoscale.ch> <bernat@luffy.cx>
Antonio Murdaca <antonio.murdaca@gmail.com> <amurdaca@redhat.com>
Antonio Murdaca <antonio.murdaca@gmail.com> <runcom@redhat.com>
Antonio Murdaca <antonio.murdaca@gmail.com> <me@runcom.ninja>
Antonio Murdaca <antonio.murdaca@gmail.com> <runcom@linux.com>
Antonio Murdaca <antonio.murdaca@gmail.com> <runcom@users.noreply.github.com>
@@ -159,9 +151,8 @@ Deshi Xiao <dxiao@redhat.com> <xiaods@gmail.com>
Doug Davis <dug@us.ibm.com> <duglin@users.noreply.github.com>
Jacob Atzen <jacob@jacobatzen.dk> <jatzen@gmail.com>
Jeff Nickoloff <jeff.nickoloff@gmail.com> <jeff@allingeek.com>
John Howard (VM) <John.Howard@microsoft.com>
John Howard (VM) <John.Howard@microsoft.com> <john.howard@microsoft.com>
John Howard (VM) <John.Howard@microsoft.com> <jhoward@microsoft.com>
<jess@docker.com> <princess@docker.com>
John Howard (VM) <John.Howard@microsoft.com> John Howard <jhoward@microsoft.com>
Madhu Venugopal <madhu@socketplane.io> <madhu@docker.com>
Mary Anthony <mary.anthony@docker.com> <mary@docker.com>
Mary Anthony <mary.anthony@docker.com> moxiegirl <mary@docker.com>
@@ -178,60 +169,3 @@ bin liu <liubin0329@users.noreply.github.com> <liubin0329@gmail.com>
John Howard (VM) <John.Howard@microsoft.com> jhowardmsft <jhoward@microsoft.com>
Ankush Agarwal <ankushagarwal11@gmail.com> <ankushagarwal@users.noreply.github.com>
Tangi COLIN <tangicolin@gmail.com> tangicolin <tangicolin@gmail.com>
Allen Sun <allen.sun@daocloud.io>
Adrien Gallouët <adrien@gallouet.fr> <angt@users.noreply.github.com>
<aanm90@gmail.com> <martins@noironetworks.com>
Anuj Bahuguna <anujbahuguna.dev@gmail.com>
Anusha Ragunathan <anusha.ragunathan@docker.com> <anusha@docker.com>
Avi Miller <avi.miller@oracle.com> <avi.miller@gmail.com>
Brent Salisbury <brent.salisbury@docker.com> <brent@docker.com>
Chander G <chandergovind@gmail.com>
Chun Chen <ramichen@tencent.com> <chenchun.feed@gmail.com>
Ying Li <cyli@twistedmatrix.com>
Daehyeok Mun <daehyeok@gmail.com> <daehyeok@daehyeok-ui-MacBook-Air.local>
<dqminh@cloudflare.com> <dqminh89@gmail.com>
Daniel, Dao Quang Minh <dqminh@cloudflare.com>
Daniel Nephin <dnephin@docker.com> <dnephin@gmail.com>
Dave Tucker <dt@docker.com> <dave@dtucker.co.uk>
Doug Tangren <d.tangren@gmail.com>
Frederick F. Kautz IV <fkautz@redhat.com> <fkautz@alumni.cmu.edu>
Ben Golub <ben.golub@dotcloud.com>
Harold Cooper <hrldcpr@gmail.com>
hsinko <21551195@zju.edu.cn> <hsinko@users.noreply.github.com>
Josh Hawn <josh.hawn@docker.com> <jlhawn@berkeley.edu>
Justin Cormack <justin.cormack@docker.com>
<justin.cormack@docker.com> <justin.cormack@unikernel.com>
<justin.cormack@docker.com> <justin@specialbusservice.com>
Kamil Domański <kamil@domanski.co>
Lei Jitang <leijitang@huawei.com>
<leijitang@huawei.com> <leijitang@gmail.com>
Linus Heckemann <lheckemann@twig-world.com>
<lheckemann@twig-world.com> <anonymouse2048@gmail.com>
Lynda O'Leary <lyndaoleary29@gmail.com>
<lyndaoleary29@gmail.com> <lyndaoleary@hotmail.com>
Marianna Tessel <mtesselh@gmail.com>
Michael Huettermann <michael@huettermann.net>
Moysés Borges <moysesb@gmail.com>
<moysesb@gmail.com> <moyses.furtado@wplex.com.br>
Nigel Poulton <nigelpoulton@hotmail.com>
Qiang Huang <h.huangqiang@huawei.com>
<h.huangqiang@huawei.com> <qhuang@10.0.2.15>
Boaz Shuster <ripcurld.github@gmail.com>
Shuwei Hao <haosw@cn.ibm.com>
<haosw@cn.ibm.com> <haoshuwei24@gmail.com>
Soshi Katsuta <soshi.katsuta@gmail.com>
<soshi.katsuta@gmail.com> <katsuta_soshi@cyberagent.co.jp>
Stefan Berger <stefanb@linux.vnet.ibm.com>
<stefanb@linux.vnet.ibm.com> <stefanb@us.ibm.com>
Stephen Day <stephen.day@docker.com>
<stephen.day@docker.com> <stevvooe@users.noreply.github.com>
Toli Kuznets <toli@docker.com>
Tristan Carel <tristan@cogniteev.com>
<tristan@cogniteev.com> <tristan.carel@gmail.com>
Vincent Demeester <vincent@sbr.pm>
<vincent@sbr.pm> <vincent+github@demeester.fr>
Vishnu Kannan <vishnuk@google.com>
xlgao-zju <xlgao@zju.edu.cn> xlgao <xlgao@zju.edu.cn>
yuchangchun <yuchangchun1@huawei.com> y00277921 <yuchangchun1@huawei.com>
<zij@case.edu> <zjaffee@us.ibm.com>

461
AUTHORS

File diff suppressed because it is too large Load Diff

View File

@@ -2,273 +2,18 @@
Items starting with `DEPRECATE` are important deprecation notices. For more
information on the list of deprecated flags and APIs please have a look at
https://docs.docker.com/engine/deprecated/ where target removal dates can also
https://docs.docker.com/misc/deprecated/ where target removal dates can also
be found.
## 1.11.0 (2016-04-13)
**IMPORTANT**: With Docker 1.11, a Linux docker installation is now made of 4 binaries (`docker`, [`docker-containerd`](https://github.com/docker/containerd), [`docker-containerd-shim`](https://github.com/docker/containerd) and [`docker-runc`](https://github.com/opencontainers/runc)). If you have scripts relying on docker being a single static binaries, please make sure to update them. Interaction with the daemon stay the same otherwise, the usage of the other binaries should be transparent. A Windows docker installation remains a single binary, `docker.exe`.
### Builder
- Fix a bug where Docker would not used the correct uid/gid when processing the `WORKDIR` command ([#21033](https://github.com/docker/docker/pull/21033))
- Fix a bug where copy operations with userns would not use the proper uid/gid ([#20782](https://github.com/docker/docker/pull/20782), [#21162](https://github.com/docker/docker/pull/21162))
### Client
* Usage of the `:` separator for security option has been deprecated. `=` should be used instead ([#21232](https://github.com/docker/docker/pull/21232))
+ The client user agent is now passed to the registry on `pull`, `build`, `push`, `login` and `search` operations ([#21306](https://github.com/docker/docker/pull/21306), [#21373](https://github.com/docker/docker/pull/21373))
* Allow setting the Domainname and Hostname separately through the API ([#20200](https://github.com/docker/docker/pull/20200))
* Docker info will now warn users if it can not detect the kernel version or the operating system ([#21128](https://github.com/docker/docker/pull/21128))
- Fix an issue where `docker stats --no-stream` output could be all 0s ([#20803](https://github.com/docker/docker/pull/20803))
- Fix a bug where some newly started container would not appear in a running `docker stats` command ([#20792](https://github.com/docker/docker/pull/20792))
* Post processing is no longer enabled for linux-cgo terminals ([#20587](https://github.com/docker/docker/pull/20587))
- Values to `--hostname` are now refused if they do not comply with [RFC1123](https://tools.ietf.org/html/rfc1123) ([#20566](https://github.com/docker/docker/pull/20566))
+ Docker learned how to use a SOCKS proxy ([#20366](https://github.com/docker/docker/pull/20366), [#18373](https://github.com/docker/docker/pull/18373))
+ Docker now supports external credential stores ([#20107](https://github.com/docker/docker/pull/20107))
* `docker ps` now supports displaying the list of volumes mounted inside a container ([#20017](https://github.com/docker/docker/pull/20017))
* `docker info` now also report Docker's root directory location ([#19986](https://github.com/docker/docker/pull/19986))
- Docker now prohibits login in with an empty username (spaces are trimmed) ([#19806](https://github.com/docker/docker/pull/19806))
* Docker events attributes are now sorted by key ([#19761](https://github.com/docker/docker/pull/19761))
* `docker ps` no longer show exported port for stopped containers ([#19483](https://github.com/docker/docker/pull/19483))
- Docker now cleans after itself if a save/export command fails ([#17849](https://github.com/docker/docker/pull/17849))
* Docker load learned how to display a progress bar ([#17329](https://github.com/docker/docker/pull/17329), [#120078](https://github.com/docker/docker/pull/20078))
### Distribution
- Fix a panic that occurred when pulling an images with 0 layers ([#21222](https://github.com/docker/docker/pull/21222))
- Fix a panic that could occur on error while pushing to a registry with a misconfigured token service ([#21212](https://github.com/docker/docker/pull/21212))
+ All first-level delegation roles are now signed when doing a trusted push ([#21046](https://github.com/docker/docker/pull/21046))
+ OAuth support for registries was added ([#20970](https://github.com/docker/docker/pull/20970))
* `docker login` now handles token using the implementation found in [docker/distribution](https://github.com/docker/distribution) ([#20832](https://github.com/docker/docker/pull/20832))
* `docker login` will no longer prompt for an email ([#20565](https://github.com/docker/docker/pull/20565))
* Docker will now fallback to registry V1 if no basic auth credentials are available ([#20241](https://github.com/docker/docker/pull/20241))
* Docker will now try to resume layer download where it left off after a network error/timeout ([#19840](https://github.com/docker/docker/pull/19840))
- Fix generated manifest mediaType when pushing cross-repository ([#19509](https://github.com/docker/docker/pull/19509))
- Fix docker requesting additional push credentials when pulling an image if Content Trust is enabled ([#20382](https://github.com/docker/docker/pull/20382))
### Logging
- Fix a race in the journald log driver ([#21311](https://github.com/docker/docker/pull/21311))
* Docker syslog driver now uses the RFC-5424 format when emitting logs ([#20121](https://github.com/docker/docker/pull/20121))
* Docker GELF log driver now allows to specify the compression algorithm and level via the `gelf-compression-type` and `gelf-compression-level` options ([#19831](https://github.com/docker/docker/pull/19831))
* Docker daemon learned to output uncolorized logs via the `--raw-logs` options ([#19794](https://github.com/docker/docker/pull/19794))
+ Docker, on Windows platform, now includes an ETW (Event Tracing in Windows) logging driver named `etwlogs` ([#19689](https://github.com/docker/docker/pull/19689))
* Journald log driver learned how to handle tags ([#19564](https://github.com/docker/docker/pull/19564))
+ The fluentd log driver learned the following options: `fluentd-address`, `fluentd-buffer-limit`, `fluentd-retry-wait`, `fluentd-max-retries` and `fluentd-async-connect` ([#19439](https://github.com/docker/docker/pull/19439))
+ Docker learned to send log to Google Cloud via the new `gcplogs` logging driver. ([#18766](https://github.com/docker/docker/pull/18766))
### Misc
+ When saving linked images together with `docker save` a subsequent `docker load` will correctly restore their parent/child relationship ([#21385](https://github.com/docker/docker/pull/c))
+ Support for building the Docker cli for OpenBSD was added ([#21325](https://github.com/docker/docker/pull/21325))
+ Labels can now be applied at network, volume and image creation ([#21270](https://github.com/docker/docker/pull/21270))
* The `dockremap` is now created as a system user ([#21266](https://github.com/docker/docker/pull/21266))
- Fix a few response body leaks ([#21258](https://github.com/docker/docker/pull/21258))
- Docker, when run as a service with systemd, will now properly manage its processes cgroups ([#20633](https://github.com/docker/docker/pull/20633))
* Docker info now reports the value of cgroup KernelMemory or emits a warning if it is not supported ([#20863](https://github.com/docker/docker/pull/20863))
* Docker info now also reports the cgroup driver in use ([#20388](https://github.com/docker/docker/pull/20388))
* Docker completion is now available on PowerShell ([#19894](https://github.com/docker/docker/pull/19894))
* `dockerinit` is no more ([#19490](https://github.com/docker/docker/pull/19490),[#19851](https://github.com/docker/docker/pull/19851))
+ Support for building Docker on arm64 was added ([#19013](https://github.com/docker/docker/pull/19013))
+ Experimental support for building docker.exe in a native Windows Docker installation ([#18348](https://github.com/docker/docker/pull/18348))
### Networking
- Fix panic if a node is forcibly removed from the cluster ([#21671](https://github.com/docker/docker/pull/21671))
- Fix "error creating vxlan interface" when starting a container in a Swarm cluster ([#21671](https://github.com/docker/docker/pull/21671))
* `docker network inspect` will now report all endpoints whether they have an active container or not ([#21160](https://github.com/docker/docker/pull/21160))
+ Experimental support for the MacVlan and IPVlan network drivers have been added ([#21122](https://github.com/docker/docker/pull/21122))
* Output of `docker network ls` is now sorted by network name ([#20383](https://github.com/docker/docker/pull/20383))
- Fix a bug where Docker would allow a network to be created with the reserved `default` name ([#19431](https://github.com/docker/docker/pull/19431))
* `docker network inspect` returns whether a network is internal or not ([#19357](https://github.com/docker/docker/pull/19357))
+ Control IPv6 via explicit option when creating a network (`docker network create --ipv6`). This shows up as a new `EnableIPv6` field in `docker network inspect` ([#17513](https://github.com/docker/docker/pull/17513))
* Support for AAAA Records (aka IPv6 Service Discovery) in embedded DNS Server ([#21396](https://github.com/docker/docker/pull/21396))
- Fix to not forward docker domain IPv6 queries to external servers ([#21396](https://github.com/docker/docker/pull/21396))
* Multiple A/AAAA records from embedded DNS Server for DNS Round robin ([#21019](https://github.com/docker/docker/pull/21019))
- Fix endpoint count inconsistency after an ungraceful dameon restart ([#21261](https://github.com/docker/docker/pull/21261))
- Move the ownership of exposed ports and port-mapping options from Endpoint to Sandbox ([#21019](https://github.com/docker/docker/pull/21019))
- Fixed a bug which prevents docker reload when host is configured with ipv6.disable=1 ([#21019](https://github.com/docker/docker/pull/21019))
- Added inbuilt nil IPAM driver ([#21019](https://github.com/docker/docker/pull/21019))
- Fixed bug in iptables.Exists() logic [#21019](https://github.com/docker/docker/pull/21019)
- Fixed a Veth interface leak when using overlay network ([#21019](https://github.com/docker/docker/pull/21019))
- Fixed a bug which prevents docker reload after a network delete during shutdown ([#20214](https://github.com/docker/docker/pull/20214))
- Make sure iptables chains are recreated on firewalld reload ([#20419](https://github.com/docker/docker/pull/20419))
- Allow to pass global datastore during config reload ([#20419](https://github.com/docker/docker/pull/20419))
- For anonymous containers use the alias name for IP to name mapping, ie:DNS PTR record ([#21019](https://github.com/docker/docker/pull/21019))
- Fix a panic when deleting an entry from /etc/hosts file ([#21019](https://github.com/docker/docker/pull/21019))
- Source the forwarded DNS queries from the container net namespace ([#21019](https://github.com/docker/docker/pull/21019))
- Fix to retain the network internal mode config for bridge networks on daemon reload ([#21780] (https://github.com/docker/docker/pull/21780))
- Fix to retain IPAM driver option configs on daemon reload ([#21914] (https://github.com/docker/docker/pull/21914))
### Plugins
- Fix a file descriptor leak that would occur every time plugins were enumerated ([#20686](https://github.com/docker/docker/pull/20686))
- Fix an issue where Authz plugin would corrupt the payload body when faced with a large amount of data ([#20602](https://github.com/docker/docker/pull/20602))
### Runtime
- Fix a panic that could occur when cleanup after a container started with invalid parameters ([#21716](https://github.com/docker/docker/pull/21716))
- Fix a race with event timers stopping early ([#21692](https://github.com/docker/docker/pull/21692))
- Fix race conditions in the layer store, potentially corrupting the map and crashing the process ([#21677](https://github.com/docker/docker/pull/21677))
- Un-deprecate auto-creation of host directories for mounts. This feature was marked deprecated in ([#21666](https://github.com/docker/docker/pull/21666))
Docker 1.9, but was decided to be too much of an backward-incompatible change, so it was decided to keep the feature.
+ It is now possible for containers to share the NET and IPC namespaces when `userns` is enabled ([#21383](https://github.com/docker/docker/pull/21383))
+ `docker inspect <image-id>` will now expose the rootfs layers ([#21370](https://github.com/docker/docker/pull/21370))
+ Docker Windows gained a minimal `top` implementation ([#21354](https://github.com/docker/docker/pull/21354))
* Docker learned to report the faulty exe when a container cannot be started due to its condition ([#21345](https://github.com/docker/docker/pull/21345))
* Docker with device mapper will now refuse to run if `udev sync` is not available ([#21097](https://github.com/docker/docker/pull/21097))
- Fix a bug where Docker would not validate the config file upon configuration reload ([#21089](https://github.com/docker/docker/pull/21089))
- Fix a hang that would happen on attach if initial start was to fail ([#21048](https://github.com/docker/docker/pull/21048))
- Fix an issue where registry service options in the daemon configuration file were not properly taken into account ([#21045](https://github.com/docker/docker/pull/21045))
- Fix a race between the exec and resize operations ([#21022](https://github.com/docker/docker/pull/21022))
- Fix an issue where nanoseconds were not correctly taken in account when filtering Docker events ([#21013](https://github.com/docker/docker/pull/21013))
- Fix the handling of Docker command when passed a 64 bytes id ([#21002](https://github.com/docker/docker/pull/21002))
* Docker will now return a `204` (i.e http.StatusNoContent) code when it successfully deleted a network ([#20977](https://github.com/docker/docker/pull/20977))
- Fix a bug where the daemon would wait indefinitely in case the process it was about to killed had already exited on its own ([#20967](https://github.com/docker/docker/pull/20967)
* The devmapper driver learned the `dm.min_free_space` option. If the mapped device free space reaches the passed value, new device creation will be prohibited. ([#20786](https://github.com/docker/docker/pull/20786))
+ Docker can now prevent processes in container to gain new privileges via the `--security-opt=no-new-privileges` flag ([#20727](https://github.com/docker/docker/pull/20727))
- Starting a container with the `--device` option will now correctly resolves symlinks ([#20684](https://github.com/docker/docker/pull/20684))
+ Docker now relies on [`containerd`](https://github.com/docker/containerd) and [`runc`](https://github.com/opencontainers/runc) to spawn containers. ([#20662](https://github.com/docker/docker/pull/20662))
- Fix docker configuration reloading to only alter value present in the given config file ([#20604](https://github.com/docker/docker/pull/20604))
+ Docker now allows setting a container hostname via the `--hostname` flag when `--net=host` ([#20177](https://github.com/docker/docker/pull/20177))
+ Docker now allows executing privileged container while running with `--userns-remap` if both `--privileged` and the new `--userns=host` flag are specified ([#20111](https://github.com/docker/docker/pull/20111))
- Fix Docker not cleaning up correctly old containers upon restarting after a crash ([#19679](https://github.com/docker/docker/pull/19679))
* Docker will now error out if it doesn't recognize a configuration key within the config file ([#19517](https://github.com/docker/docker/pull/19517))
- Fix container loading, on daemon startup, when they depends on a plugin running within a container ([#19500](https://github.com/docker/docker/pull/19500))
* `docker update` learned how to change a container restart policy ([#19116](https://github.com/docker/docker/pull/19116))
* `docker inspect` now also returns a new `State` field containing the container state in a human readable way (i.e. one of `created`, `restarting`, `running`, `paused`, `exited` or `dead`)([#18966](https://github.com/docker/docker/pull/18966))
+ Docker learned to limit the number of active pids (i.e. processes) within the container via the `pids-limit` flags. NOTE: This requires `CGROUP_PIDS=y` to be in the kernel configuration. ([#18697](https://github.com/docker/docker/pull/18697))
- `docker load` now has a `--quiet` option to suppress the load output ([#20078](https://github.com/docker/docker/pull/20078))
- Fix a bug in neighbor discovery for IPv6 peers ([#20842](https://github.com/docker/docker/pull/20842))
- Fix a panic during cleanup if a container was started with invalid options ([#21802](https://github.com/docker/docker/pull/21802))
- Fix a situation where a container cannot be stopped if the terminal is closed ([#21840](https://github.com/docker/docker/pull/21840))
### Security
* Object with the `pcp_pmcd_t` selinux type were given management access to `/var/lib/docker(/.*)?` ([#21370](https://github.com/docker/docker/pull/21370))
* `restart_syscall`, `copy_file_range`, `mlock2` joined the list of allowed calls in the default seccomp profile ([#21117](https://github.com/docker/docker/pull/21117), [#21262](https://github.com/docker/docker/pull/21262))
* `send`, `recv` and `x32` were added to the list of allowed syscalls and arch in the default seccomp profile ([#19432](https://github.com/docker/docker/pull/19432))
* Docker Content Trust now requests the server to perform snapshot signing ([#21046](https://github.com/docker/docker/pull/21046))
* Support for using YubiKeys for Content Trust signing has been moved out of experimental ([#21591](https://github.com/docker/docker/pull/21591))
### Volumes
* Output of `docker volume ls` is now sorted by volume name ([#20389](https://github.com/docker/docker/pull/20389))
* Local volumes can now accepts options similar to the unix `mount` tool ([#20262](https://github.com/docker/docker/pull/20262))
- Fix an issue where one letter directory name could not be used as source for volumes ([#21106](https://github.com/docker/docker/pull/21106))
+ `docker run -v` now accepts a new flag `nocopy`. This tell the runtime not to copy the container path content into the volume (which is the default behavior) ([#21223](https://github.com/docker/docker/pull/21223))
## 1.10.3 (2016-03-10)
### Runtime
- Fix Docker client exiting with an "Unrecognized input header" error [#20706](https://github.com/docker/docker/pull/20706)
- Fix Docker exiting if Exec is started with both `AttachStdin` and `Detach` [#20647](https://github.com/docker/docker/pull/20647)
### Distribution
- Fix a crash when pushing multiple images sharing the same layers to the same repository in parallel [#20831](https://github.com/docker/docker/pull/20831)
- Fix a panic when pushing images to a registry which uses a misconfigured token service [#21030](https://github.com/docker/docker/pull/21030)
### Plugin system
- Fix issue preventing volume plugins to start when SELinux is enabled [#20834](https://github.com/docker/docker/pull/20834)
- Prevent Docker from exiting if a volume plugin returns a null response for Get requests [#20682](https://github.com/docker/docker/pull/20682)
- Fix plugin system leaking file descriptors if a plugin has an error [#20680](https://github.com/docker/docker/pull/20680)
### Security
- Fix linux32 emulation to fail during docker build [#20672](https://github.com/docker/docker/pull/20672)
It was due to the `personality` syscall being blocked by the default seccomp profile.
- Fix Oracle XE 10g failing to start in a container [#20981](https://github.com/docker/docker/pull/20981)
It was due to the `ipc` syscall being blocked by the default seccomp profile.
- Fix user namespaces not working on Linux From Scratch [#20685](https://github.com/docker/docker/pull/20685)
- Fix issue preventing daemon to start if userns is enabled and the `subuid` or `subgid` files contain comments [#20725](https://github.com/docker/docker/pull/20725)
## 1.10.2 (2016-02-22)
### Runtime
- Prevent systemd from deleting containers' cgroups when its configuration is reloaded [#20518](https://github.com/docker/docker/pull/20518)
- Fix SELinux issues by disregarding `--read-only` when mounting `/dev/mqueue` [#20333](https://github.com/docker/docker/pull/20333)
- Fix chown permissions used during `docker cp` when userns is used [#20446](https://github.com/docker/docker/pull/20446)
- Fix configuration loading issue with all booleans defaulting to `true` [#20471](https://github.com/docker/docker/pull/20471)
- Fix occasional panic with `docker logs -f` [#20522](https://github.com/docker/docker/pull/20522)
### Distribution
- Keep layer reference if deletion failed to avoid a badly inconsistent state [#20513](https://github.com/docker/docker/pull/20513)
- Handle gracefully a corner case when canceling migration [#20372](https://github.com/docker/docker/pull/20372)
- Fix docker import on compressed data [#20367](https://github.com/docker/docker/pull/20367)
- Fix tar-split files corruption during migration that later cause docker push and docker save to fail [#20458](https://github.com/docker/docker/pull/20458)
### Networking
- Fix daemon crash if embedded DNS is sent garbage [#20510](https://github.com/docker/docker/pull/20510)
### Volumes
- Fix issue with multiple volume references with same name [#20381](https://github.com/docker/docker/pull/20381)
### Security
- Fix potential cache corruption and delegation conflict issues [#20523](https://github.com/docker/docker/pull/20523)
## 1.10.1 (2016-02-11)
### Runtime
* Do not stop daemon on migration hard failure [#20156](https://github.com/docker/docker/pull/20156)
- Fix various issues with migration to content-addressable images [#20058](https://github.com/docker/docker/pull/20058)
- Fix ZFS permission bug with user namespaces [#20045](https://github.com/docker/docker/pull/20045)
- Do not leak /dev/mqueue from the host to all containers, keep it container-specific [#19876](https://github.com/docker/docker/pull/19876) [#20133](https://github.com/docker/docker/pull/20133)
- Fix `docker ps --filter before=...` to not show stopped containers without providing `-a` flag [#20135](https://github.com/docker/docker/pull/20135)
### Security
- Fix issue preventing docker events to work properly with authorization plugin [#20002](https://github.com/docker/docker/pull/20002)
### Distribution
* Add additional verifications and prevent from uploading invalid data to registries [#20164](https://github.com/docker/docker/pull/20164)
- Fix regression preventing uppercase characters in image reference hostname [#20175](https://github.com/docker/docker/pull/20175)
### Networking
- Fix embedded DNS for user-defined networks in the presence of firewalld [#20060](https://github.com/docker/docker/pull/20060)
- Fix issue where removing a network during shutdown left Docker inoperable [#20181](https://github.com/docker/docker/issues/20181) [#20235](https://github.com/docker/docker/issues/20235)
- Embedded DNS is now able to return compressed results [#20181](https://github.com/docker/docker/issues/20181)
- Fix port-mapping issue with `userland-proxy=false` [#20181](https://github.com/docker/docker/issues/20181)
### Logging
- Fix bug where tcp+tls protocol would be rejected [#20109](https://github.com/docker/docker/pull/20109)
### Volumes
- Fix issue whereby older volume drivers would not receive volume options [#19983](https://github.com/docker/docker/pull/19983)
### Misc
- Remove TasksMax from Docker systemd service [#20167](https://github.com/docker/docker/pull/20167)
## 1.10.0 (2016-02-04)
**IMPORTANT**: Docker 1.10 uses a new content-addressable storage for images and layers.
A migration is performed the first time docker is run, and can take a significant amount of time depending on the number of images present.
Refer to this page on the wiki for more information: https://github.com/docker/docker/wiki/Engine-v1.10.0-content-addressability-migration
We also released a cool migration utility that enables you to perform the migration before updating to reduce downtime.
Engine 1.10 migrator can be found on Docker Hub: https://hub.docker.com/r/docker/v1.10-migrator/
### Runtime
+ New `docker update` command that allows updating resource constraints on running containers [#15078](https://github.com/docker/docker/pull/15078)
+ Add `--tmpfs` flag to `docker run` to create a tmpfs mount in a container [#13587](https://github.com/docker/docker/pull/13587)
+ Add `--format` flag to `docker images` command [#17692](https://github.com/docker/docker/pull/17692)
+ Allow to set daemon configuration in a file and hot-reload it with the `SIGHUP` signal [#18587](https://github.com/docker/docker/pull/18587)
+ Updated docker events to include more meta-data and event types [#18888](https://github.com/docker/docker/pull/18888)
+ Updated docker events to include more meta-data and event types [#18888](https://github.com/docker/docker/pull/18888)
This change is backward compatible in the API, but not on the CLI.
+ Add `--blkio-weight-device` flag to `docker run` [#13959](https://github.com/docker/docker/pull/13959)
+ Add `--device-read-bps` and `--device-write-bps` flags to `docker run` [#14466](https://github.com/docker/docker/pull/14466)
@@ -291,8 +36,11 @@ Engine 1.10 migrator can be found on Docker Hub: https://hub.docker.com/r/docker
* Permit `OPTIONS` request against any url, thus fixing issue with CORS [#19569](https://github.com/docker/docker/pull/19569)
- Fix the `--quiet` flag on `docker build` to actually be quiet [#17428](https://github.com/docker/docker/pull/17428)
- Fix `docker images --filter dangling=false` to now show all non-dangling images [#19326](https://github.com/docker/docker/pull/19326)
- Fix `docker volumes ls --dangling=false` to now show all non-dangling volumes [#19671](https://github.com/docker/docker/pull/19671)
- Fix race condition causing autorestart turning off on restart [#17629](https://github.com/docker/docker/pull/17629)
- Recognize GPFS filesystems [#19216](https://github.com/docker/docker/pull/19216)
- Fix issues preventing volume drivers from being containerized [#19500](https://github.com/docker/docker/pull/19500)
- Do not remove named mountpoints on container removal [#19568](https://github.com/docker/docker/pull/19568)
- Fix obscure bug preventing to start containers [#19751](https://github.com/docker/docker/pull/19751)
- Forbid `exec` during container restart [#19722](https://github.com/docker/docker/pull/19722)
- devicemapper: Increasing `--storage-opt dm.basesize` will now increase the base device size on daemon restart [#19123](https://github.com/docker/docker/pull/19123)
@@ -303,18 +51,17 @@ Engine 1.10 migrator can be found on Docker Hub: https://hub.docker.com/r/docker
+ Add support for custom seccomp profiles in `--security-opt` [#17989](https://github.com/docker/docker/pull/17989)
+ Add default seccomp profile [#18780](https://github.com/docker/docker/pull/18780)
+ Add `--authorization-plugin` flag to `daemon` to customize ACLs [#15365](https://github.com/docker/docker/pull/15365)
+ Docker Content Trust now supports the ability to read and write user delegations [#18887](https://github.com/docker/docker/pull/18887)
This is an optional, opt-in feature that requires the explicit use of the Notary command-line utility in order to be enabled.
+ Docker Content Trust now supports the ability to read and write user delegations [#18887](https://github.com/docker/docker/pull/18887)
This is an optional, opt-in feature that requires the explicit use of the Notary command-line utility in order to be enabled.
Enabling delegation support in a specific repository will break the ability of Docker 1.9 and 1.8 to pull from that repository, if content trust is enabled.
* Allow SELinux to run in a container when using the BTRFS storage driver [#16452](https://github.com/docker/docker/pull/16452)
### Distribution
* Use content-addressable storage for images and layers [#17924](https://github.com/docker/docker/pull/17924)
Note that a migration is performed the first time docker is run; it can take a significant amount of time depending on the number of images and containers present.
Images no longer depend on the parent chain but contain a list of layer references.
* Use content-addressable storage for images and layers [#17924](https://github.com/docker/docker/pull/17924)
Note that a migration is performed the first time docker is run; it can take a significant amount of time depending on the number of images and containers present.
Images no longer depend on the parent chain but contain a list of layer references.
`docker load`/`docker save` tarballs now also contain content-addressable image configurations.
For more information: https://github.com/docker/docker/wiki/Engine-v1.10.0-content-addressability-migration
* Add support for the new [manifest format ("schema2")](https://github.com/docker/distribution/blob/master/docs/spec/manifest-v2-2.md) [#18785](https://github.com/docker/docker/pull/18785)
* Lots of improvements for push and pull: performance++, retries on failed downloads, cancelling on client disconnect [#18353](https://github.com/docker/docker/pull/18353), [#18418](https://github.com/docker/docker/pull/18418), [#19109](https://github.com/docker/docker/pull/19109), [#18353](https://github.com/docker/docker/pull/18353)
* Limit v1 protocol fallbacks [#18590](https://github.com/docker/docker/pull/18590)
@@ -356,13 +103,10 @@ Engine 1.10 migrator can be found on Docker Hub: https://hub.docker.com/r/docker
### Volumes
+ Add support to set the mount propagation mode for a volume [#17034](https://github.com/docker/docker/pull/17034)
* Add `ls` and `inspect` endpoints to volume plugin API [#16534](https://github.com/docker/docker/pull/16534)
Existing plugins need to make use of these new APIs to satisfy users' expectation
* Add `ls` and `inspect` endpoints to volume plugin API [#16534](https://github.com/docker/docker/pull/16534)
Existing plugins need to make use of these new APIs to satisfy users' expectation
For that, please use the new MIME type `application/vnd.docker.plugins.v1.2+json` [#19549](https://github.com/docker/docker/pull/19549)
- Fix data not being copied to named volumes [#19175](https://github.com/docker/docker/pull/19175)
- Fix issues preventing volume drivers from being containerized [#19500](https://github.com/docker/docker/pull/19500)
- Fix `docker volumes ls --dangling=false` to now show all non-dangling volumes [#19671](https://github.com/docker/docker/pull/19671)
- Do not remove named volumes on container removal [#19568](https://github.com/docker/docker/pull/19568)
- Allow external volume drivers to host anonymous volumes [#19190](https://github.com/docker/docker/pull/19190)
### Builder
@@ -1686,7 +1430,7 @@ With the ongoing changes to the networking and execution subsystems of docker te
+ Add -rm to docker run for removing a container on exit
- Remove error messages which are not actually errors
- Fix `docker rm` with volumes
- Fix some error cases where an HTTP body might not be closed
- Fix some error cases where a HTTP body might not be closed
- Fix panic with wrong dockercfg file
- Fix the attach behavior with -i
* Record termination time in state.
@@ -2020,7 +1764,7 @@ With the ongoing changes to the networking and execution subsystems of docker te
+ Containers can expose public UDP ports (eg, '-p 123/udp')
+ Optionally specify an exact public port (eg. '-p 80:4500')
* 'docker login' supports additional options
- Don't save a container`s hostname when committing an image.
- Dont save a container`s hostname when committing an image.
#### Registry

View File

@@ -152,10 +152,8 @@ However, there might be a way to implement that feature *on top of* Docker.
<a href="https://groups.google.com/forum/#!forum/docker-user" target="_blank">Docker-user</a>
is for people using Docker containers.
The <a href="https://groups.google.com/forum/#!forum/docker-dev" target="_blank">docker-dev</a>
group is for contributors and other people contributing to the Docker project.
You can join them without a google account by sending an email to
<a href="mailto:docker-dev+subscribe@googlegroups.com">docker-dev+subscribe@googlegroups.com</a>.
After receiving the join-request message, you can simply reply to that to confirm the subscribtion.
group is for contributors and other people contributing to the Docker
project.
</td>
</tr>
<tr>

View File

@@ -23,30 +23,22 @@
# the case. Therefore, you don't have to disable it anymore.
#
FROM debian:jessie
FROM ubuntu:trusty
# add zfs ppa
RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys E871F18B51E0147C77796AC81196BA81F6B0FC61 \
|| apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys E871F18B51E0147C77796AC81196BA81F6B0FC61
RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys E871F18B51E0147C77796AC81196BA81F6B0FC61
RUN echo deb http://ppa.launchpad.net/zfs-native/stable/ubuntu trusty main > /etc/apt/sources.list.d/zfs.list
# add llvm repo
RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 6084F3CF814B57C1CF12EFD515CF4D18AF4F7421 \
|| apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 6084F3CF814B57C1CF12EFD515CF4D18AF4F7421
RUN echo deb http://llvm.org/apt/jessie/ llvm-toolchain-jessie-3.8 main > /etc/apt/sources.list.d/llvm.list
# allow replacing httpredir mirror
ARG APT_MIRROR=httpredir.debian.org
RUN sed -i s/httpredir.debian.org/$APT_MIRROR/g /etc/apt/sources.list
RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 6084F3CF814B57C1CF12EFD515CF4D18AF4F7421
RUN echo deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty main > /etc/apt/sources.list.d/llvm.list
# Packaged dependencies
RUN apt-get update && apt-get install -y \
apparmor \
apt-utils \
aufs-tools \
automake \
bash-completion \
bsdmainutils \
btrfs-tools \
build-essential \
clang-3.8 \
@@ -64,19 +56,17 @@ RUN apt-get update && apt-get install -y \
libsystemd-journal-dev \
libtool \
mercurial \
net-tools \
pkg-config \
python-dev \
python-mock \
python-pip \
python-websocket \
s3cmd=1.1.0* \
ubuntu-zfs \
xfsprogs \
libzfs-dev \
tar \
zip \
--no-install-recommends \
&& pip install awscli==1.10.15 \
&& ln -snf /usr/bin/clang-3.8 /usr/local/bin/clang \
&& ln -snf /usr/bin/clang++-3.8 /usr/local/bin/clang++
@@ -96,37 +86,11 @@ RUN cd /usr/local/lvm2 \
&& make install_device-mapper
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
# Configure the container for OSX cross compilation
ENV OSX_SDK MacOSX10.11.sdk
ENV OSX_CROSS_COMMIT 8aa9b71a394905e6c5f4b59e2b97b87a004658a4
RUN set -x \
&& export OSXCROSS_PATH="/osxcross" \
&& git clone https://github.com/tpoechtrager/osxcross.git $OSXCROSS_PATH \
&& ( cd $OSXCROSS_PATH && git checkout -q $OSX_CROSS_COMMIT) \
&& curl -sSL https://s3.dockerproject.org/darwin/v2/${OSX_SDK}.tar.xz -o "${OSXCROSS_PATH}/tarballs/${OSX_SDK}.tar.xz" \
&& UNATTENDED=yes OSX_VERSION_MIN=10.6 ${OSXCROSS_PATH}/build.sh
ENV PATH /osxcross/target/bin:$PATH
# install seccomp: the version shipped in trusty is too old
ENV SECCOMP_VERSION 2.3.0
RUN set -x \
&& export SECCOMP_PATH="$(mktemp -d)" \
&& curl -fsSL "https://github.com/seccomp/libseccomp/releases/download/v${SECCOMP_VERSION}/libseccomp-${SECCOMP_VERSION}.tar.gz" \
| tar -xzC "$SECCOMP_PATH" --strip-components=1 \
&& ( \
cd "$SECCOMP_PATH" \
&& ./configure --prefix=/usr/local \
&& make \
&& make install \
&& ldconfig \
) \
&& rm -rf "$SECCOMP_PATH"
# Install Go
# IMPORTANT: If the version of Go is updated, the Windows to Linux CI machines
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
# with a heads-up.
ENV GO_VERSION 1.5.4
ENV GO_VERSION 1.5.3
RUN curl -fsSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" \
| tar -xzC /usr/local
ENV PATH /go/bin:/usr/local/go/bin:$PATH
@@ -139,6 +103,9 @@ ENV DOCKER_CROSSPLATFORMS \
freebsd/amd64 freebsd/386 freebsd/arm \
windows/amd64 windows/386
# (set an explicit GOARM of 5 for maximum compatibility)
ENV GOARM 5
# This has been commented out and kept as reference because we don't support compiling with older Go anymore.
# ENV GOFMT_VERSION 1.3.3
# RUN curl -sSL https://storage.googleapis.com/golang/go${GOFMT_VERSION}.$(go env GOOS)-$(go env GOARCH).tar.gz | tar -C /go/bin -xz --strip-components=2 go/bin/gofmt
@@ -157,6 +124,32 @@ RUN git clone https://github.com/golang/lint.git /go/src/github.com/golang/lint
&& (cd /go/src/github.com/golang/lint && git checkout -q $GO_LINT_COMMIT) \
&& go install -v github.com/golang/lint/golint
# Configure the container for OSX cross compilation
ENV OSX_SDK MacOSX10.11.sdk
RUN set -x \
&& export OSXCROSS_PATH="/osxcross" \
&& git clone --depth 1 https://github.com/tpoechtrager/osxcross.git $OSXCROSS_PATH \
&& curl -sSL https://s3.dockerproject.org/darwin/${OSX_SDK}.tar.xz -o "${OSXCROSS_PATH}/tarballs/${OSX_SDK}.tar.xz" \
&& UNATTENDED=yes OSX_VERSION_MIN=10.6 ${OSXCROSS_PATH}/build.sh
ENV PATH /osxcross/target/bin:$PATH
# install seccomp
# this can be changed to the ubuntu package libseccomp-dev if dockerinit is removed,
# we need libseccomp.a (which the package does not provide) for dockerinit
ENV SECCOMP_VERSION 2.2.3
RUN set -x \
&& export SECCOMP_PATH="$(mktemp -d)" \
&& curl -fsSL "https://github.com/seccomp/libseccomp/releases/download/v${SECCOMP_VERSION}/libseccomp-${SECCOMP_VERSION}.tar.gz" \
| tar -xzC "$SECCOMP_PATH" --strip-components=1 \
&& ( \
cd "$SECCOMP_PATH" \
&& ./configure --prefix=/usr/local \
&& make \
&& make install \
&& ldconfig \
) \
&& rm -rf "$SECCOMP_PATH"
# Install two versions of the registry. The first is an older version that
# only supports schema1 manifests. The second is a newer version that supports
# both. This allows integration-cli tests to cover push/pull with both schema1
@@ -175,15 +168,14 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install notary server
ENV NOTARY_VERSION docker-v1.11-3
ENV NOTARY_VERSION docker-v1.10-5
RUN set -x \
&& export GO15VENDOREXPERIMENT=1 \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \
&& rm -rf "$GOPATH"
@@ -194,6 +186,13 @@ RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& git checkout -q $DOCKER_PY_COMMIT \
&& pip install -r test-requirements.txt
# Setup s3cmd config
RUN { \
echo '[default]'; \
echo 'access_key=$AWS_ACCESS_KEY'; \
echo 'secret_key=$AWS_SECRET_KEY'; \
} > ~/.s3cfg
# Set user.email so crosbymichael's in-container merge commits go smoothly
RUN git config --global user.email 'docker-dummy@example.com'
@@ -203,7 +202,7 @@ RUN useradd --create-home --gid docker unprivilegeduser
VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor pkcs11 seccomp selinux
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
# Let us use a .bashrc file
RUN ln -sfv $PWD/.bashrc ~/.bashrc
@@ -214,9 +213,8 @@ RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling
COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/
RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \
buildpack-deps:jessie@sha256:25785f89240fbcdd8a74bdaf30dd5599a9523882c6dfc567f2e9ef7cf6f79db6 \
busybox:latest@sha256:e4f93f6ed15a0cdd342f5aae387886fba0ab98af0a102da6276eaf24d6e6ade0 \
debian:jessie@sha256:f968f10b4b523737e253a97eac59b0d1420b5c19b69928d35801a6373ffe330e \
debian:jessie@sha256:24a900d1671b269d6640b4224e7b63801880d8e3cb2bcbfaa10a5dddcf4469ed \
hello-world:latest@sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7
# see also "hack/make/.ensure-frozen-images" (which needs to be updated any time this list is)
@@ -239,36 +237,13 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Build/install the tool for embedding resources in Windows binaries
ENV RSRC_COMMIT ba14da1f827188454a4591717fff29999010887f
ENV RSRC_VERSION v2
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/akavel/rsrc.git "$GOPATH/src/github.com/akavel/rsrc" \
&& (cd "$GOPATH/src/github.com/akavel/rsrc" && git checkout -q "$RSRC_COMMIT") \
&& git clone --depth 1 -b "$RSRC_VERSION" https://github.com/akavel/rsrc.git "$GOPATH/src/github.com/akavel/rsrc" \
&& go build -v -o /usr/local/bin/rsrc github.com/akavel/rsrc \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT e87436998478d222be209707503c27f6f91be0c5
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \
&& cp runc /usr/local/bin/docker-runc
# Install containerd
ENV CONTAINERD_COMMIT d2f03861c91edaafdcb3961461bf82ae83785ed7
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
&& cd "$GOPATH/src/github.com/docker/containerd" \
&& git checkout -q "$CONTAINERD_COMMIT" \
&& make static \
&& cp bin/containerd /usr/local/bin/docker-containerd \
&& cp bin/containerd-shim /usr/local/bin/docker-containerd-shim \
&& cp bin/ctr /usr/local/bin/docker-containerd-ctr
# Wrap all commands in the "docker-in-docker" script to allow nested containers
ENTRYPOINT ["hack/dind"]

View File

@@ -1,209 +0,0 @@
# This file describes the standard way to build Docker on aarch64, using docker
#
# Usage:
#
# # Assemble the full dev environment. This is slow the first time.
# docker build -t docker -f Dockerfile.aarch64 .
#
# # Mount your source in an interactive container for quick testing:
# docker run -v `pwd`:/go/src/github.com/docker/docker --privileged -i -t docker bash
#
# # Run the test suite:
# docker run --privileged docker hack/make.sh test
#
# Note: AppArmor used to mess with privileged mode, but this is no longer
# the case. Therefore, you don't have to disable it anymore.
#
FROM aarch64/ubuntu:wily
# Packaged dependencies
RUN apt-get update && apt-get install -y \
apparmor \
aufs-tools \
automake \
bash-completion \
btrfs-tools \
build-essential \
createrepo \
curl \
dpkg-sig \
g++ \
gcc \
git \
iptables \
jq \
libapparmor-dev \
libc6-dev \
libcap-dev \
libsqlite3-dev \
libsystemd-dev \
mercurial \
net-tools \
parallel \
pkg-config \
python-dev \
python-mock \
python-pip \
python-websocket \
gccgo \
--no-install-recommends
# Install armhf loader to use armv6 binaries on armv8
RUN dpkg --add-architecture armhf \
&& apt-get update \
&& apt-get install -y libc6:armhf
# Get lvm2 source for compiling statically
ENV LVM2_VERSION 2.02.103
RUN mkdir -p /usr/local/lvm2 \
&& curl -fsSL "https://mirrors.kernel.org/sourceware/lvm2/LVM2.${LVM2_VERSION}.tgz" \
| tar -xzC /usr/local/lvm2 --strip-components=1
# see https://git.fedorahosted.org/cgit/lvm2.git/refs/tags for release tags
# fix platform enablement in lvm2 to support aarch64 properly
RUN set -e \
&& for f in config.guess config.sub; do \
curl -fsSL -o "/usr/local/lvm2/autoconf/$f" "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=$f;hb=HEAD"; \
done
# "arch.c:78:2: error: #error the arch code needs to know about your machine type"
# Compile and install lvm2
RUN cd /usr/local/lvm2 \
&& ./configure \
--build="$(gcc -print-multiarch)" \
--enable-static_link \
&& make device-mapper \
&& make install_device-mapper
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
# install seccomp: the version shipped in trusty is too old
ENV SECCOMP_VERSION 2.3.0
RUN set -x \
&& export SECCOMP_PATH="$(mktemp -d)" \
&& curl -fsSL "https://github.com/seccomp/libseccomp/releases/download/v${SECCOMP_VERSION}/libseccomp-${SECCOMP_VERSION}.tar.gz" \
| tar -xzC "$SECCOMP_PATH" --strip-components=1 \
&& ( \
cd "$SECCOMP_PATH" \
&& ./configure --prefix=/usr/local \
&& make \
&& make install \
&& ldconfig \
) \
&& rm -rf "$SECCOMP_PATH"
# Install Go
# We don't have official binary tarballs for ARM64, eigher for Go or bootstrap,
# so we use the official armv6 released binaries as a GOROOT_BOOTSTRAP, and
# build Go from source code.
ENV GO_VERSION 1.5.4
RUN mkdir /usr/src/go && curl -fsSL https://storage.googleapis.com/golang/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
&& cd /usr/src/go/src \
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
ENV PATH /usr/src/go/bin:$PATH
ENV GOPATH /go:/go/src/github.com/docker/docker/vendor
# Only install one version of the registry, because old version which support
# schema1 manifests is not working on ARM64, we should skip integration-cli
# tests for schema1 manifests on ARM64.
ENV REGISTRY_COMMIT 47a064d4195a9b56133891bbb13620c3ac83a827
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/docker/distribution.git "$GOPATH/src/github.com/docker/distribution" \
&& (cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT") \
&& GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH" \
go build -o /usr/local/bin/registry-v2 github.com/docker/distribution/cmd/registry \
&& rm -rf "$GOPATH"
# Install notary server
ENV NOTARY_VERSION docker-v1.11-3
RUN set -x \
&& export GO15VENDOREXPERIMENT=1 \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \
&& rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT e2878cbcc3a7eef99917adc1be252800b0e41ece
RUN git clone https://github.com/docker/docker-py.git /docker-py \
&& cd /docker-py \
&& git checkout -q $DOCKER_PY_COMMIT \
&& pip install -r test-requirements.txt
# Set user.email so crosbymichael's in-container merge commits go smoothly
RUN git config --global user.email 'docker-dummy@example.com'
# Add an unprivileged user to be used for tests which need it
RUN groupadd -r docker
RUN useradd --create-home --gid docker unprivilegeduser
VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor pkcs11 seccomp selinux
# Let us use a .bashrc file
RUN ln -sfv $PWD/.bashrc ~/.bashrc
# Register Docker's bash completion.
RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling
COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/
RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \
aarch64/buildpack-deps:jessie@sha256:6aa1d6910791b7ac78265fd0798e5abd6cb3f27ae992f6f960f6c303ec9535f2 \
aarch64/busybox:latest@sha256:b23a6a37cf269dff6e46d2473b6e227afa42b037e6d23435f1d2bc40fc8c2828 \
aarch64/debian:jessie@sha256:4be74a41a7c70ebe887b634b11ffe516cf4fcd56864a54941e56bb49883c3170 \
aarch64/hello-world:latest@sha256:65a4a158587b307bb02db4de41b836addb0c35175bdc801367b1ac1ddeb9afda
# see also "hack/make/.ensure-frozen-images" (which needs to be updated any time this list is)
# Download man page generator
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone --depth 1 -b v1.0.4 https://github.com/cpuguy83/go-md2man.git "$GOPATH/src/github.com/cpuguy83/go-md2man" \
&& git clone --depth 1 -b v1.4 https://github.com/russross/blackfriday.git "$GOPATH/src/github.com/russross/blackfriday" \
&& go get -v -d github.com/cpuguy83/go-md2man \
&& go build -v -o /usr/local/bin/go-md2man github.com/cpuguy83/go-md2man \
&& rm -rf "$GOPATH"
# Download toml validator
ENV TOMLV_COMMIT 9baf8a8a9f2ed20a8e54160840c492f937eeaf9a
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/BurntSushi/toml.git "$GOPATH/src/github.com/BurntSushi/toml" \
&& (cd "$GOPATH/src/github.com/BurntSushi/toml" && git checkout -q "$TOMLV_COMMIT") \
&& go build -v -o /usr/local/bin/tomlv github.com/BurntSushi/toml/cmd/tomlv \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT e87436998478d222be209707503c27f6f91be0c5
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \
&& cp runc /usr/local/bin/docker-runc
# Install containerd
ENV CONTAINERD_COMMIT d2f03861c91edaafdcb3961461bf82ae83785ed7
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
&& cd "$GOPATH/src/github.com/docker/containerd" \
&& git checkout -q "$CONTAINERD_COMMIT" \
&& make static \
&& cp bin/containerd /usr/local/bin/docker-containerd \
&& cp bin/containerd-shim /usr/local/bin/docker-containerd-shim \
&& cp bin/ctr /usr/local/bin/docker-containerd-ctr
# Wrap all commands in the "docker-in-docker" script to allow nested containers
ENTRYPOINT ["hack/dind"]
# Upload docker source
COPY . /go/src/github.com/docker/docker

View File

@@ -11,11 +11,19 @@
# # Run the test suite:
# docker run --privileged docker hack/make.sh test
#
# # Publish a release:
# docker run --privileged \
# -e AWS_S3_BUCKET=baz \
# -e AWS_ACCESS_KEY=foo \
# -e AWS_SECRET_KEY=bar \
# -e GPG_PASSPHRASE=gloubiboulga \
# docker hack/release.sh
#
# Note: AppArmor used to mess with privileged mode, but this is no longer
# the case. Therefore, you don't have to disable it anymore.
#
FROM armhf/debian:jessie
FROM armhf/ubuntu:trusty
# Packaged dependencies
RUN apt-get update && apt-get install -y \
@@ -65,11 +73,14 @@ RUN cd /usr/local/lvm2 \
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
# Install Go
# TODO Update to 1.5.4 once available, or build from source, as these builds
# are marked "end of life", see http://dave.cheney.net/unofficial-arm-tarballs
ENV GO_VERSION 1.5.3
RUN curl -fsSL "http://dave.cheney.net/paste/go${GO_VERSION}.linux-arm.tar.gz" \
#ENV GO_VERSION 1.5.3
# TODO update GO_TOOLS_COMMIT below when this updates to 1.5+
ENV GO_VERSION 1.4.3
RUN curl -fsSL "https://github.com/hypriot/golang-armbuilds/releases/download/v${GO_VERSION}/go${GO_VERSION}.linux-armv7.tar.gz" \
| tar -xzC /usr/local
# temporarily using Hypriot's tarballs while we wait for official 1.6+
#RUN curl -fsSL https://golang.org/dl/go${GO_VERSION}.linux-arm6.tar.gz \
# | tar -xzC /usr/local
ENV PATH /go/bin:/usr/local/go/bin:$PATH
ENV GOPATH /go:/go/src/github.com/docker/docker/vendor
@@ -81,7 +92,9 @@ ENV GOARM 7
# ENV GOFMT_VERSION 1.3.3
# RUN curl -sSL https://storage.googleapis.com/golang/go${GOFMT_VERSION}.$(go env GOOS)-$(go env GOARCH).tar.gz | tar -C /go/bin -xz --strip-components=2 go/bin/gofmt
ENV GO_TOOLS_COMMIT 823804e1ae08dbb14eb807afc7db9993bc9e3cc3
#ENV GO_TOOLS_COMMIT 823804e1ae08dbb14eb807afc7db9993bc9e3cc3
# TODO update this sha when we upgrade to Go 1.5+
ENV GO_TOOLS_COMMIT 069d2f3bcb68257b627205f0486d6cc69a231ff9
# Grab Go's cover tool for dead-simple code coverage testing
# Grab Go's vet tool for examining go code to find suspicious constructs
# and help prevent errors that the compiler might not catch
@@ -90,13 +103,17 @@ RUN git clone https://github.com/golang/tools.git /go/src/golang.org/x/tools \
&& go install -v golang.org/x/tools/cmd/cover \
&& go install -v golang.org/x/tools/cmd/vet
# Grab Go's lint tool
ENV GO_LINT_COMMIT 32a87160691b3c96046c0c678fe57c5bef761456
#ENV GO_LINT_COMMIT 32a87160691b3c96046c0c678fe57c5bef761456
# TODO update this sha when we upgrade to Go 1.5+
ENV GO_LINT_COMMIT f42f5c1c440621302702cb0741e9d2ca547ae80f
RUN git clone https://github.com/golang/lint.git /go/src/github.com/golang/lint \
&& (cd /go/src/github.com/golang/lint && git checkout -q $GO_LINT_COMMIT) \
&& go install -v github.com/golang/lint/golint
# install seccomp: the version shipped in trusty is too old
ENV SECCOMP_VERSION 2.3.0
# install seccomp
# this can be changed to the ubuntu package libseccomp-dev if dockerinit is removed,
# we need libseccomp.a (which the package does not provide) for dockerinit
ENV SECCOMP_VERSION 2.2.3
RUN set -x \
&& export SECCOMP_PATH="$(mktemp -d)" \
&& curl -fsSL "https://github.com/seccomp/libseccomp/releases/download/v${SECCOMP_VERSION}/libseccomp-${SECCOMP_VERSION}.tar.gz" \
@@ -115,7 +132,7 @@ RUN set -x \
# both. This allows integration-cli tests to cover push/pull with both schema1
# and schema2 manifests.
ENV REGISTRY_COMMIT_SCHEMA1 ec87e9b6971d831f0eff752ddb54fb64693e51cd
ENV REGISTRY_COMMIT cb08de17d74bef86ce6c5abe8b240e282f5750be
ENV REGISTRY_COMMIT a7ae88da459b98b481a245e5b1750134724ac67d
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/docker/distribution.git "$GOPATH/src/github.com/docker/distribution" \
@@ -128,15 +145,14 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install notary server
ENV NOTARY_VERSION docker-v1.11-3
ENV NOTARY_VERSION docker-v1.10-5
RUN set -x \
&& export GO15VENDOREXPERIMENT=1 \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \
&& rm -rf "$GOPATH"
@@ -156,7 +172,7 @@ RUN useradd --create-home --gid docker unprivilegeduser
VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor pkcs11 seccomp selinux
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
# Let us use a .bashrc file
RUN ln -sfv $PWD/.bashrc ~/.bashrc
@@ -167,9 +183,8 @@ RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling
COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/
RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \
armhf/buildpack-deps:jessie@sha256:ca6cce8e5bf5c952129889b5cc15cd6aa8d995d77e55e3749bbaadae50e476cb \
armhf/busybox:latest@sha256:d98a7343ac750ffe387e3d514f8521ba69846c216778919b01414b8617cfb3d4 \
armhf/debian:jessie@sha256:4a2187483f04a84f9830910fe3581d69b3c985cc045d9f01d8e2f3795b28107b \
armhf/debian:jessie@sha256:094687129906d2a43cb4e5946ea379b5619c9ca8e4e27b3ba28b40f237a4150c \
armhf/hello-world:latest@sha256:161dcecea0225975b2ad5f768058212c1e0d39e8211098666ffa1ac74cfb7791
# see also "hack/make/.ensure-frozen-images" (which needs to be updated any time this list is)
@@ -199,28 +214,7 @@ RUN set -x \
&& go build -v -o /usr/local/bin/rsrc github.com/akavel/rsrc \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT e87436998478d222be209707503c27f6f91be0c5
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \
&& cp runc /usr/local/bin/docker-runc
# Install containerd
ENV CONTAINERD_COMMIT d2f03861c91edaafdcb3961461bf82ae83785ed7
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
&& cd "$GOPATH/src/github.com/docker/containerd" \
&& git checkout -q "$CONTAINERD_COMMIT" \
&& make static \
&& cp bin/containerd /usr/local/bin/docker-containerd \
&& cp bin/containerd-shim /usr/local/bin/docker-containerd-shim \
&& cp bin/ctr /usr/local/bin/docker-containerd-ctr
# Wrap all commands in the "docker-in-docker" script to allow nested containers
ENTRYPOINT ["hack/dind"]
# Upload docker source

View File

@@ -23,7 +23,6 @@ RUN apt-get update && apt-get install -y \
libcap-dev \
libsqlite3-dev \
mercurial \
net-tools \
parallel \
python-dev \
python-mock \
@@ -42,8 +41,10 @@ RUN cd /usr/local/lvm2 \
&& make install_device-mapper
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
# install seccomp: the version shipped in jessie is too old
ENV SECCOMP_VERSION v2.3.0
# install seccomp
# this can be changed to the ubuntu package libseccomp-dev if dockerinit is removed,
# we need libseccomp.a (which the package does not provide) for dockerinit
ENV SECCOMP_VERSION v2.2.3
RUN set -x \
&& export SECCOMP_PATH=$(mktemp -d) \
&& git clone https://github.com/seccomp/libseccomp.git "$SECCOMP_PATH" \
@@ -73,28 +74,6 @@ VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
# Install runc
ENV RUNC_COMMIT e87436998478d222be209707503c27f6f91be0c5
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \
&& cp runc /usr/local/bin/docker-runc
# Install containerd
ENV CONTAINERD_COMMIT d2f03861c91edaafdcb3961461bf82ae83785ed7
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
&& cd "$GOPATH/src/github.com/docker/containerd" \
&& git checkout -q "$CONTAINERD_COMMIT" \
&& make static \
&& cp bin/containerd /usr/local/bin/docker-containerd \
&& cp bin/containerd-shim /usr/local/bin/docker-containerd-shim \
&& cp bin/ctr /usr/local/bin/docker-containerd-ctr
# Wrap all commands in the "docker-in-docker" script to allow nested containers
ENTRYPOINT ["hack/dind"]

View File

@@ -11,6 +11,14 @@
# # Run the test suite:
# docker run --privileged docker hack/make.sh test
#
# # Publish a release:
# docker run --privileged \
# -e AWS_S3_BUCKET=baz \
# -e AWS_ACCESS_KEY=foo \
# -e AWS_SECRET_KEY=bar \
# -e GPG_PASSPHRASE=gloubiboulga \
# docker hack/release.sh
#
# Note: AppArmor used to mess with privileged mode, but this is no longer
# the case. Therefore, you don't have to disable it anymore.
#
@@ -74,28 +82,15 @@ RUN cd /usr/local/lvm2 \
# TODO install Go, using gccgo as GOROOT_BOOTSTRAP (Go 1.5+ supports ppc64le properly)
# possibly a ppc64le/golang image?
## BUILD GOLANG
ENV GO_VERSION 1.5.4
ENV GO_DOWNLOAD_URL https://golang.org/dl/go${GO_VERSION}.src.tar.gz
ENV GO_DOWNLOAD_SHA256 002acabce7ddc140d0d55891f9d4fcfbdd806b9332fb8b110c91bc91afb0bc93
ENV GOROOT_BOOTSTRAP /usr/local
RUN curl -fsSL "$GO_DOWNLOAD_URL" -o golang.tar.gz \
&& echo "$GO_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - \
&& tar -C /usr/src -xzf golang.tar.gz \
&& rm golang.tar.gz \
&& cd /usr/src/go/src && ./make.bash 2>&1
ENV GOROOT_BOOTSTRAP /usr/src/
ENV PATH /usr/src/go/bin/:/go/bin:$PATH
ENV PATH /go/bin:$PATH
ENV GOPATH /go:/go/src/github.com/docker/docker/vendor
# This has been commented out and kept as reference because we don't support compiling with older Go anymore.
# ENV GOFMT_VERSION 1.3.3
# RUN curl -sSL https://storage.googleapis.com/golang/go${GOFMT_VERSION}.$(go env GOOS)-$(go env GOARCH).tar.gz | tar -C /go/bin -xz --strip-components=2 go/bin/gofmt
ENV GO_TOOLS_COMMIT 823804e1ae08dbb14eb807afc7db9993bc9e3cc3
# TODO update this sha when we upgrade to Go 1.5+
ENV GO_TOOLS_COMMIT 069d2f3bcb68257b627205f0486d6cc69a231ff9
# Grab Go's cover tool for dead-simple code coverage testing
# Grab Go's vet tool for examining go code to find suspicious constructs
# and help prevent errors that the compiler might not catch
@@ -104,40 +99,31 @@ RUN git clone https://github.com/golang/tools.git /go/src/golang.org/x/tools \
&& go install -v golang.org/x/tools/cmd/cover \
&& go install -v golang.org/x/tools/cmd/vet
# Grab Go's lint tool
ENV GO_LINT_COMMIT 32a87160691b3c96046c0c678fe57c5bef761456
ENV GO_LINT_COMMIT f42f5c1c440621302702cb0741e9d2ca547ae80f
RUN git clone https://github.com/golang/lint.git /go/src/github.com/golang/lint \
&& (cd /go/src/github.com/golang/lint && git checkout -q $GO_LINT_COMMIT) \
&& go install -v github.com/golang/lint/golint
# Install two versions of the registry. The first is an older version that
# only supports schema1 manifests. The second is a newer version that supports
# both. This allows integration-cli tests to cover push/pull with both schema1
# and schema2 manifests.
ENV REGISTRY_COMMIT_SCHEMA1 ec87e9b6971d831f0eff752ddb54fb64693e51cd
ENV REGISTRY_COMMIT 47a064d4195a9b56133891bbb13620c3ac83a827
# Install registry
ENV REGISTRY_COMMIT ec87e9b6971d831f0eff752ddb54fb64693e51cd
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/docker/distribution.git "$GOPATH/src/github.com/docker/distribution" \
&& (cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT") \
&& GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH" \
go build -o /usr/local/bin/registry-v2 github.com/docker/distribution/cmd/registry \
&& (cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT_SCHEMA1") \
&& GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH" \
go build -o /usr/local/bin/registry-v2-schema1 github.com/docker/distribution/cmd/registry \
&& rm -rf "$GOPATH"
# Install notary and notary-server
ENV NOTARY_VERSION docker-v1.11-3
RUN set -x \
&& export GO15VENDOREXPERIMENT=1 \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary \
&& rm -rf "$GOPATH"
# Install notary server
#ENV NOTARY_VERSION docker-v1.10-5
#RUN set -x \
# && export GOPATH="$(mktemp -d)" \
# && git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
# && (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
# && GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
# go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
# && rm -rf "$GOPATH"
# Get the "docker-py" source so we can run their integration tests
ENV DOCKER_PY_COMMIT e2878cbcc3a7eef99917adc1be252800b0e41ece
@@ -155,7 +141,7 @@ RUN useradd --create-home --gid docker unprivilegeduser
VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor pkcs11 selinux
ENV DOCKER_BUILDTAGS apparmor selinux
# Let us use a .bashrc file
RUN ln -sfv $PWD/.bashrc ~/.bashrc
@@ -166,9 +152,8 @@ RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling
COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/
RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \
ppc64le/buildpack-deps:jessie@sha256:902bfe4ef1389f94d143d64516dd50a2de75bca2e66d4a44b1d73f63ddf05dda \
ppc64le/busybox:latest@sha256:38bb82085248d5a3c24bd7a5dc146f2f2c191e189da0441f1c2ca560e3fc6f1b \
ppc64le/debian:jessie@sha256:412845f51b6ab662afba71bc7a716e20fdb9b84f185d180d4c7504f8a75c4f91 \
ppc64le/debian:jessie@sha256:74e06e6506b23cf8abd00250782838b2d19910824d8e7eab3d14dc1845ea10c6 \
ppc64le/hello-world:latest@sha256:186a40a9a02ca26df0b6c8acdfb8ac2f3ae6678996a838f977e57fac9d963974
# see also "hack/make/.ensure-frozen-images" (which needs to be updated any time this list is)
@@ -198,28 +183,6 @@ RUN set -x \
&& go build -v -o /usr/local/bin/rsrc github.com/akavel/rsrc \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT e87436998478d222be209707503c27f6f91be0c5
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="apparmor selinux" \
&& cp runc /usr/local/bin/docker-runc
# Install containerd
ENV CONTAINERD_COMMIT d2f03861c91edaafdcb3961461bf82ae83785ed7
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
&& cd "$GOPATH/src/github.com/docker/containerd" \
&& git checkout -q "$CONTAINERD_COMMIT" \
&& make static \
&& cp bin/containerd /usr/local/bin/docker-containerd \
&& cp bin/containerd-shim /usr/local/bin/docker-containerd-shim \
&& cp bin/ctr /usr/local/bin/docker-containerd-ctr
# Wrap all commands in the "docker-in-docker" script to allow nested containers
ENTRYPOINT ["hack/dind"]

View File

@@ -11,6 +11,14 @@
# # Run the test suite:
# docker run --privileged docker hack/make.sh test
#
# # Publish a release:
# docker run --privileged \
# -e AWS_S3_BUCKET=baz \
# -e AWS_ACCESS_KEY=foo \
# -e AWS_SECRET_KEY=bar \
# -e GPG_PASSPHRASE=gloubiboulga \
# docker hack/release.sh
#
# Note: AppArmor used to mess with privileged mode, but this is no longer
# the case. Therefore, you don't have to disable it anymore.
#
@@ -108,13 +116,12 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install notary server
ENV NOTARY_VERSION docker-v1.11-3
ENV NOTARY_VERSION docker-v1.10-5
RUN set -x \
&& export GO15VENDOREXPERIMENT=1 \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" \
&& (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") \
&& GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \
&& GOPATH="$GOPATH/src/github.com/docker/notary/Godeps/_workspace:$GOPATH" \
go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server \
&& rm -rf "$GOPATH"
@@ -134,7 +141,7 @@ RUN useradd --create-home --gid docker unprivilegeduser
VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor pkcs11 selinux
ENV DOCKER_BUILDTAGS apparmor selinux
# Let us use a .bashrc file
RUN ln -sfv $PWD/.bashrc ~/.bashrc
@@ -145,9 +152,8 @@ RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling
COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/
RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \
s390x/buildpack-deps:jessie@sha256:4d1381224acaca6c4bfe3604de3af6972083a8558a99672cb6989c7541780099 \
s390x/busybox:latest@sha256:dd61522c983884a66ed72d60301925889028c6d2d5e0220a8fe1d9b4c6a4f01b \
s390x/debian:jessie@sha256:b74c863400909eff3c5e196cac9bfd1f6333ce47aae6a38398d87d5875da170a \
s390x/debian:jessie@sha256:3c478e199f60c877c00306356267798d32727dc3cd38512cdb4b060659ea9d20 \
s390x/hello-world:latest@sha256:780d80b3a7677c3788c0d5cd9168281320c8d4a6d9183892d8ee5cdd610f5699
# see also "hack/make/.ensure-frozen-images" (which needs to be updated any time this list is)
@@ -177,28 +183,6 @@ RUN set -x \
&& go build -v -o /usr/local/bin/rsrc github.com/akavel/rsrc \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT e87436998478d222be209707503c27f6f91be0c5
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \
&& cp runc /usr/local/bin/docker-runc
# Install containerd
ENV CONTAINERD_COMMIT d2f03861c91edaafdcb3961461bf82ae83785ed7
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
&& cd "$GOPATH/src/github.com/docker/containerd" \
&& git checkout -q "$CONTAINERD_COMMIT" \
&& make static \
&& cp bin/containerd /usr/local/bin/docker-containerd \
&& cp bin/containerd-shim /usr/local/bin/docker-containerd-shim \
&& cp bin/ctr /usr/local/bin/docker-containerd-ctr
# Wrap all commands in the "docker-in-docker" script to allow nested containers
ENTRYPOINT ["hack/dind"]

View File

@@ -29,28 +29,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
aufs-tools \
&& rm -rf /var/lib/apt/lists/*
# Install runc
ENV RUNC_COMMIT e87436998478d222be209707503c27f6f91be0c5
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \
&& cp runc /usr/local/bin/docker-runc
# Install containerd
ENV CONTAINERD_COMMIT d2f03861c91edaafdcb3961461bf82ae83785ed7
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone git://github.com/docker/containerd.git "$GOPATH/src/github.com/docker/containerd" \
&& cd "$GOPATH/src/github.com/docker/containerd" \
&& git checkout -q "$CONTAINERD_COMMIT" \
&& make static \
&& cp bin/containerd /usr/local/bin/docker-containerd \
&& cp bin/containerd-shim /usr/local/bin/docker-containerd-shim \
&& cp bin/ctr /usr/local/bin/docker-containerd-ctr
ENV AUTO_GOPATH 1
WORKDIR /usr/src/docker
COPY . /usr/src/docker

View File

@@ -1,101 +0,0 @@
# This file describes the standard way to build Docker, using a docker container on Windows
# Server 2016
#
# Usage:
#
# # Assemble the full dev environment. This is slow the first time. Run this from
# # a directory containing the sources you are validating. For example from
# # c:\go\src\github.com\docker\docker
#
# docker build -t docker -f Dockerfile.windows .
#
#
# # Build docker in a container. Run the following from a Windows cmd command prommpt,
# # replacing c:\built with the directory you want the binaries to be placed on the
# # host system.
#
# docker run --rm -v "c:\built:c:\target" docker sh -c 'cd /c/go/src/github.com/docker/docker; hack/make.sh binary; ec=$?; if [ $ec -eq 0 ]; then robocopy /c/go/src/github.com/docker/docker/bundles/$(cat VERSION)/binary /c/target/binary; fi; exit $ec'
#
# Important notes:
# ---------------
#
# 'Start-Sleep' is a deliberate workaround for a current problem on containers in Windows
# Server 2016. It ensures that the network is up and available for when the command is
# network related. This bug is being tracked internally at Microsoft and exists in TP4.
# Generally sleep 1 or 2 is probably enough, but making it 5 to make the build file
# as bullet proof as possible. This isn't a big deal as this only runs the first time.
#
# The cygwin posix utilities from GIT aren't usable interactively as at January 2016. This
# is because they require a console window which isn't present in a container in Windows.
# See the example at the top of this file. Do NOT use -it in that docker run!!!
#
# Don't try to use a volume for passing the source through. The cygwin posix utilities will
# balk at reparse points. Again, see the example at the top of this file on how use a volume
# to get the built binary out of the container.
#
# The steps are minimised dramatically to improve performance (TP4 is slow on commit)
FROM windowsservercore
# Environment variable notes:
# - GO_VERSION must consistent with 'Dockerfile' used by Linux'.
# - FROM_DOCKERFILE is used for detection of building within a container.
ENV GO_VERSION=1.5.4 \
GIT_LOCATION=https://github.com/git-for-windows/git/releases/download/v2.7.2.windows.1/Git-2.7.2-64-bit.exe \
RSRC_COMMIT=ba14da1f827188454a4591717fff29999010887f \
GOPATH=C:/go;C:/go/src/github.com/docker/docker/vendor \
FROM_DOCKERFILE=1
WORKDIR c:/
# Everything downloaded/installed in one go (better performance, esp on TP4)
RUN \
setx /M Path "c:\git\cmd;c:\git\bin;c:\git\usr\bin;%Path%;c:\gcc\bin;c:\go\bin" && \
setx GOROOT "c:\go" && \
powershell -command \
$ErrorActionPreference = 'Stop'; \
Start-Sleep -Seconds 5; \
Function Download-File([string] $source, [string] $target) { \
$wc = New-Object net.webclient; $wc.Downloadfile($source, $target) \
} \
\
Write-Host INFO: Downloading git...; \
Download-File %GIT_LOCATION% gitsetup.exe; \
\
Write-Host INFO: Downloading go...; \
Download-File https://storage.googleapis.com/golang/go%GO_VERSION%.windows-amd64.msi go.msi; \
\
Write-Host INFO: Downloading compiler 1 of 3...; \
Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/gcc.zip gcc.zip; \
\
Write-Host INFO: Downloading compiler 2 of 3...; \
Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/runtime.zip runtime.zip; \
\
Write-Host INFO: Downloading compiler 3 of 3...; \
Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/binutils.zip binutils.zip; \
\
Write-Host INFO: Installing git...; \
Start-Process gitsetup.exe -ArgumentList '/VERYSILENT /SUPPRESSMSGBOXES /CLOSEAPPLICATIONS /DIR=c:\git\' -Wait; \
\
Write-Host INFO: Installing go..."; \
Start-Process msiexec -ArgumentList '-i go.msi -quiet' -Wait; \
\
Write-Host INFO: Unzipping compiler...; \
c:\git\usr\bin\unzip.exe -q -o gcc.zip -d /c/gcc; \
c:\git\usr\bin\unzip.exe -q -o runtime.zip -d /c/gcc; \
c:\git\usr\bin\unzip.exe -q -o binutils.zip -d /c/gcc"; \
\
Write-Host INFO: Removing interim files; \
Remove-Item *.zip; \
Remove-Item go.msi; \
Remove-Item gitsetup.exe; \
\
Write-Host INFO: Cloning and installing RSRC; \
c:\git\bin\git.exe clone https://github.com/akavel/rsrc.git c:\go\src\github.com\akavel\rsrc; \
cd \go\src\github.com\akavel\rsrc; c:\git\bin\git.exe checkout -q %RSRC_COMMIT%; c:\go\bin\go.exe install -v; \
\
Write-Host INFO: Completed
# Prepare for building
COPY . /go/src/github.com/docker/docker

View File

@@ -26,7 +26,6 @@
# the release process is clear and up-to-date.
people = [
"aaronlehmann",
"calavera",
"coolljt0725",
"cpuguy83",
@@ -34,7 +33,6 @@
"duglin",
"estesp",
"icecrime",
"jhowardmsft",
"jfrazelle",
"lk4d4",
"mhbauer",
@@ -71,7 +69,6 @@
# - close an issue or pull request when it's inappropriate or off-topic
people = [
"programmerq",
"thajeztah"
]
@@ -82,7 +79,7 @@
# Thank you!
people = [
# As a maintainer, Erik was responsible for the "builder", and
# As a maintainer, Erik was responsible for the "builder", and
# started the first designs for the new networking model in
# Docker. Erik is now working on all kinds of plugins for Docker
# (https://github.com/contiv) and various open source projects
@@ -114,11 +111,6 @@
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.aaronlehmann]
Name = "Aaron Lehmann"
Email = "aaron.lehmann@docker.com"
GitHub = "aaronlehmann"
[people.calavera]
Name = "David Calavera"
Email = "david.calavera@gmail.com"
@@ -164,14 +156,9 @@
Email = "james@lovedthanlost.net"
GitHub = "jamtur01"
[people.jhowardmsft]
Name = "John Howard"
Email = "jhoward@microsoft.com"
GitHub = "jhowardmsft"
[people.jfrazelle]
Name = "Jessie Frazelle"
Email = "jess@linux.com"
Email = "j@docker.com"
GitHub = "jfrazelle"
[people.lk4d4]
@@ -189,11 +176,6 @@
Email = "mary.anthony@docker.com"
GitHub = "moxiegirl"
[people.programmerq]
Name = "Jeff Anderson"
Email = "jeff@docker.com"
GitHub = "programmerq"
[people.runcom]
Name = "Antonio Murdaca"
Email = "runcom@redhat.com"
@@ -214,6 +196,11 @@
Email = "github@gone.nl"
GitHub = "thaJeztah"
[people.theadactyl]
Name = "Thea Lamkin"
Email = "thea@docker.com"
GitHub = "theadactyl"
[people.tianon]
Name = "Tianon Gravi"
Email = "admwiggin@gmail.com"

View File

@@ -1,22 +1,38 @@
.PHONY: all binary build cross default docs docs-build docs-shell shell test test-docker-py test-integration-cli test-unit validate
# get OS/Arch of docker engine
DOCKER_OSARCH := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $${DOCKER_ENGINE_OSARCH:-$$DOCKER_CLIENT_OSARCH}')
DOCKERFILE := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $${DOCKERFILE}')
DOCKER_OSARCH := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $${DOCKER_ENGINE_OSARCH:+$$DOCKER_CLIENT_OSARCH}')
# default for linux/amd64 and others
DOCKERFILE := Dockerfile
# switch to different Dockerfile for linux/arm
ifeq ($(DOCKER_OSARCH), linux/arm)
DOCKERFILE := Dockerfile.armhf
else
ifeq ($(DOCKER_OSARCH), linux/arm64)
# TODO .arm64
DOCKERFILE := Dockerfile.armhf
else
ifeq ($(DOCKER_OSARCH), linux/ppc64le)
DOCKERFILE := Dockerfile.ppc64le
else
ifeq ($(DOCKER_OSARCH), linux/s390x)
DOCKERFILE := Dockerfile.s390x
endif
endif
endif
endif
export DOCKERFILE
# env vars passed through directly to Docker's build scripts
# to allow things like `make DOCKER_CLIENTONLY=1 binary` easily
# `docs/sources/contributing/devenvironment.md ` and `project/PACKAGERS.md` have some limited documentation of some of these
DOCKER_ENVS := \
-e BUILDFLAGS \
-e KEEPBUNDLE \
-e DOCKER_BUILD_GOGC \
-e DOCKER_BUILD_PKGS \
-e DOCKER_CLIENTONLY \
-e DOCKER_DEBUG \
-e DOCKER_EXPERIMENTAL \
-e DOCKERFILE \
-e DOCKER_GRAPHDRIVER \
-e DOCKER_INCREMENTAL_BINARY \
-e DOCKER_REMAP_ROOT \
-e DOCKER_STORAGE_OPTS \
-e DOCKER_USERLANDPROXY \
@@ -31,10 +47,6 @@ DOCKER_ENVS := \
BIND_DIR := $(if $(BINDDIR),$(BINDDIR),$(if $(DOCKER_HOST),,bundles))
DOCKER_MOUNT := $(if $(BIND_DIR),-v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/docker/docker/$(BIND_DIR)")
# This allows the test suite to be able to run without worrying about the underlying fs used by the container running the daemon (e.g. aufs-on-aufs), so long as the host running the container is running a supported fs.
# The volume will be cleaned up when the container is removed due to `--rm`.
# Note that `BIND_DIR` will already be set to `bundles` if `DOCKER_HOST` is not set (see above BIND_DIR line), in such case this will do nothing since `DOCKER_MOUNT` will already be set.
DOCKER_MOUNT := $(if $(DOCKER_MOUNT),$(DOCKER_MOUNT),-v "/go/src/github.com/docker/docker/bundles")
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
DOCKER_IMAGE := docker-dev$(if $(GIT_BRANCH),:$(GIT_BRANCH))
@@ -61,7 +73,7 @@ binary: build
$(DOCKER_RUN_DOCKER) hack/make.sh binary
build: bundles
docker build ${DOCKER_BUILD_ARGS} -t "$(DOCKER_IMAGE)" -f "$(DOCKERFILE)" .
docker build -t "$(DOCKER_IMAGE)" -f "$(DOCKERFILE)" .
bundles:
mkdir bundles
@@ -69,21 +81,12 @@ bundles:
cross: build
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary binary cross
win: build
$(DOCKER_RUN_DOCKER) hack/make.sh win
tgz: build
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary binary cross tgz
deb: build
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary build-deb
docs:
$(MAKE) -C docs docs
gccgo: build
$(DOCKER_RUN_DOCKER) hack/make.sh gccgo
rpm: build
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary build-rpm
@@ -103,4 +106,4 @@ test-unit: build
$(DOCKER_RUN_DOCKER) hack/make.sh test-unit
validate: build
$(DOCKER_RUN_DOCKER) hack/make.sh validate-dco validate-default-seccomp validate-gofmt validate-pkg validate-lint validate-test validate-toml validate-vet validate-vendor
$(DOCKER_RUN_DOCKER) hack/make.sh validate-dco validate-gofmt validate-pkg validate-lint validate-test validate-toml validate-vet validate-vendor

View File

@@ -216,7 +216,7 @@ We are always open to suggestions on process improvements, and are always lookin
<td>Internet&nbsp;Relay&nbsp;Chat&nbsp;(IRC)</td>
<td>
<p>
IRC is a direct line to our most knowledgeable Docker users; we have
IRC a direct line to our most knowledgeable Docker users; we have
both the <code>#docker</code> and <code>#docker-dev</code> group on
<strong>irc.freenode.net</strong>.
IRC is a rich chat protocol but it can overwhelm new users. You can search
@@ -234,8 +234,6 @@ We are always open to suggestions on process improvements, and are always lookin
The <a href="https://groups.google.com/forum/#!forum/docker-dev" target="_blank">docker-dev</a>
group is for contributors and other people contributing to the Docker
project.
You can join them without an google account by sending an email to e.g. "docker-user+subscribe@googlegroups.com".
After receiving the join-request message, you can simply reply to that to confirm the subscribtion.
</td>
</tr>
<tr>

View File

@@ -33,58 +33,97 @@ won't be accepting pull requests adding or removing items from this file.
# 1. Features and refactoring
## 1.1 Runtime improvements
## 1.1 Security
We recently introduced [`runC`](https://runc.io) as a standalone low-level tool for container
execution. The initial goal was to integrate runC as a replacement in the Engine for the traditional
default libcontainer `execdriver`, but the Engine internals were not ready for this.
Security is a top objective for the Docker Engine. The most notable items we intend to provide in
the near future are:
As runC continued evolving, and the OCI specification along with it, we created
[`containerd`](https://containerd.tools/), a daemon to control and monitor multiple `runC`. This is
the new target for Engine integration, as it can entirely replace the whole `execdriver`
architecture, and container monitoring along with it.
- Trusted distribution of images: the effort is driven by the [distribution](https://github.com/docker/distribution)
group but will have significant impact on the Engine
- [User namespaces](https://github.com/docker/docker/pull/12648)
- [Seccomp support](https://github.com/docker/libcontainer/pull/613)
Docker Engine will rely on a long-running `containerd` companion daemon for all container execution
related operations. This could open the door in the future for Engine restarts without interrupting
running containers.
## 1.2 Plumbing project
## 1.2 Plugins improvements
We define a plumbing tool as a standalone piece of software usable and meaningful on its own. In
the current state of the Docker Engine, most subsystems provide independent functionalities (such
the builder, pushing and pulling images, running applications in a containerized environment, etc)
but all are coupled in a single binary. We want to offer the users to flexibility to use only the
pieces they need, and we will also gain in maintainability by splitting the project among multiple
repositories.
Docker Engine 1.7.0 introduced plugin support, initially for the use cases of volumes and networks
extensions. The plugin infrastructure was kept minimal as we were collecting use cases and real
world feedback before optimizing for any particular workflow.
As it currently stands, the rough design outlines is to have:
- Low level plumbing tools, each dealing with one responsibility (e.g., [runC](https://runc.io))
- Docker subsystems services, each exposing an elementary concept over an API, and relying on one or
multiple lower level plumbing tools for their implementation (e.g., network management)
- Docker Engine to expose higher level actions (e.g., create a container with volume `V` and network
`N`), while still providing pass-through access to the individual subsystems.
In the future, we'd like plugins to become first class citizens, and encourage an ecosystem of
plugins. This implies in particular making it trivially easy to distribute plugins as containers
through any Registry instance, as well as solving the commonly heard pain points of plugins needing
to be treated as somewhat special (being active at all time, started before any other user
containers, and not as easily dismissed).
The architectural details are still being worked on, but one thing we know for sure is that we need
to technically decouple the pieces.
## 1.3 Internal decoupling
### 1.2.1 Runtime
A lot of work has been done in trying to decouple the Docker Engine's internals. In particular, the
API implementation has been refactored and ongoing work is happening to move the code to a separate
repository ([`docker/engine-api`](https://github.com/docker/engine-api)), and the Builder side of
the daemon is now [fully independent](https://github.com/docker/docker/tree/master/builder) while
still residing in the same repository.
A Runtime tool already exists today in the form of [runC](https://github.com/opencontainers/runc).
We intend to modify the Engine to directly call out to a binary implementing the Open Containers
Specification such as runC rather than relying on libcontainer to set the container runtime up.
We are exploring ways to go further with that decoupling, capitalizing on the work introduced by the
runtime renovation and plugins improvement efforts. Indeed, the combination of `containerd` support
with the concept of "special" containers opens the door for bootstrapping more Engine internals
using the same facilities.
This plan will deprecate the existing [`execdriver`](https://github.com/docker/docker/tree/master/daemon/execdriver)
as different runtime backends will be implemented as separated binaries instead of being compiled
into the Engine.
## 1.4 Cluster capable Engine
### 1.2.2 Builder
The community has been pushing for a more cluster capable Docker Engine, and a huge effort was spent
adding features such as multihost networking, and node discovery down at the Engine level. Yet, the
Engine is currently incapable of taking scheduling decisions alone, and continues relying on Swarm
for that.
The Builder (i.e., the ability to build an image from a Dockerfile) is already nicely decoupled,
but would benefit from being entirely separated from the Engine, and rely on the standard Engine
API for its operations.
We plan to complete this effort and make Engine fully cluster capable. Multiple instances of the
Docker Engine being already capable of discovering each other and establish overlay networking for
their container to communicate, the next step is for a given Engine to gain ability to dispatch work
to another node in the cluster. This will be introduced in a backward compatible way, such that a
`docker run` invocation on a particular node remains fully deterministic.
### 1.2.3 Distribution
Distribution already has a [dedicated repository](https://github.com/docker/distribution) which
holds the implementation for Registry v2 and client libraries. We could imagine going further by
having the Engine call out to a binary providing image distribution related functionalities.
There are two short term goals related to image distribution. The first is stabilize and simplify
the push/pull code. Following that is the conversion to the more secure Registry V2 protocol.
### 1.2.4 Networking
Most of networking related code was already decoupled today in [libnetwork](https://github.com/docker/libnetwork).
As with other ingredients, we might want to take it a step further and make it a meaningful utility
that the Engine would call out to instead of a library.
## 1.3 Plugins
An initiative around plugins started with Docker 1.7.0, with the goal of allowing for out of
process extensibility of some Docker functionalities, starting with volumes and networking. The
approach is to provide specific extension points rather than generic hooking facilities. We also
deliberately keep the extensions API the simplest possible, expanding as we discover valid use
cases that cannot be implemented.
At the time of writing:
- Plugin support is merged as an experimental feature: real world use cases and user feedback will
help us refine the UX to make the feature more user friendly.
- There are no immediate plans to expand on the number of pluggable subsystems.
- Golang 1.5 might add language support for [plugins](https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ)
which we consider supporting as an alternative to JSON/HTTP.
## 1.4 Volume management
Volumes are not a first class citizen in the Engine today: we would like better volume management,
similar to the way network are managed in the new [CNM](https://github.com/docker/docker/issues/9983).
## 1.5 Better API implementation
The current Engine API is insufficiently typed, versioned, and ultimately hard to maintain. We
also suffer from the lack of a common implementation with [Swarm](https://github.com/docker/swarm).
## 1.6 Checkpoint/restore
Support for checkpoint/restore was [merged](https://github.com/docker/libcontainer/pull/479) in
[libcontainer](https://github.com/docker/libcontainer) and made available through [runC](https://runc.io):
we intend to take advantage of it in the Engine.
# 2 Frozen features
@@ -100,41 +139,45 @@ The Dockerfile syntax as we know it is simple, and has proven successful in supp
definitive move, we temporarily won't accept more patches to the Dockerfile syntax for several
reasons:
- Long term impact of syntax changes is a sensitive matter that require an amount of attention the
volume of Engine codebase and activity today doesn't allow us to provide.
- Allowing the Builder to be implemented as a separate utility consuming the Engine's API will
open the door for many possibilities, such as offering alternate syntaxes or DSL for existing
languages without cluttering the Engine's codebase.
- A standalone Builder will also offer the opportunity for a better dedicated group of maintainers
to own the Dockerfile syntax and decide collectively on the direction to give it.
- Our experience with official images tend to show that no new instruction or syntax expansion is
*strictly* necessary for the majority of use cases, and although we are aware many things are
still lacking for many, we cannot make it a priority yet for the above reasons.
- Long term impact of syntax changes is a sensitive matter that require an amount of attention
the volume of Engine codebase and activity today doesn't allow us to provide.
- Allowing the Builder to be implemented as a separate utility consuming the Engine's API will
open the door for many possibilities, such as offering alternate syntaxes or DSL for existing
languages without cluttering the Engine's codebase.
- A standalone Builder will also offer the opportunity for a better dedicated group of maintainers
to own the Dockerfile syntax and decide collectively on the direction to give it.
- Our experience with official images tend to show that no new instruction or syntax expansion is
*strictly* necessary for the majority of use cases, and although we are aware many things are still
lacking for many, we cannot make it a priority yet for the above reasons.
Again, this is not about saying that the Dockerfile syntax is done, it's about making choices about
what we want to do first!
## 2.3 Remote Registry Operations
A large amount of work is ongoing in the area of image distribution and provenance. This includes
moving to the V2 Registry API and heavily refactoring the code that powers these features. The
desired result is more secure, reliable and easier to use image distribution.
A large amount of work is ongoing in the area of image distribution and
provenance. This includes moving to the V2 Registry API and heavily
refactoring the code that powers these features. The desired result is more
secure, reliable and easier to use image distribution.
Part of the problem with this part of the code base is the lack of a stable and flexible interface.
If new features are added that access the registry without solidifying these interfaces, achieving
feature parity will continue to be elusive. While we get a handle on this situation, we are imposing
a moratorium on new code that accesses the Registry API in commands that don't already make remote
calls.
Part of the problem with this part of the code base is the lack of a stable
and flexible interface. If new features are added that access the registry
without solidifying these interfaces, achieving feature parity will continue
to be elusive. While we get a handle on this situation, we are imposing a
moratorium on new code that accesses the Registry API in commands that don't
already make remote calls.
Currently, only the following commands cause interaction with a remote registry:
Currently, only the following commands cause interaction with a remote
registry:
- push
- pull
- run
- build
- search
- login
- push
- pull
- run
- build
- search
- login
In the interest of stabilizing the registry access model during this ongoing work, we are not
accepting additions to other commands that will cause remote interaction with the Registry API. This
moratorium will lift when the goals of the distribution project have been met.
In the interest of stabilizing the registry access model during this ongoing
work, we are not accepting additions to other commands that will cause remote
interaction with the Registry API. This moratorium will lift when the goals of
the distribution project have been met.

View File

@@ -1 +1 @@
1.11.0
1.10.0-rc4

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"io"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
@@ -26,7 +24,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
cmd.ParseFlags(args, true)
c, err := cli.client.ContainerInspect(context.Background(), cmd.Arg(0))
c, err := cli.client.ContainerInspect(cmd.Arg(0))
if err != nil {
return err
}
@@ -43,6 +41,12 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
return err
}
if c.Config.Tty && cli.isTerminalOut {
if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
logrus.Debugf("Error monitoring TTY size: %s", err)
}
}
if *detachKeys != "" {
cli.configFile.DetachKeys = *detachKeys
}
@@ -66,7 +70,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
defer signal.StopCatch(sigc)
}
resp, err := cli.client.ContainerAttach(context.Background(), options)
resp, err := cli.client.ContainerAttach(options)
if err != nil {
return err
}
@@ -78,21 +82,6 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
defer cli.restoreTerminal(in)
}
if c.Config.Tty && cli.isTerminalOut {
height, width := cli.getTtySize()
// To handle the case where a user repeatedly attaches/detaches without resizing their
// terminal, the only way to get the shell prompt to display for attaches 2+ is to artificially
// resize it, then go back to normal. Without this, every attach after the first will
// require the user to manually resize or hit enter.
cli.resizeTtyTo(cmd.Arg(0), height+1, width+1, false)
// After the above resizing occurs, the call to monitorTtySize below will handle resetting back
// to the actual size.
if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
logrus.Debugf("Error monitoring TTY size: %s", err)
}
}
if err := cli.holdHijackedConnection(c.Config.Tty, in, cli.out, cli.err, resp); err != nil {
return err
}

View File

@@ -6,20 +6,23 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"golang.org/x/net/context"
"strings"
"github.com/docker/docker/api"
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/dockerignore"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/gitutils"
"github.com/docker/docker/pkg/httputils"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/jsonmessage"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/progress"
@@ -60,10 +63,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
flCgroupParent := cmd.String([]string{"-cgroup-parent"}, "", "Optional parent cgroup for the container")
flBuildArg := opts.NewListOpts(runconfigopts.ValidateEnv)
cmd.Var(&flBuildArg, []string{"-build-arg"}, "Set build-time variables")
isolation := cmd.String([]string{"-isolation"}, "", "Container isolation technology")
flLabels := opts.NewListOpts(nil)
cmd.Var(&flLabels, []string{"-label"}, "Set metadata for an image")
isolation := cmd.String([]string{"-isolation"}, "", "Container isolation level")
ulimits := make(map[string]*units.Ulimit)
flUlimits := runconfigopts.NewUlimitOpt(&ulimits)
@@ -77,8 +77,9 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
cmd.ParseFlags(args, true)
var (
ctx io.ReadCloser
err error
context io.ReadCloser
isRemote bool
err error
)
specifiedContext := cmd.Arg(0)
@@ -100,13 +101,13 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
switch {
case specifiedContext == "-":
ctx, relDockerfile, err = builder.GetContextFromReader(cli.in, *dockerfileName)
context, relDockerfile, err = getContextFromReader(cli.in, *dockerfileName)
case urlutil.IsGitURL(specifiedContext):
tempDir, relDockerfile, err = builder.GetContextFromGitURL(specifiedContext, *dockerfileName)
tempDir, relDockerfile, err = getContextFromGitURL(specifiedContext, *dockerfileName)
case urlutil.IsURL(specifiedContext):
ctx, relDockerfile, err = builder.GetContextFromURL(progBuff, specifiedContext, *dockerfileName)
context, relDockerfile, err = getContextFromURL(progBuff, specifiedContext, *dockerfileName)
default:
contextDir, relDockerfile, err = builder.GetContextFromLocalDir(specifiedContext, *dockerfileName)
contextDir, relDockerfile, err = getContextFromLocalDir(specifiedContext, *dockerfileName)
}
if err != nil {
@@ -121,7 +122,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
contextDir = tempDir
}
if ctx == nil {
if context == nil {
// And canonicalize dockerfile name to a platform-independent one
relDockerfile, err = archive.CanonicalTarNameForPath(relDockerfile)
if err != nil {
@@ -141,7 +142,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
}
}
if err := builder.ValidateContextDirectory(contextDir, excludes); err != nil {
if err := validateContextDirectory(contextDir, excludes); err != nil {
return fmt.Errorf("Error checking context: '%s'.", err)
}
@@ -159,7 +160,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
includes = append(includes, ".dockerignore", relDockerfile)
}
ctx, err = archive.TarWithOptions(contextDir, &archive.TarOptions{
context, err = archive.TarWithOptions(contextDir, &archive.TarOptions{
Compression: archive.Uncompressed,
ExcludePatterns: excludes,
IncludeFiles: includes,
@@ -173,13 +174,13 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
if isTrusted() {
// Wrap the tar archive to replace the Dockerfile entry with the rewritten
// Dockerfile which uses trusted pulls.
ctx = replaceDockerfileTarWrapper(ctx, relDockerfile, cli.trustedReference, &resolvedTags)
context = replaceDockerfileTarWrapper(context, relDockerfile, cli.trustedReference, &resolvedTags)
}
// Setup an upload progress bar
progressOutput := streamformatter.NewStreamFormatter().NewProgressOutput(progBuff, true)
var body io.Reader = progress.NewProgressReader(ctx, progressOutput, 0, "", "Sending build context to Docker daemon")
var body io.Reader = progress.NewProgressReader(context, progressOutput, 0, "", "Sending build context to Docker daemon")
var memory int64
if *flMemoryString != "" {
@@ -211,17 +212,23 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
}
}
var remoteContext string
if isRemote {
remoteContext = cmd.Arg(0)
}
options := types.ImageBuildOptions{
Context: body,
Memory: memory,
MemorySwap: memorySwap,
Tags: flTags.GetAll(),
SuppressOutput: *suppressOutput,
RemoteContext: remoteContext,
NoCache: *noCache,
Remove: *rm,
ForceRemove: *forceRm,
PullParent: *pull,
Isolation: container.Isolation(*isolation),
IsolationLevel: container.IsolationLevel(*isolation),
CPUSetCPUs: *flCPUSetCpus,
CPUSetMems: *flCPUSetMems,
CPUShares: *flCPUShares,
@@ -232,15 +239,13 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
ShmSize: shmSize,
Ulimits: flUlimits.GetList(),
BuildArgs: runconfigopts.ConvertKVStringsToMap(flBuildArg.GetAll()),
AuthConfigs: cli.retrieveAuthConfigs(),
Labels: runconfigopts.ConvertKVStringsToMap(flLabels.GetAll()),
AuthConfigs: cli.configFile.AuthConfigs,
}
response, err := cli.client.ImageBuild(context.Background(), options)
response, err := cli.client.ImageBuild(options)
if err != nil {
return err
}
defer response.Body.Close()
err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, cli.outFd, cli.isTerminalOut, nil)
if err != nil {
@@ -281,6 +286,54 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
return nil
}
// validateContextDirectory checks if all the contents of the directory
// can be read and returns an error if some files can't be read
// symlinks which point to non-existing files don't trigger an error
func validateContextDirectory(srcPath string, excludes []string) error {
contextRoot, err := getContextRoot(srcPath)
if err != nil {
return err
}
return filepath.Walk(contextRoot, func(filePath string, f os.FileInfo, err error) error {
// skip this directory/file if it's not in the path, it won't get added to the context
if relFilePath, err := filepath.Rel(contextRoot, filePath); err != nil {
return err
} else if skip, err := fileutils.Matches(relFilePath, excludes); err != nil {
return err
} else if skip {
if f.IsDir() {
return filepath.SkipDir
}
return nil
}
if err != nil {
if os.IsPermission(err) {
return fmt.Errorf("can't stat '%s'", filePath)
}
if os.IsNotExist(err) {
return nil
}
return err
}
// skip checking if symlinks point to non-existing files, such symlinks can be useful
// also skip named pipes, because they hanging on open
if f.Mode()&(os.ModeSymlink|os.ModeNamedPipe) != 0 {
return nil
}
if !f.IsDir() {
currentFile, err := os.Open(filePath)
if err != nil && os.IsPermission(err) {
return fmt.Errorf("no permission to read from '%s'", filePath)
}
currentFile.Close()
}
return nil
})
}
// validateTag checks if the given image name can be resolved.
func validateTag(rawRepo string) (string, error) {
_, err := reference.ParseNamed(rawRepo)
@@ -291,6 +344,213 @@ func validateTag(rawRepo string) (string, error) {
return rawRepo, nil
}
// isUNC returns true if the path is UNC (one starting \\). It always returns
// false on Linux.
func isUNC(path string) bool {
return runtime.GOOS == "windows" && strings.HasPrefix(path, `\\`)
}
// getDockerfileRelPath uses the given context directory for a `docker build`
// and returns the absolute path to the context directory, the relative path of
// the dockerfile in that context directory, and a non-nil error on success.
func getDockerfileRelPath(givenContextDir, givenDockerfile string) (absContextDir, relDockerfile string, err error) {
if absContextDir, err = filepath.Abs(givenContextDir); err != nil {
return "", "", fmt.Errorf("unable to get absolute context directory: %v", err)
}
// The context dir might be a symbolic link, so follow it to the actual
// target directory.
//
// FIXME. We use isUNC (always false on non-Windows platforms) to workaround
// an issue in golang. On Windows, EvalSymLinks does not work on UNC file
// paths (those starting with \\). This hack means that when using links
// on UNC paths, they will not be followed.
if !isUNC(absContextDir) {
absContextDir, err = filepath.EvalSymlinks(absContextDir)
if err != nil {
return "", "", fmt.Errorf("unable to evaluate symlinks in context path: %v", err)
}
}
stat, err := os.Lstat(absContextDir)
if err != nil {
return "", "", fmt.Errorf("unable to stat context directory %q: %v", absContextDir, err)
}
if !stat.IsDir() {
return "", "", fmt.Errorf("context must be a directory: %s", absContextDir)
}
absDockerfile := givenDockerfile
if absDockerfile == "" {
// No -f/--file was specified so use the default relative to the
// context directory.
absDockerfile = filepath.Join(absContextDir, api.DefaultDockerfileName)
// Just to be nice ;-) look for 'dockerfile' too but only
// use it if we found it, otherwise ignore this check
if _, err = os.Lstat(absDockerfile); os.IsNotExist(err) {
altPath := filepath.Join(absContextDir, strings.ToLower(api.DefaultDockerfileName))
if _, err = os.Lstat(altPath); err == nil {
absDockerfile = altPath
}
}
}
// If not already an absolute path, the Dockerfile path should be joined to
// the base directory.
if !filepath.IsAbs(absDockerfile) {
absDockerfile = filepath.Join(absContextDir, absDockerfile)
}
// Evaluate symlinks in the path to the Dockerfile too.
//
// FIXME. We use isUNC (always false on non-Windows platforms) to workaround
// an issue in golang. On Windows, EvalSymLinks does not work on UNC file
// paths (those starting with \\). This hack means that when using links
// on UNC paths, they will not be followed.
if !isUNC(absDockerfile) {
absDockerfile, err = filepath.EvalSymlinks(absDockerfile)
if err != nil {
return "", "", fmt.Errorf("unable to evaluate symlinks in Dockerfile path: %v", err)
}
}
if _, err := os.Lstat(absDockerfile); err != nil {
if os.IsNotExist(err) {
return "", "", fmt.Errorf("Cannot locate Dockerfile: %q", absDockerfile)
}
return "", "", fmt.Errorf("unable to stat Dockerfile: %v", err)
}
if relDockerfile, err = filepath.Rel(absContextDir, absDockerfile); err != nil {
return "", "", fmt.Errorf("unable to get relative Dockerfile path: %v", err)
}
if strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
return "", "", fmt.Errorf("The Dockerfile (%s) must be within the build context (%s)", givenDockerfile, givenContextDir)
}
return absContextDir, relDockerfile, nil
}
// writeToFile copies from the given reader and writes it to a file with the
// given filename.
func writeToFile(r io.Reader, filename string) error {
file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
if err != nil {
return fmt.Errorf("unable to create file: %v", err)
}
defer file.Close()
if _, err := io.Copy(file, r); err != nil {
return fmt.Errorf("unable to write file: %v", err)
}
return nil
}
// getContextFromReader will read the contents of the given reader as either a
// Dockerfile or tar archive. Returns a tar archive used as a context and a
// path to the Dockerfile inside the tar.
func getContextFromReader(r io.ReadCloser, dockerfileName string) (out io.ReadCloser, relDockerfile string, err error) {
buf := bufio.NewReader(r)
magic, err := buf.Peek(archive.HeaderSize)
if err != nil && err != io.EOF {
return nil, "", fmt.Errorf("failed to peek context header from STDIN: %v", err)
}
if archive.IsArchive(magic) {
return ioutils.NewReadCloserWrapper(buf, func() error { return r.Close() }), dockerfileName, nil
}
// Input should be read as a Dockerfile.
tmpDir, err := ioutil.TempDir("", "docker-build-context-")
if err != nil {
return nil, "", fmt.Errorf("unbale to create temporary context directory: %v", err)
}
f, err := os.Create(filepath.Join(tmpDir, api.DefaultDockerfileName))
if err != nil {
return nil, "", err
}
_, err = io.Copy(f, buf)
if err != nil {
f.Close()
return nil, "", err
}
if err := f.Close(); err != nil {
return nil, "", err
}
if err := r.Close(); err != nil {
return nil, "", err
}
tar, err := archive.Tar(tmpDir, archive.Uncompressed)
if err != nil {
return nil, "", err
}
return ioutils.NewReadCloserWrapper(tar, func() error {
err := tar.Close()
os.RemoveAll(tmpDir)
return err
}), api.DefaultDockerfileName, nil
}
// getContextFromGitURL uses a Git URL as context for a `docker build`. The
// git repo is cloned into a temporary directory used as the context directory.
// Returns the absolute path to the temporary context directory, the relative
// path of the dockerfile in that context directory, and a non-nil error on
// success.
func getContextFromGitURL(gitURL, dockerfileName string) (absContextDir, relDockerfile string, err error) {
if _, err := exec.LookPath("git"); err != nil {
return "", "", fmt.Errorf("unable to find 'git': %v", err)
}
if absContextDir, err = gitutils.Clone(gitURL); err != nil {
return "", "", fmt.Errorf("unable to 'git clone' to temporary context directory: %v", err)
}
return getDockerfileRelPath(absContextDir, dockerfileName)
}
// getContextFromURL uses a remote URL as context for a `docker build`. The
// remote resource is downloaded as either a Dockerfile or a tar archive.
// Returns the tar archive used for the context and a path of the
// dockerfile inside the tar.
func getContextFromURL(out io.Writer, remoteURL, dockerfileName string) (io.ReadCloser, string, error) {
response, err := httputils.Download(remoteURL)
if err != nil {
return nil, "", fmt.Errorf("unable to download remote context %s: %v", remoteURL, err)
}
progressOutput := streamformatter.NewStreamFormatter().NewProgressOutput(out, true)
// Pass the response body through a progress reader.
progReader := progress.NewProgressReader(response.Body, progressOutput, response.ContentLength, "", fmt.Sprintf("Downloading build context from remote url: %s", remoteURL))
return getContextFromReader(ioutils.NewReadCloserWrapper(progReader, func() error { return response.Body.Close() }), dockerfileName)
}
// getContextFromLocalDir uses the given local directory as context for a
// `docker build`. Returns the absolute path to the local context directory,
// the relative path of the dockerfile in that context directory, and a non-nil
// error on success.
func getContextFromLocalDir(localDir, dockerfileName string) (absContextDir, relDockerfile string, err error) {
// When using a local context directory, when the Dockerfile is specified
// with the `-f/--file` option then it is considered relative to the
// current directory and not the context directory.
if dockerfileName != "" {
if dockerfileName, err = filepath.Abs(dockerfileName); err != nil {
return "", "", fmt.Errorf("unable to get absolute path to Dockerfile: %v", err)
}
}
return getDockerfileRelPath(localDir, dockerfileName)
}
var dockerfileFromLinePattern = regexp.MustCompile(`(?i)^[\s]*FROM[ \f\r\t\v]+(?P<image>[^ \f\r\t\v\n#]+)`)
// resolvedTag records the repository, tag, and resolved digest reference

View File

@@ -11,12 +11,10 @@ import (
"github.com/docker/docker/api"
"github.com/docker/docker/cli"
"github.com/docker/docker/cliconfig"
"github.com/docker/docker/cliconfig/credentials"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/term"
"github.com/docker/engine-api/client"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
)
@@ -126,9 +124,6 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, clientFlags *cli.ClientF
if e != nil {
fmt.Fprintf(cli.err, "WARNING: Error loading config file:%v\n", e)
}
if !configFile.ContainsAuth() {
credentials.DetectDefaultStore(configFile)
}
cli.configFile = configFile
host, err := getServerHost(clientFlags.Common.Hosts, clientFlags.Common.TLSOptions)
@@ -140,19 +135,19 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, clientFlags *cli.ClientF
if customHeaders == nil {
customHeaders = map[string]string{}
}
customHeaders["User-Agent"] = clientUserAgent()
customHeaders["User-Agent"] = "Docker-Client/" + dockerversion.Version + " (" + runtime.GOOS + ")"
verStr := api.DefaultVersion.String()
if tmpStr := os.Getenv("DOCKER_API_VERSION"); tmpStr != "" {
verStr = tmpStr
}
httpClient, err := newHTTPClient(host, clientFlags.Common.TLSOptions)
clientTransport, err := newClientTransport(clientFlags.Common.TLSOptions)
if err != nil {
return err
}
client, err := client.NewClient(host, verStr, httpClient, customHeaders)
client, err := client.NewClient(host, verStr, clientTransport, customHeaders)
if err != nil {
return err
}
@@ -181,35 +176,25 @@ func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (host string,
return "", errors.New("Please specify only one -H")
}
host, err = opts.ParseHost(tlsOptions != nil, host)
defaultHost := opts.DefaultTCPHost
if tlsOptions != nil {
defaultHost = opts.DefaultTLSHost
}
host, err = opts.ParseHost(defaultHost, host)
return
}
func newHTTPClient(host string, tlsOptions *tlsconfig.Options) (*http.Client, error) {
func newClientTransport(tlsOptions *tlsconfig.Options) (*http.Transport, error) {
if tlsOptions == nil {
// let the api client configure the default transport.
return nil, nil
return &http.Transport{}, nil
}
config, err := tlsconfig.Client(*tlsOptions)
if err != nil {
return nil, err
}
tr := &http.Transport{
return &http.Transport{
TLSClientConfig: config,
}
proto, addr, _, err := client.ParseHost(host)
if err != nil {
return nil, err
}
sockets.ConfigureTransport(tr, proto, addr)
return &http.Client{
Transport: tr,
}, nil
}
func clientUserAgent() string {
return "Docker-Client/" + dockerversion.Version + " (" + runtime.GOOS + ")"
}

View File

@@ -5,8 +5,6 @@ import (
"errors"
"fmt"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
@@ -75,7 +73,7 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
Config: config,
}
response, err := cli.client.ContainerCommit(context.Background(), options)
response, err := cli.client.ContainerCommit(options)
if err != nil {
return err
}

View File

@@ -7,8 +7,6 @@ import (
"path/filepath"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/pkg/archive"
flag "github.com/docker/docker/pkg/mflag"
@@ -127,7 +125,7 @@ func splitCpArg(arg string) (container, path string) {
}
func (cli *DockerCli) statContainerPath(containerName, path string) (types.ContainerPathStat, error) {
return cli.client.ContainerStatPath(context.Background(), containerName, path)
return cli.client.ContainerStatPath(containerName, path)
}
func resolveLocalPath(localPath string) (absPath string, err error) {
@@ -167,7 +165,7 @@ func (cli *DockerCli) copyFromContainer(srcContainer, srcPath, dstPath string, c
}
content, stat, err := cli.client.CopyFromContainer(context.Background(), srcContainer, srcPath)
content, stat, err := cli.client.CopyFromContainer(srcContainer, srcPath)
if err != nil {
return err
}
@@ -294,5 +292,5 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string, cpP
AllowOverwriteDirWithFile: false,
}
return cli.client.CopyToContainer(context.Background(), options)
return cli.client.CopyToContainer(options)
}

View File

@@ -5,8 +5,6 @@ import (
"io"
"os"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/reference"
@@ -42,7 +40,7 @@ func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
return err
}
authConfig := cli.resolveAuthConfig(repoInfo.Index)
authConfig := cli.resolveAuthConfig(cli.configFile.AuthConfigs, repoInfo.Index)
encodedAuth, err := encodeAuthToBase64(authConfig)
if err != nil {
return err
@@ -54,7 +52,7 @@ func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
RegistryAuth: encodedAuth,
}
responseBody, err := cli.client.ImageCreate(context.Background(), options)
responseBody, err := cli.client.ImageCreate(options)
if err != nil {
return err
}
@@ -92,30 +90,29 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
defer containerIDFile.Close()
}
var trustedRef reference.Canonical
_, ref, err := reference.ParseIDOrReference(config.Image)
ref, err := reference.ParseNamed(config.Image)
if err != nil {
return nil, err
}
if ref != nil {
ref = reference.WithDefaultTag(ref)
ref = reference.WithDefaultTag(ref)
if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
var err error
trustedRef, err = cli.trustedReference(ref)
if err != nil {
return nil, err
}
config.Image = trustedRef.String()
var trustedRef reference.Canonical
if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
var err error
trustedRef, err = cli.trustedReference(ref)
if err != nil {
return nil, err
}
config.Image = trustedRef.String()
}
//create the container
response, err := cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name)
response, err := cli.client.ContainerCreate(config, hostConfig, networkingConfig, name)
//if image not found try to pull it
if err != nil {
if client.IsErrImageNotFound(err) && ref != nil {
if client.IsErrImageNotFound(err) {
fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.String())
// we don't want to write to stdout anything apart from container.ID
@@ -129,7 +126,7 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
}
// Retry
var retryErr error
response, retryErr = cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name)
response, retryErr = cli.client.ContainerCreate(config, hostConfig, networkingConfig, name)
if retryErr != nil {
return nil, retryErr
}

View File

@@ -3,8 +3,6 @@ package client
import (
"fmt"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/pkg/archive"
flag "github.com/docker/docker/pkg/mflag"
@@ -27,7 +25,7 @@ func (cli *DockerCli) CmdDiff(args ...string) error {
return fmt.Errorf("Container name cannot be empty")
}
changes, err := cli.client.ContainerDiff(context.Background(), cmd.Arg(0))
changes, err := cli.client.ContainerDiff(cmd.Arg(0))
if err != nil {
return err
}

View File

@@ -4,14 +4,9 @@ import (
"encoding/json"
"fmt"
"io"
"sort"
"strings"
"sync"
"time"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/jsonlog"
@@ -52,7 +47,7 @@ func (cli *DockerCli) CmdEvents(args ...string) error {
Filters: eventFilterArgs,
}
responseBody, err := cli.client.Events(context.Background(), options)
responseBody, err := cli.client.Events(options)
if err != nil {
return err
}
@@ -104,43 +99,10 @@ func printOutput(event eventtypes.Message, output io.Writer) {
if len(event.Actor.Attributes) > 0 {
var attrs []string
var keys []string
for k := range event.Actor.Attributes {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
v := event.Actor.Attributes[k]
for k, v := range event.Actor.Attributes {
attrs = append(attrs, fmt.Sprintf("%s=%s", k, v))
}
fmt.Fprintf(output, " (%s)", strings.Join(attrs, ", "))
}
fmt.Fprint(output, "\n")
}
type eventHandler struct {
handlers map[string]func(eventtypes.Message)
mu sync.Mutex
}
func (w *eventHandler) Handle(action string, h func(eventtypes.Message)) {
w.mu.Lock()
w.handlers[action] = h
w.mu.Unlock()
}
// Watch ranges over the passed in event chan and processes the events based on the
// handlers created for a given action.
// To stop watching, close the event chan.
func (w *eventHandler) Watch(c <-chan eventtypes.Message) {
for e := range c {
w.mu.Lock()
h, exists := w.handlers[e.Action]
w.mu.Unlock()
if !exists {
continue
}
logrus.Debugf("event handler: received event: %v", e)
go h(e)
}
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"io"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
@@ -33,7 +31,7 @@ func (cli *DockerCli) CmdExec(args ...string) error {
// Send client escape keys
execConfig.DetachKeys = cli.configFile.DetachKeys
response, err := cli.client.ContainerExecCreate(context.Background(), *execConfig)
response, err := cli.client.ContainerExecCreate(*execConfig)
if err != nil {
return err
}
@@ -55,7 +53,7 @@ func (cli *DockerCli) CmdExec(args ...string) error {
Tty: execConfig.Tty,
}
if err := cli.client.ContainerExecStart(context.Background(), execID, execStartCheck); err != nil {
if err := cli.client.ContainerExecStart(execID, execStartCheck); err != nil {
return err
}
// For now don't print this - wait for when we support exec wait()
@@ -84,7 +82,7 @@ func (cli *DockerCli) CmdExec(args ...string) error {
}
}
resp, err := cli.client.ContainerExecAttach(context.Background(), execID, *execConfig)
resp, err := cli.client.ContainerExecAttach(execID, *execConfig)
if err != nil {
return err
}

View File

@@ -3,8 +3,7 @@ package client
import (
"errors"
"io"
"golang.org/x/net/context"
"os"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
@@ -22,21 +21,25 @@ func (cli *DockerCli) CmdExport(args ...string) error {
cmd.ParseFlags(args, true)
if *outfile == "" && cli.isTerminalOut {
var (
output = cli.out
err error
)
if *outfile != "" {
output, err = os.Create(*outfile)
if err != nil {
return err
}
} else if cli.isTerminalOut {
return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.")
}
responseBody, err := cli.client.ContainerExport(context.Background(), cmd.Arg(0))
responseBody, err := cli.client.ContainerExport(cmd.Arg(0))
if err != nil {
return err
}
defer responseBody.Close()
if *outfile == "" {
_, err := io.Copy(cli.out, responseBody)
return err
}
return copyToFile(*outfile, responseBody)
_, err = io.Copy(output, responseBody)
return err
}

View File

@@ -31,7 +31,6 @@ const (
repositoryHeader = "REPOSITORY"
tagHeader = "TAG"
digestHeader = "DIGEST"
mountsHeader = "MOUNTS"
)
type containerContext struct {
@@ -143,25 +142,6 @@ func (c *containerContext) Label(name string) string {
return c.c.Labels[name]
}
func (c *containerContext) Mounts() string {
c.addHeader(mountsHeader)
var name string
var mounts []string
for _, m := range c.c.Mounts {
if m.Name == "" {
name = m.Source
} else {
name = m.Name
}
if c.trunc {
name = stringutils.Truncate(name, 15)
}
mounts = append(mounts, name)
}
return strings.Join(mounts, ",")
}
type imageContext struct {
baseSubContext
trunc bool

View File

@@ -12,7 +12,7 @@ import (
func TestContainerPsContext(t *testing.T) {
containerID := stringid.GenerateRandomID()
unix := time.Now().Add(-65 * time.Second).Unix()
unix := time.Now().Unix()
var ctx containerContext
cases := []struct {
@@ -55,7 +55,7 @@ func TestContainerPsContext(t *testing.T) {
{types.Container{SizeRw: 10, SizeRootFs: 20}, true, "10 B (virtual 20 B)", sizeHeader, ctx.Size},
{types.Container{}, true, "", labelsHeader, ctx.Labels},
{types.Container{Labels: map[string]string{"cpu": "6", "storage": "ssd"}}, true, "cpu=6,storage=ssd", labelsHeader, ctx.Labels},
{types.Container{Created: unix}, true, "About a minute", runningForHeader, ctx.RunningFor},
{types.Container{Created: unix}, true, "Less than a second", runningForHeader, ctx.RunningFor},
}
for _, c := range cases {

View File

@@ -9,7 +9,6 @@ import (
"text/template"
"github.com/docker/docker/reference"
"github.com/docker/docker/utils/templates"
"github.com/docker/engine-api/types"
)
@@ -55,7 +54,7 @@ func (c *Context) preformat() {
}
func (c *Context) parseFormat() (*template.Template, error) {
tmpl, err := templates.Parse(c.finalFormat)
tmpl, err := template.New("").Parse(c.finalFormat)
if err != nil {
c.buffer.WriteString(fmt.Sprintf("Template parsing error: %v\n", err))
c.buffer.WriteTo(c.Output)

View File

@@ -7,8 +7,6 @@ import (
"text/tabwriter"
"time"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/stringid"
@@ -28,7 +26,7 @@ func (cli *DockerCli) CmdHistory(args ...string) error {
cmd.ParseFlags(args, true)
history, err := cli.client.ImageHistory(context.Background(), cmd.Arg(0))
history, err := cli.client.ImageHistory(cmd.Arg(0))
if err != nil {
return err
}

View File

@@ -1,8 +1,6 @@
package client
import (
"golang.org/x/net/context"
"github.com/docker/docker/api/client/formatter"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
@@ -50,7 +48,7 @@ func (cli *DockerCli) CmdImages(args ...string) error {
Filters: imageFilterArgs,
}
images, err := cli.client.ImageList(context.Background(), options)
images, err := cli.client.ImageList(options)
if err != nil {
return err
}

View File

@@ -5,8 +5,6 @@ import (
"io"
"os"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/jsonmessage"
@@ -72,7 +70,7 @@ func (cli *DockerCli) CmdImport(args ...string) error {
Changes: changes,
}
responseBody, err := cli.client.ImageImport(context.Background(), options)
responseBody, err := cli.client.ImageImport(options)
if err != nil {
return err
}

View File

@@ -4,12 +4,9 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/pkg/ioutils"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/utils"
"github.com/docker/go-units"
)
@@ -22,7 +19,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
cmd.ParseFlags(args, true)
info, err := cli.client.Info(context.Background())
info, err := cli.client.Info()
if err != nil {
return err
}
@@ -52,7 +49,6 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
}
ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver)
ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver)
ioutils.FprintfIfNotEmpty(cli.out, "Cgroup Driver: %s\n", info.CgroupDriver)
fmt.Fprintf(cli.out, "Plugins: \n")
fmt.Fprintf(cli.out, " Volume:")
@@ -76,15 +72,16 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal)))
ioutils.FprintfIfNotEmpty(cli.out, "Name: %s\n", info.Name)
ioutils.FprintfIfNotEmpty(cli.out, "ID: %s\n", info.ID)
fmt.Fprintf(cli.out, "Docker Root Dir: %s\n", info.DockerRootDir)
fmt.Fprintf(cli.out, "Debug mode (client): %v\n", utils.IsDebugEnabled())
fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug)
if info.Debug {
fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug)
fmt.Fprintf(cli.out, " File Descriptors: %d\n", info.NFd)
fmt.Fprintf(cli.out, " Goroutines: %d\n", info.NGoroutines)
fmt.Fprintf(cli.out, " System Time: %s\n", info.SystemTime)
fmt.Fprintf(cli.out, " EventsListeners: %d\n", info.NEventsListener)
fmt.Fprintf(cli.out, " Init SHA1: %s\n", info.InitSha1)
fmt.Fprintf(cli.out, " Init Path: %s\n", info.InitPath)
fmt.Fprintf(cli.out, " Docker Root Dir: %s\n", info.DockerRootDir)
}
ioutils.FprintfIfNotEmpty(cli.out, "Http Proxy: %s\n", info.HTTPProxy)
@@ -95,8 +92,8 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username
if len(u) > 0 {
fmt.Fprintf(cli.out, "Username: %v\n", u)
fmt.Fprintf(cli.out, "Registry: %v\n", info.IndexServerAddress)
}
fmt.Fprintf(cli.out, "Registry: %v\n", info.IndexServerAddress)
}
// Only output these warnings if the server does not support these features
@@ -107,9 +104,6 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
if !info.SwapLimit {
fmt.Fprintln(cli.err, "WARNING: No swap limit support")
}
if !info.KernelMemory {
fmt.Fprintln(cli.err, "WARNING: No kernel memory limit support")
}
if !info.OomKillDisable {
fmt.Fprintln(cli.err, "WARNING: No oom kill disable support")
}

View File

@@ -1,17 +1,23 @@
package client
import (
"encoding/json"
"fmt"
"golang.org/x/net/context"
"text/template"
"github.com/docker/docker/api/client/inspect"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/utils/templates"
"github.com/docker/engine-api/client"
)
var funcMap = template.FuncMap{
"json": func(v interface{}) string {
a, _ := json.Marshal(v)
return string(a)
},
}
// CmdInspect displays low-level information on one or more containers or images.
//
// Usage: docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...]
@@ -43,23 +49,23 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
func (cli *DockerCli) inspectContainers(getSize bool) inspectSearcher {
return func(ref string) (interface{}, []byte, error) {
return cli.client.ContainerInspectWithRaw(context.Background(), ref, getSize)
return cli.client.ContainerInspectWithRaw(ref, getSize)
}
}
func (cli *DockerCli) inspectImages(getSize bool) inspectSearcher {
return func(ref string) (interface{}, []byte, error) {
return cli.client.ImageInspectWithRaw(context.Background(), ref, getSize)
return cli.client.ImageInspectWithRaw(ref, getSize)
}
}
func (cli *DockerCli) inspectAll(getSize bool) inspectSearcher {
return func(ref string) (interface{}, []byte, error) {
c, rawContainer, err := cli.client.ContainerInspectWithRaw(context.Background(), ref, getSize)
c, rawContainer, err := cli.client.ContainerInspectWithRaw(ref, getSize)
if err != nil {
// Search for image with that id if a container doesn't exist.
if client.IsErrContainerNotFound(err) {
i, rawImage, err := cli.client.ImageInspectWithRaw(context.Background(), ref, getSize)
i, rawImage, err := cli.client.ImageInspectWithRaw(ref, getSize)
if err != nil {
if client.IsErrImageNotFound(err) {
return nil, nil, fmt.Errorf("Error: No such image or container: %s", ref)
@@ -117,7 +123,7 @@ func (cli *DockerCli) inspectErrorStatus(err error) (status int) {
func (cli *DockerCli) newInspectorWithTemplate(tmplStr string) (inspect.Inspector, error) {
elementInspector := inspect.NewIndentedInspector(cli.out)
if tmplStr != "" {
tmpl, err := templates.Parse(tmplStr)
tmpl, err := template.New("").Funcs(funcMap).Parse(tmplStr)
if err != nil {
return nil, fmt.Errorf("Template parsing error: %s", err)
}

View File

@@ -4,8 +4,7 @@ import (
"bytes"
"strings"
"testing"
"github.com/docker/docker/utils/templates"
"text/template"
)
type testElement struct {
@@ -14,7 +13,7 @@ type testElement struct {
func TestTemplateInspectorDefault(t *testing.T) {
b := new(bytes.Buffer)
tmpl, err := templates.Parse("{{.DNS}}")
tmpl, err := template.New("test").Parse("{{.DNS}}")
if err != nil {
t.Fatal(err)
}
@@ -33,7 +32,7 @@ func TestTemplateInspectorDefault(t *testing.T) {
func TestTemplateInspectorEmpty(t *testing.T) {
b := new(bytes.Buffer)
tmpl, err := templates.Parse("{{.DNS}}")
tmpl, err := template.New("test").Parse("{{.DNS}}")
if err != nil {
t.Fatal(err)
}
@@ -49,7 +48,7 @@ func TestTemplateInspectorEmpty(t *testing.T) {
func TestTemplateInspectorTemplateError(t *testing.T) {
b := new(bytes.Buffer)
tmpl, err := templates.Parse("{{.Foo}}")
tmpl, err := template.New("test").Parse("{{.Foo}}")
if err != nil {
t.Fatal(err)
}
@@ -67,7 +66,7 @@ func TestTemplateInspectorTemplateError(t *testing.T) {
func TestTemplateInspectorRawFallback(t *testing.T) {
b := new(bytes.Buffer)
tmpl, err := templates.Parse("{{.Dns}}")
tmpl, err := template.New("test").Parse("{{.Dns}}")
if err != nil {
t.Fatal(err)
}
@@ -86,7 +85,7 @@ func TestTemplateInspectorRawFallback(t *testing.T) {
func TestTemplateInspectorRawFallbackError(t *testing.T) {
b := new(bytes.Buffer)
tmpl, err := templates.Parse("{{.Dns}}")
tmpl, err := template.New("test").Parse("{{.Dns}}")
if err != nil {
t.Fatal(err)
}
@@ -103,7 +102,7 @@ func TestTemplateInspectorRawFallbackError(t *testing.T) {
func TestTemplateInspectorMultiple(t *testing.T) {
b := new(bytes.Buffer)
tmpl, err := templates.Parse("{{.DNS}}")
tmpl, err := template.New("test").Parse("{{.DNS}}")
if err != nil {
t.Fatal(err)
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
)
@@ -22,8 +20,8 @@ func (cli *DockerCli) CmdKill(args ...string) error {
var errs []string
for _, name := range cmd.Args() {
if err := cli.client.ContainerKill(context.Background(), name, *signal); err != nil {
errs = append(errs, err.Error())
if err := cli.client.ContainerKill(name, *signal); err != nil {
errs = append(errs, fmt.Sprintf("Failed to kill container (%s): %s", name, err))
} else {
fmt.Fprintf(cli.out, "%s\n", name)
}

View File

@@ -4,8 +4,6 @@ import (
"io"
"os"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/pkg/jsonmessage"
flag "github.com/docker/docker/pkg/mflag"
@@ -19,7 +17,6 @@ import (
func (cli *DockerCli) CmdLoad(args ...string) error {
cmd := Cli.Subcmd("load", nil, Cli.DockerCommands["load"].Description, true)
infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN")
quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Suppress the load output")
cmd.Require(flag.Exact, 0)
cmd.ParseFlags(args, true)
@@ -32,16 +29,14 @@ func (cli *DockerCli) CmdLoad(args ...string) error {
defer file.Close()
input = file
}
if !cli.isTerminalOut {
*quiet = true
}
response, err := cli.client.ImageLoad(context.Background(), input, *quiet)
response, err := cli.client.ImageLoad(input)
if err != nil {
return err
}
defer response.Body.Close()
if response.Body != nil && response.JSON {
if response.JSON {
return jsonmessage.DisplayJSONMessagesStream(response.Body, cli.out, cli.outFd, cli.isTerminalOut, nil)
}

View File

@@ -8,17 +8,14 @@ import (
"runtime"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/cliconfig"
"github.com/docker/docker/cliconfig/credentials"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/term"
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
)
// CmdLogin logs in a user to a Docker registry service.
// CmdLogin logs in or registers a user to a Docker registry service.
//
// If no server is specified, the user will be logged into or registered to the registry's index server.
//
@@ -29,9 +26,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
flUser := cmd.String([]string{"u", "-username"}, "", "Username")
flPassword := cmd.String([]string{"p", "-password"}, "", "Password")
// Deprecated in 1.11: Should be removed in docker 1.13
cmd.String([]string{"#e", "#-email"}, "", "Email")
flEmail := cmd.String([]string{"e", "-email"}, "", "Email")
cmd.ParseFlags(args, true)
@@ -41,34 +36,35 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
}
var serverAddress string
var isDefaultRegistry bool
if len(cmd.Args()) > 0 {
serverAddress = cmd.Arg(0)
} else {
serverAddress = cli.electAuthServer()
isDefaultRegistry = true
}
authConfig, err := cli.configureAuth(*flUser, *flPassword, serverAddress, isDefaultRegistry)
authConfig, err := cli.configureAuth(*flUser, *flPassword, *flEmail, serverAddress)
if err != nil {
return err
}
response, err := cli.client.RegistryLogin(context.Background(), authConfig)
response, err := cli.client.RegistryLogin(authConfig)
if err != nil {
if client.IsErrUnauthorized(err) {
delete(cli.configFile.AuthConfigs, serverAddress)
if err2 := cli.configFile.Save(); err2 != nil {
fmt.Fprintf(cli.out, "WARNING: could not save config file: %v\n", err2)
}
}
return err
}
if response.IdentityToken != "" {
authConfig.Password = ""
authConfig.IdentityToken = response.IdentityToken
}
if err := storeCredentials(cli.configFile, authConfig); err != nil {
return fmt.Errorf("Error saving credentials: %v", err)
if err := cli.configFile.Save(); err != nil {
return fmt.Errorf("Error saving config file: %v", err)
}
fmt.Fprintf(cli.out, "WARNING: login credentials saved in %s\n", cli.configFile.Filename())
if response.Status != "" {
fmt.Fprintln(cli.out, response.Status)
fmt.Fprintf(cli.out, "%s\n", response.Status)
}
return nil
}
@@ -81,19 +77,13 @@ func (cli *DockerCli) promptWithDefault(prompt string, configDefault string) {
}
}
func (cli *DockerCli) configureAuth(flUser, flPassword, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
authconfig, err := getCredentials(cli.configFile, serverAddress)
if err != nil {
return authconfig, err
func (cli *DockerCli) configureAuth(flUser, flPassword, flEmail, serverAddress string) (types.AuthConfig, error) {
authconfig, ok := cli.configFile.AuthConfigs[serverAddress]
if !ok {
authconfig = types.AuthConfig{}
}
authconfig.Username = strings.TrimSpace(authconfig.Username)
if flUser = strings.TrimSpace(flUser); flUser == "" {
if isDefaultRegistry {
// if this is a defauly registry (docker hub), then display the following message.
fmt.Fprintln(cli.out, "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.")
}
if flUser == "" {
cli.promptWithDefault("Username", authconfig.Username)
flUser = readInput(cli.in, cli.out)
flUser = strings.TrimSpace(flUser)
@@ -102,10 +92,6 @@ func (cli *DockerCli) configureAuth(flUser, flPassword, serverAddress string, is
}
}
if flUser == "" {
return authconfig, fmt.Errorf("Error: Non-null Username Required")
}
if flPassword == "" {
oldState, err := term.SaveState(cli.inFd)
if err != nil {
@@ -119,15 +105,34 @@ func (cli *DockerCli) configureAuth(flUser, flPassword, serverAddress string, is
term.RestoreTerminal(cli.inFd, oldState)
if flPassword == "" {
return authconfig, fmt.Errorf("Error: Password Required")
return authconfig, fmt.Errorf("Error : Password Required")
}
}
// Assume that a different username means they may not want to use
// the email from the config file, so prompt it
if flUser != authconfig.Username {
if flEmail == "" {
cli.promptWithDefault("Email", authconfig.Email)
flEmail = readInput(cli.in, cli.out)
if flEmail == "" {
flEmail = authconfig.Email
}
}
} else {
// However, if they don't override the username use the
// email from the cmd line if specified. IOW, allow
// then to change/override them. And if not specified, just
// use what's in the config file
if flEmail == "" {
flEmail = authconfig.Email
}
}
authconfig.Username = flUser
authconfig.Password = flPassword
authconfig.Email = flEmail
authconfig.ServerAddress = serverAddress
authconfig.IdentityToken = ""
cli.configFile.AuthConfigs[serverAddress] = authconfig
return authconfig, nil
}
@@ -140,38 +145,3 @@ func readInput(in io.Reader, out io.Writer) string {
}
return string(line)
}
// getCredentials loads the user credentials from a credentials store.
// The store is determined by the config file settings.
func getCredentials(c *cliconfig.ConfigFile, serverAddress string) (types.AuthConfig, error) {
s := loadCredentialsStore(c)
return s.Get(serverAddress)
}
func getAllCredentials(c *cliconfig.ConfigFile) (map[string]types.AuthConfig, error) {
s := loadCredentialsStore(c)
return s.GetAll()
}
// storeCredentials saves the user credentials in a credentials store.
// The store is determined by the config file settings.
func storeCredentials(c *cliconfig.ConfigFile, auth types.AuthConfig) error {
s := loadCredentialsStore(c)
return s.Store(auth)
}
// eraseCredentials removes the user credentials from a credentials store.
// The store is determined by the config file settings.
func eraseCredentials(c *cliconfig.ConfigFile, serverAddress string) error {
s := loadCredentialsStore(c)
return s.Erase(serverAddress)
}
// loadCredentialsStore initializes a new credentials store based
// in the settings provided in the configuration file.
func loadCredentialsStore(c *cliconfig.ConfigFile) credentials.Store {
if c.CredentialsStore != "" {
return credentials.NewNativeStore(c)
}
return credentials.NewFileStore(c)
}

View File

@@ -25,16 +25,15 @@ func (cli *DockerCli) CmdLogout(args ...string) error {
serverAddress = cli.electAuthServer()
}
// check if we're logged in based on the records in the config file
// which means it couldn't have user/pass cause they may be in the creds store
if _, ok := cli.configFile.AuthConfigs[serverAddress]; !ok {
fmt.Fprintf(cli.out, "Not logged in to %s\n", serverAddress)
return nil
}
fmt.Fprintf(cli.out, "Remove login credentials for %s\n", serverAddress)
if err := eraseCredentials(cli.configFile, serverAddress); err != nil {
fmt.Fprintf(cli.out, "WARNING: could not erase credentials: %v\n", err)
delete(cli.configFile.AuthConfigs, serverAddress)
if err := cli.configFile.Save(); err != nil {
return fmt.Errorf("Failed to save docker config: %v", err)
}
return nil

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"io"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/stdcopy"
@@ -32,7 +30,7 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
name := cmd.Arg(0)
c, err := cli.client.ContainerInspect(context.Background(), name)
c, err := cli.client.ContainerInspect(name)
if err != nil {
return err
}
@@ -50,7 +48,7 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
Follow: *follow,
Tail: *tail,
}
responseBody, err := cli.client.ContainerLogs(context.Background(), options)
responseBody, err := cli.client.ContainerLogs(options)
if err != nil {
return err
}

View File

@@ -3,12 +3,9 @@ package client
import (
"fmt"
"net"
"sort"
"strings"
"text/tabwriter"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
@@ -44,7 +41,6 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
flIpamGateway := opts.NewListOpts(nil)
flIpamAux := opts.NewMapOpts(nil, nil)
flIpamOpt := opts.NewMapOpts(nil, nil)
flLabels := opts.NewListOpts(nil)
cmd.Var(&flIpamSubnet, []string{"-subnet"}, "subnet in CIDR format that represents a network segment")
cmd.Var(&flIpamIPRange, []string{"-ip-range"}, "allocate container ip from a sub-range")
@@ -52,10 +48,8 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
cmd.Var(flIpamAux, []string{"-aux-address"}, "auxiliary ipv4 or ipv6 addresses used by Network driver")
cmd.Var(flOpts, []string{"o", "-opt"}, "set driver specific options")
cmd.Var(flIpamOpt, []string{"-ipam-opt"}, "set IPAM driver specific options")
cmd.Var(&flLabels, []string{"-label"}, "set metadata on a network")
flInternal := cmd.Bool([]string{"-internal"}, false, "restricts external access to the network")
flIPv6 := cmd.Bool([]string{"-ipv6"}, false, "enable IPv6 networking")
cmd.Require(flag.Exact, 1)
err := cmd.ParseFlags(args, true)
@@ -83,11 +77,9 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
Options: flOpts.GetAll(),
CheckDuplicate: true,
Internal: *flInternal,
EnableIPv6: *flIPv6,
Labels: runconfigopts.ConvertKVStringsToMap(flLabels.GetAll()),
}
resp, err := cli.client.NetworkCreate(context.Background(), nc)
resp, err := cli.client.NetworkCreate(nc)
if err != nil {
return err
}
@@ -107,7 +99,7 @@ func (cli *DockerCli) CmdNetworkRm(args ...string) error {
status := 0
for _, net := range cmd.Args() {
if err := cli.client.NetworkRemove(context.Background(), net); err != nil {
if err := cli.client.NetworkRemove(net); err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
status = 1
continue
@@ -142,7 +134,7 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
Links: flLinks.GetAll(),
Aliases: flAliases.GetAll(),
}
return cli.client.NetworkConnect(context.Background(), cmd.Arg(0), cmd.Arg(1), epConfig)
return cli.client.NetworkConnect(cmd.Arg(0), cmd.Arg(1), epConfig)
}
// CmdNetworkDisconnect disconnects a container from a network
@@ -156,7 +148,7 @@ func (cli *DockerCli) CmdNetworkDisconnect(args ...string) error {
return err
}
return cli.client.NetworkDisconnect(context.Background(), cmd.Arg(0), cmd.Arg(1), *force)
return cli.client.NetworkDisconnect(cmd.Arg(0), cmd.Arg(1), *force)
}
// CmdNetworkLs lists all the networks managed by docker daemon
@@ -189,7 +181,7 @@ func (cli *DockerCli) CmdNetworkLs(args ...string) error {
Filters: netFilterArgs,
}
networkResources, err := cli.client.NetworkList(context.Background(), options)
networkResources, err := cli.client.NetworkList(options)
if err != nil {
return err
}
@@ -200,7 +192,7 @@ func (cli *DockerCli) CmdNetworkLs(args ...string) error {
if !*quiet {
fmt.Fprintln(wr, "NETWORK ID\tNAME\tDRIVER")
}
sort.Sort(byNetworkName(networkResources))
for _, networkResource := range networkResources {
ID := networkResource.ID
netName := networkResource.Name
@@ -222,12 +214,6 @@ func (cli *DockerCli) CmdNetworkLs(args ...string) error {
return nil
}
type byNetworkName []types.NetworkResource
func (r byNetworkName) Len() int { return len(r) }
func (r byNetworkName) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r byNetworkName) Less(i, j int) bool { return r[i].Name < r[j].Name }
// CmdNetworkInspect inspects the network object for more details
//
// Usage: docker network inspect [OPTIONS] <NETWORK> [NETWORK...]
@@ -241,7 +227,7 @@ func (cli *DockerCli) CmdNetworkInspect(args ...string) error {
}
inspectSearcher := func(name string) (interface{}, []byte, error) {
i, err := cli.client.NetworkInspect(context.Background(), name)
i, err := cli.client.NetworkInspect(name)
return i, nil, err
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
)
@@ -21,8 +19,8 @@ func (cli *DockerCli) CmdPause(args ...string) error {
var errs []string
for _, name := range cmd.Args() {
if err := cli.client.ContainerPause(context.Background(), name); err != nil {
errs = append(errs, err.Error())
if err := cli.client.ContainerPause(name); err != nil {
errs = append(errs, fmt.Sprintf("Failed to pause container (%s): %s", name, err))
} else {
fmt.Fprintf(cli.out, "%s\n", name)
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/go-connections/nat"
@@ -21,7 +19,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
cmd.ParseFlags(args, true)
c, err := cli.client.ContainerInspect(context.Background(), cmd.Arg(0))
c, err := cli.client.ContainerInspect(cmd.Arg(0))
if err != nil {
return err
}

View File

@@ -1,8 +1,6 @@
package client
import (
"golang.org/x/net/context"
"github.com/docker/docker/api/client/formatter"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
@@ -58,7 +56,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
Filter: psFilterArgs,
}
containers, err := cli.client.ContainerList(context.Background(), options)
containers, err := cli.client.ContainerList(options)
if err != nil {
return err
}

View File

@@ -4,8 +4,6 @@ import (
"errors"
"fmt"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/pkg/jsonmessage"
flag "github.com/docker/docker/pkg/mflag"
@@ -56,7 +54,7 @@ func (cli *DockerCli) CmdPull(args ...string) error {
return err
}
authConfig := cli.resolveAuthConfig(repoInfo.Index)
authConfig := cli.resolveAuthConfig(cli.configFile.AuthConfigs, repoInfo.Index)
requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "pull")
if isTrusted() && !ref.HasDigest() {
@@ -79,7 +77,7 @@ func (cli *DockerCli) imagePullPrivileged(authConfig types.AuthConfig, imageID,
RegistryAuth: encodedAuth,
}
responseBody, err := cli.client.ImagePull(context.Background(), options, requestPrivilege)
responseBody, err := cli.client.ImagePull(options, requestPrivilege)
if err != nil {
return err
}

View File

@@ -4,8 +4,6 @@ import (
"errors"
"io"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/pkg/jsonmessage"
flag "github.com/docker/docker/pkg/mflag"
@@ -44,7 +42,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
return err
}
// Resolve the Auth config relevant for this server
authConfig := cli.resolveAuthConfig(repoInfo.Index)
authConfig := cli.resolveAuthConfig(cli.configFile.AuthConfigs, repoInfo.Index)
requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "push")
if isTrusted() {
@@ -72,5 +70,5 @@ func (cli *DockerCli) imagePushPrivileged(authConfig types.AuthConfig, imageID,
RegistryAuth: encodedAuth,
}
return cli.client.ImagePush(context.Background(), options, requestPrivilege)
return cli.client.ImagePush(options, requestPrivilege)
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
)
@@ -26,7 +24,7 @@ func (cli *DockerCli) CmdRename(args ...string) error {
return fmt.Errorf("Error: Neither old nor new names may be empty")
}
if err := cli.client.ContainerRename(context.Background(), oldName, newName); err != nil {
if err := cli.client.ContainerRename(oldName, newName); err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
return fmt.Errorf("Error: failed to rename container named %s", oldName)
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
)
@@ -22,8 +20,8 @@ func (cli *DockerCli) CmdRestart(args ...string) error {
var errs []string
for _, name := range cmd.Args() {
if err := cli.client.ContainerRestart(context.Background(), name, *nSeconds); err != nil {
errs = append(errs, err.Error())
if err := cli.client.ContainerRestart(name, *nSeconds); err != nil {
errs = append(errs, fmt.Sprintf("Failed to kill container (%s): %s", name, err))
} else {
fmt.Fprintf(cli.out, "%s\n", name)
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/engine-api/types"
@@ -30,8 +28,15 @@ func (cli *DockerCli) CmdRm(args ...string) error {
}
name = strings.Trim(name, "/")
if err := cli.removeContainer(name, *v, *link, *force); err != nil {
errs = append(errs, err.Error())
options := types.ContainerRemoveOptions{
ContainerID: name,
RemoveVolumes: *v,
RemoveLinks: *link,
Force: *force,
}
if err := cli.client.ContainerRemove(options); err != nil {
errs = append(errs, fmt.Sprintf("Failed to remove container (%s): %s", name, err))
} else {
fmt.Fprintf(cli.out, "%s\n", name)
}
@@ -41,16 +46,3 @@ func (cli *DockerCli) CmdRm(args ...string) error {
}
return nil
}
func (cli *DockerCli) removeContainer(containerID string, removeVolumes, removeLinks, force bool) error {
options := types.ContainerRemoveOptions{
ContainerID: containerID,
RemoveVolumes: removeVolumes,
RemoveLinks: removeLinks,
Force: force,
}
if err := cli.client.ContainerRemove(context.Background(), options); err != nil {
return err
}
return nil
}

View File

@@ -5,8 +5,6 @@ import (
"net/url"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/engine-api/types"
@@ -39,9 +37,9 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
PruneChildren: !*noprune,
}
dels, err := cli.client.ImageRemove(context.Background(), options)
dels, err := cli.client.ImageRemove(options)
if err != nil {
errs = append(errs, err.Error())
errs = append(errs, fmt.Sprintf("Failed to remove image (%s): %s", name, err))
} else {
for _, del := range dels {
if del.Deleted != "" {

View File

@@ -7,10 +7,9 @@ import (
"runtime"
"strings"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
Cli "github.com/docker/docker/cli"
derr "github.com/docker/docker/errors"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/promise"
"github.com/docker/docker/pkg/signal"
@@ -19,11 +18,6 @@ import (
"github.com/docker/libnetwork/resolvconf/dns"
)
const (
errCmdNotFound = "not found or does not exist."
errCmdCouldNotBeInvoked = "could not be invoked."
)
func (cid *cidFile) Close() error {
cid.file.Close()
@@ -49,16 +43,21 @@ func (cid *cidFile) Write(id string) error {
// return 125 for generic docker daemon failures
func runStartContainerErr(err error) error {
trimmedErr := strings.Trim(err.Error(), "Error response from daemon: ")
statusError := Cli.StatusError{StatusCode: 125}
if strings.HasPrefix(trimmedErr, "Container command") {
if strings.Contains(trimmedErr, errCmdNotFound) {
statusError = Cli.StatusError{StatusCode: 127}
} else if strings.Contains(trimmedErr, errCmdCouldNotBeInvoked) {
statusError = Cli.StatusError{StatusCode: 126}
}
statusError := Cli.StatusError{}
derrCmdNotFound := derr.ErrorCodeCmdNotFound.Message()
derrCouldNotInvoke := derr.ErrorCodeCmdCouldNotBeInvoked.Message()
derrNoSuchImage := derr.ErrorCodeNoSuchImageHash.Message()
derrNoSuchImageTag := derr.ErrorCodeNoSuchImageTag.Message()
switch trimmedErr {
case derrCmdNotFound:
statusError = Cli.StatusError{StatusCode: 127}
case derrCouldNotInvoke:
statusError = Cli.StatusError{StatusCode: 126}
case derrNoSuchImage, derrNoSuchImageTag:
statusError = Cli.StatusError{StatusCode: 125}
default:
statusError = Cli.StatusError{StatusCode: 125}
}
return statusError
}
@@ -204,7 +203,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
DetachKeys: cli.configFile.DetachKeys,
}
resp, err := cli.client.ContainerAttach(context.Background(), options)
resp, err := cli.client.ContainerAttach(options)
if err != nil {
return err
}
@@ -219,16 +218,20 @@ func (cli *DockerCli) CmdRun(args ...string) error {
})
}
if *flAutoRemove {
defer func() {
if err := cli.removeContainer(createResponse.ID, true, false, false); err != nil {
fmt.Fprintf(cli.err, "%v\n", err)
defer func() {
if *flAutoRemove {
options := types.ContainerRemoveOptions{
ContainerID: createResponse.ID,
RemoveVolumes: true,
}
}()
}
if err := cli.client.ContainerRemove(options); err != nil {
fmt.Fprintf(cli.err, "Error deleting container: %s\n", err)
}
}
}()
//start the container
if err := cli.client.ContainerStart(context.Background(), createResponse.ID); err != nil {
if err := cli.client.ContainerStart(createResponse.ID); err != nil {
cmd.ReportError(err.Error(), false)
return runStartContainerErr(err)
}
@@ -259,7 +262,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
if *flAutoRemove {
// Autoremove: wait for the container to finish, retrieve
// the exit code and remove the container
if status, err = cli.client.ContainerWait(context.Background(), createResponse.ID); err != nil {
if status, err = cli.client.ContainerWait(createResponse.ID); err != nil {
return runStartContainerErr(err)
}
if _, status, err = getExitCode(cli, createResponse.ID); err != nil {
@@ -269,7 +272,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
// No Autoremove: Simply retrieve the exit code
if !config.Tty {
// In non-TTY mode, we can't detach, so we must wait for container exit
if status, err = cli.client.ContainerWait(context.Background(), createResponse.ID); err != nil {
if status, err = cli.client.ContainerWait(createResponse.ID); err != nil {
return err
}
} else {

View File

@@ -3,8 +3,7 @@ package client
import (
"errors"
"io"
"golang.org/x/net/context"
"os"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
@@ -22,21 +21,26 @@ func (cli *DockerCli) CmdSave(args ...string) error {
cmd.ParseFlags(args, true)
var (
output = cli.out
err error
)
if *outfile == "" && cli.isTerminalOut {
return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.")
}
if *outfile != "" {
if output, err = os.Create(*outfile); err != nil {
return err
}
}
responseBody, err := cli.client.ImageSave(context.Background(), cmd.Args())
responseBody, err := cli.client.ImageSave(cmd.Args())
if err != nil {
return err
}
defer responseBody.Close()
if *outfile == "" {
_, err := io.Copy(cli.out, responseBody)
return err
}
return copyToFile(*outfile, responseBody)
_, err = io.Copy(output, responseBody)
return err
}

View File

@@ -7,8 +7,6 @@ import (
"strings"
"text/tabwriter"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/stringutils"
@@ -38,7 +36,7 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
return err
}
authConfig := cli.resolveAuthConfig(indexInfo)
authConfig := cli.resolveAuthConfig(cli.configFile.AuthConfigs, indexInfo)
requestPrivilege := cli.registryAuthenticationPrivilegedFunc(indexInfo, "search")
encodedAuth, err := encodeAuthToBase64(authConfig)
@@ -51,7 +49,7 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
RegistryAuth: encodedAuth,
}
unorderedResults, err := cli.client.ImageSearch(context.Background(), options, requestPrivilege)
unorderedResults, err := cli.client.ImageSearch(options, requestPrivilege)
if err != nil {
return err
}

View File

@@ -6,8 +6,6 @@ import (
"os"
"strings"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
@@ -21,7 +19,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
signal.CatchAll(sigc)
go func() {
for s := range sigc {
if s == signal.SIGCHLD || s == signal.SIGPIPE {
if s == signal.SIGCHLD {
continue
}
var sig string
@@ -36,7 +34,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
continue
}
if err := cli.client.ContainerKill(context.Background(), cid, sig); err != nil {
if err := cli.client.ContainerKill(cid, sig); err != nil {
logrus.Debugf("Error sending signal: %s", err)
}
}
@@ -65,7 +63,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
// 2. Attach to the container.
containerID := cmd.Arg(0)
c, err := cli.client.ContainerInspect(context.Background(), containerID)
c, err := cli.client.ContainerInspect(containerID)
if err != nil {
return err
}
@@ -93,7 +91,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
in = cli.in
}
resp, err := cli.client.ContainerAttach(context.Background(), options)
resp, err := cli.client.ContainerAttach(options)
if err != nil {
return err
}
@@ -110,7 +108,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
})
// 3. Start the container.
if err := cli.client.ContainerStart(context.Background(), containerID); err != nil {
if err := cli.client.ContainerStart(containerID); err != nil {
return err
}
@@ -142,7 +140,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
func (cli *DockerCli) startContainersWithoutAttachments(containerIDs []string) error {
var failedContainers []string
for _, containerID := range containerIDs {
if err := cli.client.ContainerStart(context.Background(), containerID); err != nil {
if err := cli.client.ContainerStart(containerID); err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
failedContainers = append(failedContainers, containerID)
} else {

View File

@@ -1,21 +1,138 @@
package client
import (
"encoding/json"
"fmt"
"io"
"sort"
"strings"
"sync"
"text/tabwriter"
"time"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/events"
"github.com/docker/engine-api/types/filters"
"github.com/docker/go-units"
)
type containerStats struct {
Name string
CPUPercentage float64
Memory float64
MemoryLimit float64
MemoryPercentage float64
NetworkRx float64
NetworkTx float64
BlockRead float64
BlockWrite float64
mu sync.RWMutex
err error
}
type stats struct {
mu sync.Mutex
cs []*containerStats
}
func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
responseBody, err := cli.client.ContainerStats(s.Name, streamStats)
if err != nil {
s.mu.Lock()
s.err = err
s.mu.Unlock()
return
}
defer responseBody.Close()
var (
previousCPU uint64
previousSystem uint64
dec = json.NewDecoder(responseBody)
u = make(chan error, 1)
)
go func() {
for {
var v *types.StatsJSON
if err := dec.Decode(&v); err != nil {
u <- err
return
}
var memPercent = 0.0
var cpuPercent = 0.0
// MemoryStats.Limit will never be 0 unless the container is not running and we haven't
// got any data from cgroup
if v.MemoryStats.Limit != 0 {
memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0
}
previousCPU = v.PreCPUStats.CPUUsage.TotalUsage
previousSystem = v.PreCPUStats.SystemUsage
cpuPercent = calculateCPUPercent(previousCPU, previousSystem, v)
blkRead, blkWrite := calculateBlockIO(v.BlkioStats)
s.mu.Lock()
s.CPUPercentage = cpuPercent
s.Memory = float64(v.MemoryStats.Usage)
s.MemoryLimit = float64(v.MemoryStats.Limit)
s.MemoryPercentage = memPercent
s.NetworkRx, s.NetworkTx = calculateNetwork(v.Networks)
s.BlockRead = float64(blkRead)
s.BlockWrite = float64(blkWrite)
s.mu.Unlock()
u <- nil
if !streamStats {
return
}
}
}()
for {
select {
case <-time.After(2 * time.Second):
// zero out the values if we have not received an update within
// the specified duration.
s.mu.Lock()
s.CPUPercentage = 0
s.Memory = 0
s.MemoryPercentage = 0
s.MemoryLimit = 0
s.NetworkRx = 0
s.NetworkTx = 0
s.BlockRead = 0
s.BlockWrite = 0
s.mu.Unlock()
case err := <-u:
if err != nil {
s.mu.Lock()
s.err = err
s.mu.Unlock()
return
}
}
if !streamStats {
return
}
}
}
func (s *containerStats) Display(w io.Writer) error {
s.mu.RLock()
defer s.mu.RUnlock()
if s.err != nil {
return s.err
}
fmt.Fprintf(w, "%s\t%.2f%%\t%s / %s\t%.2f%%\t%s / %s\t%s / %s\n",
s.Name,
s.CPUPercentage,
units.HumanSize(s.Memory), units.HumanSize(s.MemoryLimit),
s.MemoryPercentage,
units.HumanSize(s.NetworkRx), units.HumanSize(s.NetworkTx),
units.HumanSize(s.BlockRead), units.HumanSize(s.BlockWrite))
return nil
}
// CmdStats displays a live stream of resource usage statistics for one or more containers.
//
// This shows real-time information on CPU usage, memory usage, and network I/O.
@@ -30,143 +147,125 @@ func (cli *DockerCli) CmdStats(args ...string) error {
names := cmd.Args()
showAll := len(names) == 0
closeChan := make(chan error)
// monitorContainerEvents watches for container creation and removal (only
// used when calling `docker stats` without arguments).
monitorContainerEvents := func(started chan<- struct{}, c chan events.Message) {
f := filters.NewArgs()
f.Add("type", "container")
options := types.EventsOptions{
Filters: f,
}
resBody, err := cli.client.Events(context.Background(), options)
// Whether we successfully subscribed to events or not, we can now
// unblock the main goroutine.
close(started)
if err != nil {
closeChan <- err
return
}
defer resBody.Close()
decodeEvents(resBody, func(event events.Message, err error) error {
if err != nil {
closeChan <- err
return nil
}
c <- event
return nil
})
}
// waitFirst is a WaitGroup to wait first stat data's reach for each container
waitFirst := &sync.WaitGroup{}
cStats := stats{}
// getContainerList simulates creation event for all previously existing
// containers (only used when calling `docker stats` without arguments).
getContainerList := func() {
if showAll {
options := types.ContainerListOptions{
All: *all,
}
cs, err := cli.client.ContainerList(context.Background(), options)
cs, err := cli.client.ContainerList(options)
if err != nil {
closeChan <- err
return err
}
for _, container := range cs {
s := &containerStats{Name: container.ID[:12]}
if cStats.add(s) {
waitFirst.Add(1)
go s.Collect(cli.client, !*noStream, waitFirst)
}
for _, c := range cs {
names = append(names, c.ID[:12])
}
}
if showAll {
// If no names were specified, start a long running goroutine which
// monitors container events. We make sure we're subscribed before
// retrieving the list of running containers to avoid a race where we
// would "miss" a creation.
started := make(chan struct{})
eh := eventHandler{handlers: make(map[string]func(events.Message))}
eh.Handle("create", func(e events.Message) {
if *all {
s := &containerStats{Name: e.ID[:12]}
if cStats.add(s) {
waitFirst.Add(1)
go s.Collect(cli.client, !*noStream, waitFirst)
}
}
})
eh.Handle("start", func(e events.Message) {
s := &containerStats{Name: e.ID[:12]}
if cStats.add(s) {
waitFirst.Add(1)
go s.Collect(cli.client, !*noStream, waitFirst)
}
})
eh.Handle("die", func(e events.Message) {
if !*all {
cStats.remove(e.ID[:12])
}
})
eventChan := make(chan events.Message)
go eh.Watch(eventChan)
go monitorContainerEvents(started, eventChan)
defer close(eventChan)
<-started
// Start a short-lived goroutine to retrieve the initial list of
// containers.
getContainerList()
} else {
// Artificially send creation events for the containers we were asked to
// monitor (same code path than we use when monitoring all containers).
for _, name := range names {
s := &containerStats{Name: name}
if cStats.add(s) {
waitFirst.Add(1)
go s.Collect(cli.client, !*noStream, waitFirst)
}
}
// We don't expect any asynchronous errors: closeChan can be closed.
close(closeChan)
// Do a quick pause to detect any error with the provided list of
// container names.
time.Sleep(1500 * time.Millisecond)
var errs []string
cStats.mu.Lock()
for _, c := range cStats.cs {
c.mu.Lock()
if c.err != nil {
errs = append(errs, fmt.Sprintf("%s: %v", c.Name, c.err))
}
c.mu.Unlock()
}
cStats.mu.Unlock()
if len(errs) > 0 {
return fmt.Errorf("%s", strings.Join(errs, ", "))
}
if len(names) == 0 && !showAll {
return fmt.Errorf("No containers found")
}
sort.Strings(names)
// before print to screen, make sure each container get at least one valid stat data
waitFirst.Wait()
w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
var (
cStats = stats{}
w = tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
)
printHeader := func() {
if !*noStream {
fmt.Fprint(cli.out, "\033[2J")
fmt.Fprint(cli.out, "\033[H")
}
io.WriteString(w, "CONTAINER\tCPU %\tMEM USAGE / LIMIT\tMEM %\tNET I/O\tBLOCK I/O\tPIDS\n")
io.WriteString(w, "CONTAINER\tCPU %\tMEM USAGE / LIMIT\tMEM %\tNET I/O\tBLOCK I/O\n")
}
for _, n := range names {
s := &containerStats{Name: n}
// no need to lock here since only the main goroutine is running here
cStats.cs = append(cStats.cs, s)
go s.Collect(cli, !*noStream)
}
closeChan := make(chan error)
if showAll {
type watch struct {
cid string
event string
err error
}
getNewContainers := func(c chan<- watch) {
f := filters.NewArgs()
f.Add("type", "container")
options := types.EventsOptions{
Filters: f,
}
resBody, err := cli.client.Events(options)
if err != nil {
c <- watch{err: err}
return
}
defer resBody.Close()
decodeEvents(resBody, func(event events.Message, err error) error {
if err != nil {
c <- watch{err: err}
return nil
}
c <- watch{event.ID[:12], event.Action, nil}
return nil
})
}
go func(stopChan chan<- error) {
cChan := make(chan watch)
go getNewContainers(cChan)
for {
c := <-cChan
if c.err != nil {
stopChan <- c.err
return
}
switch c.event {
case "create":
s := &containerStats{Name: c.cid}
cStats.mu.Lock()
cStats.cs = append(cStats.cs, s)
cStats.mu.Unlock()
go s.Collect(cli, !*noStream)
case "stop":
case "die":
if !*all {
var remove int
// cStats cannot be O(1) with a map cause ranging over it would cause
// containers in stats to move up and down in the list...:(
cStats.mu.Lock()
for i, s := range cStats.cs {
if s.Name == c.cid {
remove = i
break
}
}
cStats.cs = append(cStats.cs[:remove], cStats.cs[remove+1:]...)
cStats.mu.Unlock()
}
}
}
}(closeChan)
} else {
close(closeChan)
}
// 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(1500 * time.Millisecond)
var errs []string
cStats.mu.Lock()
for _, c := range cStats.cs {
c.mu.Lock()
if c.err != nil {
errs = append(errs, fmt.Sprintf("%s: %v", c.Name, c.err))
}
c.mu.Unlock()
}
cStats.mu.Unlock()
if len(errs) > 0 {
return fmt.Errorf("%s", strings.Join(errs, ", "))
}
for range time.Tick(500 * time.Millisecond) {
printHeader()
toRemove := []int{}
@@ -206,3 +305,40 @@ func (cli *DockerCli) CmdStats(args ...string) error {
}
return nil
}
func calculateCPUPercent(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
var (
cpuPercent = 0.0
// calculate the change for the cpu usage of the container in between readings
cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU)
// calculate the change for the entire system between readings
systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem)
)
if systemDelta > 0.0 && cpuDelta > 0.0 {
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
}
return cpuPercent
}
func calculateBlockIO(blkio types.BlkioStats) (blkRead uint64, blkWrite uint64) {
for _, bioEntry := range blkio.IoServiceBytesRecursive {
switch strings.ToLower(bioEntry.Op) {
case "read":
blkRead = blkRead + bioEntry.Value
case "write":
blkWrite = blkWrite + bioEntry.Value
}
}
return
}
func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) {
var rx, tx float64
for _, v := range network {
rx += float64(v.RxBytes)
tx += float64(v.TxBytes)
}
return rx, tx
}

View File

@@ -1,219 +0,0 @@
package client
import (
"encoding/json"
"fmt"
"io"
"strings"
"sync"
"time"
"github.com/docker/engine-api/client"
"github.com/docker/engine-api/types"
"github.com/docker/go-units"
"golang.org/x/net/context"
)
type containerStats struct {
Name string
CPUPercentage float64
Memory float64
MemoryLimit float64
MemoryPercentage float64
NetworkRx float64
NetworkTx float64
BlockRead float64
BlockWrite float64
PidsCurrent uint64
mu sync.RWMutex
err error
}
type stats struct {
mu sync.Mutex
cs []*containerStats
}
func (s *stats) add(cs *containerStats) bool {
s.mu.Lock()
defer s.mu.Unlock()
if _, exists := s.isKnownContainer(cs.Name); !exists {
s.cs = append(s.cs, cs)
return true
}
return false
}
func (s *stats) remove(id string) {
s.mu.Lock()
if i, exists := s.isKnownContainer(id); exists {
s.cs = append(s.cs[:i], s.cs[i+1:]...)
}
s.mu.Unlock()
}
func (s *stats) isKnownContainer(cid string) (int, bool) {
for i, c := range s.cs {
if c.Name == cid {
return i, true
}
}
return -1, false
}
func (s *containerStats) Collect(cli client.APIClient, streamStats bool, waitFirst *sync.WaitGroup) {
var (
getFirst bool
previousCPU uint64
previousSystem uint64
u = make(chan error, 1)
)
defer func() {
// if error happens and we get nothing of stats, release wait group whatever
if !getFirst {
getFirst = true
waitFirst.Done()
}
}()
responseBody, err := cli.ContainerStats(context.Background(), s.Name, streamStats)
if err != nil {
s.mu.Lock()
s.err = err
s.mu.Unlock()
return
}
defer responseBody.Close()
dec := json.NewDecoder(responseBody)
go func() {
for {
var v *types.StatsJSON
if err := dec.Decode(&v); err != nil {
u <- err
return
}
var memPercent = 0.0
var cpuPercent = 0.0
// MemoryStats.Limit will never be 0 unless the container is not running and we haven't
// got any data from cgroup
if v.MemoryStats.Limit != 0 {
memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0
}
previousCPU = v.PreCPUStats.CPUUsage.TotalUsage
previousSystem = v.PreCPUStats.SystemUsage
cpuPercent = calculateCPUPercent(previousCPU, previousSystem, v)
blkRead, blkWrite := calculateBlockIO(v.BlkioStats)
s.mu.Lock()
s.CPUPercentage = cpuPercent
s.Memory = float64(v.MemoryStats.Usage)
s.MemoryLimit = float64(v.MemoryStats.Limit)
s.MemoryPercentage = memPercent
s.NetworkRx, s.NetworkTx = calculateNetwork(v.Networks)
s.BlockRead = float64(blkRead)
s.BlockWrite = float64(blkWrite)
s.PidsCurrent = v.PidsStats.Current
s.mu.Unlock()
u <- nil
if !streamStats {
return
}
}
}()
for {
select {
case <-time.After(2 * time.Second):
// zero out the values if we have not received an update within
// the specified duration.
s.mu.Lock()
s.CPUPercentage = 0
s.Memory = 0
s.MemoryPercentage = 0
s.MemoryLimit = 0
s.NetworkRx = 0
s.NetworkTx = 0
s.BlockRead = 0
s.BlockWrite = 0
s.PidsCurrent = 0
s.mu.Unlock()
// if this is the first stat you get, release WaitGroup
if !getFirst {
getFirst = true
waitFirst.Done()
}
case err := <-u:
if err != nil {
s.mu.Lock()
s.err = err
s.mu.Unlock()
return
}
// if this is the first stat you get, release WaitGroup
if !getFirst {
getFirst = true
waitFirst.Done()
}
}
if !streamStats {
return
}
}
}
func (s *containerStats) Display(w io.Writer) error {
s.mu.RLock()
defer s.mu.RUnlock()
if s.err != nil {
return s.err
}
fmt.Fprintf(w, "%s\t%.2f%%\t%s / %s\t%.2f%%\t%s / %s\t%s / %s\t%d\n",
s.Name,
s.CPUPercentage,
units.HumanSize(s.Memory), units.HumanSize(s.MemoryLimit),
s.MemoryPercentage,
units.HumanSize(s.NetworkRx), units.HumanSize(s.NetworkTx),
units.HumanSize(s.BlockRead), units.HumanSize(s.BlockWrite),
s.PidsCurrent)
return nil
}
func calculateCPUPercent(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
var (
cpuPercent = 0.0
// calculate the change for the cpu usage of the container in between readings
cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU)
// calculate the change for the entire system between readings
systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem)
)
if systemDelta > 0.0 && cpuDelta > 0.0 {
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
}
return cpuPercent
}
func calculateBlockIO(blkio types.BlkioStats) (blkRead uint64, blkWrite uint64) {
for _, bioEntry := range blkio.IoServiceBytesRecursive {
switch strings.ToLower(bioEntry.Op) {
case "read":
blkRead = blkRead + bioEntry.Value
case "write":
blkWrite = blkWrite + bioEntry.Value
}
}
return
}
func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) {
var rx, tx float64
for _, v := range network {
rx += float64(v.RxBytes)
tx += float64(v.TxBytes)
}
return rx, tx
}

View File

@@ -19,7 +19,6 @@ func TestDisplay(t *testing.T) {
NetworkTx: 800 * 1024 * 1024,
BlockRead: 100 * 1024 * 1024,
BlockWrite: 800 * 1024 * 1024,
PidsCurrent: 1,
mu: sync.RWMutex{},
}
var b bytes.Buffer
@@ -27,7 +26,7 @@ func TestDisplay(t *testing.T) {
t.Fatalf("c.Display() gave error: %s", err)
}
got := b.String()
want := "app\t30.00%\t104.9 MB / 2.147 GB\t4.88%\t104.9 MB / 838.9 MB\t104.9 MB / 838.9 MB\t1\n"
want := "app\t30.00%\t104.9 MB / 2.147 GB\t4.88%\t104.9 MB / 838.9 MB\t104.9 MB / 838.9 MB\n"
if got != want {
t.Fatalf("c.Display() = %q, want %q", got, want)
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
)
@@ -24,8 +22,8 @@ func (cli *DockerCli) CmdStop(args ...string) error {
var errs []string
for _, name := range cmd.Args() {
if err := cli.client.ContainerStop(context.Background(), name, *nSeconds); err != nil {
errs = append(errs, err.Error())
if err := cli.client.ContainerStop(name, *nSeconds); err != nil {
errs = append(errs, fmt.Sprintf("Failed to stop container (%s): %s", name, err))
} else {
fmt.Fprintf(cli.out, "%s\n", name)
}

View File

@@ -3,8 +3,6 @@ package client
import (
"errors"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/reference"
@@ -42,5 +40,5 @@ func (cli *DockerCli) CmdTag(args ...string) error {
Force: *force,
}
return cli.client.ImageTag(context.Background(), options)
return cli.client.ImageTag(options)
}

View File

@@ -5,8 +5,6 @@ import (
"strings"
"text/tabwriter"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
)
@@ -25,7 +23,7 @@ func (cli *DockerCli) CmdTop(args ...string) error {
arguments = cmd.Args()[1:]
}
procList, err := cli.client.ContainerTop(context.Background(), cmd.Arg(0), arguments)
procList, err := cli.client.ContainerTop(cmd.Arg(0), arguments)
if err != nil {
return err
}

View File

@@ -15,8 +15,6 @@ import (
"strconv"
"time"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/digest"
"github.com/docker/distribution/registry/client/auth"
@@ -108,17 +106,7 @@ func (scs simpleCredentialStore) Basic(u *url.URL) (string, string) {
return scs.auth.Username, scs.auth.Password
}
func (scs simpleCredentialStore) RefreshToken(u *url.URL, service string) string {
return scs.auth.IdentityToken
}
func (scs simpleCredentialStore) SetRefreshToken(*url.URL, string, string) {
}
// getNotaryRepository returns a NotaryRepository which stores all the
// information needed to operate on a notary repository.
// It creates a HTTP transport providing authentication support.
func (cli *DockerCli) getNotaryRepository(repoInfo *registry.RepositoryInfo, authConfig types.AuthConfig, actions ...string) (*client.NotaryRepository, error) {
func (cli *DockerCli) getNotaryRepository(repoInfo *registry.RepositoryInfo, authConfig types.AuthConfig) (*client.NotaryRepository, error) {
server, err := trustServer(repoInfo.Index)
if err != nil {
return nil, err
@@ -151,7 +139,7 @@ func (cli *DockerCli) getNotaryRepository(repoInfo *registry.RepositoryInfo, aut
}
// Skip configuration headers since request is not going to Docker daemon
modifiers := registry.DockerHeaders(clientUserAgent(), http.Header{})
modifiers := registry.DockerHeaders(http.Header{})
authTransport := transport.NewTransport(base, modifiers...)
pingClient := &http.Client{
Transport: authTransport,
@@ -180,7 +168,7 @@ func (cli *DockerCli) getNotaryRepository(repoInfo *registry.RepositoryInfo, aut
}
creds := simpleCredentialStore{auth: authConfig}
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoInfo.FullName(), actions...)
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoInfo.FullName(), "push", "pull")
basicHandler := auth.NewBasicHandler(creds)
modifiers = append(modifiers, transport.RequestModifier(auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler)))
tr := transport.NewTransport(base, modifiers...)
@@ -202,17 +190,17 @@ func convertTarget(t client.Target) (target, error) {
func (cli *DockerCli) getPassphraseRetriever() passphrase.Retriever {
aliasMap := map[string]string{
"root": "root",
"snapshot": "repository",
"targets": "repository",
"default": "repository",
"root": "root",
"snapshot": "repository",
"targets": "repository",
"targets/releases": "repository",
}
baseRetriever := passphrase.PromptRetrieverWithInOut(cli.in, cli.out, aliasMap)
env := map[string]string{
"root": os.Getenv("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE"),
"snapshot": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"),
"targets": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"),
"default": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"),
"root": os.Getenv("DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE"),
"snapshot": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"),
"targets": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"),
"targets/releases": os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"),
}
// Backwards compatibility with old env names. We should remove this in 1.10
@@ -222,11 +210,11 @@ func (cli *DockerCli) getPassphraseRetriever() passphrase.Retriever {
fmt.Fprintf(cli.err, "[DEPRECATED] The environment variable DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE has been deprecated and will be removed in v1.10. Please use DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE\n")
}
}
if env["snapshot"] == "" || env["targets"] == "" || env["default"] == "" {
if env["snapshot"] == "" || env["targets"] == "" || env["targets/releases"] == "" {
if passphrase := os.Getenv("DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE"); passphrase != "" {
env["snapshot"] = passphrase
env["targets"] = passphrase
env["default"] = passphrase
env["targets/releases"] = passphrase
fmt.Fprintf(cli.err, "[DEPRECATED] The environment variable DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE has been deprecated and will be removed in v1.10. Please use DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE\n")
}
}
@@ -235,10 +223,6 @@ func (cli *DockerCli) getPassphraseRetriever() passphrase.Retriever {
if v := env[alias]; v != "" {
return v, numAttempts > 1, nil
}
// For non-root roles, we can also try the "default" alias if it is specified
if v := env["default"]; v != "" && alias != data.CanonicalRootRole {
return v, numAttempts > 1, nil
}
return baseRetriever(keyName, alias, createNew, numAttempts)
}
}
@@ -250,9 +234,9 @@ func (cli *DockerCli) trustedReference(ref reference.NamedTagged) (reference.Can
}
// Resolve the Auth config relevant for this server
authConfig := cli.resolveAuthConfig(repoInfo.Index)
authConfig := cli.resolveAuthConfig(cli.configFile.AuthConfigs, repoInfo.Index)
notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig, "pull")
notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig)
if err != nil {
fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err)
return nil, err
@@ -262,11 +246,6 @@ func (cli *DockerCli) trustedReference(ref reference.NamedTagged) (reference.Can
if err != nil {
return nil, err
}
// Only list tags in the top level targets role or the releases delegation role - ignore
// all other delegation roles
if t.Role != releasesRole && t.Role != data.CanonicalTargetsRole {
return nil, notaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.Tag()))
}
r, err := convertTarget(t.Target)
if err != nil {
return nil, err
@@ -286,7 +265,7 @@ func (cli *DockerCli) tagTrusted(trustedRef reference.Canonical, ref reference.N
Force: true,
}
return cli.client.ImageTag(context.Background(), options)
return cli.client.ImageTag(options)
}
func notaryError(repoName string, err error) error {
@@ -322,7 +301,7 @@ func notaryError(repoName string, err error) error {
func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig types.AuthConfig, requestPrivilege apiclient.RequestPrivilegeFunc) error {
var refs []target
notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig, "pull")
notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig)
if err != nil {
fmt.Fprintf(cli.out, "Error establishing connection to trust repository: %s\n", err)
return err
@@ -340,28 +319,13 @@ func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registr
fmt.Fprintf(cli.out, "Skipping target for %q\n", repoInfo.Name())
continue
}
// Only list tags in the top level targets role or the releases delegation role - ignore
// all other delegation roles
if tgt.Role != releasesRole && tgt.Role != data.CanonicalTargetsRole {
continue
}
refs = append(refs, t)
}
if len(refs) == 0 {
return notaryError(repoInfo.FullName(), fmt.Errorf("No trusted tags for %s", repoInfo.FullName()))
}
} else {
t, err := notaryRepo.GetTargetByName(ref.String(), releasesRole, data.CanonicalTargetsRole)
if err != nil {
return notaryError(repoInfo.FullName(), err)
}
// Only get the tag if it's in the top level targets role or the releases delegation role
// ignore it if it's in any other delegation roles
if t.Role != releasesRole && t.Role != data.CanonicalTargetsRole {
return notaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.String()))
}
logrus.Debugf("retrieving target for %s role\n", t.Role)
r, err := convertTarget(t.Target)
if err != nil {
return err
@@ -407,153 +371,82 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
defer responseBody.Close()
// If it is a trusted push we would like to find the target entry which match the
// tag provided in the function and then do an AddTarget later.
target := &client.Target{}
// Count the times of calling for handleTarget,
// if it is called more that once, that should be considered an error in a trusted push.
cnt := 0
targets := []target{}
handleTarget := func(aux *json.RawMessage) {
cnt++
if cnt > 1 {
// handleTarget should only be called one. This will be treated as an error.
return
}
var pushResult distribution.PushResult
err := json.Unmarshal(*aux, &pushResult)
if err == nil && pushResult.Tag != "" && pushResult.Digest.Validate() == nil {
h, err := hex.DecodeString(pushResult.Digest.Hex())
if err != nil {
target = nil
return
}
target.Name = registry.ParseReference(pushResult.Tag).String()
target.Hashes = data.Hashes{string(pushResult.Digest.Algorithm()): h}
target.Length = int64(pushResult.Size)
targets = append(targets, target{
reference: registry.ParseReference(pushResult.Tag),
digest: pushResult.Digest,
size: int64(pushResult.Size),
})
}
}
// We want trust signatures to always take an explicit tag,
// otherwise it will act as an untrusted push.
if tag == "" {
if err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil); err != nil {
return err
}
fmt.Fprintln(cli.out, "No tag specified, skipping trust metadata push")
return nil
}
if err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, handleTarget); err != nil {
err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, handleTarget)
if err != nil {
return err
}
if cnt > 1 {
return fmt.Errorf("internal error: only one call to handleTarget expected")
if tag == "" {
fmt.Fprintf(cli.out, "No tag specified, skipping trust metadata push\n")
return nil
}
if target == nil {
fmt.Fprintln(cli.out, "No targets found, please provide a specific tag in order to sign it")
if len(targets) == 0 {
fmt.Fprintf(cli.out, "No targets found, skipping trust metadata push\n")
return nil
}
fmt.Fprintln(cli.out, "Signing and pushing trust metadata")
fmt.Fprintf(cli.out, "Signing and pushing trust metadata\n")
repo, err := cli.getNotaryRepository(repoInfo, authConfig, "push", "pull")
repo, err := cli.getNotaryRepository(repoInfo, authConfig)
if err != nil {
fmt.Fprintf(cli.out, "Error establishing connection to notary repository: %s\n", err)
return err
}
// get the latest repository metadata so we can figure out which roles to sign
_, err = repo.Update(false)
switch err.(type) {
case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
keys := repo.CryptoService.ListKeys(data.CanonicalRootRole)
var rootKeyID string
// always select the first root key
if len(keys) > 0 {
sort.Strings(keys)
rootKeyID = keys[0]
} else {
rootPublicKey, err := repo.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey)
if err != nil {
return err
}
rootKeyID = rootPublicKey.ID()
for _, target := range targets {
h, err := hex.DecodeString(target.digest.Hex())
if err != nil {
return err
}
// Initialize the notary repository with a remotely managed snapshot key
if err := repo.Initialize(rootKeyID, data.CanonicalSnapshotRole); err != nil {
return notaryError(repoInfo.FullName(), err)
t := &client.Target{
Name: target.reference.String(),
Hashes: data.Hashes{
string(target.digest.Algorithm()): h,
},
Length: int64(target.size),
}
fmt.Fprintf(cli.out, "Finished initializing %q\n", repoInfo.FullName())
err = repo.AddTarget(target, data.CanonicalTargetsRole)
case nil:
// already initialized and we have successfully downloaded the latest metadata
err = cli.addTargetToAllSignableRoles(repo, target)
default:
if err := repo.AddTarget(t, releasesRole); err != nil {
return err
}
}
err = repo.Publish()
if _, ok := err.(client.ErrRepoNotInitialized); !ok {
return notaryError(repoInfo.FullName(), err)
}
if err == nil {
err = repo.Publish()
keys := repo.CryptoService.ListKeys(data.CanonicalRootRole)
var rootKeyID string
// always select the first root key
if len(keys) > 0 {
sort.Strings(keys)
rootKeyID = keys[0]
} else {
rootPublicKey, err := repo.CryptoService.Create(data.CanonicalRootRole, data.ECDSAKey)
if err != nil {
return err
}
rootKeyID = rootPublicKey.ID()
}
if err != nil {
fmt.Fprintf(cli.out, "Failed to sign %q:%s - %s\n", repoInfo.FullName(), tag, err.Error())
if err := repo.Initialize(rootKeyID); err != nil {
return notaryError(repoInfo.FullName(), err)
}
fmt.Fprintf(cli.out, "Finished initializing %q\n", repoInfo.FullName())
fmt.Fprintf(cli.out, "Successfully signed %q:%s\n", repoInfo.FullName(), tag)
return nil
}
// Attempt to add the image target to all the top level delegation roles we can
// (based on whether we have the signing key and whether the role's path allows
// us to).
// If there are no delegation roles, we add to the targets role.
func (cli *DockerCli) addTargetToAllSignableRoles(repo *client.NotaryRepository, target *client.Target) error {
var signableRoles []string
// translate the full key names, which includes the GUN, into just the key IDs
allCanonicalKeyIDs := make(map[string]struct{})
for fullKeyID := range repo.CryptoService.ListAllKeys() {
allCanonicalKeyIDs[path.Base(fullKeyID)] = struct{}{}
}
allDelegationRoles, err := repo.GetDelegationRoles()
if err != nil {
return err
}
// if there are no delegation roles, then just try to sign it into the targets role
if len(allDelegationRoles) == 0 {
return repo.AddTarget(target, data.CanonicalTargetsRole)
}
// there are delegation roles, find every delegation role we have a key for, and
// attempt to sign into into all those roles.
for _, delegationRole := range allDelegationRoles {
// We do not support signing any delegation role that isn't a direct child of the targets role.
// Also don't bother checking the keys if we can't add the target
// to this role due to path restrictions
if path.Dir(delegationRole.Name) != data.CanonicalTargetsRole || !delegationRole.CheckPaths(target.Name) {
continue
}
for _, canonicalKeyID := range delegationRole.KeyIDs {
if _, ok := allCanonicalKeyIDs[canonicalKeyID]; ok {
signableRoles = append(signableRoles, delegationRole.Name)
break
}
}
}
if len(signableRoles) == 0 {
return fmt.Errorf("no valid signing keys for delegation roles")
}
return repo.AddTarget(target, signableRoles...)
return notaryError(repoInfo.FullName(), repo.Publish())
}

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
)
@@ -21,8 +19,8 @@ func (cli *DockerCli) CmdUnpause(args ...string) error {
var errs []string
for _, name := range cmd.Args() {
if err := cli.client.ContainerUnpause(context.Background(), name); err != nil {
errs = append(errs, err.Error())
if err := cli.client.ContainerUnpause(name); err != nil {
errs = append(errs, fmt.Sprintf("Failed to unpause container (%s): %s", name, err))
} else {
fmt.Fprintf(cli.out, "%s\n", name)
}

View File

@@ -4,11 +4,8 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/runconfig/opts"
"github.com/docker/engine-api/types/container"
"github.com/docker/go-units"
)
@@ -28,7 +25,6 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
flMemoryReservation := cmd.String([]string{"-memory-reservation"}, "", "Memory soft limit")
flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap")
flKernelMemory := cmd.String([]string{"-kernel-memory"}, "", "Kernel memory limit")
flRestartPolicy := cmd.String([]string{"-restart"}, "", "Restart policy to apply when a container exits")
cmd.Require(flag.Min, 1)
cmd.ParseFlags(args, true)
@@ -73,14 +69,6 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
}
}
var restartPolicy container.RestartPolicy
if *flRestartPolicy != "" {
restartPolicy, err = opts.ParseRestartPolicy(*flRestartPolicy)
if err != nil {
return err
}
}
resources := container.Resources{
BlkioWeight: *flBlkioWeight,
CpusetCpus: *flCpusetCpus,
@@ -95,15 +83,14 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
}
updateConfig := container.UpdateConfig{
Resources: resources,
RestartPolicy: restartPolicy,
Resources: resources,
}
names := cmd.Args()
var errs []string
for _, name := range names {
if err := cli.client.ContainerUpdate(context.Background(), name, updateConfig); err != nil {
errs = append(errs, err.Error())
if err := cli.client.ContainerUpdate(name, updateConfig); err != nil {
errs = append(errs, fmt.Sprintf("Failed to update container (%s): %s", name, err))
} else {
fmt.Fprintf(cli.out, "%s\n", name)
}

View File

@@ -4,16 +4,12 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
gosignal "os/signal"
"path/filepath"
"runtime"
"strings"
"time"
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/term"
@@ -29,7 +25,7 @@ func (cli *DockerCli) electAuthServer() string {
// example a Linux client might be interacting with a Windows daemon, hence
// the default registry URL might be Windows specific.
serverAddress := registry.IndexServer
if info, err := cli.client.Info(context.Background()); err != nil {
if info, err := cli.client.Info(); err != nil {
fmt.Fprintf(cli.out, "Warning: failed to get default registry endpoint from daemon (%v). Using system default: %s\n", err, serverAddress)
} else {
serverAddress = info.IndexServerAddress
@@ -46,11 +42,16 @@ func encodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
return base64.URLEncoding.EncodeToString(buf), nil
}
func (cli *DockerCli) encodeRegistryAuth(index *registrytypes.IndexInfo) (string, error) {
authConfig := registry.ResolveAuthConfig(cli.configFile.AuthConfigs, index)
return encodeAuthToBase64(authConfig)
}
func (cli *DockerCli) registryAuthenticationPrivilegedFunc(index *registrytypes.IndexInfo, cmdName string) client.RequestPrivilegeFunc {
return func() (string, error) {
fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", cmdName)
indexServer := registry.GetAuthConfigKey(index)
authConfig, err := cli.configureAuth("", "", indexServer, false)
authConfig, err := cli.configureAuth("", "", "", indexServer)
if err != nil {
return "", err
}
@@ -60,10 +61,6 @@ func (cli *DockerCli) registryAuthenticationPrivilegedFunc(index *registrytypes.
func (cli *DockerCli) resizeTty(id string, isExec bool) {
height, width := cli.getTtySize()
cli.resizeTtyTo(id, height, width, isExec)
}
func (cli *DockerCli) resizeTtyTo(id string, height, width int, isExec bool) {
if height == 0 && width == 0 {
return
}
@@ -76,9 +73,9 @@ func (cli *DockerCli) resizeTtyTo(id string, height, width int, isExec bool) {
var err error
if isExec {
err = cli.client.ContainerExecResize(context.Background(), options)
err = cli.client.ContainerExecResize(options)
} else {
err = cli.client.ContainerResize(context.Background(), options)
err = cli.client.ContainerResize(options)
}
if err != nil {
@@ -89,7 +86,7 @@ func (cli *DockerCli) resizeTtyTo(id string, height, width int, isExec bool) {
// getExitCode perform an inspect on the container. It returns
// the running state and the exit code.
func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
c, err := cli.client.ContainerInspect(context.Background(), containerID)
c, err := cli.client.ContainerInspect(containerID)
if err != nil {
// If we can't connect, then the daemon probably died.
if err != client.ErrConnectionFailed {
@@ -104,7 +101,7 @@ func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
// getExecExitCode perform an inspect on the exec command. It returns
// the running state and the exit code.
func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
resp, err := cli.client.ContainerExecInspect(context.Background(), execID)
resp, err := cli.client.ContainerExecInspect(execID)
if err != nil {
// If we can't connect, then the daemon probably died.
if err != client.ErrConnectionFailed {
@@ -159,44 +156,41 @@ func (cli *DockerCli) getTtySize() (int, int) {
return int(ws.Height), int(ws.Width)
}
func copyToFile(outfile string, r io.Reader) error {
tmpFile, err := ioutil.TempFile(filepath.Dir(outfile), ".docker_temp_")
if err != nil {
return err
}
tmpPath := tmpFile.Name()
_, err = io.Copy(tmpFile, r)
tmpFile.Close()
if err != nil {
os.Remove(tmpPath)
return err
}
if err = os.Rename(tmpPath, outfile); err != nil {
os.Remove(tmpPath)
return err
}
return nil
}
// resolveAuthConfig is like registry.ResolveAuthConfig, but if using the
// default index, it uses the default index name for the daemon's platform,
// not the client's platform.
func (cli *DockerCli) resolveAuthConfig(index *registrytypes.IndexInfo) types.AuthConfig {
func (cli *DockerCli) resolveAuthConfig(authConfigs map[string]types.AuthConfig, index *registrytypes.IndexInfo) types.AuthConfig {
configKey := index.Name
if index.Official {
configKey = cli.electAuthServer()
}
a, _ := getCredentials(cli.configFile, configKey)
return a
}
// First try the happy case
if c, found := authConfigs[configKey]; found || index.Official {
return c
}
func (cli *DockerCli) retrieveAuthConfigs() map[string]types.AuthConfig {
acs, _ := getAllCredentials(cli.configFile)
return acs
convertToHostname := func(url string) string {
stripped := url
if strings.HasPrefix(url, "http://") {
stripped = strings.Replace(url, "http://", "", 1)
} else if strings.HasPrefix(url, "https://") {
stripped = strings.Replace(url, "https://", "", 1)
}
nameParts := strings.SplitN(stripped, "/", 2)
return nameParts[0]
}
// Maybe they have a legacy config file, we will iterate the keys converting
// them to the new format and testing
for registry, ac := range authConfigs {
if configKey == convertToHostname(registry) {
return ac
}
}
// When all else fails, return an empty auth config
return types.AuthConfig{}
}

View File

@@ -1,6 +1,6 @@
// +build !windows
package builder
package client
import (
"path/filepath"

View File

@@ -1,6 +1,6 @@
// +build windows
package builder
package client
import (
"path/filepath"

View File

@@ -5,13 +5,10 @@ import (
"text/template"
"time"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/dockerversion"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/utils"
"github.com/docker/docker/utils/templates"
"github.com/docker/engine-api/types"
)
@@ -51,7 +48,7 @@ func (cli *DockerCli) CmdVersion(args ...string) (err error) {
}
var tmpl *template.Template
if tmpl, err = templates.Parse(templateFormat); err != nil {
if tmpl, err = template.New("").Funcs(funcMap).Parse(templateFormat); err != nil {
return Cli.StatusError{StatusCode: 64,
Status: "Template parsing error: " + err.Error()}
}
@@ -69,7 +66,7 @@ func (cli *DockerCli) CmdVersion(args ...string) (err error) {
},
}
serverVersion, err := cli.client.ServerVersion(context.Background())
serverVersion, err := cli.client.ServerVersion()
if err == nil {
vd.Server = &serverVersion
}

View File

@@ -2,15 +2,11 @@ package client
import (
"fmt"
"sort"
"text/tabwriter"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
runconfigopts "github.com/docker/docker/runconfig/opts"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
)
@@ -62,7 +58,7 @@ func (cli *DockerCli) CmdVolumeLs(args ...string) error {
}
}
volumes, err := cli.client.VolumeList(context.Background(), volFilterArgs)
volumes, err := cli.client.VolumeList(volFilterArgs)
if err != nil {
return err
}
@@ -76,7 +72,6 @@ func (cli *DockerCli) CmdVolumeLs(args ...string) error {
fmt.Fprintf(w, "\n")
}
sort.Sort(byVolumeName(volumes.Volumes))
for _, vol := range volumes.Volumes {
if *quiet {
fmt.Fprintln(w, vol.Name)
@@ -88,14 +83,6 @@ func (cli *DockerCli) CmdVolumeLs(args ...string) error {
return nil
}
type byVolumeName []*types.Volume
func (r byVolumeName) Len() int { return len(r) }
func (r byVolumeName) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r byVolumeName) Less(i, j int) bool {
return r[i].Name < r[j].Name
}
// CmdVolumeInspect displays low-level information on one or more volumes.
//
// Usage: docker volume inspect [OPTIONS] VOLUME [VOLUME...]
@@ -111,7 +98,7 @@ func (cli *DockerCli) CmdVolumeInspect(args ...string) error {
}
inspectSearcher := func(name string) (interface{}, []byte, error) {
i, err := cli.client.VolumeInspect(context.Background(), name)
i, err := cli.client.VolumeInspect(name)
return i, nil, err
}
@@ -129,9 +116,6 @@ func (cli *DockerCli) CmdVolumeCreate(args ...string) error {
flDriverOpts := opts.NewMapOpts(nil, nil)
cmd.Var(flDriverOpts, []string{"o", "-opt"}, "Set driver specific options")
flLabels := opts.NewListOpts(nil)
cmd.Var(&flLabels, []string{"-label"}, "Set metadata for a volume")
cmd.Require(flag.Exact, 0)
cmd.ParseFlags(args, true)
@@ -139,10 +123,9 @@ func (cli *DockerCli) CmdVolumeCreate(args ...string) error {
Driver: *flDriver,
DriverOpts: flDriverOpts.GetAll(),
Name: *flName,
Labels: runconfigopts.ConvertKVStringsToMap(flLabels.GetAll()),
}
vol, err := cli.client.VolumeCreate(context.Background(), volReq)
vol, err := cli.client.VolumeCreate(volReq)
if err != nil {
return err
}
@@ -162,7 +145,7 @@ func (cli *DockerCli) CmdVolumeRm(args ...string) error {
var status = 0
for _, name := range cmd.Args() {
if err := cli.client.VolumeRemove(context.Background(), name); err != nil {
if err := cli.client.VolumeRemove(name); err != nil {
fmt.Fprintf(cli.err, "%s\n", err)
status = 1
continue

View File

@@ -4,8 +4,6 @@ import (
"fmt"
"strings"
"golang.org/x/net/context"
Cli "github.com/docker/docker/cli"
flag "github.com/docker/docker/pkg/mflag"
)
@@ -23,9 +21,9 @@ func (cli *DockerCli) CmdWait(args ...string) error {
var errs []string
for _, name := range cmd.Args() {
status, err := cli.client.ContainerWait(context.Background(), name)
status, err := cli.client.ContainerWait(name)
if err != nil {
errs = append(errs, err.Error())
errs = append(errs, fmt.Sprintf("Failed to wait container (%s): %s", name, err))
} else {
fmt.Fprintf(cli.out, "%d\n", status)
}

View File

@@ -18,11 +18,14 @@ import (
// Common constants for daemon and client.
const (
// Version of Current REST API
DefaultVersion version.Version = "1.23"
DefaultVersion version.Version = "1.22"
// MinVersion represents Minimum REST API version supported
MinVersion version.Version = "1.12"
// DefaultDockerfileName is the Default filename with Docker commands, read by docker build
DefaultDockerfileName string = "Dockerfile"
// NoBaseImageSpecifier is the symbol used by the FROM
// command to specify that no base image is to be used.
NoBaseImageSpecifier string = "scratch"

View File

@@ -310,7 +310,7 @@ func TestLoadOrCreateTrustKeyCreateKey(t *testing.T) {
}
// With the need to create the folder hierarchy as tmpKeyFie is in a path
// where some folders do not exist.
// where some folder do not exists.
tmpKeyFile = filepath.Join(tmpKeyFolderPath, "folder/hierarchy/keyfile")
if key, err := LoadOrCreateTrustKey(tmpKeyFile); err != nil || key == nil {

View File

@@ -1,69 +0,0 @@
package httputils
import (
"net/http"
"strings"
"github.com/Sirupsen/logrus"
)
// httpStatusError is an interface
// that errors with custom status codes
// implement to tell the api layer
// which response status to set.
type httpStatusError interface {
HTTPErrorStatusCode() int
}
// inputValidationError is an interface
// that errors generated by invalid
// inputs can implement to tell the
// api layer to set a 400 status code
// in the response.
type inputValidationError interface {
IsValidationError() bool
}
// WriteError decodes a specific docker error and sends it in the response.
func WriteError(w http.ResponseWriter, err error) {
if err == nil || w == nil {
logrus.WithFields(logrus.Fields{"error": err, "writer": w}).Error("unexpected HTTP error handling")
return
}
var statusCode int
errMsg := err.Error()
switch e := err.(type) {
case httpStatusError:
statusCode = e.HTTPErrorStatusCode()
case inputValidationError:
statusCode = http.StatusBadRequest
default:
// FIXME: this is brittle and should not be necessary, but we still need to identify if
// there are errors falling back into this logic.
// If we need to differentiate between different possible error types,
// we should create appropriate error types that implement the httpStatusError interface.
errStr := strings.ToLower(errMsg)
for keyword, status := range map[string]int{
"not found": http.StatusNotFound,
"no such": http.StatusNotFound,
"bad parameter": http.StatusBadRequest,
"conflict": http.StatusConflict,
"impossible": http.StatusNotAcceptable,
"wrong login/password": http.StatusUnauthorized,
"hasn't been activated": http.StatusForbidden,
} {
if strings.Contains(errStr, keyword) {
statusCode = status
break
}
}
}
if statusCode == 0 {
statusCode = http.StatusInternalServerError
}
http.Error(w, errMsg, statusCode)
}

View File

@@ -9,6 +9,8 @@ import (
"golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/docker/api"
"github.com/docker/docker/pkg/version"
)
@@ -16,11 +18,8 @@ import (
// APIVersionKey is the client's requested API version.
const APIVersionKey = "api-version"
// UAStringKey is used as key type for user-agent string in net/context struct
const UAStringKey = "upstream-user-agent"
// APIFunc is an adapter to allow the use of ordinary functions as Docker API endpoints.
// Any function that has the appropriate signature can be registered as a API endpoint (e.g. getVersion).
// Any function that has the appropriate signature can be register as a API endpoint (e.g. getVersion).
type APIFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error
// HijackConnection interrupts the http response writer to get the
@@ -78,7 +77,7 @@ func ParseForm(r *http.Request) error {
return nil
}
// ParseMultipartForm ensures the request form is parsed, even with invalid content types.
// ParseMultipartForm ensure the request form is parsed, even with invalid content types.
func ParseMultipartForm(r *http.Request) error {
if err := r.ParseMultipartForm(4096); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
return err
@@ -86,6 +85,78 @@ func ParseMultipartForm(r *http.Request) error {
return nil
}
// WriteError decodes a specific docker error and sends it in the response.
func WriteError(w http.ResponseWriter, err error) {
if err == nil || w == nil {
logrus.WithFields(logrus.Fields{"error": err, "writer": w}).Error("unexpected HTTP error handling")
return
}
statusCode := http.StatusInternalServerError
errMsg := err.Error()
// Based on the type of error we get we need to process things
// slightly differently to extract the error message.
// In the 'errcode.*' cases there are two different type of
// error that could be returned. errocode.ErrorCode is the base
// type of error object - it is just an 'int' that can then be
// used as the look-up key to find the message. errorcode.Error
// extends errorcode.Error by adding error-instance specific
// data, like 'details' or variable strings to be inserted into
// the message.
//
// Ideally, we should just be able to call err.Error() for all
// cases but the errcode package doesn't support that yet.
//
// Additionally, in both errcode cases, there might be an http
// status code associated with it, and if so use it.
switch err.(type) {
case errcode.ErrorCode:
daError, _ := err.(errcode.ErrorCode)
statusCode = daError.Descriptor().HTTPStatusCode
errMsg = daError.Message()
case errcode.Error:
// For reference, if you're looking for a particular error
// then you can do something like :
// import ( derr "github.com/docker/docker/errors" )
// if daError.ErrorCode() == derr.ErrorCodeNoSuchContainer { ... }
daError, _ := err.(errcode.Error)
statusCode = daError.ErrorCode().Descriptor().HTTPStatusCode
errMsg = daError.Message
default:
// This part of will be removed once we've
// converted everything over to use the errcode package
// FIXME: this is brittle and should not be necessary.
// If we need to differentiate between different possible error types,
// we should create appropriate error types with clearly defined meaning
errStr := strings.ToLower(err.Error())
for keyword, status := range map[string]int{
"not found": http.StatusNotFound,
"no such": http.StatusNotFound,
"bad parameter": http.StatusBadRequest,
"conflict": http.StatusConflict,
"impossible": http.StatusNotAcceptable,
"wrong login/password": http.StatusUnauthorized,
"hasn't been activated": http.StatusForbidden,
} {
if strings.Contains(errStr, keyword) {
statusCode = status
break
}
}
}
if statusCode == 0 {
statusCode = http.StatusInternalServerError
}
http.Error(w, errMsg, statusCode)
}
// WriteJSON writes the value v to the http response stream as json with standard json encoding.
func WriteJSON(w http.ResponseWriter, code int, v interface{}) error {
w.Header().Set("Content-Type", "application/json")

View File

@@ -1,41 +1,195 @@
package server
import (
"bufio"
"encoding/json"
"io"
"net/http"
"runtime"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/server/middleware"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/errors"
"github.com/docker/docker/pkg/authorization"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/version"
"golang.org/x/net/context"
)
// middleware is an adapter to allow the use of ordinary functions as Docker API filters.
// Any function that has the appropriate signature can be register as a middleware.
type middleware func(handler httputils.APIFunc) httputils.APIFunc
// debugRequestMiddleware dumps the request to logger
func debugRequestMiddleware(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
logrus.Debugf("%s %s", r.Method, r.RequestURI)
if r.Method != "POST" {
return handler(ctx, w, r, vars)
}
if err := httputils.CheckForJSON(r); err != nil {
return handler(ctx, w, r, vars)
}
maxBodySize := 4096 // 4KB
if r.ContentLength > int64(maxBodySize) {
return handler(ctx, w, r, vars)
}
body := r.Body
bufReader := bufio.NewReaderSize(body, maxBodySize)
r.Body = ioutils.NewReadCloserWrapper(bufReader, func() error { return body.Close() })
b, err := bufReader.Peek(maxBodySize)
if err != io.EOF {
// either there was an error reading, or the buffer is full (in which case the request is too large)
return handler(ctx, w, r, vars)
}
var postForm map[string]interface{}
if err := json.Unmarshal(b, &postForm); err == nil {
if _, exists := postForm["password"]; exists {
postForm["password"] = "*****"
}
formStr, errMarshal := json.Marshal(postForm)
if errMarshal == nil {
logrus.Debugf("form data: %s", string(formStr))
} else {
logrus.Debugf("form data: %q", postForm)
}
}
return handler(ctx, w, r, vars)
}
}
// authorizationMiddleware perform authorization on the request.
func (s *Server) authorizationMiddleware(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
// FIXME: fill when authN gets in
// User and UserAuthNMethod are taken from AuthN plugins
// Currently tracked in https://github.com/docker/docker/pull/13994
user := ""
userAuthNMethod := ""
authCtx := authorization.NewCtx(s.authZPlugins, user, userAuthNMethod, r.Method, r.RequestURI)
if err := authCtx.AuthZRequest(w, r); err != nil {
logrus.Errorf("AuthZRequest for %s %s returned error: %s", r.Method, r.RequestURI, err)
return err
}
rw := authorization.NewResponseModifier(w)
if err := handler(ctx, rw, r, vars); err != nil {
logrus.Errorf("Handler for %s %s returned error: %s", r.Method, r.RequestURI, err)
return err
}
if err := authCtx.AuthZResponse(rw, r); err != nil {
logrus.Errorf("AuthZResponse for %s %s returned error: %s", r.Method, r.RequestURI, err)
return err
}
return nil
}
}
// userAgentMiddleware checks the User-Agent header looking for a valid docker client spec.
func (s *Server) userAgentMiddleware(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
dockerVersion := version.Version(s.cfg.Version)
userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
// v1.20 onwards includes the GOOS of the client after the version
// such as Docker/1.7.0 (linux)
if len(userAgent) == 2 && strings.Contains(userAgent[1], " ") {
userAgent[1] = strings.Split(userAgent[1], " ")[0]
}
if len(userAgent) == 2 && !dockerVersion.Equal(version.Version(userAgent[1])) {
logrus.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion)
}
}
return handler(ctx, w, r, vars)
}
}
// corsMiddleware sets the CORS header expectations in the server.
func (s *Server) corsMiddleware(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
// If "api-cors-header" is not given, but "api-enable-cors" is true, we set cors to "*"
// otherwise, all head values will be passed to HTTP handler
corsHeaders := s.cfg.CorsHeaders
if corsHeaders == "" && s.cfg.EnableCors {
corsHeaders = "*"
}
if corsHeaders != "" {
writeCorsHeaders(w, r, corsHeaders)
}
return handler(ctx, w, r, vars)
}
}
// versionMiddleware checks the api version requirements before passing the request to the server handler.
func versionMiddleware(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
apiVersion := version.Version(vars["version"])
if apiVersion == "" {
apiVersion = api.DefaultVersion
}
if apiVersion.GreaterThan(api.DefaultVersion) {
return errors.ErrorCodeNewerClientVersion.WithArgs(apiVersion, api.DefaultVersion)
}
if apiVersion.LessThan(api.MinVersion) {
return errors.ErrorCodeOldClientVersion.WithArgs(apiVersion, api.MinVersion)
}
w.Header().Set("Server", "Docker/"+dockerversion.Version+" ("+runtime.GOOS+")")
ctx = context.WithValue(ctx, httputils.APIVersionKey, apiVersion)
return handler(ctx, w, r, vars)
}
}
// handleWithGlobalMiddlwares wraps the handler function for a request with
// the server's global middlewares. The order of the middlewares is backwards,
// meaning that the first in the list will be evaluated last.
//
// Example: handleWithGlobalMiddlewares(s.getContainersName)
//
// s.loggingMiddleware(
// s.userAgentMiddleware(
// s.corsMiddleware(
// versionMiddleware(s.getContainersName)
// )
// )
// )
// )
func (s *Server) handleWithGlobalMiddlewares(handler httputils.APIFunc) httputils.APIFunc {
next := handler
handleVersion := middleware.NewVersionMiddleware(dockerversion.Version, api.DefaultVersion, api.MinVersion)
next = handleVersion(next)
if s.cfg.EnableCors {
handleCORS := middleware.NewCORSMiddleware(s.cfg.CorsHeaders)
next = handleCORS(next)
middlewares := []middleware{
versionMiddleware,
s.corsMiddleware,
s.userAgentMiddleware,
}
handleUserAgent := middleware.NewUserAgentMiddleware(s.cfg.Version)
next = handleUserAgent(next)
// Only want this on debug level
if s.cfg.Logging && logrus.GetLevel() == logrus.DebugLevel {
next = middleware.DebugRequestMiddleware(next)
middlewares = append(middlewares, debugRequestMiddleware)
}
if len(s.cfg.AuthorizationPluginNames) > 0 {
s.authZPlugins = authorization.NewPlugins(s.cfg.AuthorizationPluginNames)
handleAuthorization := middleware.NewAuthorizationMiddleware(s.authZPlugins)
next = handleAuthorization(next)
middlewares = append(middlewares, s.authorizationMiddleware)
}
return next
h := handler
for _, m := range middlewares {
h = m(h)
}
return h
}

View File

@@ -1,42 +0,0 @@
package middleware
import (
"net/http"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/pkg/authorization"
"golang.org/x/net/context"
)
// NewAuthorizationMiddleware creates a new Authorization middleware.
func NewAuthorizationMiddleware(plugins []authorization.Plugin) Middleware {
return func(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
// FIXME: fill when authN gets in
// User and UserAuthNMethod are taken from AuthN plugins
// Currently tracked in https://github.com/docker/docker/pull/13994
user := ""
userAuthNMethod := ""
authCtx := authorization.NewCtx(plugins, user, userAuthNMethod, r.Method, r.RequestURI)
if err := authCtx.AuthZRequest(w, r); err != nil {
logrus.Errorf("AuthZRequest for %s %s returned error: %s", r.Method, r.RequestURI, err)
return err
}
rw := authorization.NewResponseModifier(w)
if err := handler(ctx, rw, r, vars); err != nil {
logrus.Errorf("Handler for %s %s returned error: %s", r.Method, r.RequestURI, err)
return err
}
if err := authCtx.AuthZResponse(rw, r); err != nil {
logrus.Errorf("AuthZResponse for %s %s returned error: %s", r.Method, r.RequestURI, err)
return err
}
return nil
}
}
}

View File

@@ -1,33 +0,0 @@
package middleware
import (
"net/http"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
"golang.org/x/net/context"
)
// NewCORSMiddleware creates a new CORS middleware.
func NewCORSMiddleware(defaultHeaders string) Middleware {
return func(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
// If "api-cors-header" is not given, but "api-enable-cors" is true, we set cors to "*"
// otherwise, all head values will be passed to HTTP handler
corsHeaders := defaultHeaders
if corsHeaders == "" {
corsHeaders = "*"
}
writeCorsHeaders(w, r, corsHeaders)
return handler(ctx, w, r, vars)
}
}
}
func writeCorsHeaders(w http.ResponseWriter, r *http.Request, corsHeaders string) {
logrus.Debugf("CORS header is enabled and set to: %s", corsHeaders)
w.Header().Add("Access-Control-Allow-Origin", corsHeaders)
w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth")
w.Header().Add("Access-Control-Allow-Methods", "HEAD, GET, POST, DELETE, PUT, OPTIONS")
}

View File

@@ -1,56 +0,0 @@
package middleware
import (
"bufio"
"encoding/json"
"io"
"net/http"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/pkg/ioutils"
"golang.org/x/net/context"
)
// DebugRequestMiddleware dumps the request to logger
func DebugRequestMiddleware(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
logrus.Debugf("Calling %s %s", r.Method, r.RequestURI)
if r.Method != "POST" {
return handler(ctx, w, r, vars)
}
if err := httputils.CheckForJSON(r); err != nil {
return handler(ctx, w, r, vars)
}
maxBodySize := 4096 // 4KB
if r.ContentLength > int64(maxBodySize) {
return handler(ctx, w, r, vars)
}
body := r.Body
bufReader := bufio.NewReaderSize(body, maxBodySize)
r.Body = ioutils.NewReadCloserWrapper(bufReader, func() error { return body.Close() })
b, err := bufReader.Peek(maxBodySize)
if err != io.EOF {
// either there was an error reading, or the buffer is full (in which case the request is too large)
return handler(ctx, w, r, vars)
}
var postForm map[string]interface{}
if err := json.Unmarshal(b, &postForm); err == nil {
if _, exists := postForm["password"]; exists {
postForm["password"] = "*****"
}
formStr, errMarshal := json.Marshal(postForm)
if errMarshal == nil {
logrus.Debugf("form data: %s", string(formStr))
} else {
logrus.Debugf("form data: %q", postForm)
}
}
return handler(ctx, w, r, vars)
}
}

View File

@@ -1,7 +0,0 @@
package middleware
import "github.com/docker/docker/api/server/httputils"
// Middleware is an adapter to allow the use of ordinary functions as Docker API filters.
// Any function that has the appropriate signature can be registered as a middleware.
type Middleware func(handler httputils.APIFunc) httputils.APIFunc

View File

@@ -1,37 +0,0 @@
package middleware
import (
"net/http"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/pkg/version"
"golang.org/x/net/context"
)
// NewUserAgentMiddleware creates a new UserAgent middleware.
func NewUserAgentMiddleware(versionCheck string) Middleware {
serverVersion := version.Version(versionCheck)
return func(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
ctx = context.WithValue(ctx, httputils.UAStringKey, r.Header.Get("User-Agent"))
if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
// v1.20 onwards includes the GOOS of the client after the version
// such as Docker/1.7.0 (linux)
if len(userAgent) == 2 && strings.Contains(userAgent[1], " ") {
userAgent[1] = strings.Split(userAgent[1], " ")[0]
}
if len(userAgent) == 2 && !serverVersion.Equal(version.Version(userAgent[1])) {
logrus.Debugf("Client and server don't have the same version (client: %s, server: %s)", userAgent[1], serverVersion)
}
}
return handler(ctx, w, r, vars)
}
}
}

View File

@@ -1,45 +0,0 @@
package middleware
import (
"fmt"
"net/http"
"runtime"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/pkg/version"
"golang.org/x/net/context"
)
type badRequestError struct {
error
}
func (badRequestError) HTTPErrorStatusCode() int {
return http.StatusBadRequest
}
// NewVersionMiddleware creates a new Version middleware.
func NewVersionMiddleware(versionCheck string, defaultVersion, minVersion version.Version) Middleware {
serverVersion := version.Version(versionCheck)
return func(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
apiVersion := version.Version(vars["version"])
if apiVersion == "" {
apiVersion = defaultVersion
}
if apiVersion.GreaterThan(defaultVersion) {
return badRequestError{fmt.Errorf("client is newer than server (client API version: %s, server API version: %s)", apiVersion, defaultVersion)}
}
if apiVersion.LessThan(minVersion) {
return badRequestError{fmt.Errorf("client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", apiVersion, minVersion)}
}
header := fmt.Sprintf("Docker/%s (%s)", serverVersion, runtime.GOOS)
w.Header().Set("Server", header)
ctx = context.WithValue(ctx, httputils.APIVersionKey, apiVersion)
return handler(ctx, w, r, vars)
}
}
}

View File

@@ -1,13 +1,13 @@
package middleware
package server
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/pkg/version"
"github.com/docker/docker/errors"
"golang.org/x/net/context"
)
@@ -19,10 +19,7 @@ func TestVersionMiddleware(t *testing.T) {
return nil
}
defaultVersion := version.Version("1.10.0")
minVersion := version.Version("1.2.0")
m := NewVersionMiddleware(defaultVersion.String(), defaultVersion, minVersion)
h := m(handler)
h := versionMiddleware(handler)
req, _ := http.NewRequest("GET", "/containers/json", nil)
resp := httptest.NewRecorder()
@@ -40,10 +37,7 @@ func TestVersionMiddlewareWithErrors(t *testing.T) {
return nil
}
defaultVersion := version.Version("1.10.0")
minVersion := version.Version("1.2.0")
m := NewVersionMiddleware(defaultVersion.String(), defaultVersion, minVersion)
h := m(handler)
h := versionMiddleware(handler)
req, _ := http.NewRequest("GET", "/containers/json", nil)
resp := httptest.NewRecorder()
@@ -51,14 +45,13 @@ func TestVersionMiddlewareWithErrors(t *testing.T) {
vars := map[string]string{"version": "0.1"}
err := h(ctx, resp, req, vars)
if !strings.Contains(err.Error(), "client version 0.1 is too old. Minimum supported API version is 1.2.0") {
t.Fatalf("Expected too old client error, got %v", err)
if derr, ok := err.(errcode.Error); !ok || derr.ErrorCode() != errors.ErrorCodeOldClientVersion {
t.Fatalf("Expected ErrorCodeOldClientVersion, got %v", err)
}
vars["version"] = "100000"
err = h(ctx, resp, req, vars)
if !strings.Contains(err.Error(), "client is newer than server") {
t.Fatalf("Expected client newer than server error, got %v", err)
if derr, ok := err.(errcode.Error); !ok || derr.ErrorCode() != errors.ErrorCodeNewerClientVersion {
t.Fatalf("Expected ErrorCodeNewerClientVersion, got %v", err)
}
}

View File

@@ -9,10 +9,8 @@ import (
"github.com/gorilla/mux"
)
const debugPathPrefix = "/debug/"
func profilerSetup(mainRouter *mux.Router) {
var r = mainRouter.PathPrefix(debugPathPrefix).Subrouter()
func profilerSetup(mainRouter *mux.Router, path string) {
var r = mainRouter.PathPrefix(path).Subrouter()
r.HandleFunc("/vars", expVars)
r.HandleFunc("/pprof/", pprof.Index)
r.HandleFunc("/pprof/cmdline", pprof.Cmdline)

View File

@@ -1,13 +1,5 @@
package build
import (
"io"
"github.com/docker/docker/builder"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// Backend abstracts an image builder whose only purpose is to build an image referenced by an imageID.
type Backend interface {
// Build builds a Docker image referenced by an imageID string.
@@ -16,5 +8,5 @@ type Backend interface {
// by the caller.
//
// TODO: make this return a reference instead of string
Build(clientCtx context.Context, config *types.ImageBuildOptions, context builder.Context, stdout io.Writer, stderr io.Writer, out io.Writer, clientGone <-chan bool) (string, error)
Build() (imageID string)
}

View File

@@ -1,15 +1,19 @@
package build
import "github.com/docker/docker/api/server/router"
import (
"github.com/docker/docker/api/server/router"
"github.com/docker/docker/api/server/router/local"
"github.com/docker/docker/daemon"
)
// buildRouter is a router to talk with the build controller
type buildRouter struct {
backend Backend
backend *daemon.Daemon
routes []router.Route
}
// NewRouter initializes a new build router
func NewRouter(b Backend) router.Router {
func NewRouter(b *daemon.Daemon) router.Router {
r := &buildRouter{
backend: b,
}
@@ -24,6 +28,6 @@ func (r *buildRouter) Routes() []router.Route {
func (r *buildRouter) initRoutes() {
r.routes = []router.Route{
router.NewPostRoute("/build", r.postBuild),
local.NewPostRoute("/build", r.postBuild),
}
}

View File

@@ -4,25 +4,70 @@ import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strconv"
"strings"
"sync"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/daemon/daemonbuilder"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
"github.com/docker/docker/reference"
"github.com/docker/docker/utils"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
"github.com/docker/go-units"
"golang.org/x/net/context"
)
// sanitizeRepoAndTags parses the raw "t" parameter received from the client
// to a slice of repoAndTag.
// It also validates each repoName and tag.
func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
var (
repoAndTags []reference.Named
// This map is used for deduplicating the "-t" parameter.
uniqNames = make(map[string]struct{})
)
for _, repo := range names {
if repo == "" {
continue
}
ref, err := reference.ParseNamed(repo)
if err != nil {
return nil, err
}
ref = reference.WithDefaultTag(ref)
if _, isCanonical := ref.(reference.Canonical); isCanonical {
return nil, errors.New("build tag cannot contain a digest")
}
if _, isTagged := ref.(reference.NamedTagged); !isTagged {
ref, err = reference.WithTag(ref, reference.DefaultTag)
}
nameWithTag := ref.String()
if _, exists := uniqNames[nameWithTag]; !exists {
uniqNames[nameWithTag] = struct{}{}
repoAndTags = append(repoAndTags, ref)
}
}
return repoAndTags, nil
}
func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
version := httputils.VersionFromContext(ctx)
options := &types.ImageBuildOptions{}
@@ -49,7 +94,6 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
options.CPUSetCPUs = r.FormValue("cpusetcpus")
options.CPUSetMems = r.FormValue("cpusetmems")
options.CgroupParent = r.FormValue("cgroupparent")
options.Tags = r.Form["t"]
if r.Form.Get("shmsize") != "" {
shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
@@ -59,11 +103,11 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
options.ShmSize = shmSize
}
if i := container.Isolation(r.FormValue("isolation")); i != "" {
if !container.Isolation.IsValid(i) {
if i := container.IsolationLevel(r.FormValue("isolation")); i != "" {
if !container.IsolationLevel.IsValid(i) {
return nil, fmt.Errorf("Unsupported isolation: %q", i)
}
options.Isolation = i
options.IsolationLevel = i
}
var buildUlimits = []*units.Ulimit{}
@@ -83,30 +127,9 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
}
options.BuildArgs = buildArgs
}
var labels = map[string]string{}
labelsJSON := r.FormValue("labels")
if labelsJSON != "" {
if err := json.NewDecoder(strings.NewReader(labelsJSON)).Decode(&labels); err != nil {
return nil, err
}
options.Labels = labels
}
return options, nil
}
type syncWriter struct {
w io.Writer
mu sync.Mutex
}
func (s *syncWriter) Write(b []byte) (count int, err error) {
s.mu.Lock()
count, err = s.w.Write(b)
s.mu.Unlock()
return
}
func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
var (
authConfigs = map[string]types.AuthConfig{}
@@ -137,7 +160,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
if !output.Flushed() {
return err
}
_, err = w.Write(sf.FormatError(err))
_, err = w.Write(sf.FormatError(errors.New(utils.GetErrorMessage(err))))
if err != nil {
logrus.Warnf("could not write error response: %v", err)
}
@@ -149,6 +172,11 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
return errf(err)
}
repoAndTags, err := sanitizeRepoAndTags(r.Form["t"])
if err != nil {
return errf(err)
}
remoteURL := r.FormValue("remote")
// Currently, only used if context is from a remote url.
@@ -164,9 +192,8 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
var (
context builder.ModifiableContext
dockerfileName string
out io.Writer
)
context, dockerfileName, err = builder.DetectContextFromRemoteURL(r.Body, remoteURL, createProgressReader)
context, dockerfileName, err = daemonbuilder.DetectContextFromRemoteURL(r.Body, remoteURL, createProgressReader)
if err != nil {
return errf(err)
}
@@ -179,28 +206,62 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
buildOptions.Dockerfile = dockerfileName
}
buildOptions.AuthConfigs = authConfigs
uidMaps, gidMaps := br.backend.GetUIDGIDMaps()
defaultArchiver := &archive.Archiver{
Untar: chrootarchive.Untar,
UIDMaps: uidMaps,
GIDMaps: gidMaps,
}
out = output
docker := &daemonbuilder.Docker{
Daemon: br.backend,
OutOld: output,
AuthConfigs: authConfigs,
Archiver: defaultArchiver,
}
if buildOptions.SuppressOutput {
out = notVerboseBuffer
}
out = &syncWriter{w: out}
stdout := &streamformatter.StdoutFormatter{Writer: out, StreamFormatter: sf}
stderr := &streamformatter.StderrFormatter{Writer: out, StreamFormatter: sf}
closeNotifier := make(<-chan bool)
if notifier, ok := w.(http.CloseNotifier); ok {
closeNotifier = notifier.CloseNotify()
docker.OutOld = notVerboseBuffer
}
imgID, err := br.backend.Build(ctx, buildOptions,
b, err := dockerfile.NewBuilder(
buildOptions, // result of newBuildConfig
docker,
builder.DockerIgnoreContext{ModifiableContext: context},
stdout, stderr, out,
closeNotifier)
nil)
if err != nil {
return errf(err)
}
b.Stdout = &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
b.Stderr = &streamformatter.StderrFormatter{Writer: output, StreamFormatter: sf}
if buildOptions.SuppressOutput {
b.Stdout = &streamformatter.StdoutFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
b.Stderr = &streamformatter.StderrFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
}
if closeNotifier, ok := w.(http.CloseNotifier); ok {
finished := make(chan struct{})
defer close(finished)
clientGone := closeNotifier.CloseNotify()
go func() {
select {
case <-finished:
case <-clientGone:
logrus.Infof("Client disconnected, cancelling job: build")
b.Cancel()
}
}()
}
imgID, err := b.Build()
if err != nil {
return errf(err)
}
for _, rt := range repoAndTags {
if err := br.backend.TagImage(rt, imgID); err != nil {
return errf(err)
}
}
// Everything worked so if -q was provided the output from the daemon
// should be just the image ID and we'll print that to stdout.

View File

@@ -4,7 +4,8 @@ import (
"io"
"time"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/daemon"
"github.com/docker/docker/daemon/exec"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/version"
"github.com/docker/engine-api/types"
@@ -14,7 +15,7 @@ import (
// execBackend includes functions to implement to provide exec functionality.
type execBackend interface {
ContainerExecCreate(config *types.ExecConfig) (string, error)
ContainerExecInspect(id string) (*backend.ExecInspect, error)
ContainerExecInspect(id string) (*exec.Config, error)
ContainerExecResize(name string, height, width int) error
ContainerExecStart(name string, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) error
ExecExists(name string) (bool, error)
@@ -43,22 +44,24 @@ type stateBackend interface {
ContainerUnpause(name string) error
ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error)
ContainerWait(name string, timeout time.Duration) (int, error)
Exists(id string) bool
}
// monitorBackend includes functions to implement to provide containers monitoring functionality.
type monitorBackend interface {
ContainerChanges(name string) ([]archive.Change, error)
ContainerInspect(name string, size bool, version version.Version) (interface{}, error)
ContainerLogs(name string, config *backend.ContainerLogsConfig, started chan struct{}) error
ContainerStats(name string, config *backend.ContainerStatsConfig) error
ContainerLogs(name string, config *daemon.ContainerLogsConfig) error
ContainerStats(name string, config *daemon.ContainerStatsConfig) error
ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error)
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
Containers(config *daemon.ContainersConfig) ([]*types.Container, error)
}
// attachBackend includes function to implement to provide container attaching functionality.
type attachBackend interface {
ContainerAttach(name string, c *backend.ContainerAttachConfig) error
ContainerAttachWithLogs(name string, c *daemon.ContainerAttachWithLogsConfig) error
ContainerWsAttachWithLogs(name string, c *daemon.ContainerWsAttachWithLogsConfig) error
}
// Backend is all the methods that need to be implemented to provide container specific functionality.

View File

@@ -1,6 +1,9 @@
package container
import "github.com/docker/docker/api/server/router"
import (
"github.com/docker/docker/api/server/router"
"github.com/docker/docker/api/server/router/local"
)
// containerRouter is a router to talk with the container controller
type containerRouter struct {
@@ -17,7 +20,7 @@ func NewRouter(b Backend) router.Router {
return r
}
// Routes returns the available routes to the container controller
// Routes returns the available routers to the container controller
func (r *containerRouter) Routes() []router.Route {
return r.routes
}
@@ -26,38 +29,38 @@ func (r *containerRouter) Routes() []router.Route {
func (r *containerRouter) initRoutes() {
r.routes = []router.Route{
// HEAD
router.NewHeadRoute("/containers/{name:.*}/archive", r.headContainersArchive),
local.NewHeadRoute("/containers/{name:.*}/archive", r.headContainersArchive),
// GET
router.NewGetRoute("/containers/json", r.getContainersJSON),
router.NewGetRoute("/containers/{name:.*}/export", r.getContainersExport),
router.NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges),
router.NewGetRoute("/containers/{name:.*}/json", r.getContainersByName),
router.NewGetRoute("/containers/{name:.*}/top", r.getContainersTop),
router.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs),
router.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats),
router.NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach),
router.NewGetRoute("/exec/{id:.*}/json", r.getExecByID),
router.NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive),
local.NewGetRoute("/containers/json", r.getContainersJSON),
local.NewGetRoute("/containers/{name:.*}/export", r.getContainersExport),
local.NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges),
local.NewGetRoute("/containers/{name:.*}/json", r.getContainersByName),
local.NewGetRoute("/containers/{name:.*}/top", r.getContainersTop),
local.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs),
local.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats),
local.NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach),
local.NewGetRoute("/exec/{id:.*}/json", r.getExecByID),
local.NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive),
// POST
router.NewPostRoute("/containers/create", r.postContainersCreate),
router.NewPostRoute("/containers/{name:.*}/kill", r.postContainersKill),
router.NewPostRoute("/containers/{name:.*}/pause", r.postContainersPause),
router.NewPostRoute("/containers/{name:.*}/unpause", r.postContainersUnpause),
router.NewPostRoute("/containers/{name:.*}/restart", r.postContainersRestart),
router.NewPostRoute("/containers/{name:.*}/start", r.postContainersStart),
router.NewPostRoute("/containers/{name:.*}/stop", r.postContainersStop),
router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait),
router.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize),
router.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach),
router.NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy),
router.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate),
router.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart),
router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),
router.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename),
router.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate),
local.NewPostRoute("/containers/create", r.postContainersCreate),
local.NewPostRoute("/containers/{name:.*}/kill", r.postContainersKill),
local.NewPostRoute("/containers/{name:.*}/pause", r.postContainersPause),
local.NewPostRoute("/containers/{name:.*}/unpause", r.postContainersUnpause),
local.NewPostRoute("/containers/{name:.*}/restart", r.postContainersRestart),
local.NewPostRoute("/containers/{name:.*}/start", r.postContainersStart),
local.NewPostRoute("/containers/{name:.*}/stop", r.postContainersStop),
local.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait),
local.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize),
local.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach),
local.NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy),
local.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate),
local.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart),
local.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),
local.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename),
local.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate),
// PUT
router.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive),
local.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive),
// DELETE
router.NewDeleteRoute("/containers/{name:.*}", r.deleteContainers),
local.NewDeleteRoute("/containers/{name:.*}", r.deleteContainers),
}
}

View File

@@ -11,15 +11,18 @@ import (
"time"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/daemon"
derr "github.com/docker/docker/errors"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/utils"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/filters"
timetypes "github.com/docker/engine-api/types/time"
"golang.org/x/net/context"
"golang.org/x/net/websocket"
)
@@ -28,17 +31,13 @@ func (s *containerRouter) getContainersJSON(ctx context.Context, w http.Response
if err := httputils.ParseForm(r); err != nil {
return err
}
filter, err := filters.FromParam(r.Form.Get("filters"))
if err != nil {
return err
}
config := &types.ContainerListOptions{
All: httputils.BoolValue(r, "all"),
Size: httputils.BoolValue(r, "size"),
Since: r.Form.Get("since"),
Before: r.Form.Get("before"),
Filter: filter,
config := &daemon.ContainersConfig{
All: httputils.BoolValue(r, "all"),
Size: httputils.BoolValue(r, "size"),
Since: r.Form.Get("since"),
Before: r.Form.Get("before"),
Filters: r.Form.Get("filters"),
}
if tmpLimit := r.Form.Get("limit"); tmpLimit != "" {
@@ -63,8 +62,14 @@ func (s *containerRouter) getContainersStats(ctx context.Context, w http.Respons
}
stream := httputils.BoolValueOrDefault(r, "stream", true)
var out io.Writer
if !stream {
w.Header().Set("Content-Type", "application/json")
out = w
} else {
wf := ioutils.NewWriteFlusher(w)
out = wf
defer wf.Close()
}
var closeNotifier <-chan bool
@@ -72,11 +77,11 @@ func (s *containerRouter) getContainersStats(ctx context.Context, w http.Respons
closeNotifier = notifier.CloseNotify()
}
config := &backend.ContainerStatsConfig{
config := &daemon.ContainerStatsConfig{
Stream: stream,
OutStream: w,
OutStream: out,
Stop: closeNotifier,
Version: string(httputils.VersionFromContext(ctx)),
Version: httputils.VersionFromContext(ctx),
}
return s.backend.ContainerStats(vars["name"], config)
@@ -97,36 +102,53 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response
return fmt.Errorf("Bad parameters: you must choose at least one stream")
}
var since time.Time
if r.Form.Get("since") != "" {
s, n, err := timetypes.ParseTimestamps(r.Form.Get("since"), 0)
if err != nil {
return err
}
since = time.Unix(s, n)
}
var closeNotifier <-chan bool
if notifier, ok := w.(http.CloseNotifier); ok {
closeNotifier = notifier.CloseNotify()
}
containerName := vars["name"]
logsConfig := &backend.ContainerLogsConfig{
ContainerLogsOptions: types.ContainerLogsOptions{
Follow: httputils.BoolValue(r, "follow"),
Timestamps: httputils.BoolValue(r, "timestamps"),
Since: r.Form.Get("since"),
Tail: r.Form.Get("tail"),
ShowStdout: stdout,
ShowStderr: stderr,
},
OutStream: w,
Stop: closeNotifier,
if !s.backend.Exists(containerName) {
return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
}
chStarted := make(chan struct{})
if err := s.backend.ContainerLogs(containerName, logsConfig, chStarted); err != nil {
select {
case <-chStarted:
// The client may be expecting all of the data we're sending to
// be multiplexed, so send it through OutStream, which will
// have been set up to handle that if needed.
fmt.Fprintf(logsConfig.OutStream, "Error running logs job: %v\n", err)
default:
return err
}
// write an empty chunk of data (this is to ensure that the
// HTTP Response is sent immediately, even if the container has
// not yet produced any data)
w.WriteHeader(http.StatusOK)
if flusher, ok := w.(http.Flusher); ok {
flusher.Flush()
}
output := ioutils.NewWriteFlusher(w)
defer output.Close()
logsConfig := &daemon.ContainerLogsConfig{
Follow: httputils.BoolValue(r, "follow"),
Timestamps: httputils.BoolValue(r, "timestamps"),
Since: since,
Tail: r.Form.Get("tail"),
UseStdout: stdout,
UseStderr: stderr,
OutStream: output,
Stop: closeNotifier,
}
if err := s.backend.ContainerLogs(containerName, logsConfig); err != nil {
// The client may be expecting all of the data we're sending to
// be multiplexed, so send it through OutStream, which will
// have been set up to handle that if needed.
fmt.Fprintf(logsConfig.OutStream, "Error running logs job: %s\n", utils.GetErrorMessage(err))
}
return nil
@@ -179,10 +201,6 @@ func (s *containerRouter) postContainersStop(ctx context.Context, w http.Respons
return nil
}
type errContainerIsRunning interface {
ContainerIsRunning() bool
}
func (s *containerRouter) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
@@ -200,17 +218,15 @@ func (s *containerRouter) postContainersKill(ctx context.Context, w http.Respons
}
if err := s.backend.ContainerKill(name, uint64(sig)); err != nil {
var isStopped bool
if e, ok := err.(errContainerIsRunning); ok {
isStopped = !e.ContainerIsRunning()
}
theErr, isDerr := err.(errcode.ErrorCoder)
isStopped := isDerr && theErr.ErrorCode() == derr.ErrorCodeNotRunning
// Return error that's not caused because the container is stopped.
// Return error if the container is not running and the api is >= 1.20
// to keep backwards compatibility.
version := httputils.VersionFromContext(ctx)
if version.GreaterThanOrEqualTo("1.20") || !isStopped {
return fmt.Errorf("Cannot kill container %s: %v", name, err)
return fmt.Errorf("Cannot kill container %s: %v", name, utils.GetErrorMessage(err))
}
}
@@ -325,8 +341,7 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
}
hostConfig := &container.HostConfig{
Resources: updateConfig.Resources,
RestartPolicy: updateConfig.RestartPolicy,
Resources: updateConfig.Resources,
}
name := vars["name"]
@@ -431,45 +446,18 @@ func (s *containerRouter) postContainersAttach(ctx context.Context, w http.Respo
}
}
hijacker, ok := w.(http.Hijacker)
if !ok {
return fmt.Errorf("error attaching to container %s, hijack connection missing", containerName)
}
setupStreams := func() (io.ReadCloser, io.Writer, io.Writer, error) {
conn, _, err := hijacker.Hijack()
if err != nil {
return nil, nil, nil, err
}
// set raw mode
conn.Write([]byte{})
if upgrade {
fmt.Fprintf(conn, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
} else {
fmt.Fprintf(conn, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
}
closer := func() error {
httputils.CloseStreams(conn)
return nil
}
return ioutils.NewReadCloserWrapper(conn, closer), conn, conn, nil
}
attachConfig := &backend.ContainerAttachConfig{
GetStreams: setupStreams,
attachWithLogsConfig := &daemon.ContainerAttachWithLogsConfig{
Hijacker: w.(http.Hijacker),
Upgrade: upgrade,
UseStdin: httputils.BoolValue(r, "stdin"),
UseStdout: httputils.BoolValue(r, "stdout"),
UseStderr: httputils.BoolValue(r, "stderr"),
Logs: httputils.BoolValue(r, "logs"),
Stream: httputils.BoolValue(r, "stream"),
DetachKeys: keys,
MuxStreams: true,
}
return s.backend.ContainerAttach(containerName, attachConfig)
return s.backend.ContainerAttachWithLogs(containerName, attachWithLogsConfig)
}
func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
@@ -478,6 +466,10 @@ func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.Respons
}
containerName := vars["name"]
if !s.backend.Exists(containerName) {
return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
}
var keys []byte
var err error
detachKeys := r.FormValue("detachKeys")
@@ -488,44 +480,24 @@ func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.Respons
}
}
done := make(chan struct{})
started := make(chan struct{})
h := websocket.Handler(func(ws *websocket.Conn) {
defer ws.Close()
setupStreams := func() (io.ReadCloser, io.Writer, io.Writer, error) {
wsChan := make(chan *websocket.Conn)
h := func(conn *websocket.Conn) {
wsChan <- conn
<-done
wsAttachWithLogsConfig := &daemon.ContainerWsAttachWithLogsConfig{
InStream: ws,
OutStream: ws,
ErrStream: ws,
Logs: httputils.BoolValue(r, "logs"),
Stream: httputils.BoolValue(r, "stream"),
DetachKeys: keys,
}
srv := websocket.Server{Handler: h, Handshake: nil}
go func() {
close(started)
srv.ServeHTTP(w, r)
}()
if err := s.backend.ContainerWsAttachWithLogs(containerName, wsAttachWithLogsConfig); err != nil {
logrus.Errorf("Error attaching websocket: %s", utils.GetErrorMessage(err))
}
})
ws := websocket.Server{Handler: h, Handshake: nil}
ws.ServeHTTP(w, r)
conn := <-wsChan
return conn, conn, conn, nil
}
attachConfig := &backend.ContainerAttachConfig{
GetStreams: setupStreams,
Logs: httputils.BoolValue(r, "logs"),
Stream: httputils.BoolValue(r, "stream"),
DetachKeys: keys,
UseStdin: true,
UseStdout: true,
UseStderr: true,
MuxStreams: false, // TODO: this should be true since it's a single stream for both stdout and stderr
}
err = s.backend.ContainerAttach(containerName, attachConfig)
close(done)
select {
case <-started:
logrus.Errorf("Error attaching websocket: %s", err)
return nil
default:
}
return err
return nil
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/pkg/stdcopy"
"github.com/docker/docker/utils"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
@@ -45,7 +46,7 @@ func (s *containerRouter) postContainerExecCreate(ctx context.Context, w http.Re
// Register an instance of Exec in container.
id, err := s.backend.ContainerExecCreate(execConfig)
if err != nil {
logrus.Errorf("Error setting up exec command in container %s: %v", name, err)
logrus.Errorf("Error setting up exec command in container %s: %s", name, utils.GetErrorMessage(err))
return err
}
@@ -103,6 +104,8 @@ func (s *containerRouter) postContainerExecStart(ctx context.Context, w http.Res
stderr = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
stdout = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
}
} else {
outStream = w
}
// Now run the user process in container.
@@ -110,9 +113,7 @@ func (s *containerRouter) postContainerExecStart(ctx context.Context, w http.Res
if execStartCheck.Detach {
return err
}
stdout.Write([]byte(err.Error()))
logrus.Errorf("Error running exec in container: %v\n", err)
return err
logrus.Errorf("Error running exec in container: %v\n", utils.GetErrorMessage(err))
}
return nil
}

View File

@@ -7,7 +7,7 @@ import (
"golang.org/x/net/context"
)
// getContainersByName inspects container's configuration and serializes it as json.
// getContainersByName inspects containers configuration and serializes it as json.
func (s *containerRouter) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
displaySize := httputils.BoolValue(r, "size")

View File

@@ -1,44 +0,0 @@
package image
import (
"io"
"github.com/docker/docker/reference"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/registry"
"golang.org/x/net/context"
)
// Backend is all the methods that need to be implemented
// to provide image specific functionality.
type Backend interface {
containerBackend
imageBackend
importExportBackend
registryBackend
}
type containerBackend interface {
Commit(name string, config *types.ContainerCommitConfig) (imageID string, err error)
}
type imageBackend interface {
ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error)
ImageHistory(imageName string) ([]*types.ImageHistory, error)
Images(filterArgs string, filter string, all bool) ([]*types.Image, error)
LookupImage(name string) (*types.ImageInspect, error)
TagImage(newTag reference.Named, imageName string) error
}
type importExportBackend interface {
LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, config *container.Config) error
ExportImage(names []string, outStream io.Writer) error
}
type registryBackend interface {
PullImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
SearchRegistryForImages(ctx context.Context, term string, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error)
}

View File

@@ -1,44 +0,0 @@
package image
import "github.com/docker/docker/api/server/router"
// imageRouter is a router to talk with the image controller
type imageRouter struct {
backend Backend
routes []router.Route
}
// NewRouter initializes a new image router
func NewRouter(backend Backend) router.Router {
r := &imageRouter{
backend: backend,
}
r.initRoutes()
return r
}
// Routes returns the available routes to the image controller
func (r *imageRouter) Routes() []router.Route {
return r.routes
}
// initRoutes initializes the routes in the image router
func (r *imageRouter) initRoutes() {
r.routes = []router.Route{
// GET
router.NewGetRoute("/images/json", r.getImagesJSON),
router.NewGetRoute("/images/search", r.getImagesSearch),
router.NewGetRoute("/images/get", r.getImagesGet),
router.NewGetRoute("/images/{name:.*}/get", r.getImagesGet),
router.NewGetRoute("/images/{name:.*}/history", r.getImagesHistory),
router.NewGetRoute("/images/{name:.*}/json", r.getImagesByName),
// POST
router.NewPostRoute("/commit", r.postCommit),
router.NewPostRoute("/images/create", r.postImagesCreate),
router.NewPostRoute("/images/load", r.postImagesLoad),
router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush),
router.NewPostRoute("/images/{name:.*}/tag", r.postImagesTag),
// DELETE
router.NewDeleteRoute("/images/{name:.*}", r.deleteImages),
}
}

View File

@@ -1,61 +0,0 @@
package router
import "github.com/docker/docker/api/server/httputils"
// localRoute defines an individual API route to connect
// with the docker daemon. It implements Route.
type localRoute struct {
method string
path string
handler httputils.APIFunc
}
// Handler returns the APIFunc to let the server wrap it in middlewares.
func (l localRoute) Handler() httputils.APIFunc {
return l.handler
}
// Method returns the http method that the route responds to.
func (l localRoute) Method() string {
return l.method
}
// Path returns the subpath where the route responds to.
func (l localRoute) Path() string {
return l.path
}
// NewRoute initializes a new local route for the router.
func NewRoute(method, path string, handler httputils.APIFunc) Route {
return localRoute{method, path, handler}
}
// NewGetRoute initializes a new route with the http method GET.
func NewGetRoute(path string, handler httputils.APIFunc) Route {
return NewRoute("GET", path, handler)
}
// NewPostRoute initializes a new route with the http method POST.
func NewPostRoute(path string, handler httputils.APIFunc) Route {
return NewRoute("POST", path, handler)
}
// NewPutRoute initializes a new route with the http method PUT.
func NewPutRoute(path string, handler httputils.APIFunc) Route {
return NewRoute("PUT", path, handler)
}
// NewDeleteRoute initializes a new route with the http method DELETE.
func NewDeleteRoute(path string, handler httputils.APIFunc) Route {
return NewRoute("DELETE", path, handler)
}
// NewOptionsRoute initializes a new route with the http method OPTIONS.
func NewOptionsRoute(path string, handler httputils.APIFunc) Route {
return NewRoute("OPTIONS", path, handler)
}
// NewHeadRoute initializes a new route with the http method HEAD.
func NewHeadRoute(path string, handler httputils.APIFunc) Route {
return NewRoute("HEAD", path, handler)
}

View File

@@ -1,4 +1,4 @@
package image
package local
import (
"encoding/base64"
@@ -14,6 +14,7 @@ import (
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/builder/dockerfile"
derr "github.com/docker/docker/errors"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/streamformatter"
"github.com/docker/docker/reference"
@@ -23,7 +24,7 @@ import (
"golang.org/x/net/context"
)
func (s *imageRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -48,6 +49,10 @@ func (s *imageRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *
c = &container.Config{}
}
if !s.daemon.Exists(cname) {
return derr.ErrorCodeNoSuchContainer.WithArgs(cname)
}
newConfig, err := dockerfile.BuildFromConfig(c, r.Form["changes"])
if err != nil {
return err
@@ -63,7 +68,7 @@ func (s *imageRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *
MergeConfigs: true,
}
imgID, err := s.backend.Commit(cname, commitCfg)
imgID, err := s.daemon.Commit(cname, commitCfg)
if err != nil {
return err
}
@@ -74,7 +79,7 @@ func (s *imageRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *
}
// Creates an image from Pull or from Import
func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -84,8 +89,21 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
repo = r.Form.Get("repo")
tag = r.Form.Get("tag")
message = r.Form.Get("message")
err error
output = ioutils.NewWriteFlusher(w)
)
authEncoded := r.Header.Get("X-Registry-Auth")
authConfig := &types.AuthConfig{}
if authEncoded != "" {
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
// for a pull it is not an error if no auth was given
// to increase compatibility with the existing api it is defaulting to be empty
authConfig = &types.AuthConfig{}
}
}
var (
err error
output = ioutils.NewWriteFlusher(w)
)
defer output.Close()
@@ -118,18 +136,7 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
}
}
authEncoded := r.Header.Get("X-Registry-Auth")
authConfig := &types.AuthConfig{}
if authEncoded != "" {
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
// for a pull it is not an error if no auth was given
// to increase compatibility with the existing api it is defaulting to be empty
authConfig = &types.AuthConfig{}
}
}
err = s.backend.PullImage(ctx, ref, metaHeaders, authConfig, output)
err = s.daemon.PullImage(ref, metaHeaders, authConfig, output)
}
}
// Check the error from pulling an image to make sure the request
@@ -170,7 +177,7 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
return err
}
err = s.backend.ImportImage(src, newRef, message, r.Body, output, newConfig)
err = s.daemon.ImportImage(src, newRef, message, r.Body, output, newConfig)
}
if err != nil {
if !output.Flushed() {
@@ -183,7 +190,7 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
return nil
}
func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
metaHeaders := map[string][]string{}
for k, v := range r.Header {
if strings.HasPrefix(k, "X-Meta-") {
@@ -228,7 +235,7 @@ func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter,
w.Header().Set("Content-Type", "application/json")
if err := s.backend.PushImage(ctx, ref, metaHeaders, authConfig, output); err != nil {
if err := s.daemon.PushImage(ref, metaHeaders, authConfig, output); err != nil {
if !output.Flushed() {
return err
}
@@ -238,7 +245,7 @@ func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter,
return nil
}
func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -254,7 +261,7 @@ func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r
names = r.Form["names"]
}
if err := s.backend.ExportImage(names, output); err != nil {
if err := s.daemon.ExportImage(names, output); err != nil {
if !output.Flushed() {
return err
}
@@ -264,26 +271,11 @@ func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r
return nil
}
func (s *imageRouter) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}
quiet := httputils.BoolValueOrDefault(r, "quiet", true)
if !quiet {
w.Header().Set("Content-Type", "application/json")
output := ioutils.NewWriteFlusher(w)
defer output.Close()
if err := s.backend.LoadImage(r.Body, output, quiet); err != nil {
output.Write(streamformatter.NewJSONStreamFormatter().FormatError(err))
}
return nil
}
return s.backend.LoadImage(r.Body, w, quiet)
func (s *router) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
return s.daemon.LoadImage(r.Body, w)
}
func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -297,7 +289,7 @@ func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r
force := httputils.BoolValue(r, "force")
prune := !httputils.BoolValue(r, "noprune")
list, err := s.backend.ImageDelete(name, force, prune)
list, err := s.daemon.ImageDelete(name, force, prune)
if err != nil {
return err
}
@@ -305,8 +297,8 @@ func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r
return httputils.WriteJSON(w, http.StatusOK, list)
}
func (s *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
imageInspect, err := s.backend.LookupImage(vars["name"])
func (s *router) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
imageInspect, err := s.daemon.LookupImage(vars["name"])
if err != nil {
return err
}
@@ -314,13 +306,13 @@ func (s *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWriter
return httputils.WriteJSON(w, http.StatusOK, imageInspect)
}
func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}
// FIXME: The filter parameter could just be a match filter
images, err := s.backend.Images(r.Form.Get("filters"), r.Form.Get("filter"), httputils.BoolValue(r, "all"))
images, err := s.daemon.Images(r.Form.Get("filters"), r.Form.Get("filter"), httputils.BoolValue(r, "all"))
if err != nil {
return err
}
@@ -328,9 +320,9 @@ func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter,
return httputils.WriteJSON(w, http.StatusOK, images)
}
func (s *imageRouter) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
name := vars["name"]
history, err := s.backend.ImageHistory(name)
history, err := s.daemon.ImageHistory(name)
if err != nil {
return err
}
@@ -338,7 +330,7 @@ func (s *imageRouter) getImagesHistory(ctx context.Context, w http.ResponseWrite
return httputils.WriteJSON(w, http.StatusOK, history)
}
func (s *imageRouter) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -353,14 +345,14 @@ func (s *imageRouter) postImagesTag(ctx context.Context, w http.ResponseWriter,
return err
}
}
if err := s.backend.TagImage(newTag, vars["name"]); err != nil {
if err := s.daemon.TagImage(newTag, vars["name"]); err != nil {
return err
}
w.WriteHeader(http.StatusCreated)
return nil
}
func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
func (s *router) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -383,7 +375,7 @@ func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter
headers[k] = v
}
}
query, err := s.backend.SearchRegistryForImages(ctx, r.Form.Get("term"), config, headers)
query, err := s.daemon.SearchRegistryForImages(r.Form.Get("term"), config, headers)
if err != nil {
return err
}

View File

@@ -0,0 +1,107 @@
package local
import (
"github.com/docker/docker/api/server/httputils"
dkrouter "github.com/docker/docker/api/server/router"
"github.com/docker/docker/daemon"
)
// router is a docker router that talks with the local docker daemon.
type router struct {
daemon *daemon.Daemon
routes []dkrouter.Route
}
// localRoute defines an individual API route to connect with the docker daemon.
// It implements router.Route.
type localRoute struct {
method string
path string
handler httputils.APIFunc
}
// Handler returns the APIFunc to let the server wrap it in middlewares
func (l localRoute) Handler() httputils.APIFunc {
return l.handler
}
// Method returns the http method that the route responds to.
func (l localRoute) Method() string {
return l.method
}
// Path returns the subpath where the route responds to.
func (l localRoute) Path() string {
return l.path
}
// NewRoute initializes a new local router for the reouter
func NewRoute(method, path string, handler httputils.APIFunc) dkrouter.Route {
return localRoute{method, path, handler}
}
// NewGetRoute initializes a new route with the http method GET.
func NewGetRoute(path string, handler httputils.APIFunc) dkrouter.Route {
return NewRoute("GET", path, handler)
}
// NewPostRoute initializes a new route with the http method POST.
func NewPostRoute(path string, handler httputils.APIFunc) dkrouter.Route {
return NewRoute("POST", path, handler)
}
// NewPutRoute initializes a new route with the http method PUT.
func NewPutRoute(path string, handler httputils.APIFunc) dkrouter.Route {
return NewRoute("PUT", path, handler)
}
// NewDeleteRoute initializes a new route with the http method DELETE.
func NewDeleteRoute(path string, handler httputils.APIFunc) dkrouter.Route {
return NewRoute("DELETE", path, handler)
}
// NewOptionsRoute initializes a new route with the http method OPTIONS
func NewOptionsRoute(path string, handler httputils.APIFunc) dkrouter.Route {
return NewRoute("OPTIONS", path, handler)
}
// NewHeadRoute initializes a new route with the http method HEAD.
func NewHeadRoute(path string, handler httputils.APIFunc) dkrouter.Route {
return NewRoute("HEAD", path, handler)
}
// NewRouter initializes a local router with a new daemon.
func NewRouter(daemon *daemon.Daemon) dkrouter.Router {
r := &router{
daemon: daemon,
}
r.initRoutes()
return r
}
// Routes returns the list of routes registered in the router.
func (r *router) Routes() []dkrouter.Route {
return r.routes
}
// initRoutes initializes the routes in this router
func (r *router) initRoutes() {
r.routes = []dkrouter.Route{
// OPTIONS
// GET
NewGetRoute("/images/json", r.getImagesJSON),
NewGetRoute("/images/search", r.getImagesSearch),
NewGetRoute("/images/get", r.getImagesGet),
NewGetRoute("/images/{name:.*}/get", r.getImagesGet),
NewGetRoute("/images/{name:.*}/history", r.getImagesHistory),
NewGetRoute("/images/{name:.*}/json", r.getImagesByName),
// POST
NewPostRoute("/commit", r.postCommit),
NewPostRoute("/images/create", r.postImagesCreate),
NewPostRoute("/images/load", r.postImagesLoad),
NewPostRoute("/images/{name:.*}/push", r.postImagesPush),
NewPostRoute("/images/{name:.*}/tag", r.postImagesTag),
// DELETE
NewDeleteRoute("/images/{name:.*}", r.deleteImages),
}
}

View File

@@ -5,15 +5,18 @@ import (
"github.com/docker/libnetwork"
)
// Backend is all the methods that need to be implemented
// to provide network specific functionality.
// Backend is all the methods that need to be implemented to provide
// network specific functionality
type Backend interface {
FindNetwork(idName string) (libnetwork.Network, error)
GetNetworkByName(idName string) (libnetwork.Network, error)
GetNetwork(idName string, by int) (libnetwork.Network, error)
GetNetworksByID(partialID string) []libnetwork.Network
GetAllNetworks() []libnetwork.Network
CreateNetwork(name, driver string, ipam network.IPAM, options map[string]string, labels map[string]string, internal bool, enableIPv6 bool) (libnetwork.Network, error)
CreateNetwork(name, driver string, ipam network.IPAM,
options map[string]string, internal bool) (libnetwork.Network, error)
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error
DisconnectContainerFromNetwork(containerName string,
network libnetwork.Network, force bool) error
NetworkControllerEnabled() bool
DeleteNetwork(name string) error
}

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