Compare commits

..

89 Commits

Author SHA1 Message Date
Jessica Frazelle 94159c9559 Bump version to v1.7.0
Signed-off-by: Jessica Frazelle <princess@docker.com>
2015-06-12 11:56:43 -07:00
Brian Goff 73e41874b6 Fixes content-type/length for stats stream=false
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 855a056af7)
2015-06-12 11:56:31 -07:00
Darren Shepherd 64552d0b49 Set omitempty for IP and PublicPort to conform w/ API 1.18
Signed-off-by: Darren Shepherd <darren@rancher.com>
(cherry picked from commit 09de92b891)
2015-06-12 10:46:07 -07:00
Chun Chen 84b21b55b9 Fix send on closed channel bug
Signed-off-by: Chun Chen <chenchun.feed@gmail.com>
(cherry picked from commit a408790de8)
2015-06-12 10:29:58 -07:00
Madhu Venugopal 7ffbd7eaee Vendoring in libnetwork to fix #13873.
Libnetwork sha# e578e95aa101441481411ff1d620f343895f24fe

Signed-off-by: Madhu Venugopal <madhu@docker.com>
(cherry picked from commit f3d1826350)
2015-06-12 10:29:58 -07:00
Brian (bex) Exelbierd 469534c855 Update man page Dockerfile to use go-md2man v1.0.1 and go-lang 1.4
The main Dockerfile to was updated - this update brings the
sub-directory specific file inline with it.

Fixes #12866

Signed-off-by: Brian Exelbierd <bex@pobox.com>
(cherry picked from commit 5d51118c7c)
2015-06-11 14:12:55 -07:00
Eric-Olivier Lamey 85d6e7c4ec Display empty string instead of <nil> when IP opt is nil.
Fixes #13878.

Signed-off-by: Eric-Olivier Lamey <eo@lamey.me>
(cherry picked from commit 9ad89281ae)
2015-06-11 12:53:36 -07:00
Doug Davis a1f16a3738 Remove duplicate call to net.ParseIP
and a little cleanup

Signed-off-by: Doug Davis <dug@us.ibm.com>
(cherry picked from commit b180de55ca)
2015-06-11 12:53:36 -07:00
David Calavera 2ef2967570 Cleanup driver and graph db after stopping containers.
Signed-off-by: David Calavera <david.calavera@gmail.com>
(cherry picked from commit 0964a664e8)
2015-06-11 12:49:52 -07:00
Jörg Thalheim ceda1e75a4 zfs: correctly apply selinux context
fixes #13858

Signed-off-by: Jörg Thalheim <joerg@higgsboson.tk>
(cherry picked from commit 19c31a703f)
2015-06-11 12:48:45 -07:00
Jana Radhakrishnan 2519689e99 Vendoring libnetwork to fix stale arp cache issue
Vendoring in libnetwork 90638ec9cf7fa7b7f5d0e96b0854f136d66bff92

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
(cherry picked from commit 386ab25137)
2015-06-11 12:48:45 -07:00
Eric-Olivier Lamey 009ba67dd0 Fix docs URL not using https.
Fixes #13838.

Signed-off-by: Eric-Olivier Lamey <eo@lamey.me>
(cherry picked from commit 212dfb45de)
2015-06-11 12:48:45 -07:00
Jessica Frazelle 4743f3b3aa update gitignore for new manpages
Signed-off-by: Jessica Frazelle <princess@docker.com>
(cherry picked from commit f88e620359)
2015-06-11 12:48:45 -07:00
Mary Anthony 759cdd8ed6 Moving man pages out of docs
Adding in other areas per comments
Updating with comments; equalizing generating man page info
Updating with duglin's comments
Doug is right here again;fixing.

Signed-off-by: Mary Anthony <mary@docker.com>
(cherry picked from commit eacae64bd8)
2015-06-10 15:32:19 -07:00
Michael Crosby ff770d33cd Revert shared container rootfs
This is breaking various setups where the host's rootfs is mount shared
correctly and breaks live migration with bind mounts.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
(cherry picked from commit c9d71317be)
2015-06-10 14:16:11 -07:00
Brian Goff 1d3f7cc012 Default events since to current time
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 74c12aa429)
2015-06-10 10:38:33 -07:00
David Calavera 5291de79ae Allow to downgrade local volumes from > 1.7 to 1.6.
Signed-off-by: David Calavera <david.calavera@gmail.com>
(cherry picked from commit bd9814f0db)
2015-06-10 10:19:12 -07:00
Zefan Li 821f9450fc Cleanup Daemon.verifyVolumesInfo() a bit
vols.VolumesRW has been initialized so it can't be nil. Furthermore
it's ok to read a nil map.

Signed-off-by: Zefan Li <lizefan@huawei.com>
(cherry picked from commit 8b4c0decfc)
2015-06-10 10:19:11 -07:00
John Howard 6a04940f86 Windows: Fix PR13278 compile break
Signed-off-by: John Howard <jhoward@microsoft.com>
(cherry picked from commit 71eadd4176)
2015-06-10 10:19:11 -07:00
Alexander Morozov cf13497ca8 Update libcontainer to v2.1.1
It includes fix for mounting / as volume on SELinux.
docker/libcontainer#619

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit 38acd31e8a)
2015-06-09 17:47:07 -07:00
Jana Radhakrishnan 2b15a888cd libnetwork: Add garbage collection trigger
When the daemon is going down trigger immediate
garbage collection of libnetwork resources deleted
like namespace path since there will be no way to
remove them when the daemon restarts.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
(cherry picked from commit c68e7f96f9)
2015-06-09 17:28:08 -07:00
Tibor Vass 455ad3afe2 Do not set auth headers if 302
This patch ensures no auth headers are set for v1 registries if there
was a 302 redirect.

This also ensures v2 does not use authTransport.

Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 123a0582b2)
2015-06-09 15:37:55 -07:00
Alessandro Boch b5086a7494 Add integ test for unpublished ports in ps o/p
- This is a test to assert the fix #13734

Signed-off-by: Alessandro Boch <aboch@docker.com>
(cherry picked from commit 7b9ae696d8)
2015-06-09 11:47:25 -07:00
Jessica Frazelle 80157b35ac skip test on lxc
Signed-off-by: Jessica Frazelle <princess@docker.com>
(cherry picked from commit 1392f99a97)
2015-06-09 11:47:25 -07:00
Zefan Li 4ebcd0d544 test: Skip TestDevicePermissions on lxc
Closes: #13641

Signed-off-by: Zefan Li <lizefan@huawei.com>
(cherry picked from commit e55649192e)
2015-06-09 11:47:25 -07:00
Flavio Castelli 3e4284bd7c Added openSUSE and SUSE Linux Enterprise support to install.sh
Handle docker installation on openSUSE and SUSE Linux Enterprise
via https://get.docker.io/

Signed-off-by: Flavio Castelli <fcastelli@suse.com>
(cherry picked from commit d0c4c7c83f)
2015-06-09 10:14:15 -07:00
Eric-Olivier Lamey eb4798a10e Tiny improvements to systemd docs.
Show how to use `systemctl show` and recommend against modifying
system unit files in `/usr` and `/lib`.

Fixes #13796.

Signed-off-by: Eric-Olivier Lamey <eo@lamey.me>
(cherry picked from commit 68bfd9e3ae)
2015-06-09 10:14:15 -07:00
Doug Davis 6c90a239ed Fix COPY/ADD quoted/json form
Minor tweak to the quoted/json form and made man page look like the Dockerfile
docs.  W/o the `,` people may think there should be a space delimited list.

Signed-off-by: Doug Davis <dug@us.ibm.com>
(cherry picked from commit f4a3e8bef0)
2015-06-09 10:14:15 -07:00
Eric-Olivier Lamey 8e81f3711f Fix a typo and a minor formatting issue in the docs.
Signed-off-by: Eric-Olivier Lamey <eo@lamey.me>
(cherry picked from commit 173d0918a8)
2015-06-09 10:14:15 -07:00
Doug Davis d10ed90080 Minor doc edit to add clarity around the --volume path format
Also add a comment to the ValidatePath func so devs/reviewers
know exactly what its looking for.

Signed-off-by: Doug Davis <dug@us.ibm.com>
(cherry picked from commit 3fcf53db92)
2015-06-09 10:14:15 -07:00
Ben Severson 7223584e10 quick doc fix for windows versions
Signed-off-by: Ben Severson <BenSeverson@users.noreply.github.com>
(cherry picked from commit a448b7aff2)
2015-06-09 10:14:15 -07:00
Chris Wahl c4ba3a8352 Corrected VMWare to VMware
Corrected spelling of VMware.

Signed-off-by: Chris Wahl <github@wahlnetwork.com>
(cherry picked from commit 55cea4952b)
2015-06-09 10:14:15 -07:00
Antonio Murdaca 33588c23c3 Avoid nil pointer dereference while creating a container with an empty Config
Signed-off-by: Antonio Murdaca <runcom@linux.com>
(cherry picked from commit 4ce817796e)
2015-06-08 11:39:17 -07:00
Eric-Olivier Lamey 6a5cbd0dd4 Fix docs URL in systemd service file.
Fixes #13799.

Signed-off-by: Eric-Olivier Lamey <eo@lamey.me>
(cherry picked from commit dbf5e36fd6)
2015-06-08 11:39:17 -07:00
Eric-Olivier Lamey 495640005a Restore --default-gateway{,-v6} daemon options.
This was added before the libnetwork merge, and then lost. Fixes #13755.

Signed-off-by: Eric-Olivier Lamey <eo@lamey.me>
(cherry picked from commit 5fa60149e2)
2015-06-08 11:36:48 -07:00
John Howard 5c408158a6 Windows: factor out bridge server+config
Signed-off-by: John Howard <jhoward@microsoft.com>
(cherry picked from commit ead2f80073)
2015-06-08 11:36:48 -07:00
Arnaud Porterie ede1c3f0c2 Remove reference to experimental release
Remove reference to experimental releases as it is really a nightly
channel rather than a scheduled release.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
(cherry picked from commit d8680f7beb)
2015-06-05 10:50:50 -07:00
Arnaud Porterie 09295a1453 Rename EXPERIMENTAL.md to README.md
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
(cherry picked from commit 8352f2e264)
2015-06-05 10:50:50 -07:00
Mary Anthony 1f6eca7b99 Moving experimental
Signed-off-by: Mary Anthony <mary@docker.com>
(cherry picked from commit 95dfc4c4a5)
2015-06-05 10:50:50 -07:00
Jessica Frazelle 8f211fde46 fix lxc build
Signed-off-by: Jessica Frazelle <princess@docker.com>
(cherry picked from commit 0adfb908a6)
2015-06-05 10:29:08 -07:00
Sven Dowideit 5c70b1eadd Bring over DHE docs updates for publishing
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
(cherry picked from commit 9ed2cb300b)
2015-06-05 09:04:00 -07:00
Tianon Gravi b3adf94d81 Fix release script to release _both_ .deb files
Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
(cherry picked from commit 4572329d4b)
2015-06-04 16:39:20 -07:00
David Calavera 8e7ea1a8fd Migrate data from old vfs paths to new local volumes path.
Signed-off-by: David Calavera <david.calavera@gmail.com>
(cherry picked from commit 16a5590c5b)
2015-06-04 12:14:21 -07:00
Alessandro Boch c11128520c Fix for #13720
Signed-off-by: Alessandro Boch <aboch@docker.com>
(cherry picked from commit ea180a73bc)
2015-06-04 12:12:50 -07:00
Tianon Gravi 25fc200dcf Swap build-* to use UTC instead of local time
Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
(cherry picked from commit aa54a93f74)
2015-06-04 09:03:54 -07:00
Tianon Gravi d17f27a13f Make "DEST" a make.sh construct instead of ad-hoc
Using "DEST" for our build artifacts inside individual bundlescripts was already well-established convention, but this officializes it by having `make.sh` itself set the variable and create the directory, also handling CYGWIN oddities in a single central place (instead of letting them spread outward from `hack/make/binary` like was definitely on their roadmap, whether they knew it or not; sneaky oddities).

Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
(cherry picked from commit ac3388367b)
2015-06-04 09:03:54 -07:00
Madhu Venugopal f2f2c492e1 Using container NetworkDisabled to fix #13725
container.config.NetworkDisabled is set for both daemon's
DisableNetwork and --networking=false case. Hence using
this flag instead to fix #13725.

There is an existing integration-test to catch this issue,
but it is working for the wrong reasons.

Signed-off-by: Madhu Venugopal <madhu@docker.com>
(cherry picked from commit 83208a531d)
2015-06-04 09:03:54 -07:00
Jessica Frazelle 18af7fdbba fix version struct on old versions
Signed-off-by: Jessica Frazelle <princess@docker.com>
(cherry picked from commit 229b599259)
2015-06-03 17:33:10 -07:00
Antonio Murdaca 339f0a128a SizeRW & SizeRootFs omitted if empty in /container/json call
Signed-off-by: Antonio Murdaca <runcom@linux.com>
(cherry picked from commit 6945ac2d02)
2015-06-03 17:33:10 -07:00
Jessica Frazelle 5a0fa9545a Update urls from .com to .org.
I added 301 redirects from dockerproject.com to dockerproject.org but may as
well make sure everything is updated anyways.

Signed-off-by: Jessica Frazelle <princess@docker.com>
(cherry picked from commit 7943bce894)
2015-06-03 14:23:45 -07:00
Alexander Morozov 930f691919 Support CloseNotifier for events
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit 9e7fc245a7)
2015-06-03 13:47:20 -07:00
Antonio Murdaca bf371ab2a5 Do not omit empty json field in /containers/json api response
Signed-off-by: Antonio Murdaca <runcom@linux.com>
(cherry picked from commit 725f34151c)
2015-06-03 12:43:08 -07:00
Michael Crosby d283999b1c Fix nat integration tests
This removes complexity of current implementation and makes the test
correct and assert the right things.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
(cherry picked from commit 4f42097883)
2015-06-02 18:54:54 -07:00
Arnaud Porterie 2786c4d0e2 Update vendoring
Update libnetwork to 005bc475ee49a36ef2ad9c112d1b5ccdaba277d4
Synchronize changes to distribution (was missing _test.go file)

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
(cherry picked from commit 1664d6cd66)
2015-06-02 17:42:41 -07:00
Antonio Murdaca 2939617c8b Expose old config field for api < 1.19
Signed-off-by: Antonio Murdaca <me@runcom.ninja>
(cherry picked from commit 6deaa58ba5)
2015-06-02 16:02:13 -07:00
David Calavera f5e3c68c93 Update libnetwork to 4ded6fe3641b71863cc5985652930ce40efc3af4
Signed-off-by: David Calavera <david.calavera@gmail.com>
(cherry picked from commit ad244668c3)
2015-06-02 12:06:40 -07:00
David Calavera c96b03797a Bump libnetwork for 1.7 release.
Signed-off-by: David Calavera <david.calavera@gmail.com>
(cherry picked from commit ad41efd9a2)
2015-06-02 12:06:40 -07:00
Stephen J Day 0f06c54f40 Break down loadManifest function into constituent parts
Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit 84413be3c9)
2015-06-02 11:56:42 -07:00
Stephen J Day 32fcacdedb Add tests for loadManifest digest verification
Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit 74528be903)
2015-06-02 11:56:42 -07:00
Stephen J Day 140e36a77e Attempt to retain tagging behavior
Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit 1e653ab645)
2015-06-02 11:56:42 -07:00
Stephen J Day 4945a51f73 Properly verify manifests and layer digests on pull
To ensure manifest integrity when pulling by digest, this changeset ensures
that not only the remote digest provided by the registry is verified but also
that the digest provided on the command line is checked, as well. If this check
fails, the pull is cancelled as with an error. Inspection also should that
while layers were being verified against their digests, the error was being
treated as tech preview image signing verification error. This, in fact, is not
a tech preview and opens up the docker daemon to man in the middle attacks that
can be avoided with the v2 registry protocol.

As a matter of cleanliness, the digest package from the distribution project
has been updated to latest version. There were some recent improvements in the
digest package.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit 06612cc0fe)
2015-06-02 11:56:41 -07:00
Jeffrey van Gogh c881349e5e Upon HTTP 302 redirect do not include "Authorization" header on 'untrusted' registries.
Refactoring in Docker 1.7 changed the behavior to add this header where as Docker <= 1.6 wouldn't emit this Header on a HTTP 302 redirect.

This closes #13649

Signed-off-by: Jeffrey van Gogh <jvg@google.com>
(cherry picked from commit 65c5105fcc)
2015-06-02 11:56:41 -07:00
Victor Vieux ecdf1297a3 no not print empty keys in docker info
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
(cherry picked from commit c790aa36ea)
2015-06-02 11:03:06 -07:00
Antonio Murdaca db3daa7bdd Fix wrong kill signal parsing
Signed-off-by: Antonio Murdaca <antonio.murdaca@gmail.com>
(cherry picked from commit 39eec4c25b)
2015-06-02 09:43:43 -07:00
Richard c0fc839e2b If no endpoint could be established with the given mirror configuration,
fallback to pulling from the hub as per v1 behavior.

Signed-off-by: Richard Scothern <richard.scothern@gmail.com>
(cherry picked from commit 6e4ff1bb13)
2015-06-01 18:11:10 -07:00
Alexander Morozov 2e29eadb5c Fix race condition in registry/session
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit 9d98c28855)
2015-06-01 14:45:22 -07:00
Tonis Tiigi ecda5c0a6d Fix breakouts from git root during build
Signed-off-by: Tõnis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 7f7ebeffe8)
2015-06-01 13:06:12 -07:00
Arnaud Porterie 4872f86d00 Add note about overlay not being production ready
Add a paragraph in cli.md mentioning that overlay is not a production
ready graphdriver.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
(cherry picked from commit 67cb748e26)
2015-06-01 12:26:57 -07:00
Lei Jitang 6ca78fff63 Add docker stats --no-stream show cpu usage
Signed-off-by: Lei Jitang <leijitang@huawei.com>
(cherry picked from commit 96123a1fd5)

Conflicts:
	daemon/stats.go
2015-06-01 10:09:14 -07:00
David R. Jenni e9c51c3edc Fix issue #10184.
Merge user specified devices correctly with default devices.
Otherwise the user specified devices end up without permissions.

Signed-off-by: David R. Jenni <david.r.jenni@gmail.com>
(cherry picked from commit c913c9921b)
2015-06-01 09:32:50 -07:00
Jessica Frazelle b38c720f19 fix experimental version and release script
add api version experimental

Signed-off-by: Jessica Frazelle <princess@docker.com>
(cherry picked from commit b372f9f224)

Conflicts:
	docs/sources/reference/api/docker_remote_api_v1.20.md
2015-06-01 09:31:32 -07:00
Jana Radhakrishnan 3bed793ba1 Do not attempt releasing network when not attached to any network
Sometimes container.cleanup() can be called from multiple paths
for the same container during error conditions from monitor and
regular startup path. So if the container network has been already
released do not try to release it again.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
(cherry picked from commit 6cdf8623d5)
2015-06-01 08:53:49 -07:00
Doug Davis ab7e7a7338 Carry #11858
Continues 11858 by:
- Making sure the exit code is always zero when we ask for help
- Making sure the exit code isn't zero when we print help on error cases
- Making sure both short and long usage go to the same stream (stdout vs stderr)
- Making sure all docker commands support --help
- Test that all cmds send --help to stdout, exit code 0, show full usage, no blank lines at end
- Test that all cmds (that support it) show short usage on bad arg to stderr, no blank line at end
- Test that all cmds complain about a bad option, no blank line at end
- Test that docker (w/o subcmd) does the same stuff mentioned above properly

Signed-off-by: Doug Davis <dug@us.ibm.com>
(cherry picked from commit 8324d7918b)
2015-06-01 08:53:49 -07:00
Lei Jitang 4fefcde5a6 Ensure all the running containers are killed on daemon shutdown
Signed-off-by: Lei Jitang <leijitang@huawei.com>
(cherry picked from commit bdb77078b5)
2015-05-29 16:50:23 -07:00
Arnaud Porterie 63e3b7433f Add note about overlay not being production ready
Add a paragraph in cli.md mentioning that overlay is not a production
ready graphdriver.

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
(cherry picked from commit 67cb748e26)
2015-05-29 16:28:00 -07:00
Jessica Frazelle 736c216d58 fix bug with rmi multiple tag
Signed-off-by: Jessica Frazelle <princess@docker.com>
(cherry picked from commit 185f392691)
2015-05-29 15:12:33 -07:00
Antonio Murdaca 85f0e01833 Fix regression in stats API endpoint where stream query param default is true
Signed-off-by: Antonio Murdaca <me@runcom.ninja>
(cherry picked from commit ec97f41465)
2015-05-29 15:06:01 -07:00
Zhang Wei eb3ed436a4 bug fix: close http response body no longer in use
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
(cherry picked from commit 6c49576a86)
2015-05-29 14:34:25 -07:00
Burke Libbey d77d7a0056 Use bufio.Reader instead of bufio.Scanner for logger.Copier
When using a scanner, log lines over 64K will crash the Copier with
bufio.ErrTooLong. Subsequently, the ioutils.bufReader will grow without
bound as the logs are no longer being flushed to disk.

Signed-off-by: Burke Libbey <burke.libbey@shopify.com>
(cherry picked from commit f779cfc5d8)
2015-05-29 13:39:21 -07:00
Antonio Murdaca a0aad0d4de Add syslog-address log-opt
Signed-off-by: Antonio Murdaca <me@runcom.ninja>
(cherry picked from commit e8c88d2533)
2015-05-29 10:28:28 -07:00
Mary Anthony baf9ea5ce4 Fixes to the 1.19 version
updating with changes to this instant
Signed-off-by: Mary Anthony <mary@docker.com>

(cherry picked from commit 30901609a8)
2015-05-29 10:28:28 -07:00
David Calavera a6fe70c696 Mount bind volumes coming from the old volumes configuration.
Signed-off-by: David Calavera <david.calavera@gmail.com>
(cherry picked from commit 53d9609de4)
2015-05-29 09:52:36 -07:00
Harald Albers eee959a9b9 Update bash completion for 1.7.0
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit b2832dffe5)
2015-05-29 09:52:36 -07:00
Alexander Morozov d000ba05fd Treat systemd listeners as all other
Fix #13549

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit 6f9fa64645)
2015-05-28 14:16:28 -07:00
Antonio Murdaca d8eff999e0 Fix race in httpsRequestModifier.ModifyRequest when writing tlsConfig
Signed-off-by: Antonio Murdaca <me@runcom.ninja>
(cherry picked from commit a27395e6df)
2015-05-28 11:33:34 -07:00
Jason Shepherd fb124bcad0 adding nicer help when missing arguments (#11858)
Signed-off-by: Jason Shepherd <jason@jasonshepherd.net>
(cherry picked from commit 48231d623f)
2015-05-28 11:33:34 -07:00
Lei Jitang 9827107dcf Fix automatically publish ports without --publish-all
Signed-off-by: Lei Jitang <leijitang@huawei.com>
(cherry picked from commit 9a09664b51)
2015-05-28 10:03:29 -07:00
Jessica Frazelle e57d649057 fix release script
Signed-off-by: Jessica Frazelle <princess@docker.com>
(cherry picked from commit 9f619282db)
2015-05-28 10:03:29 -07:00
Tianon Gravi d6ff6e2c6f Add fedora:22 to our rpm targets
Signed-off-by: Andrew "Tianon" Page <admwiggin@gmail.com>
(cherry picked from commit 96903c837f)
2015-05-28 10:03:29 -07:00
217 changed files with 4381 additions and 1735 deletions
+3
View File
@@ -30,5 +30,8 @@ docs/_build
docs/_static
docs/_templates
docs/changed-files
# generated by man/man/md2man-all.sh
man/man1
man/man5
pyenv
vendor/pkg/
+1 -1
View File
@@ -17,7 +17,7 @@
#### Quality
* Networking stack was entirely rewritten as part of the libnetwork effort
* Engine internals refactoring (shout out to the contributors?)
* Engine internals refactoring
* Volumes code was entirely rewritten to support the plugins effort
+ Sending SIGUSR1 to a daemon will dump all goroutines stacks without exiting
+4 -4
View File
@@ -30,7 +30,7 @@ security@docker.com and not by creating a github issue.
A common method for distributing applications and sandboxing their
execution is to use virtual machines, or VMs. Typical VM formats are
VMWare's vmdk, Oracle Virtualbox's vdi, and Amazon EC2's ami. In theory
VMware's vmdk, Oracle Virtualbox's vdi, and Amazon EC2's ami. In theory
these formats should allow every developer to automatically package
their application into a "machine" for easy distribution and deployment.
In practice, that almost never happens, for a few reasons:
@@ -180,7 +180,7 @@ Contributing to Docker
======================
[![GoDoc](https://godoc.org/github.com/docker/docker?status.svg)](https://godoc.org/github.com/docker/docker)
[![Jenkins Build Status](https://jenkins.dockerproject.com/job/Docker%20Master/badge/icon)](https://jenkins.dockerproject.com/job/Docker%20Master/)
[![Jenkins Build Status](https://jenkins.dockerproject.org/job/Docker%20Master/badge/icon)](https://jenkins.dockerproject.org/job/Docker%20Master/)
Want to hack on Docker? Awesome! We have [instructions to help you get
started contributing code or documentation.](https://docs.docker.com/project/who-written-for/).
@@ -192,12 +192,12 @@ Getting the development builds
==============================
Want to run Docker from a master build? You can download
master builds at [master.dockerproject.com](https://master.dockerproject.com).
master builds at [master.dockerproject.org](https://master.dockerproject.org).
They are updated with each commit merged into the master branch.
Don't know how to use that super cool new feature in the master build? Check
out the master docs at
[docs.master.dockerproject.com](http://docs.master.dockerproject.com).
[docs.master.dockerproject.org](http://docs.master.dockerproject.org).
How the project is run
======================
+1 -1
View File
@@ -1 +1 @@
1.7.0-rc1
1.7.0-rc3
+9 -9
View File
@@ -7,7 +7,6 @@ import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"reflect"
"strings"
@@ -97,7 +96,7 @@ func (cli *DockerCli) Cmd(args ...string) error {
if len(args) > 0 {
method, exists := cli.getMethod(args[0])
if !exists {
return fmt.Errorf("docker: '%s' is not a docker command. See 'docker --help'.", args[0])
return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'.", args[0])
}
return method(args[1:]...)
}
@@ -117,18 +116,19 @@ func (cli *DockerCli) Subcmd(name, signature, description string, exitOnError bo
errorHandling = flag.ContinueOnError
}
flags := flag.NewFlagSet(name, errorHandling)
if signature != "" {
signature = " " + signature
}
flags.Usage = func() {
flags.ShortUsage()
flags.PrintDefaults()
}
flags.ShortUsage = func() {
options := ""
if signature != "" {
signature = " " + signature
}
if flags.FlagCountUndeprecated() > 0 {
options = " [OPTIONS]"
}
fmt.Fprintf(cli.out, "\nUsage: docker %s%s%s\n\n%s\n\n", name, options, signature, description)
flags.SetOutput(cli.out)
flags.PrintDefaults()
os.Exit(0)
fmt.Fprintf(flags.Out(), "\nUsage: docker %s%s%s\n\n%s\n", name, options, signature, description)
}
return flags
}
+1
View File
@@ -145,6 +145,7 @@ func (cli *DockerCli) CmdCreate(args ...string) error {
config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
if err != nil {
cmd.ReportError(err.Error(), true)
os.Exit(1)
}
if config.Image == "" {
cmd.Usage()
+12 -17
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/ioutils"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/units"
)
@@ -15,7 +16,7 @@ import (
func (cli *DockerCli) CmdInfo(args ...string) error {
cmd := cli.Subcmd("info", "", "Display system-wide information", true)
cmd.Require(flag.Exact, 0)
cmd.ParseFlags(args, false)
cmd.ParseFlags(args, true)
rdr, _, err := cli.call("GET", "/info", nil, nil)
if err != nil {
@@ -29,20 +30,20 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers)
fmt.Fprintf(cli.out, "Images: %d\n", info.Images)
fmt.Fprintf(cli.out, "Storage Driver: %s\n", info.Driver)
ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver)
if info.DriverStatus != nil {
for _, pair := range info.DriverStatus {
fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1])
}
}
fmt.Fprintf(cli.out, "Execution Driver: %s\n", info.ExecutionDriver)
fmt.Fprintf(cli.out, "Logging Driver: %s\n", info.LoggingDriver)
fmt.Fprintf(cli.out, "Kernel Version: %s\n", info.KernelVersion)
fmt.Fprintf(cli.out, "Operating System: %s\n", info.OperatingSystem)
ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver)
ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver)
ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion)
ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem)
fmt.Fprintf(cli.out, "CPUs: %d\n", info.NCPU)
fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal)))
fmt.Fprintf(cli.out, "Name: %s\n", info.Name)
fmt.Fprintf(cli.out, "ID: %s\n", info.ID)
ioutils.FprintfIfNotEmpty(cli.out, "Name: %s\n", info.Name)
ioutils.FprintfIfNotEmpty(cli.out, "ID: %s\n", info.ID)
if info.Debug {
fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug)
@@ -55,15 +56,9 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, "Docker Root Dir: %s\n", info.DockerRootDir)
}
if info.HttpProxy != "" {
fmt.Fprintf(cli.out, "Http Proxy: %s\n", info.HttpProxy)
}
if info.HttpsProxy != "" {
fmt.Fprintf(cli.out, "Https Proxy: %s\n", info.HttpsProxy)
}
if info.NoProxy != "" {
fmt.Fprintf(cli.out, "No Proxy: %s\n", info.NoProxy)
}
ioutils.FprintfIfNotEmpty(cli.out, "Http Proxy: %s\n", info.HttpProxy)
ioutils.FprintfIfNotEmpty(cli.out, "Https Proxy: %s\n", info.HttpsProxy)
ioutils.FprintfIfNotEmpty(cli.out, "No Proxy: %s\n", info.NoProxy)
if info.IndexServerAddress != "" {
u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username
+1 -1
View File
@@ -16,7 +16,7 @@ func (cli *DockerCli) CmdLogout(args ...string) error {
cmd := cli.Subcmd("logout", "[SERVER]", "Log out from a Docker registry, if no server is\nspecified \""+registry.IndexServerAddress()+"\" is the default.", true)
cmd.Require(flag.Max, 1)
cmd.ParseFlags(args, false)
cmd.ParseFlags(args, true)
serverAddress := registry.IndexServerAddress()
if len(cmd.Args()) > 0 {
serverAddress = cmd.Arg(0)
+1 -1
View File
@@ -12,7 +12,7 @@ import (
func (cli *DockerCli) CmdPause(args ...string) error {
cmd := cli.Subcmd("pause", "CONTAINER [CONTAINER...]", "Pause all processes within a container", true)
cmd.Require(flag.Min, 1)
cmd.ParseFlags(args, false)
cmd.ParseFlags(args, true)
var errNames []string
for _, name := range cmd.Args() {
+1
View File
@@ -57,6 +57,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
// just in case the Parse does not exit
if err != nil {
cmd.ReportError(err.Error(), true)
os.Exit(1)
}
if len(hostConfig.Dns) > 0 {
+4 -8
View File
@@ -46,7 +46,6 @@ func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
var (
previousCPU uint64
previousSystem uint64
start = true
dec = json.NewDecoder(stream)
u = make(chan error, 1)
)
@@ -61,10 +60,9 @@ func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
memPercent = float64(v.MemoryStats.Usage) / float64(v.MemoryStats.Limit) * 100.0
cpuPercent = 0.0
)
if !start {
cpuPercent = calculateCPUPercent(previousCPU, previousSystem, v)
}
start = false
previousCPU = v.PreCpuStats.CpuUsage.TotalUsage
previousSystem = v.PreCpuStats.SystemUsage
cpuPercent = calculateCPUPercent(previousCPU, previousSystem, v)
s.mu.Lock()
s.CPUPercentage = cpuPercent
s.Memory = float64(v.MemoryStats.Usage)
@@ -73,8 +71,6 @@ func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
s.NetworkRx = float64(v.Network.RxBytes)
s.NetworkTx = float64(v.Network.TxBytes)
s.mu.Unlock()
previousCPU = v.CpuStats.CpuUsage.TotalUsage
previousSystem = v.CpuStats.SystemUsage
u <- nil
if !streamStats {
return
@@ -151,7 +147,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
}
// do a quick pause so that any failed connections for containers that do not exist are able to be
// evicted before we display the initial or default values.
time.Sleep(500 * time.Millisecond)
time.Sleep(1500 * time.Millisecond)
var errs []string
for _, c := range cStats {
c.mu.Lock()
+1 -1
View File
@@ -12,7 +12,7 @@ import (
func (cli *DockerCli) CmdUnpause(args ...string) error {
cmd := cli.Subcmd("unpause", "CONTAINER [CONTAINER...]", "Unpause all processes within a container", true)
cmd.Require(flag.Min, 1)
cmd.ParseFlags(args, false)
cmd.ParseFlags(args, true)
var errNames []string
for _, name := range cmd.Args() {
+8 -2
View File
@@ -9,6 +9,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/autogen/dockerversion"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/utils"
)
// CmdVersion shows Docker version information.
@@ -20,7 +21,7 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
cmd := cli.Subcmd("version", "", "Show the Docker version information.", true)
cmd.Require(flag.Exact, 0)
cmd.ParseFlags(args, false)
cmd.ParseFlags(args, true)
if dockerversion.VERSION != "" {
fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION)
@@ -31,6 +32,9 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT)
}
fmt.Fprintf(cli.out, "OS/Arch (client): %s/%s\n", runtime.GOOS, runtime.GOARCH)
if utils.ExperimentalBuild() {
fmt.Fprintf(cli.out, "Experimental (client): true\n")
}
stream, _, err := cli.call("GET", "/version", nil, nil)
if err != nil {
@@ -50,6 +54,8 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
fmt.Fprintf(cli.out, "Go version (server): %s\n", v.GoVersion)
fmt.Fprintf(cli.out, "Git commit (server): %s\n", v.GitCommit)
fmt.Fprintf(cli.out, "OS/Arch (server): %s/%s\n", v.Os, v.Arch)
if v.Experimental {
fmt.Fprintf(cli.out, "Experimental (server): true\n")
}
return nil
}
+9
View File
@@ -11,6 +11,15 @@ func boolValue(r *http.Request, k string) bool {
return !(s == "" || s == "0" || s == "no" || s == "false" || s == "none")
}
// boolValueOrDefault returns the default bool passed if the query param is
// missing, otherwise it's just a proxy to boolValue above
func boolValueOrDefault(r *http.Request, k string, d bool) bool {
if _, ok := r.Form[k]; !ok {
return d
}
return boolValue(r, k)
}
func int64ValueOrZero(r *http.Request, k string) int64 {
val, err := strconv.ParseInt(r.FormValue(k), 10, 64)
if err != nil {
+15
View File
@@ -33,6 +33,21 @@ func TestBoolValue(t *testing.T) {
}
}
func TestBoolValueOrDefault(t *testing.T) {
r, _ := http.NewRequest("GET", "", nil)
if !boolValueOrDefault(r, "queryparam", true) {
t.Fatal("Expected to get true default value, got false")
}
v := url.Values{}
v.Set("param", "")
r, _ = http.NewRequest("GET", "", nil)
r.Form = v
if boolValueOrDefault(r, "param", true) {
t.Fatal("Expected not to get true")
}
}
func TestInt64ValueOrZero(t *testing.T) {
cases := map[string]int64{
"": 0,
+55 -44
View File
@@ -36,7 +36,6 @@ import (
"github.com/docker/docker/pkg/version"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/utils"
"github.com/docker/libnetwork/portallocator"
)
type ServerConfig struct {
@@ -97,15 +96,17 @@ func (s *Server) ServeApi(protoAddrs []string) error {
if err != nil {
return err
}
s.servers = append(s.servers, srv)
s.servers = append(s.servers, srv...)
go func(proto, addr string) {
logrus.Infof("Listening for HTTP on %s (%s)", proto, addr)
if err := srv.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") {
err = nil
}
chErrors <- err
}(protoAddrParts[0], protoAddrParts[1])
for _, s := range srv {
logrus.Infof("Listening for HTTP on %s (%s)", protoAddrParts[0], protoAddrParts[1])
go func(s serverCloser) {
if err := s.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") {
err = nil
}
chErrors <- err
}(s)
}
}
for i := 0; i < len(protoAddrs); i++ {
@@ -252,6 +253,11 @@ func (s *Server) getVersion(version version.Version, w http.ResponseWriter, r *h
Os: runtime.GOOS,
Arch: runtime.GOARCH,
}
if version.GreaterThanOrEqualTo("1.19") {
v.Experimental = utils.ExperimentalBuild()
}
if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
v.KernelVersion = kernelVersion.String()
}
@@ -271,14 +277,20 @@ func (s *Server) postContainersKill(version version.Version, w http.ResponseWrit
name := vars["name"]
// If we have a signal, look at it. Otherwise, do nothing
if sigStr := vars["signal"]; sigStr != "" {
if sigStr := r.Form.Get("signal"); sigStr != "" {
// Check if we passed the signal as a number:
// The largest legal signal is 31, so let's parse on 5 bits
sig, err := strconv.ParseUint(sigStr, 10, 5)
sigN, err := strconv.ParseUint(sigStr, 10, 5)
if err != nil {
// The signal is not a number, treat it as a string (either like
// "KILL" or like "SIGKILL")
sig = uint64(signal.SignalMap[strings.TrimPrefix(sigStr, "SIG")])
syscallSig, ok := signal.SignalMap[strings.TrimPrefix(sigStr, "SIG")]
if !ok {
return fmt.Errorf("Invalid signal: %s", sigStr)
}
sig = uint64(syscallSig)
} else {
sig = sigN
}
if sig == 0 {
@@ -386,6 +398,7 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
}
until = u
}
timer := time.NewTimer(0)
timer.Stop()
if until > 0 {
@@ -444,6 +457,9 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
}
current, l := es.Subscribe()
if since == -1 {
current = nil
}
defer es.Evict(l)
for _, ev := range current {
if ev.Time < since {
@@ -453,6 +469,12 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
return err
}
}
var closeNotify <-chan bool
if closeNotifier, ok := w.(http.CloseNotifier); ok {
closeNotify = closeNotifier.CloseNotify()
}
for {
select {
case ev := <-l:
@@ -465,6 +487,9 @@ func (s *Server) getEvents(version version.Version, w http.ResponseWriter, r *ht
}
case <-timer.C:
return nil
case <-closeNotify:
logrus.Debug("Client disconnected, stop sending events")
return nil
}
}
}
@@ -550,7 +575,16 @@ func (s *Server) getContainersStats(version version.Version, w http.ResponseWrit
return fmt.Errorf("Missing parameter")
}
return s.daemon.ContainerStats(vars["name"], boolValue(r, "stream"), ioutils.NewWriteFlusher(w))
stream := boolValueOrDefault(r, "stream", true)
var out io.Writer
if !stream {
w.Header().Set("Content-Type", "application/json")
out = w
} else {
out = ioutils.NewWriteFlusher(w)
}
return s.daemon.ContainerStats(vars["name"], stream, out)
}
func (s *Server) getContainersLogs(version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
@@ -634,10 +668,6 @@ func (s *Server) postCommit(version version.Version, w http.ResponseWriter, r *h
return err
}
if c == nil {
c = &runconfig.Config{}
}
containerCommitConfig := &daemon.ContainerCommitConfig{
Pause: pause,
Repo: r.Form.Get("repo"),
@@ -1133,6 +1163,14 @@ func (s *Server) getContainersByName(version version.Version, w http.ResponseWri
return fmt.Errorf("Missing parameter")
}
if version.LessThan("1.19") {
containerJSONRaw, err := s.daemon.ContainerInspectRaw(vars["name"])
if err != nil {
return err
}
return writeJSON(w, http.StatusOK, containerJSONRaw)
}
containerJSON, err := s.daemon.ContainerInspect(vars["name"])
if err != nil {
return err
@@ -1546,30 +1584,3 @@ func createRouter(s *Server) *mux.Router {
return r
}
func allocateDaemonPort(addr string) error {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return err
}
intPort, err := strconv.Atoi(port)
if err != nil {
return err
}
var hostIPs []net.IP
if parsedIP := net.ParseIP(host); parsedIP != nil {
hostIPs = append(hostIPs, parsedIP)
} else if hostIPs, err = net.LookupIP(host); err != nil {
return fmt.Errorf("failed to lookup %s address in host specification", host)
}
pa := portallocator.Get()
for _, hostIP := range hostIPs {
if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
}
}
return nil
}
+49 -29
View File
@@ -6,63 +6,56 @@ import (
"fmt"
"net"
"net/http"
"strconv"
"github.com/docker/docker/daemon"
"github.com/docker/docker/pkg/sockets"
"github.com/docker/docker/pkg/systemd"
"github.com/docker/libnetwork/portallocator"
)
// newServer sets up the required serverCloser and does protocol specific checking.
func (s *Server) newServer(proto, addr string) (serverCloser, error) {
// newServer sets up the required serverClosers and does protocol specific checking.
func (s *Server) newServer(proto, addr string) ([]serverCloser, error) {
var (
err error
l net.Listener
ls []net.Listener
)
switch proto {
case "fd":
ls, err := systemd.ListenFD(addr)
ls, err = systemd.ListenFD(addr)
if err != nil {
return nil, err
}
chErrors := make(chan error, len(ls))
// We don't want to start serving on these sockets until the
// daemon is initialized and installed. Otherwise required handlers
// won't be ready.
<-s.start
// Since ListenFD will return one or more sockets we have
// to create a go func to spawn off multiple serves
for i := range ls {
listener := ls[i]
go func() {
httpSrv := http.Server{Handler: s.router}
chErrors <- httpSrv.Serve(listener)
}()
}
for i := 0; i < len(ls); i++ {
if err := <-chErrors; err != nil {
return nil, err
}
}
return nil, nil
case "tcp":
l, err = s.initTcpSocket(addr)
l, err := s.initTcpSocket(addr)
if err != nil {
return nil, err
}
ls = append(ls, l)
case "unix":
if l, err = sockets.NewUnixSocket(addr, s.cfg.SocketGroup, s.start); err != nil {
l, err := sockets.NewUnixSocket(addr, s.cfg.SocketGroup, s.start)
if err != nil {
return nil, err
}
ls = append(ls, l)
default:
return nil, fmt.Errorf("Invalid protocol format: %q", proto)
}
return &HttpServer{
&http.Server{
Addr: addr,
Handler: s.router,
},
l,
}, nil
var res []serverCloser
for _, l := range ls {
res = append(res, &HttpServer{
&http.Server{
Addr: addr,
Handler: s.router,
},
l,
})
}
return res, nil
}
func (s *Server) AcceptConnections(d *daemon.Daemon) {
@@ -76,3 +69,30 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) {
close(s.start)
}
}
func allocateDaemonPort(addr string) error {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return err
}
intPort, err := strconv.Atoi(port)
if err != nil {
return err
}
var hostIPs []net.IP
if parsedIP := net.ParseIP(host); parsedIP != nil {
hostIPs = append(hostIPs, parsedIP)
} else if hostIPs, err = net.LookupIP(host); err != nil {
return fmt.Errorf("failed to lookup %s address in host specification", host)
}
pa := portallocator.Get()
for _, hostIP := range hostIPs {
if _, err := pa.RequestPort(hostIP, "tcp", intPort); err != nil {
return fmt.Errorf("failed to allocate daemon listening port %d (err: %v)", intPort, err)
}
}
return nil
}
+6 -1
View File
@@ -11,7 +11,7 @@ import (
)
// NewServer sets up the required Server and does protocol specific checking.
func (s *Server) newServer(proto, addr string) (Server, error) {
func (s *Server) newServer(proto, addr string) (serverCloser, error) {
var (
err error
l net.Listener
@@ -22,6 +22,7 @@ func (s *Server) newServer(proto, addr string) (Server, error) {
if err != nil {
return nil, err
}
default:
return nil, errors.New("Invalid protocol format. Windows only supports tcp.")
}
@@ -43,3 +44,7 @@ func (s *Server) AcceptConnections(d *daemon.Daemon) {
close(s.start)
}
}
func allocateDaemonPort(addr string) error {
return nil
}
+1
View File
@@ -81,6 +81,7 @@ type Network struct {
type Stats struct {
Read time.Time `json:"read"`
Network Network `json:"network,omitempty"`
PreCpuStats CpuStats `json:"precpu_stats,omitempty"`
CpuStats CpuStats `json:"cpu_stats,omitempty"`
MemoryStats MemoryStats `json:"memory_stats,omitempty"`
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
+35 -14
View File
@@ -94,23 +94,23 @@ type ImageInspect struct {
// GET "/containers/json"
type Port struct {
IP string
IP string `json:",omitempty"`
PrivatePort int
PublicPort int
PublicPort int `json:",omitempty"`
Type string
}
type Container struct {
ID string `json:"Id"`
Names []string `json:",omitempty"`
Image string `json:",omitempty"`
Command string `json:",omitempty"`
Created int `json:",omitempty"`
Ports []Port `json:",omitempty"`
SizeRw int `json:",omitempty"`
SizeRootFs int `json:",omitempty"`
Labels map[string]string `json:",omitempty"`
Status string `json:",omitempty"`
ID string `json:"Id"`
Names []string
Image string
Command string
Created int
Ports []Port
SizeRw int `json:",omitempty"`
SizeRootFs int `json:",omitempty"`
Labels map[string]string
Status string
}
// POST "/containers/"+containerID+"/copy"
@@ -132,6 +132,7 @@ type Version struct {
Os string
Arch string
KernelVersion string `json:",omitempty"`
Experimental bool `json:",omitempty"`
}
// GET "/info"
@@ -194,12 +195,11 @@ type ContainerState struct {
}
// GET "/containers/{name:.*}/json"
type ContainerJSON struct {
type ContainerJSONBase struct {
Id string
Created time.Time
Path string
Args []string
Config *runconfig.Config
State *ContainerState
Image string
NetworkSettings *network.Settings
@@ -219,3 +219,24 @@ type ContainerJSON struct {
ExecIDs []string
HostConfig *runconfig.HostConfig
}
type ContainerJSON struct {
*ContainerJSONBase
Config *runconfig.Config
}
// backcompatibility struct along with ContainerConfig
type ContainerJSONRaw struct {
*ContainerJSONBase
Config *ContainerConfig
}
type ContainerConfig struct {
*runconfig.Config
// backward compatibility, they now live in HostConfig
Memory int64
MemorySwap int64
CpuShares int64
Cpuset string
}
+4
View File
@@ -221,6 +221,10 @@ func Commit(d *daemon.Daemon, name string, c *daemon.ContainerCommitConfig) (str
return "", err
}
if c.Config == nil {
c.Config = &runconfig.Config{}
}
newConfig, err := BuildFromConfig(d, c.Config, c.Changes)
if err != nil {
return "", err
+15
View File
@@ -0,0 +1,15 @@
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/rpm/generate.sh"!
#
FROM fedora:22
RUN yum install -y @development-tools fedora-packager
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel sqlite-devel tar
ENV GO_VERSION 1.4.2
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
ENV AUTO_GOPATH 1
ENV DOCKER_BUILDTAGS selinux
+24 -7
View File
@@ -212,11 +212,12 @@ _docker_docker() {
--selinux-enabled
--tls
--tlsverify
--userland-proxy=false
--version -v
"
case "$prev" in
--graph|-g)
--exec-root|--graph|-g)
_filedir -d
return
;;
@@ -267,22 +268,25 @@ _docker_attach() {
_docker_build() {
case "$prev" in
--tag|-t)
__docker_image_repos_and_tags
--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--memory|-m|--memory-swap)
return
;;
--file|-f)
_filedir
return
;;
--tag|-t)
__docker_image_repos_and_tags
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--cpu-shares -c --cpuset-cpus --cpu-quota --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--cgroup-parent --cpuset-cpus --cpuset-mems --cpu-shares -c --cpu-period --cpu-quota --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t" -- "$cur" ) )
;;
*)
local counter="$(__docker_pos_first_nonflag '--tag|-t')"
local counter="$(__docker_pos_first_nonflag '--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--file|-f|--memory|-m|--memory-swap|--tag|-t')"
if [ $cword -eq $counter ]; then
_filedir -d
fi
@@ -405,6 +409,12 @@ _docker_events() {
}
_docker_exec() {
case "$prev" in
--user|-u)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--detach -d --help --interactive -i -t --tty -u --user" -- "$cur" ) )
@@ -586,7 +596,7 @@ _docker_logout() {
_docker_logs() {
case "$prev" in
--tail)
--since|--tail)
return
;;
esac
@@ -771,15 +781,16 @@ _docker_rmi() {
_docker_run() {
local options_with_args="
--add-host
--blkio-weight
--attach -a
--cap-add
--cap-drop
--cgroup-parent
--cidfile
--cpuset
--cpu-shares -c
--cpu-period
--cpu-quota
--cpu-shares -c
--device
--dns
--dns-search
@@ -805,6 +816,7 @@ _docker_run() {
--security-opt
--user -u
--ulimit
--uts
--volumes-from
--volume -v
--workdir -w
@@ -1156,6 +1168,8 @@ _docker() {
--api-cors-header
--bip
--bridge -b
--default-gateway
--default-gateway-v6
--default-ulimit
--dns
--dns-search
@@ -1203,6 +1217,9 @@ _docker() {
;;
-*)
;;
=)
(( counter++ ))
;;
*)
command="${words[$counter]}"
cpos=$counter
+1 -1
View File
@@ -1,6 +1,6 @@
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket
+1 -1
View File
@@ -80,7 +80,7 @@ sudo mkdir -m 755 dev
# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target"
# locales
sudo rm -rf usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
# docs
# docs and man pages
sudo rm -rf usr/share/{man,doc,info,gnome/help}
# cracklib
sudo rm -rf usr/share/cracklib
+1 -1
View File
@@ -10,7 +10,7 @@ shift
# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target"
# locales
rm -rf usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
# docs
# docs and man pages
rm -rf usr/share/{man,doc,info,gnome/help}
# cracklib
rm -rf usr/share/cracklib
+5 -38
View File
@@ -1,8 +1,6 @@
package daemon
import (
"net"
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/runconfig"
@@ -16,9 +14,7 @@ const (
// CommonConfig defines the configuration of a docker daemon which are
// common across platforms.
type CommonConfig struct {
AutoRestart bool
// Bridge holds bridge network specific configuration.
Bridge bridgeConfig
AutoRestart bool
Context map[string][]string
CorsHeaders string
DisableNetwork bool
@@ -26,8 +22,10 @@ type CommonConfig struct {
DnsSearch []string
EnableCors bool
ExecDriver string
ExecOptions []string
ExecRoot string
GraphDriver string
GraphOptions []string
Labels []string
LogConfig runconfig.LogConfig
Mtu int
@@ -36,57 +34,26 @@ type CommonConfig struct {
TrustKeyPath string
}
// bridgeConfig stores all the bridge driver specific
// configuration.
type bridgeConfig struct {
EnableIPv6 bool
EnableIPTables bool
EnableIPForward bool
EnableIPMasq bool
EnableUserlandProxy bool
DefaultIP net.IP
Iface string
IP string
FixedCIDR string
FixedCIDRv6 string
DefaultGatewayIPv4 string
DefaultGatewayIPv6 string
InterContainerCommunication bool
}
// InstallCommonFlags adds command-line options to the top-level flag parser for
// the current process.
// Subsequent calls to `flag.Parse` will populate config with values parsed
// from the command-line.
func (config *Config) InstallCommonFlags() {
opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
opts.ListVar(&config.ExecOptions, []string{"-exec-opt"}, "Set exec driver options")
flag.StringVar(&config.Pidfile, []string{"p", "-pidfile"}, defaultPidFile, "Path to use for daemon PID file")
flag.StringVar(&config.Root, []string{"g", "-graph"}, defaultGraph, "Root of the Docker runtime")
flag.StringVar(&config.ExecRoot, []string{"-exec-root"}, "/var/run/docker", "Root of the Docker execdriver")
flag.BoolVar(&config.AutoRestart, []string{"#r", "#-restart"}, true, "--restart on the daemon has been deprecated in favor of --restart policies on docker run")
flag.BoolVar(&config.Bridge.EnableIPTables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
flag.BoolVar(&config.Bridge.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
flag.BoolVar(&config.Bridge.EnableIPMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
flag.StringVar(&config.Bridge.DefaultGatewayIPv4, []string{"-default-gateway"}, "", "Container default gateway IPv4 address")
flag.StringVar(&config.Bridge.DefaultGatewayIPv6, []string{"-default-gateway-v6"}, "", "Container default gateway IPv6 address")
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, defaultExec, "Exec driver to use")
flag.IntVar(&config.Mtu, []string{"#mtu", "-mtu"}, 0, "Set the containers network MTU")
flag.BoolVar(&config.EnableCors, []string{"#api-enable-cors", "#-api-enable-cors"}, false, "Enable CORS headers in the remote API, this is deprecated by --api-cors-header")
flag.StringVar(&config.CorsHeaders, []string{"-api-cors-header"}, "", "Set CORS headers in the remote API")
opts.IPVar(&config.Bridge.DefaultIP, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
// FIXME: why the inconsistency between "hosts" and "sockets"?
opts.IPListVar(&config.Dns, []string{"#dns", "-dns"}, "DNS server to use")
opts.DnsSearchListVar(&config.DnsSearch, []string{"-dns-search"}, "DNS search domains to use")
opts.LabelListVar(&config.Labels, []string{"-label"}, "Set key=value labels to the daemon")
flag.StringVar(&config.LogConfig.Type, []string{"-log-driver"}, "json-file", "Default driver for container logs")
opts.LogOptsVar(config.LogConfig.Config, []string{"-log-opt"}, "Set log driver options")
flag.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, "Use userland proxy for loopback traffic")
}
+36 -4
View File
@@ -1,6 +1,8 @@
package daemon
import (
"net"
"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/ulimit"
@@ -19,13 +21,32 @@ type Config struct {
CommonConfig
// Fields below here are platform specific.
// Bridge holds bridge network specific configuration.
Bridge bridgeConfig
EnableSelinuxSupport bool
ExecOptions []string
GraphOptions []string
SocketGroup string
Ulimits map[string]*ulimit.Ulimit
}
// bridgeConfig stores all the bridge driver specific
// configuration.
type bridgeConfig struct {
EnableIPv6 bool
EnableIPTables bool
EnableIPForward bool
EnableIPMasq bool
EnableUserlandProxy bool
DefaultIP net.IP
Iface string
IP string
FixedCIDR string
FixedCIDRv6 string
DefaultGatewayIPv4 net.IP
DefaultGatewayIPv6 net.IP
InterContainerCommunication bool
}
// InstallFlags adds command-line options to the top-level flag parser for
// the current process.
// Subsequent calls to `flag.Parse` will populate config with values parsed
@@ -35,10 +56,21 @@ func (config *Config) InstallFlags() {
config.InstallCommonFlags()
// Then platform-specific install flags
opts.ListVar(&config.GraphOptions, []string{"-storage-opt"}, "Set storage driver options")
opts.ListVar(&config.ExecOptions, []string{"-exec-opt"}, "Set exec driver options")
flag.BoolVar(&config.EnableSelinuxSupport, []string{"-selinux-enabled"}, false, "Enable selinux support")
flag.StringVar(&config.SocketGroup, []string{"G", "-group"}, "docker", "Group for the unix socket")
config.Ulimits = make(map[string]*ulimit.Ulimit)
opts.UlimitMapVar(config.Ulimits, []string{"-default-ulimit"}, "Set default ulimits for containers")
flag.BoolVar(&config.Bridge.EnableIPTables, []string{"#iptables", "-iptables"}, true, "Enable addition of iptables rules")
flag.BoolVar(&config.Bridge.EnableIPForward, []string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
flag.BoolVar(&config.Bridge.EnableIPMasq, []string{"-ip-masq"}, true, "Enable IP masquerading")
flag.BoolVar(&config.Bridge.EnableIPv6, []string{"-ipv6"}, false, "Enable IPv6 networking")
flag.StringVar(&config.Bridge.IP, []string{"#bip", "-bip"}, "", "Specify network bridge IP")
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
opts.IPVar(&config.Bridge.DefaultGatewayIPv4, []string{"-default-gateway"}, "", "Container default gateway IPv4 address")
opts.IPVar(&config.Bridge.DefaultGatewayIPv6, []string{"-default-gateway-v6"}, "", "Container default gateway IPv6 address")
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
opts.IPVar(&config.Bridge.DefaultIP, []string{"#ip", "-ip"}, "0.0.0.0", "Default IP when binding container ports")
flag.BoolVar(&config.Bridge.EnableUserlandProxy, []string{"-userland-proxy"}, true, "Use userland proxy for loopback traffic")
}
+13 -1
View File
@@ -73,7 +73,10 @@ type CommonContainer struct {
MountLabel, ProcessLabel string
RestartCount int
UpdateDns bool
MountPoints map[string]*mountPoint
MountPoints map[string]*mountPoint
Volumes map[string]string // Deprecated since 1.7, kept for backwards compatibility
VolumesRW map[string]bool // Deprecated since 1.7, kept for backwards compatibility
hostConfig *runconfig.HostConfig
command *execdriver.Command
@@ -1054,6 +1057,15 @@ func (container *Container) networkMounts() []execdriver.Mount {
return mounts
}
func (container *Container) addBindMountPoint(name, source, destination string, rw bool) {
container.MountPoints[destination] = &mountPoint{
Name: name,
Source: source,
Destination: destination,
RW: rw,
}
}
func (container *Container) addLocalMountPoint(name, destination string, rw bool) {
container.MountPoints[destination] = &mountPoint{
Name: name,
+40 -4
View File
@@ -183,7 +183,7 @@ func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.
func populateCommand(c *Container, env []string) error {
var en *execdriver.Network
if !c.daemon.config.DisableNetwork {
if !c.Config.NetworkDisabled {
en = &execdriver.Network{
NamespacePath: c.NetworkSettings.SandboxKey,
}
@@ -227,9 +227,10 @@ func populateCommand(c *Container, env []string) error {
userSpecifiedDevices = append(userSpecifiedDevices, devs...)
}
allowedDevices := append(configs.DefaultAllowedDevices, userSpecifiedDevices...)
autoCreatedDevices := append(configs.DefaultAutoCreatedDevices, userSpecifiedDevices...)
allowedDevices := mergeDevices(configs.DefaultAllowedDevices, userSpecifiedDevices)
autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices)
// TODO: this can be removed after lxc-conf is fully deprecated
lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig)
@@ -309,6 +310,25 @@ func populateCommand(c *Container, env []string) error {
return nil
}
func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
if len(userDevices) == 0 {
return defaultDevices
}
paths := map[string]*configs.Device{}
for _, d := range userDevices {
paths[d.Path] = d
}
var devs []*configs.Device
for _, d := range defaultDevices {
if _, defined := paths[d.Path]; !defined {
devs = append(devs, d)
}
}
return append(devs, userDevices...)
}
// GetSize, return real size, virtual size
func (container *Container) GetSize() (int64, int64) {
var (
@@ -493,13 +513,23 @@ func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork
networkSettings.MacAddress = mac.(net.HardwareAddr).String()
}
networkSettings.Ports = nat.PortMap{}
if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
if exposedPorts, ok := expData.([]types.TransportPort); ok {
for _, tp := range exposedPorts {
natPort := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
networkSettings.Ports[natPort] = nil
}
}
}
mapData, ok := driverInfo[netlabel.PortMap]
if !ok {
return networkSettings, nil
}
if portMapping, ok := mapData.([]types.PortBinding); ok {
networkSettings.Ports = nat.PortMap{}
for _, pp := range portMapping {
natPort := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
natBndg := nat.PortBinding{HostIp: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
@@ -913,6 +943,12 @@ func (container *Container) ReleaseNetwork() {
return
}
// If the container is not attached to any network do not try
// to release network and generate spurious error messages.
if container.NetworkSettings.NetworkID == "" {
return
}
n, err := container.daemon.netController.NetworkByID(container.NetworkSettings.NetworkID)
if err != nil {
logrus.Errorf("error locating network id %s: %v", container.NetworkSettings.NetworkID, err)
+4
View File
@@ -15,6 +15,10 @@ import (
)
func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) {
if config == nil {
return "", nil, fmt.Errorf("Config cannot be empty in order to create a container")
}
warnings, err := daemon.verifyHostConfig(hostConfig)
if err != nil {
return "", warnings, err
+56 -39
View File
@@ -50,8 +50,6 @@ import (
"github.com/docker/docker/volume/local"
)
const defaultVolumesPathName = "volumes"
var (
validContainerNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`)
@@ -158,12 +156,7 @@ func (daemon *Daemon) containerRoot(id string) string {
// This is typically done at startup.
func (daemon *Daemon) load(id string) (*Container, error) {
container := &Container{
CommonContainer: CommonContainer{
State: NewState(),
root: daemon.containerRoot(id),
MountPoints: make(map[string]*mountPoint),
execCommands: newExecStore(),
},
CommonContainer: daemon.newBaseContainer(id),
}
if err := container.FromDisk(); err != nil {
@@ -213,7 +206,7 @@ func (daemon *Daemon) register(container *Container, updateSuffixarray bool) err
// we'll waste time if we update it for every container
daemon.idIndex.Add(container.ID)
if err := daemon.verifyOldVolumesInfo(container); err != nil {
if err := daemon.verifyVolumesInfo(container); err != nil {
return err
}
@@ -526,25 +519,21 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID
daemon.generateHostname(id, config)
entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)
base := daemon.newBaseContainer(id)
base.Created = time.Now().UTC()
base.Path = entrypoint
base.Args = args //FIXME: de-duplicate from config
base.Config = config
base.hostConfig = &runconfig.HostConfig{}
base.ImageID = imgID
base.NetworkSettings = &network.Settings{}
base.Name = name
base.Driver = daemon.driver.String()
base.ExecDriver = daemon.execDriver.Name()
container := &Container{
CommonContainer: CommonContainer{
ID: id, // FIXME: we should generate the ID here instead of receiving it as an argument
Created: time.Now().UTC(),
Path: entrypoint,
Args: args, //FIXME: de-duplicate from config
Config: config,
hostConfig: &runconfig.HostConfig{},
ImageID: imgID,
NetworkSettings: &network.Settings{},
Name: name,
Driver: daemon.driver.String(),
ExecDriver: daemon.execDriver.Name(),
State: NewState(),
execCommands: newExecStore(),
MountPoints: map[string]*mountPoint{},
},
CommonContainer: base,
}
container.root = daemon.containerRoot(container.ID)
return container, err
}
@@ -792,7 +781,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
return nil, err
}
volumesDriver, err := local.New(filepath.Join(config.Root, defaultVolumesPathName))
volumesDriver, err := local.New(config.Root)
if err != nil {
return nil, err
}
@@ -963,6 +952,14 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
netOption["FixedCIDRv6"] = fCIDRv6
}
if config.Bridge.DefaultGatewayIPv4 != nil {
netOption["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4
}
if config.Bridge.DefaultGatewayIPv6 != nil {
netOption["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6
}
// --ip processing
if config.Bridge.DefaultIP != nil {
netOption["DefaultBindingIP"] = config.Bridge.DefaultIP
@@ -982,16 +979,6 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
}
func (daemon *Daemon) Shutdown() error {
if daemon.containerGraph != nil {
if err := daemon.containerGraph.Close(); err != nil {
logrus.Errorf("Error during container graph.Close(): %v", err)
}
}
if daemon.driver != nil {
if err := daemon.driver.Cleanup(); err != nil {
logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
}
}
if daemon.containers != nil {
group := sync.WaitGroup{}
logrus.Debug("starting clean shutdown of all containers...")
@@ -1003,8 +990,9 @@ func (daemon *Daemon) Shutdown() error {
go func() {
defer group.Done()
if err := c.KillSig(15); err != nil {
logrus.Debugf("kill 15 error for %s - %s", c.ID, err)
// If container failed to exit in 10 seconds of SIGTERM, then using the force
if err := c.Stop(10); err != nil {
logrus.Errorf("Stop container %s with error: %v", c.ID, err)
}
c.WaitStop(-1 * time.Second)
logrus.Debugf("container stopped %s", c.ID)
@@ -1012,6 +1000,23 @@ func (daemon *Daemon) Shutdown() error {
}
}
group.Wait()
// trigger libnetwork GC only if it's initialized
if daemon.netController != nil {
daemon.netController.GC()
}
}
if daemon.containerGraph != nil {
if err := daemon.containerGraph.Close(); err != nil {
logrus.Errorf("Error during container graph.Close(): %v", err)
}
}
if daemon.driver != nil {
if err := daemon.driver.Cleanup(); err != nil {
logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
}
}
return nil
@@ -1245,3 +1250,15 @@ func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.
container.toDisk()
return nil
}
func (daemon *Daemon) newBaseContainer(id string) CommonContainer {
return CommonContainer{
ID: id,
State: NewState(),
MountPoints: make(map[string]*mountPoint),
Volumes: make(map[string]string),
VolumesRW: make(map[string]bool),
execCommands: newExecStore(),
root: daemon.containerRoot(id),
}
}
+319 -10
View File
@@ -12,6 +12,8 @@ import (
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/truncindex"
"github.com/docker/docker/volume"
"github.com/docker/docker/volume/drivers"
"github.com/docker/docker/volume/local"
)
//
@@ -129,12 +131,25 @@ func TestLoadWithVolume(t *testing.T) {
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
containerPath := filepath.Join(tmp, containerId)
if err = os.MkdirAll(containerPath, 0755); err != nil {
if err := os.MkdirAll(containerPath, 0755); err != nil {
t.Fatal(err)
}
hostVolumeId := stringid.GenerateRandomID()
volumePath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
if err := os.MkdirAll(vfsPath, 0755); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(volumePath, 0755); err != nil {
t.Fatal(err)
}
content := filepath.Join(vfsPath, "helo")
if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
t.Fatal(err)
}
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
@@ -152,7 +167,7 @@ func TestLoadWithVolume(t *testing.T) {
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
cfg := fmt.Sprintf(config, volumePath)
cfg := fmt.Sprintf(config, vfsPath)
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
t.Fatal(err)
}
@@ -165,21 +180,18 @@ func TestLoadWithVolume(t *testing.T) {
t.Fatal(err)
}
if err = os.MkdirAll(volumePath, 0755); err != nil {
daemon, err := initDaemonForVolumesTest(tmp)
if err != nil {
t.Fatal(err)
}
daemon := &Daemon{
repository: tmp,
root: tmp,
}
defer volumedrivers.Unregister(volume.DefaultDriverName)
c, err := daemon.load(containerId)
if err != nil {
t.Fatal(err)
}
err = daemon.verifyOldVolumesInfo(c)
err = daemon.verifyVolumesInfo(c)
if err != nil {
t.Fatal(err)
}
@@ -204,4 +216,301 @@ func TestLoadWithVolume(t *testing.T) {
if m.Driver != volume.DefaultDriverName {
t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
}
newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
b, err := ioutil.ReadFile(newVolumeContent)
if err != nil {
t.Fatal(err)
}
if string(b) != "HELO" {
t.Fatalf("Expected HELO, was %s\n", string(b))
}
}
func TestLoadWithBindMount(t *testing.T) {
tmp, err := ioutil.TempDir("", "docker-daemon-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
containerPath := filepath.Join(tmp, containerId)
if err = os.MkdirAll(containerPath, 0755); err != nil {
t.Fatal(err)
}
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
"UpdateDns":false,"Volumes":{"/vol1": "/vol1"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
t.Fatal(err)
}
hostConfig := `{"Binds":["/vol1:/vol1"],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
t.Fatal(err)
}
daemon, err := initDaemonForVolumesTest(tmp)
if err != nil {
t.Fatal(err)
}
defer volumedrivers.Unregister(volume.DefaultDriverName)
c, err := daemon.load(containerId)
if err != nil {
t.Fatal(err)
}
err = daemon.verifyVolumesInfo(c)
if err != nil {
t.Fatal(err)
}
if len(c.MountPoints) != 1 {
t.Fatalf("Expected 1 volume mounted, was 0\n")
}
m := c.MountPoints["/vol1"]
if m.Name != "" {
t.Fatalf("Expected empty mount name, was %s\n", m.Name)
}
if m.Source != "/vol1" {
t.Fatalf("Expected mount source /vol1, was %s\n", m.Source)
}
if m.Destination != "/vol1" {
t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
}
if !m.RW {
t.Fatalf("Expected mount point to be RW but it was not\n")
}
}
func TestLoadWithVolume17RC(t *testing.T) {
tmp, err := ioutil.TempDir("", "docker-daemon-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
containerPath := filepath.Join(tmp, containerId)
if err := os.MkdirAll(containerPath, 0755); err != nil {
t.Fatal(err)
}
hostVolumeId := "6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101"
volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
if err := os.MkdirAll(volumePath, 0755); err != nil {
t.Fatal(err)
}
content := filepath.Join(volumePath, "helo")
if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
t.Fatal(err)
}
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
"UpdateDns":false,"MountPoints":{"/vol1":{"Name":"6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101","Destination":"/vol1","Driver":"local","RW":true,"Source":"","Relabel":""}},"AppliedVolumesFrom":null}`
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
t.Fatal(err)
}
hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
t.Fatal(err)
}
daemon, err := initDaemonForVolumesTest(tmp)
if err != nil {
t.Fatal(err)
}
defer volumedrivers.Unregister(volume.DefaultDriverName)
c, err := daemon.load(containerId)
if err != nil {
t.Fatal(err)
}
err = daemon.verifyVolumesInfo(c)
if err != nil {
t.Fatal(err)
}
if len(c.MountPoints) != 1 {
t.Fatalf("Expected 1 volume mounted, was 0\n")
}
m := c.MountPoints["/vol1"]
if m.Name != hostVolumeId {
t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeId, m.Name)
}
if m.Destination != "/vol1" {
t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
}
if !m.RW {
t.Fatalf("Expected mount point to be RW but it was not\n")
}
if m.Driver != volume.DefaultDriverName {
t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
}
newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
b, err := ioutil.ReadFile(newVolumeContent)
if err != nil {
t.Fatal(err)
}
if string(b) != "HELO" {
t.Fatalf("Expected HELO, was %s\n", string(b))
}
}
func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) {
tmp, err := ioutil.TempDir("", "docker-daemon-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
containerId := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
containerPath := filepath.Join(tmp, containerId)
if err := os.MkdirAll(containerPath, 0755); err != nil {
t.Fatal(err)
}
hostVolumeId := stringid.GenerateRandomID()
vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeId)
volumePath := filepath.Join(tmp, "volumes", hostVolumeId)
if err := os.MkdirAll(vfsPath, 0755); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(volumePath, 0755); err != nil {
t.Fatal(err)
}
content := filepath.Join(vfsPath, "helo")
if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
t.Fatal(err)
}
config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
"Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
"ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
"Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
"StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
"NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
"NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
"LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","PortMapping":null,"Ports":{}},
"ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
"HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
"HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
"LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
"Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
"UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
cfg := fmt.Sprintf(config, vfsPath)
if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
t.Fatal(err)
}
hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
"Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
"Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
"SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
t.Fatal(err)
}
daemon, err := initDaemonForVolumesTest(tmp)
if err != nil {
t.Fatal(err)
}
defer volumedrivers.Unregister(volume.DefaultDriverName)
c, err := daemon.load(containerId)
if err != nil {
t.Fatal(err)
}
err = daemon.verifyVolumesInfo(c)
if err != nil {
t.Fatal(err)
}
if len(c.MountPoints) != 1 {
t.Fatalf("Expected 1 volume mounted, was 0\n")
}
m := c.MountPoints["/vol1"]
v, err := createVolume(m.Name, m.Driver)
if err != nil {
t.Fatal(err)
}
if err := removeVolume(v); err != nil {
t.Fatal(err)
}
fi, err := os.Stat(vfsPath)
if err == nil || !os.IsNotExist(err) {
t.Fatalf("Expected vfs path to not exist: %v - %v\n", fi, err)
}
}
func initDaemonForVolumesTest(tmp string) (*Daemon, error) {
daemon := &Daemon{
repository: tmp,
root: tmp,
}
volumesDriver, err := local.New(tmp)
if err != nil {
return nil, err
}
volumedrivers.Register(volumesDriver, volumesDriver.Name())
return daemon, nil
}
+1
View File
@@ -24,6 +24,7 @@ func InitContainer(c *Command) *configs.Config {
container.Devices = c.AutoCreatedDevices
container.Rootfs = c.Rootfs
container.Readonlyfs = c.ReadonlyRootfs
container.Privatefs = true
// check to see if we are running in ramdisk to disable pivot root
container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
+1 -1
View File
@@ -124,7 +124,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
dataPath = d.containerDir(c.ID)
)
if c.Network.NamespacePath == "" && c.Network.ContainerID == "" {
if c.Network == nil || (c.Network.NamespacePath == "" && c.Network.ContainerID == "") {
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("empty namespace path for non-container network")
}
+4 -2
View File
@@ -17,6 +17,7 @@ import (
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/libcontainer/label"
zfs "github.com/mistifyio/go-zfs"
)
@@ -281,14 +282,15 @@ func (d *Driver) Remove(id string) error {
func (d *Driver) Get(id, mountLabel string) (string, error) {
mountpoint := d.MountPath(id)
filesystem := d.ZfsPath(id)
log.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, mountLabel)
options := label.FormatMountLabel("", mountLabel)
log.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, options)
// Create the target directories if they don't exist
if err := os.MkdirAll(mountpoint, 0755); err != nil && !os.IsExist(err) {
return "", err
}
err := mount.Mount(filesystem, mountpoint, "zfs", mountLabel)
err := mount.Mount(filesystem, mountpoint, "zfs", options)
if err != nil {
return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
}
+3 -2
View File
@@ -63,7 +63,8 @@ func (daemon *Daemon) imgDeleteHelper(name string, list *[]types.ImageDelete, fi
repos := daemon.Repositories().ByID()[img.ID]
//If delete by id, see if the id belong only to one repository
if repoName == "" {
deleteByID := repoName == ""
if deleteByID {
for _, repoAndTag := range repos {
parsedRepo, parsedTag := parsers.ParseRepositoryTag(repoAndTag)
if repoName == "" || repoName == parsedRepo {
@@ -91,7 +92,7 @@ func (daemon *Daemon) imgDeleteHelper(name string, list *[]types.ImageDelete, fi
return nil
}
if len(repos) <= 1 {
if len(repos) <= 1 || (len(repoAndTags) <= 1 && deleteByID) {
if err := daemon.canDeleteImage(img.ID, force); err != nil {
return err
}
+36 -3
View File
@@ -25,6 +25,40 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
container.Lock()
defer container.Unlock()
base, err := daemon.getInspectData(container)
if err != nil {
return nil, err
}
return &types.ContainerJSON{base, container.Config}, nil
}
func (daemon *Daemon) ContainerInspectRaw(name string) (*types.ContainerJSONRaw, error) {
container, err := daemon.Get(name)
if err != nil {
return nil, err
}
container.Lock()
defer container.Unlock()
base, err := daemon.getInspectData(container)
if err != nil {
return nil, err
}
config := &types.ContainerConfig{
container.Config,
container.hostConfig.Memory,
container.hostConfig.MemorySwap,
container.hostConfig.CpuShares,
container.hostConfig.CpusetCpus,
}
return &types.ContainerJSONRaw{base, config}, nil
}
func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSONBase, error) {
// make a copy to play with
hostConfig := *container.hostConfig
@@ -60,12 +94,11 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
volumesRW[m.Destination] = m.RW
}
contJSON := &types.ContainerJSON{
contJSONBase := &types.ContainerJSONBase{
Id: container.ID,
Created: container.Created,
Path: container.Path,
Args: container.Args,
Config: container.Config,
State: containerState,
Image: container.ImageID,
NetworkSettings: container.NetworkSettings,
@@ -86,7 +119,7 @@ func (daemon *Daemon) ContainerInspect(name string) (*types.ContainerJSON, error
HostConfig: &hostConfig,
}
return contJSON, nil
return contJSONBase, nil
}
func (daemon *Daemon) ContainerExecInspect(id string) (*execConfig, error) {
+21 -7
View File
@@ -2,6 +2,7 @@ package logger
import (
"bufio"
"bytes"
"io"
"sync"
"time"
@@ -40,14 +41,27 @@ func (c *Copier) Run() {
func (c *Copier) copySrc(name string, src io.Reader) {
defer c.copyJobs.Done()
scanner := bufio.NewScanner(src)
for scanner.Scan() {
if err := c.dst.Log(&Message{ContainerID: c.cid, Line: scanner.Bytes(), Source: name, Timestamp: time.Now().UTC()}); err != nil {
logrus.Errorf("Failed to log msg %q for logger %s: %s", scanner.Bytes(), c.dst.Name(), err)
reader := bufio.NewReader(src)
for {
line, err := reader.ReadBytes('\n')
line = bytes.TrimSuffix(line, []byte{'\n'})
// ReadBytes can return full or partial output even when it failed.
// e.g. it can return a full entry and EOF.
if err == nil || len(line) > 0 {
if logErr := c.dst.Log(&Message{ContainerID: c.cid, Line: line, Source: name, Timestamp: time.Now().UTC()}); logErr != nil {
logrus.Errorf("Failed to log msg %q for logger %s: %s", line, c.dst.Name(), logErr)
}
}
}
if err := scanner.Err(); err != nil {
logrus.Errorf("Error scanning log stream: %s", err)
if err != nil {
if err != io.EOF {
logrus.Errorf("Error scanning log stream: %s", err)
}
return
}
}
}
+46 -2
View File
@@ -3,14 +3,17 @@
package syslog
import (
"fmt"
"io"
"log/syslog"
"net"
"net/url"
"os"
"path"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/daemon/logger"
"github.com/docker/docker/pkg/urlutil"
)
const name = "syslog"
@@ -27,7 +30,18 @@ func init() {
func New(ctx logger.Context) (logger.Logger, error) {
tag := ctx.ContainerID[:12]
log, err := syslog.New(syslog.LOG_DAEMON, fmt.Sprintf("%s/%s", path.Base(os.Args[0]), tag))
proto, address, err := parseAddress(ctx.Config["syslog-address"])
if err != nil {
return nil, err
}
log, err := syslog.Dial(
proto,
address,
syslog.LOG_DAEMON,
path.Base(os.Args[0])+"/"+tag,
)
if err != nil {
return nil, err
}
@@ -55,3 +69,33 @@ func (s *Syslog) Name() string {
func (s *Syslog) GetReader() (io.Reader, error) {
return nil, logger.ReadLogsNotSupported
}
func parseAddress(address string) (string, string, error) {
if urlutil.IsTransportURL(address) {
url, err := url.Parse(address)
if err != nil {
return "", "", err
}
// unix socket validation
if url.Scheme == "unix" {
if _, err := os.Stat(url.Path); err != nil {
return "", "", err
}
return url.Scheme, url.Path, nil
}
// here we process tcp|udp
host := url.Host
if _, _, err := net.SplitHostPort(host); err != nil {
if !strings.Contains(err.Error(), "missing port in address") {
return "", "", err
}
host = host + ":514"
}
return url.Scheme, host, nil
}
return "", "", nil
}
+24 -6
View File
@@ -15,21 +15,39 @@ func (daemon *Daemon) ContainerStats(name string, stream bool, out io.Writer) er
if err != nil {
return err
}
enc := json.NewEncoder(out)
for v := range updates {
var preCpuStats types.CpuStats
getStat := func(v interface{}) *types.Stats {
update := v.(*execdriver.ResourceStats)
ss := convertToAPITypes(update.Stats)
ss.PreCpuStats = preCpuStats
ss.MemoryStats.Limit = uint64(update.MemoryLimit)
ss.Read = update.Read
ss.CpuStats.SystemUsage = update.SystemUsage
if err := enc.Encode(ss); err != nil {
preCpuStats = ss.CpuStats
return ss
}
enc := json.NewEncoder(out)
if !stream {
// prime the cpu stats so they aren't 0 in the final output
s := getStat(<-updates)
// now pull stats again with the cpu stats primed
s = getStat(<-updates)
err := enc.Encode(s)
daemon.UnsubscribeToContainerStats(name, updates)
return err
}
for v := range updates {
s := getStat(v)
if err := enc.Encode(s); err != nil {
// TODO: handle the specific broken pipe
daemon.UnsubscribeToContainerStats(name, updates)
return err
}
if !stream {
break
}
}
return nil
}
+91 -37
View File
@@ -1,16 +1,17 @@
package daemon
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
"github.com/docker/docker/volume/local"
"github.com/docker/libcontainer/label"
)
@@ -52,6 +53,13 @@ func (m *mountPoint) Path() string {
return m.Source
}
// BackwardsCompatible decides whether this mount point can be
// used in old versions of Docker or not.
// Only bind mounts and local volumes can be used in old versions of Docker.
func (m *mountPoint) BackwardsCompatible() bool {
return len(m.Source) > 0 || m.Driver == volume.DefaultDriverName
}
func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*mountPoint, error) {
bind := &mountPoint{
RW: true,
@@ -74,7 +82,7 @@ func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*
return nil, fmt.Errorf("Invalid volume specification: %s", spec)
}
name, source, err := parseVolumeSource(arr[0], config)
name, source, err := parseVolumeSource(arr[0])
if err != nil {
return nil, err
}
@@ -231,53 +239,99 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
mountPoints[bind.Destination] = bind
}
// Keep backwards compatible structures
bcVolumes := map[string]string{}
bcVolumesRW := map[string]bool{}
for _, m := range mountPoints {
if m.BackwardsCompatible() {
bcVolumes[m.Destination] = m.Path()
bcVolumesRW[m.Destination] = m.RW
}
}
container.Lock()
container.MountPoints = mountPoints
container.Volumes = bcVolumes
container.VolumesRW = bcVolumesRW
container.Unlock()
return nil
}
// verifyOldVolumesInfo ports volumes configured for the containers pre docker 1.7.
// verifyVolumesInfo ports volumes configured for the containers pre docker 1.7.
// It reads the container configuration and creates valid mount points for the old volumes.
func (daemon *Daemon) verifyOldVolumesInfo(container *Container) error {
jsonPath, err := container.jsonPath()
if err != nil {
return err
}
f, err := os.Open(jsonPath)
if err != nil {
if os.IsNotExist(err) {
return nil
func (daemon *Daemon) verifyVolumesInfo(container *Container) error {
// Inspect old structures only when we're upgrading from old versions
// to versions >= 1.7 and the MountPoints has not been populated with volumes data.
if len(container.MountPoints) == 0 && len(container.Volumes) > 0 {
for destination, hostPath := range container.Volumes {
vfsPath := filepath.Join(daemon.root, "vfs", "dir")
rw := container.VolumesRW != nil && container.VolumesRW[destination]
if strings.HasPrefix(hostPath, vfsPath) {
id := filepath.Base(hostPath)
if err := migrateVolume(id, hostPath); err != nil {
return err
}
container.addLocalMountPoint(id, destination, rw)
} else { // Bind mount
id, source, err := parseVolumeSource(hostPath)
// We should not find an error here coming
// from the old configuration, but who knows.
if err != nil {
return err
}
container.addBindMountPoint(id, source, destination, rw)
}
}
return err
}
type oldContVolCfg struct {
Volumes map[string]string
VolumesRW map[string]bool
}
vols := oldContVolCfg{
Volumes: make(map[string]string),
VolumesRW: make(map[string]bool),
}
if err := json.NewDecoder(f).Decode(&vols); err != nil {
return err
}
for destination, hostPath := range vols.Volumes {
vfsPath := filepath.Join(daemon.root, "vfs", "dir")
if strings.HasPrefix(hostPath, vfsPath) {
id := filepath.Base(hostPath)
rw := vols.VolumesRW != nil && vols.VolumesRW[destination]
container.addLocalMountPoint(id, destination, rw)
} else if len(container.MountPoints) > 0 {
// Volumes created with a Docker version >= 1.7. We verify integrity in case of data created
// with Docker 1.7 RC versions that put the information in
// DOCKER_ROOT/volumes/VOLUME_ID rather than DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
l, err := getVolumeDriver(volume.DefaultDriverName)
if err != nil {
return err
}
for _, m := range container.MountPoints {
if m.Driver != volume.DefaultDriverName {
continue
}
dataPath := l.(*local.Root).DataPath(m.Name)
volumePath := filepath.Dir(dataPath)
d, err := ioutil.ReadDir(volumePath)
if err != nil {
// If the volume directory doesn't exist yet it will be recreated,
// so we only return the error when there is a different issue.
if !os.IsNotExist(err) {
return err
}
// Do not check when the volume directory does not exist.
continue
}
if validVolumeLayout(d) {
continue
}
if err := os.Mkdir(dataPath, 0755); err != nil {
return err
}
// Move data inside the data directory
for _, f := range d {
oldp := filepath.Join(volumePath, f.Name())
newp := filepath.Join(dataPath, f.Name())
if err := os.Rename(oldp, newp); err != nil {
logrus.Errorf("Unable to move %s to %s\n", oldp, newp)
}
}
}
return container.ToDisk()
}
return container.ToDisk()
return nil
}
func createVolume(name, driverName string) (volume.Volume, error) {
+1 -2
View File
@@ -5,7 +5,6 @@ package daemon
import (
"path/filepath"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
"github.com/docker/docker/volume/drivers"
)
@@ -17,7 +16,7 @@ func getVolumeDriver(name string) (volume.Driver, error) {
return volumedrivers.Lookup(name)
}
func parseVolumeSource(spec string, config *runconfig.Config) (string, string, error) {
func parseVolumeSource(spec string) (string, string, error) {
if !filepath.IsAbs(spec) {
return spec, "", nil
}
+49
View File
@@ -10,6 +10,8 @@ import (
"github.com/docker/docker/daemon/execdriver"
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/volume"
"github.com/docker/docker/volume/local"
)
// copyOwnership copies the permissions and uid:gid of the source file
@@ -68,3 +70,50 @@ func (m mounts) Swap(i, j int) {
func (m mounts) parts(i int) int {
return len(strings.Split(filepath.Clean(m[i].Destination), string(os.PathSeparator)))
}
// migrateVolume links the contents of a volume created pre Docker 1.7
// into the location expected by the local driver.
// It creates a symlink from DOCKER_ROOT/vfs/dir/VOLUME_ID to DOCKER_ROOT/volumes/VOLUME_ID/_container_data.
// It preserves the volume json configuration generated pre Docker 1.7 to be able to
// downgrade from Docker 1.7 to Docker 1.6 without losing volume compatibility.
func migrateVolume(id, vfs string) error {
l, err := getVolumeDriver(volume.DefaultDriverName)
if err != nil {
return err
}
newDataPath := l.(*local.Root).DataPath(id)
fi, err := os.Stat(newDataPath)
if err != nil && !os.IsNotExist(err) {
return err
}
if fi != nil && fi.IsDir() {
return nil
}
return os.Symlink(vfs, newDataPath)
}
// validVolumeLayout checks whether the volume directory layout
// is valid to work with Docker post 1.7 or not.
func validVolumeLayout(files []os.FileInfo) bool {
if len(files) == 1 && files[0].Name() == local.VolumeDataPathName && files[0].IsDir() {
return true
}
if len(files) != 2 {
return false
}
for _, f := range files {
if f.Name() == "config.json" ||
(f.Name() == local.VolumeDataPathName && f.Mode()&os.ModeSymlink == os.ModeSymlink) {
// Old volume configuration, we ignore it
continue
}
return false
}
return true
}
+1 -2
View File
@@ -6,7 +6,6 @@ import (
"fmt"
"path/filepath"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
"github.com/docker/docker/volume/drivers"
)
@@ -15,7 +14,7 @@ func getVolumeDriver(_ string) (volume.Driver, error) {
return volumedrivers.Lookup(volume.DefaultDriverName)
}
func parseVolumeSource(spec string, _ *runconfig.Config) (string, string, error) {
func parseVolumeSource(spec string) (string, string, error) {
if !filepath.IsAbs(spec) {
return "", "", fmt.Errorf("cannot bind mount volume: %s volume paths must be absolute.", spec)
}
+13 -1
View File
@@ -2,7 +2,11 @@
package daemon
import "github.com/docker/docker/daemon/execdriver"
import (
"os"
"github.com/docker/docker/daemon/execdriver"
)
// Not supported on Windows
func copyOwnership(source, destination string) error {
@@ -12,3 +16,11 @@ func copyOwnership(source, destination string) error {
func (container *Container) setupMounts() ([]execdriver.Mount, error) {
return nil, nil
}
func migrateVolume(id, vfs string) error {
return nil
}
func validVolumeLayout(files []os.FileInfo) bool {
return true
}
+6 -1
View File
@@ -16,6 +16,7 @@ import (
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/reexec"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/utils"
)
const (
@@ -161,5 +162,9 @@ func main() {
}
func showVersion() {
fmt.Printf("Docker version %s, build %s\n", dockerversion.VERSION, dockerversion.GITCOMMIT)
if utils.ExperimentalBuild() {
fmt.Printf("Docker version %s, build %s, experimental\n", dockerversion.VERSION, dockerversion.GITCOMMIT)
} else {
fmt.Printf("Docker version %s, build %s\n", dockerversion.VERSION, dockerversion.GITCOMMIT)
}
}
-3
View File
@@ -1,5 +1,2 @@
# generated by man/man/md2man-all.sh
man1/
man5/
# avoid commiting the awsconfig file used for releases
awsconfig
+6 -19
View File
@@ -12,7 +12,7 @@ Docker has two primary branches for documentation:
| Branch | Description | URL (published via commit-hook) |
|----------|--------------------------------|------------------------------------------------------------------------------|
| `docs` | Official release documentation | [https://docs.docker.com](https://docs.docker.com) |
| `master` | Merged but unreleased development work | [http://docs.master.dockerproject.com](http://docs.master.dockerproject.com) |
| `master` | Merged but unreleased development work | [http://docs.master.dockerproject.org](http://docs.master.dockerproject.org) |
Additions and updates to upcoming releases are made in a feature branch off of
the `master` branch. The Docker maintainers also support a `docs` branch that
@@ -22,7 +22,7 @@ After a release, documentation updates are continually merged into `master` as
they occur. This work includes new documentation for forthcoming features, bug
fixes, and other updates. Docker's CI system automatically builds and updates
the `master` documentation after each merge and posts it to
[http://docs.master.dockerproject.com](http://docs.master.dockerproject.com).
[http://docs.master.dockerproject.org](http://docs.master.dockerproject.org).
Periodically, the Docker maintainers update `docs.docker.com` between official
releases of Docker. They do this by cherry-picking commits from `master`,
@@ -280,24 +280,11 @@ aws cloudfront create-invalidation --profile docs.docker.com --distribution-id
aws cloudfront create-invalidation --profile docs.docker.com --distribution-id $DISTRIBUTION_ID --invalidation-batch '{"Paths":{"Quantity":1, "Items":["/v1.1/reference/api/docker_io_oauth_api/"]},"CallerReference":"6Mar2015sventest1"}'
```
### Generate the man pages for Mac OSX
### Generate the man pages
When using Docker on Mac OSX the man pages will be missing by default. You can manually generate them by following these steps:
For information on generating man pages (short for manual page), see [the man
page directory](https://github.com/docker/docker/tree/master/docker) in this
project.
1. Checkout the docker source. You must clone into your `/Users` directory because Boot2Docker can only share this path
with the docker containers.
$ git clone https://github.com/docker/docker.git
2. Build the docker image.
$ cd docker/docs/man
$ docker build -t docker/md2man .
3. Build the man pages.
$ docker run -v /Users/<path-to-git-dir>/docker/docs/man:/docs:rw -w /docs -i docker/md2man /docs/md2man-all.sh
4. Copy the generated man pages to `/usr/share/man`
$ cp -R man* /usr/share/man/
-33
View File
@@ -1,33 +0,0 @@
Docker Documentation
====================
This directory contains the Docker user manual in the Markdown format.
Do *not* edit the man pages in the man1 directory. Instead, amend the
Markdown (*.md) files.
# Generating man pages from the Markdown files
The recommended approach for generating the man pages is via a Docker
container using the supplied `Dockerfile` to create an image with the correct
environment. This uses `go-md2man`, a pure Go Markdown to man page generator.
## Building the md2man image
There is a `Dockerfile` provided in the `docker/docs/man` directory.
Using this `Dockerfile`, create a Docker image tagged `docker/md2man`:
docker build -t docker/md2man .
## Utilizing the image
Once the image is built, run a container using the image with *volumes*:
docker run -v /<path-to-git-dir>/docker/docs/man:/docs:rw \
-w /docs -i docker/md2man /docs/md2man-all.sh
The `md2man` Docker container will process the Markdown files and generate
the man pages inside the `docker/docs/man/man1` directory using
Docker volumes. For more information on Docker volumes see the man page for
`docker run` and also look at the article [Sharing Directories via Volumes]
(https://docs.docker.com/use/working_with_volumes/).
+1 -6
View File
@@ -1,5 +1,5 @@
site_name: Docker Documentation
#site_url: http://docs.docker.com/
#site_url: https://docs.docker.com/
site_url: /
site_description: Documentation for fast and lightweight Docker container based virtualization framework.
site_favicon: img/favicon.png
@@ -27,11 +27,6 @@ pages:
- ['index.md', 'About', 'Docker']
- ['introduction/understanding-docker.md', 'About', 'Understanding Docker']
- ['release-notes.md', 'About', 'Release notes']
# Experimental
- ['experimental/experimental.md', 'About', 'Experimental Features']
- ['experimental/plugin_api.md', '**HIDDEN**']
- ['experimental/plugins_volume.md', '**HIDDEN**']
- ['experimental/plugins.md', '**HIDDEN**']
- ['reference/glossary.md', 'About', 'Glossary']
- ['introduction/index.md', '**HIDDEN**']
+23 -4
View File
@@ -24,14 +24,28 @@ If you want Docker to start at boot, you should also:
## Custom Docker daemon options
There are a number of ways to configure the daemon flags and environment variables
for your Docker daemon.
for your Docker daemon.
If the `docker.service` file is set to use an `EnvironmentFile`
(often pointing to `/etc/sysconfig/docker`) then you can modify the
referenced file.
Or, you may need to edit the `docker.service` file, which can be in
`/usr/lib/systemd/system`, `/etc/systemd/service`, or `/lib/systemd/system`.
Check if the `docker.service` uses an `EnvironmentFile`:
$ sudo systemctl show docker | grep EnvironmentFile
EnvironmentFile=-/etc/sysconfig/docker (ignore_errors=yes)
Alternatively, find out where the service file is located, and look for the
property:
$ sudo systemctl status docker | grep Loaded
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
$ sudo grep EnvironmentFile /usr/lib/systemd/system/docker.service
EnvironmentFile=-/etc/sysconfig/docker
You can customize the Docker daemon options using override files as explained in the
[HTTP Proxy example](#http-proxy) below. The files located in `/usr/lib/systemd/system`
or `/lib/systemd/system` contain the default options and should not be edited.
### Runtime directory and storage driver
@@ -42,7 +56,7 @@ In this example, we'll assume that your `docker.service` file looks something li
[Unit]
Description=Docker Application Container Engine
Documentation=http://docs.docker.com
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket
@@ -90,6 +104,11 @@ Flush changes:
$ sudo systemctl daemon-reload
Verify that the configuration has been loaded:
$ sudo systemctl show docker --property Environment
Environment=HTTP_PROXY=http://proxy.example.com:80/
Restart Docker:
$ sudo systemctl restart docker
@@ -1,3 +1,4 @@
no_version_dropdown: true
page_title: Docker Hub Enterprise: Admin guide
page_description: Documentation describing administration of Docker Hub Enterprise
page_keywords: docker, documentation, about, technology, hub, enterprise
@@ -1,3 +1,4 @@
no_version_dropdown: true
page_title: Docker Hub Enterprise: Configuration options
page_description: Configuration instructions for Docker Hub Enterprise
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry
@@ -136,11 +137,11 @@ Continue by following the steps corresponding to your chosen OS.
```
$ export DOMAIN_NAME=dhe.yourdomain.com
$ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | tee /usr/local/share/ca-certificates/$DOMAIN_NAME.crt
$ update-ca-certificates
$ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /usr/local/share/ca-certificates/$DOMAIN_NAME.crt
$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
$ service docker restart
$ sudo service docker restart
docker stop/waiting
docker start/running, process 29291
```
@@ -149,9 +150,9 @@ Continue by following the steps corresponding to your chosen OS.
```
$ export DOMAIN_NAME=dhe.yourdomain.com
$ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | tee /etc/pki/ca-trust/source/anchors/$DOMAIN_NAME.crt
$ update-ca-trust
$ /bin/systemctl restart docker.service
$ openssl s_client -connect $DOMAIN_NAME:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM | sudo tee /etc/pki/ca-trust/source/anchors/$DOMAIN_NAME.crt
$ sudo update-ca-trust
$ sudo /bin/systemctl restart docker.service
```
#### Boot2Docker 1.6.0
@@ -257,7 +258,7 @@ API.
* *Yaml configuration file*: This file (`/usr/local/etc/dhe/storage.yml`) is
used to configure the image storage services. The editable text of the file is
displayed in the dialog box. The schema of this file is identical to that used
by the [Registry 2.0](http://docs.docker.com/registry/configuration/).
by the [Registry 2.0](https://docs.docker.com/registry/configuration/).
* If you are using the file system driver to provide local image storage, you will need to specify a root directory which will get mounted as a sub-path of
`/var/local/dhe/image-storage`. The default value of this root directory is
`/local`, so the full path to it is `/var/local/dhe/image-storage/local`.
@@ -1,3 +1,4 @@
no_version_dropdown: true
page_title: Docker Hub Enterprise: Overview
page_description: Docker Hub Enterprise
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry
@@ -31,6 +32,12 @@ DHE is perfect for:
DHE is built on [version 2 of the Docker registry](https://github.com/docker/distribution).
> **Note:** This initial release of DHE has limited access. To get access,
> you will need an account on [Docker Hub](https://hub.docker.com/). Once you're
> logged in to the Hub with your account, visit the
> [early access registration page](https://registry.hub.docker.com/earlyaccess/)
> and follow the steps there to get signed up.
## Available Documentation
The following documentation for DHE is available:
+18 -3
View File
@@ -1,3 +1,4 @@
no_version_dropdown: true
page_title: Docker Hub Enterprise: Install
page_description: Installation instructions for Docker Hub Enterprise
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry
@@ -20,6 +21,12 @@ Specifically, installation requires completion of these steps, in order:
3. Install DHE
4. Add your license to your DHE instance
> **Note:** This initial release of DHE has limited access. To get access,
> you will need an account on [Docker Hub](https://hub.docker.com/). Once you're
> logged in to the Hub with your account, visit the
> [early access registration page](https://registry.hub.docker.com/earlyaccess/)
> and follow the steps there to get signed up.
## Licensing
In order to run DHE, you will need to acquire a license, either by purchasing
@@ -108,6 +115,8 @@ following to install commercially supported Docker Engine and its dependencies:
```
$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install -y linux-image-extra-virtual
$ sudo reboot
$ chmod 755 docker-cs-engine-deb.sh
$ sudo ./docker-cs-engine-deb.sh
$ sudo apt-get install docker-engine-cs
@@ -139,19 +148,25 @@ so upgrading the Engine only requires you to run the update commands on your ser
### RHEL 7.0/7.1 upgrade
To upgrade CS Docker Engine, run the following command:
The following commands will stop the running DHE, upgrade CS Docker Engine,
and then start DHE again:
```
$ sudo bash -c "$(sudo docker run dockerhubenterprise/manager stop)"
$ sudo yum update
$ sudo systemctl daemon-reload && sudo systemctl restart docker
$ sudo bash -c "$(sudo docker run dockerhubenterprise/manager start)"
```
### Ubuntu 14.04 LTS upgrade
To upgrade CS Docker Engine, run the following command:
The following commands will stop the running DHE, upgrade CS Docker Engine,
and then start DHE again:
```
$ sudo apt-get update && sudo apt-get dist-upgrade docker-engine-cs
$ sudo bash -c "$(sudo docker run dockerhubenterprise/manager stop)"
$ sudo apt-get update && sudo apt-get dist-upgrade docker-engine-cs
$ sudo bash -c "$(sudo docker run dockerhubenterprise/manager start)"
```
## Installing Docker Hub Enterprise
@@ -1,3 +1,4 @@
no_version_dropdown: true
page_title: Docker Hub Enterprise: Quick-start: Basic Workflow
page_description: Brief tutorial on the basics of Docker Hub Enterprise user workflow
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry, image, repository
@@ -8,7 +9,7 @@ page_keywords: docker, documentation, about, technology, understanding, enterpri
## Overview
This Quick Start Guide will give you a hands-on look at the basics of using
Docker Hub Enterprise (DHE), Dockers on-premise image storage application.
Docker Hub Enterprise (DHE), Docker's on-premise image storage application.
This guide will walk you through using DHE to complete a typical, and critical,
part of building a development pipeline: setting up a Jenkins instance. Once you
complete the task, you should have a good idea of how DHE works and how it might
@@ -17,9 +18,9 @@ be useful to you.
Specifically, this guide demonstrates the process of retrieving the
[official Docker image for Jenkins](https://registry.hub.docker.com/_/jenkins/),
customizing it to suit your needs, and then hosting it on your private instance
of DHE located inside your enterprises firewalled environment. Your developers
of DHE located inside your enterprise's firewalled environment. Your developers
will then be able to retrieve the custom Jenkins image in order to use it to
build CI/CD infrastructure for their projects, no matter the platform theyre
build CI/CD infrastructure for their projects, no matter the platform they're
working from, be it a laptop, a VM, or a cloud provider.
The guide will walk you through the following steps:
@@ -44,7 +45,7 @@ You should be able to complete this guide in about thirty minutes.
> **Note:** This guide assumes you are familiar with basic Docker concepts such
> as images, containers, and registries. If you need to learn more about Docker
> fundamentals, please consult the
> [Docker user guide](http://docs.docker.com/userguide/).
> [Docker user guide](https://docs.docker.com/userguide/).
First, you will retrieve a copy of the official Jenkins image from the Docker Hub. By default, if
Docker can't find an image locally, it will attempt to pull the image from the
@@ -72,12 +73,12 @@ Docker will start the process of pulling the image from the Hub. Once it has com
## Customizing the Jenkins image
Now that you have a local copy of the Jenkins image, youll customize it so that
Now that you have a local copy of the Jenkins image, you'll customize it so that
the containers it builds will integrate with your infrastructure. To do this,
youll create a custom Docker image that adds a Jenkins plugin that provides
fine grained user management. Youll also configure Jenkins to be more secure by
you'll create a custom Docker image that adds a Jenkins plugin that provides
fine grained user management. You'll also configure Jenkins to be more secure by
disabling HTTP access and forcing it to use HTTPS.
Youll do this by using a `Dockerfile` and the `docker build` command.
You'll do this by using a `Dockerfile` and the `docker build` command.
> **Note:** These are obviously just a couple of examples of the many ways you
> can modify and configure Jenkins. Feel free to add or substitute whatever
@@ -105,11 +106,11 @@ line:
(The plugin version used above was the latest version at the time of writing.)
2. You will also need to make copies of the servers private key and certificate. Give the copies the following names `https.key` and `https.pem`.
2. You will also need to make copies of the server's private key and certificate. Give the copies the following names - `https.key` and `https.pem`.
> **Note:** Because creating new keys varies widely by platform and
> implementation, this guide wont cover key generation. We assume you have
> access to existing keys. If you dont have access, or cant generate keys
> implementation, this guide won't cover key generation. We assume you have
> access to existing keys. If you don't have access, or can't generate keys
> yourself, feel free to skip the steps involving them and HTTPS config. The
> guide will still walk you through building a custom Jenkins image and pushing
> and pulling that image using DHE.
@@ -142,7 +143,7 @@ defining with the `Dockerfile`.
The `RUN` instruction will execute the `/usr/local/bin/plugins.sh` script with
the newly copied `plugins` file, which will install the listed plugin.
The next two `COPY` instructions copy the servers private key and certificate
The next two `COPY` instructions copy the server's private key and certificate
into the required directories within the new image.
The `ENV` instruction creates an environment variable called `JENKINS_OPT` in
@@ -156,8 +157,8 @@ tell Jenkins to disable HTTP and operate over HTTPS.
The `Dockerfile`, the `plugins` file, as well as the private key and
certificate, must all be in the same directory because the `docker build`
command uses the directory that contains the `Dockerfile` as its build
context. Only files contained within that build context will be included in
command uses the directory that contains the `Dockerfile` as its "build
context". Only files contained within that "build context" will be included in
the image being built.
### Building your custom image
@@ -169,7 +170,7 @@ custom image using the
docker build -t dhe.yourdomain.com/ci-infrastructure/jnkns-img .
> **Note:** Dont miss the period (`.`) at the end of the command above. This
> **Note:** Don't miss the period (`.`) at the end of the command above. This
> tells the `docker build` command to use the current working directory as the
> "build context".
@@ -214,7 +215,7 @@ image pulled earlier:
> ?scope=repository%3Ahello-world%3Apull%2Cpush&service=dhe.yourdomain.com
> request failed with status: 401 Unauthorized
Now that youve created the custom image, it can be pushed to DHE using the
Now that you've created the custom image, it can be pushed to DHE using the
[`docker push`command](https://docs.docker.com/reference/commandline/cli/#push):
$ docker push dhe.yourdomain.com/ci-infrastructure/jnkns-img
@@ -263,7 +264,7 @@ in the output of the `docker images` command:
## Launching a custom Jenkins container
Now that youve successfully pulled the customized Jenkins image from DHE, you
Now that you've successfully pulled the customized Jenkins image from DHE, you
can create a container from it with the
[`docker run` command](https://docs.docker.com/reference/commandline/cli/#run):
@@ -299,7 +300,7 @@ You can view the newly launched a container, called `jenkins01`, using the
The previous `docker run` command mapped port `1973` on the container to port
`1973` on the Docker host, so the Jenkins Web UI can be accessed at
`https://<docker-host>:1973` (Dont forget the `s` at the end of `https`.)
`https://<docker-host>:1973` (Don't forget the `s` at the end of `https`.)
> **Note:** If you are using a self-signed certificate, you may get a security
> warning from your browser telling you that the certificate is self-signed and
@@ -315,7 +316,7 @@ plugin should be present with the `Uninstall` button available to the right.
![Jenkins plugin manager](../assets/jenkins-plugins.png)
In another browser session, try to access Jenkins via the default HTTP port 8080
`http://<docker-host>:8080`. This should result in a connection timeout,
`http://<docker-host>:8080`. This should result in a "connection timeout",
showing that Jenkins is not available on its default port 8080 over HTTP.
This demonstration shows your Jenkins image has been configured correctly for
@@ -1,3 +1,4 @@
no_version_dropdown: true
page_title: Docker Hub Enterprise: Release notes
page_description: Release notes for Docker Hub Enterprise
page_keywords: docker, documentation, about, technology, understanding, enterprise, hub, registry, release
+1 -1
View File
@@ -27,7 +27,7 @@ Automated Builds are supported for both public and private repositories
on both [GitHub](http://github.com) and [Bitbucket](https://bitbucket.org/).
To use Automated Builds, you must have an [account on Docker Hub](
http://docs.docker.com/userguide/dockerhub/#creating-a-docker-hub-account)
https://docs.docker.com/userguide/dockerhub/#creating-a-docker-hub-account)
and on GitHub and/or Bitbucket. In either case, the account needs
to be properly validated and activated before you can link to it.
@@ -1,5 +1,5 @@
#
# example Dockerfile for http://docs.docker.com/examples/postgresql_service/
# example Dockerfile for https://docs.docker.com/examples/postgresql_service/
#
FROM ubuntu
+1 -1
View File
@@ -21,7 +21,7 @@ Start by creating a new `Dockerfile`:
> suitably secure.
#
# example Dockerfile for http://docs.docker.com/examples/postgresql_service/
# example Dockerfile for https://docs.docker.com/examples/postgresql_service/
#
FROM ubuntu
+1 -1
View File
@@ -4,7 +4,7 @@ page_keywords: Docker, Docker documentation, Windows, requirements, virtualbox,
# Windows
> **Note:**
> Docker has been tested on Windows 7.1 and 8; it may also run on older versions.
> Docker has been tested on Windows 7 and 8.1; it may also run on older versions.
> Your processor needs to support hardware virtualization.
The Docker Engine uses Linux-specific kernel features, so to run it on Windows
+2 -2
View File
@@ -86,8 +86,8 @@ program code and documentation code.
## Merges after pull requests
* After a merge, [a master build](https://master.dockerproject.com/) is
* After a merge, [a master build](https://master.dockerproject.org/) is
available almost immediately.
* If you made a documentation change, you can see it at
[docs.master.dockerproject.com](http://docs.master.dockerproject.com/).
[docs.master.dockerproject.org](http://docs.master.dockerproject.org/).
+2 -2
View File
@@ -75,9 +75,9 @@ Always rebase and squash your commits before making a pull request.
6. Edit and save your commit message.
`git commit -s`
$ git commit -s
Make sure your message includes <a href="./set-up-git" target="_blank>your signature</a>.
Make sure your message includes <a href="../set-up-git" target="_blank">your signature</a>.
7. Force push any changes to your fork on GitHub.
+2 -2
View File
@@ -108,7 +108,7 @@ It can take time to see a merged pull request in Docker's official release.
A master build is available almost immediately though. Docker builds and
updates its development binaries after each merge to `master`.
1. Browse to <a href="https://master.dockerproject.com/" target="_blank">https://master.dockerproject.com/</a>.
1. Browse to <a href="https://master.dockerproject.org/" target="_blank">https://master.dockerproject.org/</a>.
2. Look for the binary appropriate to your system.
@@ -117,7 +117,7 @@ updates its development binaries after each merge to `master`.
You might want to run the binary in a container though. This
will keep your local host environment clean.
4. View any documentation changes at <a href="http://docs.master.dockerproject.com/" target="_blank">docs.master.dockerproject.com</a>.
4. View any documentation changes at <a href="http://docs.master.dockerproject.org/" target="_blank">docs.master.dockerproject.org</a>.
Once you've verified everything merged, feel free to delete your feature branch
from your fork. For information on how to do this,
+1 -1
View File
@@ -102,7 +102,7 @@ Run the entire test suite on your current repository:
* creates a new binary
* cross-compiles all the binaries for the various operating systems
* runs the all the tests in the system
* runs all the tests in the system
It can take several minutes to run all the tests. When they complete
successfully, you see the output concludes with something like this:
+2 -2
View File
@@ -178,9 +178,9 @@ You should pull and rebase frequently as you work.
6. Edit and save your commit message.
`git commit -s`
$ git commit -s
Make sure your message includes <a href="./set-up-git" target="_blank>your signature</a>.
Make sure your message includes <a href="../set-up-git" target="_blank">your signature</a>.
7. Force push any changes to your fork on GitHub.
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -492,7 +492,7 @@ change them using `docker run --env <key>=<value>`.
ADD has two forms:
- `ADD <src>... <dest>`
- `ADD ["<src>"... "<dest>"]` (this form is required for paths containing
- `ADD ["<src>",... "<dest>"]` (this form is required for paths containing
whitespace)
The `ADD` instruction copies new files, directories or remote file URLs from `<src>`
@@ -596,7 +596,7 @@ The copy obeys the following rules:
COPY has two forms:
- `COPY <src>... <dest>`
- `COPY ["<src>"... "<dest>"]` (this form is required for paths containing
- `COPY ["<src>",... "<dest>"]` (this form is required for paths containing
whitespace)
The `COPY` instruction copies new files or directories from `<src>`
+18
View File
@@ -169,6 +169,7 @@ expect an integer, and they can only be specified once.
-l, --log-level="info" Set the logging level
--label=[] Set key=value labels to the daemon
--log-driver="json-file" Default driver for container logs
--log-opt=[] Log driver specific options
--mtu=0 Set the containers network MTU
-p, --pidfile="/var/run/docker.pid" Path to use for daemon PID file
--registry-mirror=[] Preferred Docker registry mirror
@@ -282,6 +283,18 @@ set `zfs.fsname` option as described in [Storage driver options](#storage-driver
The `overlay` is a very fast union filesystem. It is now merged in the main
Linux kernel as of [3.18.0](https://lkml.org/lkml/2014/10/26/137).
Call `docker -d -s overlay` to use it.
> **Note:**
> As promising as `overlay` is, the feature is still quite young and should not
> be used in production. Most notably, using `overlay` can cause excessive
> inode consumption (especially as the number of images grows), as well as
> being incompatible with the use of RPMs.
> **Note:**
> As promising as `overlay` is, the feature is still quite young and should not
> be used in production. Most notably, using `overlay` can cause excessive
> inode consumption (especially as the number of images grows), as well as
> being incompatible with the use of RPMs.
> **Note:**
> It is currently unsupported on `btrfs` or any Copy on Write filesystem
> and should only be used over `ext4` partitions.
@@ -984,6 +997,7 @@ Creates a new container.
--label-file=[] Read in a line delimited file of labels
--link=[] Add link to another container
--log-driver="" Logging driver for container
--log-opt=[] Log driver specific options
--lxc-conf=[] Add custom lxc options
-m, --memory="" Memory limit
--mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33)
@@ -1101,6 +1115,9 @@ and Docker images will report:
untag, delete
If you do not provide the --since option, the command
returns only new and/or live events.
#### Filtering
The filtering flag (`-f` or `--filter`) format is of "key=value". If you would like to use
@@ -1948,6 +1965,7 @@ To remove an image using its digest:
--ipc="" IPC namespace to use
--link=[] Add link to another container
--log-driver="" Logging driver for container
--log-opt=[] Log driver specific options
--lxc-conf=[] Add custom lxc options
-m, --memory="" Memory limit
-l, --label=[] Set metadata on the container (e.g., --label=com.example.key=value)
+20 -5
View File
@@ -873,18 +873,31 @@ this driver.
Default logging driver for Docker. Writes JSON messages to file. `docker logs`
command is available only for this logging driver
The following logging options are supported for this logging driver: [none]
#### Logging driver: syslog
Syslog logging driver for Docker. Writes log messages to syslog. `docker logs`
command is not available for this logging driver
The following logging options are supported for this logging driver:
--log-opt address=[tcp|udp]://host:port
--log-opt address=unix://path
`address` specifies the remote syslog server address where the driver connects to.
If not specified it defaults to the local unix socket of the running system.
If transport is either `tcp` or `udp` and `port` is not specified it defaults to `514`
The following example shows how to have the `syslog` driver connect to a `syslog`
remote server at `192.168.0.42` on port `123`
$ docker run --log-driver=syslog --log-opt address=tcp://192.168.0.42:123
#### Logging driver: journald
Journald logging driver for Docker. Writes log messages to journald; the container id will be stored in the journal's `CONTAINER_ID` field. `docker logs` command is not available for this logging driver. For detailed information on working with this logging driver, see [the journald logging driver](reference/logging/journald) reference documentation.
#### Log Opts :
Logging options for configuring a log driver. The following log options are supported: [none]
The following logging options are supported for this logging driver: [none]
## Overriding Dockerfile image defaults
@@ -1102,8 +1115,10 @@ container's `/etc/hosts` entry will be automatically updated.
## VOLUME (shared filesystems)
-v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro].
If "container-dir" is missing, then docker creates a new volume.
-v=[]: Create a bind mount with: [host-dir:]container-dir[:rw|ro].
If 'host-dir' is missing, then docker creates a new volume.
If neither 'rw' or 'ro' is specified then the volume is mounted
in read-write mode.
--volumes-from="": Mount all volumes from the given container(s)
The volumes commands are complex enough to have their own documentation
+12 -12
View File
@@ -22,13 +22,13 @@ repository](https://github.com/docker/docker/blob/master/CHANGELOG.md).
| Feature | Description |
|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Container and Image Labels | Labels allow you to attach user-defined metadata to containers and images that can be used by your tools. For additional information on using labels, see [Apply custom metadata](http://docs.docker.com/userguide/labels-custom-metadata/#add-labels-to-images-the-label-instruction) in the documentation. |
| Container and Image Labels | Labels allow you to attach user-defined metadata to containers and images that can be used by your tools. For additional information on using labels, see [Apply custom metadata](https://docs.docker.com/userguide/labels-custom-metadata/#add-labels-to-images-the-label-instruction) in the documentation. |
| Windows Client preview | The Windows Client can be used just like the Mac OS X client is today with a remote host. Our testing infrastructure was scaled out to accommodate Windows Client testing on every PR to the Engine. See the Azure blog for [details on using this new client](http://azure.microsoft.com/blog/2015/04/16/docker-client-for-windows-is-now-available). |
| Logging drivers | The new logging driver follows the exec driver and storage driver concepts already available in Engine today. There is a new option `--log-driver` to `docker run` command. See the `run` reference for a [description on how to use this option](http://docs.docker.com/reference/run/#logging-drivers-log-driver). |
| Image digests | When you pull, build, or run images, you specify them in the form `namespace/repository:tag`, or even just `repository`. In this release, you are now able to pull, run, build and refer to images by a new content addressable identifier called a “digest” with the syntax `namespace/repo@digest`. See the the command line reference for [examples of using the digest](http://docs.docker.com/reference/commandline/cli/#listing-image-digests). |
| Custom cgroups | Containers are made from a combination of namespaces, capabilities, and cgroups. Docker already supports custom namespaces and capabilities. Additionally, in this release weve added support for custom cgroups. Using the `--cgroup-parent` flag, you can pass a specific `cgroup` to run a container in. See [the command line reference for more information](http://docs.docker.com/reference/commandline/cli/#create). |
| Ulimits | You can now specify the default `ulimit` settings for all containers when configuring the daemon. For example:`docker -d --default-ulimit nproc=1024:2048` See [Default Ulimits](http://docs.docker.com/reference/commandline/cli/#default-ulimits) in this documentation. |
| Commit and import Dockerfile | You can now make changes to images on the fly without having to re-build the entire image. The feature `commit --change` and `import --change` allows you to apply standard changes to a new image. These are expressed in the Dockerfile syntax and used to modify the image. For details on how to use these, see the [commit](http://docs.docker.com/reference/commandline/cli/#commit) and [import](http://docs.docker.com/reference/commandline/cli/#import). |
| Logging drivers | The new logging driver follows the exec driver and storage driver concepts already available in Engine today. There is a new option `--log-driver` to `docker run` command. See the `run` reference for a [description on how to use this option](https://docs.docker.com/reference/run/#logging-drivers-log-driver). |
| Image digests | When you pull, build, or run images, you specify them in the form `namespace/repository:tag`, or even just `repository`. In this release, you are now able to pull, run, build and refer to images by a new content addressable identifier called a “digest” with the syntax `namespace/repo@digest`. See the the command line reference for [examples of using the digest](https://docs.docker.com/reference/commandline/cli/#listing-image-digests). |
| Custom cgroups | Containers are made from a combination of namespaces, capabilities, and cgroups. Docker already supports custom namespaces and capabilities. Additionally, in this release weve added support for custom cgroups. Using the `--cgroup-parent` flag, you can pass a specific `cgroup` to run a container in. See [the command line reference for more information](https://docs.docker.com/reference/commandline/cli/#create). |
| Ulimits | You can now specify the default `ulimit` settings for all containers when configuring the daemon. For example:`docker -d --default-ulimit nproc=1024:2048` See [Default Ulimits](https://docs.docker.com/reference/commandline/cli/#default-ulimits) in this documentation. |
| Commit and import Dockerfile | You can now make changes to images on the fly without having to re-build the entire image. The feature `commit --change` and `import --change` allows you to apply standard changes to a new image. These are expressed in the Dockerfile syntax and used to modify the image. For details on how to use these, see the [commit](https://docs.docker.com/reference/commandline/cli/#commit) and [import](https://docs.docker.com/reference/commandline/cli/#import). |
### Known issues in Engine
@@ -62,15 +62,15 @@ around a new set of distribution APIs
- **Webhook notifications**: You can now configure the Registry to send Webhooks
when images are pushed. Spin off a CI build, send a notification to IRC
whatever you want! Included in the documentation is a detailed [notification
specification](http://docs.docker.com/registry/notifications/).
specification](https://docs.docker.com/registry/notifications/).
- **Native TLS support**: This release makes it easier to secure a registry with
TLS. This documentation includes [expanded examples of secure
deployments](http://docs.docker.com/registry/deploying/).
deployments](https://docs.docker.com/registry/deploying/).
- **New Distribution APIs**: This release includes an expanded set of new
distribution APIs. You can read the [detailed specification
here](http://docs.docker.com/registry/spec/api/).
here](https://docs.docker.com/registry/spec/api/).
## Docker Compose 1.2
@@ -86,7 +86,7 @@ with the keyword “extends”. With extends, you can refer to a service defined
elsewhere and include its configuration in a locally-defined service, while also
adding or overriding configuration as necessary. The documentation describes
[how to use extends in your
configuration](http://docs.docker.com/compose/extends/#extending-services-in-
configuration](https://docs.docker.com/compose/extends/#extending-services-in-
compose).
- **Relative directory handling may cause breaking change**: Compose now treats
@@ -103,7 +103,7 @@ another directory.
You'll find the [release for download on
GitHub](https://github.com/docker/swarm/releases/tag/v0.2.0) and [the
documentation here](http://docs.docker.com/swarm/). This release includes the
documentation here](https://docs.docker.com/swarm/). This release includes the
following features:
- **Spread strategy**: A new strategy for scheduling containers on your cluster
@@ -119,7 +119,7 @@ make it possible to use Swarm with clustering systems such as Mesos.
You'll find the [release for download on
GitHub](https://github.com/docker/machine/releases) and [the documentation
here](http://docs.docker.com/machine/). For a complete list of machine changes
here](https://docs.docker.com/machine/). For a complete list of machine changes
see [the changelog in the project
repository](https://github.com/docker/machine/blob/master/CHANGES.md#020-2015-03
-22).
+2 -2
View File
@@ -94,7 +94,7 @@ community.
## Features of Docker Hub
Let's take a closer look at some of the features of Docker Hub. You can find more
information [here](http://docs.docker.com/docker-hub/).
information [here](https://docs.docker.com/docker-hub/).
* Private repositories
* Organizations and teams
@@ -163,7 +163,7 @@ a webhook you can specify a target URL and a JSON payload that will be
delivered when the image is pushed.
See the Docker Hub documentation for [more information on
webhooks](http://docs.docker.com/docker-hub/repos/#webhooks)
webhooks](https://docs.docker.com/docker-hub/repos/#webhooks)
## Next steps
+1 -1
View File
@@ -110,7 +110,7 @@ Go to [Docker Swarm user guide](/swarm/).
* [Docker homepage](http://www.docker.com/)
* [Docker Hub](https://hub.docker.com)
* [Docker blog](http://blog.docker.com/)
* [Docker documentation](http://docs.docker.com/)
* [Docker documentation](https://docs.docker.com/)
* [Docker Getting Started Guide](http://www.docker.com/gettingstarted/)
* [Docker code on GitHub](https://github.com/docker/docker)
* [Docker mailing
@@ -38,7 +38,7 @@ notation. Use the following guidelines to name your keys:
reverse DNS notation of a domain controlled by the author. For
example, `com.example.some-label`.
- The `com.docker.*`, `io.docker.*` and `com.dockerproject.*` namespaces are
- The `com.docker.*`, `io.docker.*` and `org.dockerproject.*` namespaces are
reserved for Docker's internal use.
- Keys should only consist of lower-cased alphanumeric characters,
@@ -1,12 +1,8 @@
page_title: Overview of Experimental Features
page_keywords: experimental, Docker, feature
# Docker Experimental Features
# Experimental Features in this Release
This page contains a list of features in the Docker engine which are
experimental as of the current release. Experimental features are **not** ready
for production. They are provided for test and evaluation in your sandbox
environments.
This page contains a list of features in the Docker engine which are
experimental. Experimental features are **not** ready for production. They are
provided for test and evaluation in your sandbox environments.
The information below describes each feature and the Github pull requests and
issues associated with it. If necessary, links are provided to additional
@@ -15,6 +11,8 @@ please feel free to provide any feedback on these features you wish.
## Install Docker experimental
Unlike the regular Docker binary, the experimental channels is built and updated nightly on https://experimental.docker.com. From one day to the next, new features may appear, while existing experimental features may be refined or entirely removed.
1. Verify that you have `wget` installed.
$ which wget
@@ -44,8 +42,13 @@ please feel free to provide any feedback on these features you wish.
This command downloads a test image and runs it in a container.
## Experimental features in this Release
## Current experimental features
* [Support for Docker plugins](plugins.md)
* [Volume plugins](plugins_volume.md)
## How to comment on an experimental feature
Each feature's documentation includes a list of proposal pull requests or PRs associated with the feature. If you want to comment on or suggest a change to a feature, please add it to the existing feature PR.
Issues or problems with a feature? Inquire for help on the `#docker` IRC channel or in on the [Docker Google group](https://groups.google.com/forum/#!forum/docker-user).
@@ -1,7 +1,3 @@
page_title: Plugin API documentation
page_description: Documentation for writing a Docker plugin.
page_keywords: docker, plugins, api, extensions
# Experimental: Docker Plugin API
Docker plugins are out-of-process extensions which add capabilities to the
@@ -1,6 +1,3 @@
page_title: Experimental feature - Plugins
page_keywords: experimental, Docker, plugins
# Experimental: Extend Docker with a plugin
You can extend the capabilities of the Docker Engine by loading third-party
@@ -1,6 +1,3 @@
page_title: Experimental feature - Volume plugins
page_keywords: experimental, Docker, plugins, volume
# Experimental: Docker volume plugins
Docker volume plugins enable Docker deployments to be integrated with external
+121 -49
View File
@@ -8,92 +8,164 @@ import (
"github.com/docker/distribution/digest"
"github.com/docker/docker/registry"
"github.com/docker/docker/trust"
"github.com/docker/docker/utils"
"github.com/docker/libtrust"
)
// loadManifest loads a manifest from a byte array and verifies its content.
// The signature must be verified or an error is returned. If the manifest
// contains no signatures by a trusted key for the name in the manifest, the
// image is not considered verified. The parsed manifest object and a boolean
// for whether the manifest is verified is returned.
func (s *TagStore) loadManifest(manifestBytes []byte, dgst, ref string) (*registry.ManifestData, bool, error) {
sig, err := libtrust.ParsePrettySignature(manifestBytes, "signatures")
// loadManifest loads a manifest from a byte array and verifies its content,
// returning the local digest, the manifest itself, whether or not it was
// verified. If ref is a digest, rather than a tag, this will be treated as
// the local digest. An error will be returned if the signature verification
// fails, local digest verification fails and, if provided, the remote digest
// verification fails. The boolean return will only be false without error on
// the failure of signatures trust check.
func (s *TagStore) loadManifest(manifestBytes []byte, ref string, remoteDigest digest.Digest) (digest.Digest, *registry.ManifestData, bool, error) {
payload, keys, err := unpackSignedManifest(manifestBytes)
if err != nil {
return nil, false, fmt.Errorf("error parsing payload: %s", err)
return "", nil, false, fmt.Errorf("error unpacking manifest: %v", err)
}
keys, err := sig.Verify()
if err != nil {
return nil, false, fmt.Errorf("error verifying payload: %s", err)
}
// TODO(stevvooe): It would be a lot better here to build up a stack of
// verifiers, then push the bytes one time for signatures and digests, but
// the manifests are typically small, so this optimization is not worth
// hacking this code without further refactoring.
payload, err := sig.Payload()
if err != nil {
return nil, false, fmt.Errorf("error retrieving payload: %s", err)
}
var localDigest digest.Digest
var manifestDigest digest.Digest
// Verify the local digest, if present in ref. ParseDigest will validate
// that the ref is a digest and verify against that if present. Otherwize
// (on error), we simply compute the localDigest and proceed.
if dgst, err := digest.ParseDigest(ref); err == nil {
// verify the manifest against local ref
if err := verifyDigest(dgst, payload); err != nil {
return "", nil, false, fmt.Errorf("verifying local digest: %v", err)
}
if dgst != "" {
manifestDigest, err = digest.ParseDigest(dgst)
localDigest = dgst
} else {
// We don't have a local digest, since we are working from a tag.
// Compute the digest of the payload and return that.
logrus.Debugf("provided manifest reference %q is not a digest: %v", ref, err)
localDigest, err = digest.FromBytes(payload)
if err != nil {
return nil, false, fmt.Errorf("invalid manifest digest from registry: %s", err)
}
dgstVerifier, err := digest.NewDigestVerifier(manifestDigest)
if err != nil {
return nil, false, fmt.Errorf("unable to verify manifest digest from registry: %s", err)
}
dgstVerifier.Write(payload)
if !dgstVerifier.Verified() {
computedDigest, _ := digest.FromBytes(payload)
return nil, false, fmt.Errorf("unable to verify manifest digest: registry has %q, computed %q", manifestDigest, computedDigest)
// near impossible
logrus.Errorf("error calculating local digest during tag pull: %v", err)
return "", nil, false, err
}
}
if utils.DigestReference(ref) && ref != manifestDigest.String() {
return nil, false, fmt.Errorf("mismatching image manifest digest: got %q, expected %q", manifestDigest, ref)
// verify against the remote digest, if available
if remoteDigest != "" {
if err := verifyDigest(remoteDigest, payload); err != nil {
return "", nil, false, fmt.Errorf("verifying remote digest: %v", err)
}
}
var manifest registry.ManifestData
if err := json.Unmarshal(payload, &manifest); err != nil {
return nil, false, fmt.Errorf("error unmarshalling manifest: %s", err)
return "", nil, false, fmt.Errorf("error unmarshalling manifest: %s", err)
}
if manifest.SchemaVersion != 1 {
return nil, false, fmt.Errorf("unsupported schema version: %d", manifest.SchemaVersion)
// validate the contents of the manifest
if err := validateManifest(&manifest); err != nil {
return "", nil, false, err
}
var verified bool
verified, err = s.verifyTrustedKeys(manifest.Name, keys)
if err != nil {
return "", nil, false, fmt.Errorf("error verifying trusted keys: %v", err)
}
return localDigest, &manifest, verified, nil
}
// unpackSignedManifest takes the raw, signed manifest bytes, unpacks the jws
// and returns the payload and public keys used to signed the manifest.
// Signatures are verified for authenticity but not against the trust store.
func unpackSignedManifest(p []byte) ([]byte, []libtrust.PublicKey, error) {
sig, err := libtrust.ParsePrettySignature(p, "signatures")
if err != nil {
return nil, nil, fmt.Errorf("error parsing payload: %s", err)
}
keys, err := sig.Verify()
if err != nil {
return nil, nil, fmt.Errorf("error verifying payload: %s", err)
}
payload, err := sig.Payload()
if err != nil {
return nil, nil, fmt.Errorf("error retrieving payload: %s", err)
}
return payload, keys, nil
}
// verifyTrustedKeys checks the keys provided against the trust store,
// ensuring that the provided keys are trusted for the namespace. The keys
// provided from this method must come from the signatures provided as part of
// the manifest JWS package, obtained from unpackSignedManifest or libtrust.
func (s *TagStore) verifyTrustedKeys(namespace string, keys []libtrust.PublicKey) (verified bool, err error) {
if namespace[0] != '/' {
namespace = "/" + namespace
}
for _, key := range keys {
namespace := manifest.Name
if namespace[0] != '/' {
namespace = "/" + namespace
}
b, err := key.MarshalJSON()
if err != nil {
return nil, false, fmt.Errorf("error marshalling public key: %s", err)
return false, fmt.Errorf("error marshalling public key: %s", err)
}
// Check key has read/write permission (0x03)
v, err := s.trustService.CheckKey(namespace, b, 0x03)
if err != nil {
vErr, ok := err.(trust.NotVerifiedError)
if !ok {
return nil, false, fmt.Errorf("error running key check: %s", err)
return false, fmt.Errorf("error running key check: %s", err)
}
logrus.Debugf("Key check result: %v", vErr)
}
verified = v
if verified {
logrus.Debug("Key check result: verified")
}
}
return &manifest, verified, nil
if verified {
logrus.Debug("Key check result: verified")
}
return
}
func checkValidManifest(manifest *registry.ManifestData) error {
// verifyDigest checks the contents of p against the provided digest. Note
// that for manifests, this is the signed payload and not the raw bytes with
// signatures.
func verifyDigest(dgst digest.Digest, p []byte) error {
if err := dgst.Validate(); err != nil {
return fmt.Errorf("error validating digest %q: %v", dgst, err)
}
verifier, err := digest.NewDigestVerifier(dgst)
if err != nil {
// There are not many ways this can go wrong: if it does, its
// fatal. Likley, the cause would be poor validation of the
// incoming reference.
return fmt.Errorf("error creating verifier for digest %q: %v", dgst, err)
}
if _, err := verifier.Write(p); err != nil {
return fmt.Errorf("error writing payload to digest verifier (verifier target %q): %v", dgst, err)
}
if !verifier.Verified() {
return fmt.Errorf("verification against digest %q failed", dgst)
}
return nil
}
func validateManifest(manifest *registry.ManifestData) error {
if manifest.SchemaVersion != 1 {
return fmt.Errorf("unsupported schema version: %d", manifest.SchemaVersion)
}
if len(manifest.FSLayers) != len(manifest.History) {
return fmt.Errorf("length of history not equal to number of layers")
}
+120
View File
@@ -8,11 +8,13 @@ import (
"os"
"testing"
"github.com/docker/distribution/digest"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/tarsum"
"github.com/docker/docker/registry"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/utils"
"github.com/docker/libtrust"
)
const (
@@ -181,3 +183,121 @@ func TestManifestTarsumCache(t *testing.T) {
t.Fatalf("Unexpected json value\nExpected:\n%s\nActual:\n%s", v1compat, manifest.History[0].V1Compatibility)
}
}
// TestManifestDigestCheck ensures that loadManifest properly verifies the
// remote and local digest.
func TestManifestDigestCheck(t *testing.T) {
tmp, err := utils.TestDirectory("")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmp)
store := mkTestTagStore(tmp, t)
defer store.graph.driver.Cleanup()
archive, err := fakeTar()
if err != nil {
t.Fatal(err)
}
img := &image.Image{ID: testManifestImageID}
if err := store.graph.Register(img, archive); err != nil {
t.Fatal(err)
}
if err := store.Tag(testManifestImageName, testManifestTag, testManifestImageID, false); err != nil {
t.Fatal(err)
}
if cs, err := img.GetCheckSum(store.graph.ImageRoot(testManifestImageID)); err != nil {
t.Fatal(err)
} else if cs != "" {
t.Fatalf("Non-empty checksum file after register")
}
// Generate manifest
payload, err := store.newManifest(testManifestImageName, testManifestImageName, testManifestTag)
if err != nil {
t.Fatalf("unexpected error generating test manifest: %v", err)
}
pk, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
t.Fatalf("unexpected error generating private key: %v", err)
}
sig, err := libtrust.NewJSONSignature(payload)
if err != nil {
t.Fatalf("error creating signature: %v", err)
}
if err := sig.Sign(pk); err != nil {
t.Fatalf("error signing manifest bytes: %v", err)
}
signedBytes, err := sig.PrettySignature("signatures")
if err != nil {
t.Fatalf("error getting signed bytes: %v", err)
}
dgst, err := digest.FromBytes(payload)
if err != nil {
t.Fatalf("error getting digest of manifest: %v", err)
}
// use this as the "bad" digest
zeroDigest, err := digest.FromBytes([]byte{})
if err != nil {
t.Fatalf("error making zero digest: %v", err)
}
// Remote and local match, everything should look good
local, _, _, err := store.loadManifest(signedBytes, dgst.String(), dgst)
if err != nil {
t.Fatalf("unexpected error verifying local and remote digest: %v", err)
}
if local != dgst {
t.Fatalf("local digest not correctly calculated: %v", err)
}
// remote and no local, since pulling by tag
local, _, _, err = store.loadManifest(signedBytes, "tag", dgst)
if err != nil {
t.Fatalf("unexpected error verifying tag pull and remote digest: %v", err)
}
if local != dgst {
t.Fatalf("local digest not correctly calculated: %v", err)
}
// remote and differing local, this is the most important to fail
local, _, _, err = store.loadManifest(signedBytes, zeroDigest.String(), dgst)
if err == nil {
t.Fatalf("error expected when verifying with differing local digest")
}
// no remote, no local (by tag)
local, _, _, err = store.loadManifest(signedBytes, "tag", "")
if err != nil {
t.Fatalf("unexpected error verifying manifest without remote digest: %v", err)
}
if local != dgst {
t.Fatalf("local digest not correctly calculated: %v", err)
}
// no remote, with local
local, _, _, err = store.loadManifest(signedBytes, dgst.String(), "")
if err != nil {
t.Fatalf("unexpected error verifying manifest without remote digest: %v", err)
}
if local != dgst {
t.Fatalf("local digest not correctly calculated: %v", err)
}
// bad remote, we fail the check.
local, _, _, err = store.loadManifest(signedBytes, dgst.String(), zeroDigest)
if err == nil {
t.Fatalf("error expected when verifying with differing remote digest")
}
}
+41 -29
View File
@@ -142,7 +142,6 @@ func makeMirrorRepoInfo(repoInfo *registry.RepositoryInfo, mirror string) *regis
func configureV2Mirror(repoInfo *registry.RepositoryInfo, s *registry.Service) (*registry.Endpoint, *registry.RepositoryInfo, error) {
mirrors := repoInfo.Index.Mirrors
if len(mirrors) == 0 {
// no mirrors configured
return nil, nil, nil
@@ -151,13 +150,11 @@ func configureV2Mirror(repoInfo *registry.RepositoryInfo, s *registry.Service) (
v1MirrorCount := 0
var v2MirrorEndpoint *registry.Endpoint
var v2MirrorRepoInfo *registry.RepositoryInfo
var lastErr error
for _, mirror := range mirrors {
mirrorRepoInfo := makeMirrorRepoInfo(repoInfo, mirror)
endpoint, err := registry.NewEndpoint(mirrorRepoInfo.Index, nil)
if err != nil {
logrus.Errorf("Unable to create endpoint for %s: %s", mirror, err)
lastErr = err
continue
}
if endpoint.Version == 2 {
@@ -182,9 +179,11 @@ func configureV2Mirror(repoInfo *registry.RepositoryInfo, s *registry.Service) (
return v2MirrorEndpoint, v2MirrorRepoInfo, nil
}
if v2MirrorEndpoint != nil && v1MirrorCount > 0 {
lastErr = fmt.Errorf("v1 and v2 mirrors configured")
return nil, nil, fmt.Errorf("v1 and v2 mirrors configured")
}
return nil, nil, lastErr
// No endpoint could be established with the given mirror configurations
// Fallback to pulling from the hub as per v1 behavior.
return nil, nil, nil
}
func (s *TagStore) pullFromV2Mirror(mirrorEndpoint *registry.Endpoint, repoInfo *registry.RepositoryInfo,
@@ -458,17 +457,6 @@ func WriteStatus(requestedTag string, out io.Writer, sf *streamformatter.StreamF
}
}
// downloadInfo is used to pass information from download to extractor
type downloadInfo struct {
imgJSON []byte
img *image.Image
digest digest.Digest
tmpFile *os.File
length int64
downloaded bool
err chan error
}
func (s *TagStore) pullV2Repository(r *registry.Session, out io.Writer, repoInfo *registry.RepositoryInfo, tag string, sf *streamformatter.StreamFormatter) error {
endpoint, err := r.V2RegistryEndpoint(repoInfo.Index)
if err != nil {
@@ -518,27 +506,34 @@ func (s *TagStore) pullV2Repository(r *registry.Session, out io.Writer, repoInfo
func (s *TagStore) pullV2Tag(r *registry.Session, out io.Writer, endpoint *registry.Endpoint, repoInfo *registry.RepositoryInfo, tag string, sf *streamformatter.StreamFormatter, auth *registry.RequestAuthorization) (bool, error) {
logrus.Debugf("Pulling tag from V2 registry: %q", tag)
manifestBytes, manifestDigest, err := r.GetV2ImageManifest(endpoint, repoInfo.RemoteName, tag, auth)
remoteDigest, manifestBytes, err := r.GetV2ImageManifest(endpoint, repoInfo.RemoteName, tag, auth)
if err != nil {
return false, err
}
// loadManifest ensures that the manifest payload has the expected digest
// if the tag is a digest reference.
manifest, verified, err := s.loadManifest(manifestBytes, manifestDigest, tag)
localDigest, manifest, verified, err := s.loadManifest(manifestBytes, tag, remoteDigest)
if err != nil {
return false, fmt.Errorf("error verifying manifest: %s", err)
}
if err := checkValidManifest(manifest); err != nil {
return false, err
}
if verified {
logrus.Printf("Image manifest for %s has been verified", utils.ImageReference(repoInfo.CanonicalName, tag))
}
out.Write(sf.FormatStatus(tag, "Pulling from %s", repoInfo.CanonicalName))
// downloadInfo is used to pass information from download to extractor
type downloadInfo struct {
imgJSON []byte
img *image.Image
digest digest.Digest
tmpFile *os.File
length int64
downloaded bool
err chan error
}
downloads := make([]downloadInfo, len(manifest.FSLayers))
for i := len(manifest.FSLayers) - 1; i >= 0; i-- {
@@ -611,8 +606,7 @@ func (s *TagStore) pullV2Tag(r *registry.Session, out io.Writer, endpoint *regis
out.Write(sf.FormatProgress(stringid.TruncateID(img.ID), "Verifying Checksum", nil))
if !verifier.Verified() {
logrus.Infof("Image verification failed: checksum mismatch for %q", di.digest.String())
verified = false
return fmt.Errorf("image layer digest verification failed for %q", di.digest)
}
out.Write(sf.FormatProgress(stringid.TruncateID(img.ID), "Download complete", nil))
@@ -689,15 +683,33 @@ func (s *TagStore) pullV2Tag(r *registry.Session, out io.Writer, endpoint *regis
out.Write(sf.FormatStatus(utils.ImageReference(repoInfo.CanonicalName, tag), "The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security."))
}
if manifestDigest != "" {
out.Write(sf.FormatStatus("", "Digest: %s", manifestDigest))
if localDigest != remoteDigest { // this is not a verification check.
// NOTE(stevvooe): This is a very defensive branch and should never
// happen, since all manifest digest implementations use the same
// algorithm.
logrus.WithFields(
logrus.Fields{
"local": localDigest,
"remote": remoteDigest,
}).Debugf("local digest does not match remote")
out.Write(sf.FormatStatus("", "Remote Digest: %s", remoteDigest))
}
if utils.DigestReference(tag) {
if err = s.SetDigest(repoInfo.LocalName, tag, downloads[0].img.ID); err != nil {
out.Write(sf.FormatStatus("", "Digest: %s", localDigest))
if tag == localDigest.String() {
// TODO(stevvooe): Ideally, we should always set the digest so we can
// use the digest whether we pull by it or not. Unfortunately, the tag
// store treats the digest as a separate tag, meaning there may be an
// untagged digest image that would seem to be dangling by a user.
if err = s.SetDigest(repoInfo.LocalName, localDigest.String(), downloads[0].img.ID); err != nil {
return false, err
}
} else {
}
if !utils.DigestReference(tag) {
// only set the repository/tag -> image ID mapping when pulling by tag (i.e. not by digest)
if err = s.Tag(repoInfo.LocalName, tag, downloads[0].img.ID, true); err != nil {
return false, err
+1 -1
View File
@@ -413,7 +413,7 @@ func (s *TagStore) pushV2Repository(r *registry.Session, localRepo Repository, o
m.History[i] = &registry.ManifestHistory{V1Compatibility: string(jsonData)}
}
if err := checkValidManifest(m); err != nil {
if err := validateManifest(m); err != nil {
return fmt.Errorf("invalid manifest: %s", err)
}
+8
View File
@@ -12,6 +12,7 @@ import (
"github.com/docker/docker/daemon/graphdriver"
_ "github.com/docker/docker/daemon/graphdriver/vfs" // import the vfs driver so it is used in the tests
"github.com/docker/docker/image"
"github.com/docker/docker/trust"
"github.com/docker/docker/utils"
)
@@ -60,9 +61,16 @@ func mkTestTagStore(root string, t *testing.T) *TagStore {
if err != nil {
t.Fatal(err)
}
trust, err := trust.NewTrustStore(root + "/trust")
if err != nil {
t.Fatal(err)
}
tagCfg := &TagStoreConfig{
Graph: graph,
Events: events.New(),
Trust: trust,
}
store, err := NewTagStore(path.Join(root, "tags"), tagCfg)
if err != nil {
+15
View File
@@ -133,6 +133,21 @@ do_install() {
exit 0
;;
'opensuse project'|opensuse|'suse linux'|sled)
(
set -x
$sh_c 'sleep 3; zypper -n install docker'
)
if command_exists docker && [ -e /var/run/docker.sock ]; then
(
set -x
$sh_c 'docker version'
) || true
fi
echo_docker_as_nonroot
exit 0
;;
ubuntu|debian|linuxmint|'elementary os'|kali)
export DEBIAN_FRONTEND=noninteractive
+14 -10
View File
@@ -96,7 +96,6 @@ fi
if [ "$DOCKER_EXPERIMENTAL" ]; then
echo >&2 '# WARNING! DOCKER_EXPERIMENTAL is set: building experimental features'
echo >&2
VERSION+="-experimental"
DOCKER_BUILDTAGS+=" experimental"
fi
@@ -198,13 +197,13 @@ go_test_dir() {
# if our current go install has -cover, we want to use it :)
mkdir -p "$DEST/coverprofiles"
coverprofile="docker${dir#.}"
coverprofile="$DEST/coverprofiles/${coverprofile//\//-}"
coverprofile="$ABS_DEST/coverprofiles/${coverprofile//\//-}"
testcover=( -cover -coverprofile "$coverprofile" $coverpkg )
fi
(
export DEST
echo '+ go test' $TESTFLAGS "${DOCKER_PKG}${dir#.}"
cd "$dir"
export DEST="$ABS_DEST" # we're in a subshell, so this is safe -- our integration-cli tests need DEST, and "cd" screws it up
test_env go test ${testcover[@]} -ldflags "$LDFLAGS" "${BUILDFLAGS[@]}" $TESTFLAGS
)
}
@@ -217,7 +216,7 @@ test_env() {
DOCKER_USERLANDPROXY="$DOCKER_USERLANDPROXY" \
DOCKER_HOST="$DOCKER_HOST" \
GOPATH="$GOPATH" \
HOME="$DEST/fake-HOME" \
HOME="$ABS_DEST/fake-HOME" \
PATH="$PATH" \
TEST_DOCKERINIT_PATH="$TEST_DOCKERINIT_PATH" \
"$@"
@@ -271,11 +270,9 @@ hash_files() {
}
bundle() {
bundlescript=$1
bundle=$(basename $bundlescript)
echo "---> Making bundle: $bundle (in bundles/$VERSION/$bundle)"
mkdir -p "bundles/$VERSION/$bundle"
source "$bundlescript" "$(pwd)/bundles/$VERSION/$bundle"
local bundle="$1"; shift
echo "---> Making bundle: $(basename "$bundle") (in $DEST)"
source "$SCRIPTDIR/make/$bundle" "$@"
}
main() {
@@ -301,7 +298,14 @@ main() {
bundles=($@)
fi
for bundle in ${bundles[@]}; do
bundle "$SCRIPTDIR/make/$bundle"
export DEST="bundles/$VERSION/$(basename "$bundle")"
# Cygdrive paths don't play well with go build -o.
if [[ "$(uname -s)" == CYGWIN* ]]; then
export DEST="$(cygpath -mw "$DEST")"
fi
mkdir -p "$DEST"
ABS_DEST="$(cd "$DEST" && pwd -P)"
bundle "$bundle"
echo
done
}
+1 -1
View File
@@ -1,6 +1,6 @@
Source: docker-engine
Maintainer: Docker <support@docker.com>
Homepage: https://dockerproject.com
Homepage: https://dockerproject.org
Vcs-Browser: https://github.com/docker/docker
Vcs-Git: git://github.com/docker/docker.git
+1 -1
View File
@@ -1 +1 @@
docs/man/man*/*
man/man*/*
+1 -1
View File
@@ -9,7 +9,7 @@ override_dh_gencontrol:
override_dh_auto_build:
./hack/make.sh dynbinary
# ./docs/man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
# ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
override_dh_auto_test:
./bundles/$(VERSION)/dynbinary/docker -v
+4 -4
View File
@@ -6,7 +6,7 @@ Summary: The open-source application container engine
License: ASL 2.0
Source: %{name}.tar.gz
URL: https://dockerproject.com
URL: https://dockerproject.org
Vendor: Docker
Packager: Docker <support@docker.com>
@@ -71,7 +71,7 @@ depending on a particular stack or provider.
%build
./hack/make.sh dynbinary
# ./docs/man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
# ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
%check
./bundles/%{_origversion}/dynbinary/docker -v
@@ -113,9 +113,9 @@ install -p -m 644 contrib/completion/fish/docker.fish $RPM_BUILD_ROOT/usr/share/
# install manpages
install -d %{buildroot}%{_mandir}/man1
install -p -m 644 docs/man/man1/*.1 $RPM_BUILD_ROOT/%{_mandir}/man1
install -p -m 644 man/man1/*.1 $RPM_BUILD_ROOT/%{_mandir}/man1
install -d %{buildroot}%{_mandir}/man5
install -p -m 644 docs/man/man5/*.5 $RPM_BUILD_ROOT/%{_mandir}/man5
install -p -m 644 man/man5/*.5 $RPM_BUILD_ROOT/%{_mandir}/man5
# add vimfiles
install -d $RPM_BUILD_ROOT/usr/share/vim/vimfiles/doc
+1 -1
View File
@@ -2,7 +2,7 @@
# see test-integration-cli for example usage of this script
export PATH="$DEST/../binary:$DEST/../dynbinary:$DEST/../gccgo:$DEST/../dyngccgo:$PATH"
export PATH="$ABS_DEST/../binary:$ABS_DEST/../dynbinary:$ABS_DEST/../gccgo:$ABS_DEST/../dyngccgo:$PATH"
if ! command -v docker &> /dev/null; then
echo >&2 'error: binary or dynbinary must be run before .integration-daemon-start'
-6
View File
@@ -1,16 +1,10 @@
#!/bin/bash
set -e
DEST=$1
BINARY_NAME="docker-$VERSION"
BINARY_EXTENSION="$(binary_extension)"
BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION"
# Cygdrive paths don't play well with go build -o.
if [[ "$(uname -s)" == CYGWIN* ]]; then
DEST=$(cygpath -mw $DEST)
fi
source "${MAKEDIR}/.go-autogen"
echo "Building: $DEST/$BINARY_FULLNAME"
+4 -4
View File
@@ -1,10 +1,10 @@
#!/bin/bash
set -e
DEST=$1
# subshell so that we can export PATH without breaking other things
# subshell so that we can export PATH and TZ without breaking other things
(
export TZ=UTC # make sure our "date" variables are UTC-based
source "${MAKEDIR}/.integration-daemon-start"
# TODO consider using frozen images for the dockercore/builder-deb tags
@@ -35,7 +35,7 @@ DEST=$1
debDate="$(date --rfc-2822)"
# if go-md2man is available, pre-generate the man pages
./docs/man/md2man-all.sh -q || true
./man/md2man-all.sh -q || true
# TODO decide if it's worth getting go-md2man in _each_ builder environment to avoid this
# TODO add a configurable knob for _which_ debs to build so we don't have to modify the file or build all of them every time we need to test
+4 -4
View File
@@ -1,10 +1,10 @@
#!/bin/bash
set -e
DEST=$1
# subshell so that we can export PATH without breaking other things
# subshell so that we can export PATH and TZ without breaking other things
(
export TZ=UTC # make sure our "date" variables are UTC-based
source "$(dirname "$BASH_SOURCE")/.integration-daemon-start"
# TODO consider using frozen images for the dockercore/builder-rpm tags
@@ -38,7 +38,7 @@ DEST=$1
rpmDate="$(date +'%a %b %d %Y')"
# if go-md2man is available, pre-generate the man pages
./docs/man/md2man-all.sh -q || true
./man/md2man-all.sh -q || true
# TODO decide if it's worth getting go-md2man in _each_ builder environment to avoid this
# TODO add a configurable knob for _which_ rpms to build so we don't have to modify the file or build all of them every time we need to test
-2
View File
@@ -1,8 +1,6 @@
#!/bin/bash
set -e
DEST="$1"
bundle_cover() {
coverprofiles=( "$DEST/../"*"/coverprofiles/"* )
for p in "${coverprofiles[@]}"; do
+4 -4
View File
@@ -1,8 +1,6 @@
#!/bin/bash
set -e
DEST=$1
# explicit list of os/arch combos that support being a daemon
declare -A daemonSupporting
daemonSupporting=(
@@ -21,13 +19,15 @@ fi
for platform in $DOCKER_CROSSPLATFORMS; do
(
mkdir -p "$DEST/$platform" # bundles/VERSION/cross/GOOS/GOARCH/docker-VERSION
export DEST="$DEST/$platform" # bundles/VERSION/cross/GOOS/GOARCH/docker-VERSION
mkdir -p "$DEST"
ABS_DEST="$(cd "$DEST" && pwd -P)"
export GOOS=${platform%/*}
export GOARCH=${platform##*/}
if [ -z "${daemonSupporting[$platform]}" ]; then
export LDFLAGS_STATIC_DOCKER="" # we just need a simple client for these platforms
export BUILDFLAGS=( "${ORIG_BUILDFLAGS[@]/ daemon/}" ) # remove the "daemon" build tag from platforms that aren't supported
fi
source "${MAKEDIR}/binary" "$DEST/$platform"
source "${MAKEDIR}/binary"
)
done
-2
View File
@@ -1,8 +1,6 @@
#!/bin/bash
set -e
DEST=$1
if [ -z "$DOCKER_CLIENTONLY" ]; then
source "${MAKEDIR}/.dockerinit"
-2
View File
@@ -1,8 +1,6 @@
#!/bin/bash
set -e
DEST=$1
if [ -z "$DOCKER_CLIENTONLY" ]; then
source "${MAKEDIR}/.dockerinit-gccgo"
-1
View File
@@ -1,7 +1,6 @@
#!/bin/bash
set -e
DEST=$1
BINARY_NAME="docker-$VERSION"
BINARY_EXTENSION="$(binary_extension)"
BINARY_FULLNAME="$BINARY_NAME$BINARY_EXTENSION"
-2
View File
@@ -1,8 +1,6 @@
#!/bin/bash
set -e
DEST=$1
# subshell so that we can export PATH without breaking other things
(
source "${MAKEDIR}/.integration-daemon-start"

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