Compare commits

...

84 Commits

Author SHA1 Message Date
Tibor Vass
906eacd586 Bump VERSION to v1.12.0-rc2
Signed-off-by: Tibor Vass <tibor@docker.com>
2016-06-17 16:28:45 -04:00
Tibor Vass
02772750e1 Merge pull request #23594 from tiborvass/changelog-fix
v1.12.0: some fixes to CHANGELOG
2016-06-17 13:25:47 -07:00
Tibor Vass
2ba4108c95 Merge pull request #23661 from tiborvass/cherry-picks-for-1.12.0-rc2
Cherry picks for 1.12.0 rc2
2016-06-17 13:20:10 -07:00
Tibor Vass
11daa3e417 v1.12.0: some fixes to CHANGELOG
Signed-off-by: Tibor Vass <tibor@docker.com>
2016-06-17 13:18:49 -07:00
Arnaud Porterie (icecrime)
944a8f16c7 Improve docker service inspect --pretty
Remove capitalization in placement, and remove spurious `\t`.

Signed-off-by: Arnaud Porterie (icecrime) <arnaud.porterie@docker.com>
(cherry picked from commit 3c60b7b984)
2016-06-17 13:09:13 -07:00
Tibor Vass
70bd46293a plugins: fix name handling for legacy plugins
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 8ba17b4823)
2016-06-17 13:09:13 -07:00
Vincent Demeester
6eaac7be89 Update plugin command with defaulttag
This way, you don't have to specify the ":latest" tag for some command
and not for others

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit cb321e82db)
2016-06-17 13:09:13 -07:00
Tibor Vass
2ae7330140 plugins: fix usage for plugin commands
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 65ed9daf70)
2016-06-17 13:09:12 -07:00
Tibor Vass
1cfd620124 plugins: remove automatic mounting of a state dir
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 15ff9de658)
2016-06-17 13:09:12 -07:00
Tibor Vass
f24e5d79bc plugins: install should not automatically accept all permissions
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 4b70d4561e)
2016-06-17 13:09:12 -07:00
Jana Radhakrishnan
a7c925cba4 Vendoring libnetwork @13be89d1cf79
Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
(cherry picked from commit 70e2585d54)
2016-06-17 13:09:12 -07:00
Tonis Tiigi
bbc214fa9b Add newline to promote/demote message
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 3386e3570a)
2016-06-17 13:09:12 -07:00
Jana Radhakrishnan
8fdc925338 Check if DriverState is valid before using in convert
Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
(cherry picked from commit 4fea81154b)
2016-06-17 13:09:12 -07:00
Anil Madhavapeddy
4b2883fac6 docker swarm: more consistent CLI help
This changes `docker swarm help` to be consistent with capitals
and removes full stops.

Before:

```
Commands:
  init        Initialize a Swarm.
  join        Join a Swarm as a node and/or manager.
  update      update the Swarm.
  leave       Leave a Swarm.
  inspect     Inspect the Swarm
```

After:

```
Commands:
  init        Initialize a Swarm
  join        Join a Swarm as a node and/or manager
  update      Update the Swarm
  leave       Leave a Swarm
  inspect     Inspect the Swarm
```

Signed-off-by: Anil Madhavapeddy <anil@docker.com>
(cherry picked from commit 0ec78739ac)
2016-06-17 13:09:12 -07:00
Ke Xu
05c32e7f08 fix #23017, add zsh completion for dockerd
Signed-off-by: Ke Xu <leonhartx.k@gmail.com>
(cherry picked from commit bd1fc1e5c2)
2016-06-17 13:09:11 -07:00
Anusha Ragunathan
82608cd4ce Add disable flag for plugin Install.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
(cherry picked from commit 22e781e8e3)
2016-06-17 13:09:11 -07:00
Harald Albers
fcdd4d4a52 bash completion for docker swarm update --cert-expiry
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit dc2fc75d42)
2016-06-17 13:09:11 -07:00
Justin Cormack
445f4f2f3e Missing line feed after accepting node
Avoids
```
root@swarmatorium:~# docker node accept 3dnh6k13o44np9fwl83e7gh80
Node 3dnh6k13o44np9fwl83e7gh80 accepted in the swarm.root@swarmatorium:~#
```

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
(cherry picked from commit c34d752419)
2016-06-17 13:09:11 -07:00
Justin Cormack
b7a1f1a2d1 fix invalid typo in error message
Signed-off-by: Justin Cormack <justin.cormack@docker.com>
(cherry picked from commit 2322ccb8ff)
2016-06-17 13:09:11 -07:00
Charles Smith
aa1f241894 update output for node commands, minor edits
Signed-off-by: Charles Smith <charles.smith@docker.com>
(cherry picked from commit 3b2132c2c7)
2016-06-16 23:36:59 -07:00
Daniel Nephin
fb364d86fa Add some tests for bundlefile and improve the error messages for LoadFile
Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit c0ea589c1b)
2016-06-16 23:36:59 -07:00
Victor Vieux
d747fbc95c improve some messages in the node subcmds
Signed-off-by: Victor Vieux <vieux@docker.com>
(cherry picked from commit eb962235fb)
2016-06-16 23:36:58 -07:00
Tonis Tiigi
0efe76c62b Add integration test for parsing swarm update options
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit a933ac3c27)
2016-06-16 23:36:58 -07:00
Tonis Tiigi
ab6abb799b Add cert-expiry to swarm update
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 7d8d51aa9d)
2016-06-16 23:36:58 -07:00
Brian Goff
9647e4d6cc Implement plugin restore after daemon restart
This ensures that:

- The in-memory plugin store is populated with all the plugins
- Plugins which were active before daemon restart are active after.
  This utilizes the liverestore feature when available, otherwise it
  manually starts the plugin.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit dfd9187305)
2016-06-16 23:36:58 -07:00
Brian Goff
be82ff5c7f Fix removing plugins
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 5e156fd3d4)
2016-06-16 23:36:58 -07:00
Tonis Tiigi
efc10a92ef Fix removing containers on leaving from pending state
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 826f6f0703)
2016-06-16 23:36:58 -07:00
Victor Vieux
3635938b00 add some more fields in docker service inspect -p
Signed-off-by: Victor Vieux <vieux@docker.com>
(cherry picked from commit 4c9e21b674)
2016-06-16 23:36:58 -07:00
Tonis Tiigi
0cac3c4c23 Return membership status on join without timeout
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 1973cee0cd)
2016-06-16 23:36:57 -07:00
Tonis Tiigi
01c5b208e8 Update daemon to new swarmkit
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit a83bba467a)
2016-06-16 23:36:57 -07:00
Tonis Tiigi
528f3ab668 Update swarmkit to 310f1119
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 2783568284)
2016-06-16 23:36:57 -07:00
Derek McGowan
56b253fb3c Do not show empty tags for digest references in output
When a repository has a tag and digests, show tag for each digest value.
Do not duplicate rows for the same image name with both tag and digest.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
(cherry picked from commit 79eada3814)
2016-06-16 23:36:57 -07:00
Sebastiaan van Stijn
b3387e96ed fix "overlay" -> "overlay2" in error message
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 2d4b285a75)
2016-06-16 23:36:57 -07:00
Vincent Demeester
42f445565d Update ServiceInspectWithRaw
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 4a70cb5571)
2016-06-16 23:36:57 -07:00
Vincent Demeester
d9d24b6605 Update docker plugin install code…
… for more consistency (api side).

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 2c82337b04)
2016-06-16 23:36:57 -07:00
Vincent Demeester
7444bb2c25 Bump engine-api to c57d0447ea1ae71f6dad83c8d8a1215a89869a0c
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 58529a1553)
2016-06-16 23:36:56 -07:00
Sebastiaan van Stijn
fdb5324595 Update docker info output example
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 07e1c62bf4)
2016-06-16 23:36:56 -07:00
Madhu Venugopal
ed01cfc6db Vendoring Libnetwork caf22bd9a6a53dfe91b0266274155bc69235e8ed
* fixes https://github.com/docker/docker/issues/23622
* fixes a memory leak issue with bulk sync
* fixes external DNS resolution issue after live restore

Signed-off-by: Madhu Venugopal <madhu@docker.com>
(cherry picked from commit 7f2f6ed0d6)
2016-06-16 23:36:56 -07:00
Justin Cormack
213adac2ea Add the seccomp build tag for s390x now runc updated
This was waiting for runc bump see https://github.com/docker/docker/issues/23171
runc was bumped in https://github.com/docker/docker/pull/23603

Fixes #23171

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
(cherry picked from commit f8d970169a)
2016-06-16 23:36:56 -07:00
Lei Jitang
83fbaa3cb4 Fix restore active sandbox
we store the active sandbox after daemon.containerd.Restore, but there
is a chance the `Restore` will set the container to exit see
(https://github.com/docker/docker/blob/master/libcontainerd/client_linux.go#L469).
so we should check if the container is really running before add it to
activesandbox.

Signed-off-by: Lei Jitang <leijitang@huawei.com>
(cherry picked from commit 78f3094518)
2016-06-16 23:36:56 -07:00
Yong Tang
1ad7b517fa Add security info to docker info
The security infomation has already been added to `GET /info` in #21172.
However, it is not part of the output of `docker info` yet.

This fix adds the security information to `docker info`.

Additional tests has been added to cover changes.

This fix fixes #23500. This fix is related to #20909, #21172.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
(cherry picked from commit eee20b564f)
2016-06-16 23:36:56 -07:00
Stephen J Day
6c3d080e83 api/client/service: fix minor spelling error in service inspect
Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit 920e65ccbc)
2016-06-16 23:36:55 -07:00
Kai Qiang Wu(Kennan)
82453c84ba Add ecryptfs check for overlay2
We added docs about ecryptfs check but not in code side.
Also refactor code to make it clean.

Signed-off-by: Kai Qiang Wu(Kennan) <wkqwu@cn.ibm.com>
(cherry picked from commit 136323b043)
2016-06-16 23:36:55 -07:00
Sebastiaan van Stijn
c73e56fd7f docs: move "advisory" to general metadata
the advisory option should not be
below "menu"

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit aadd88c306)
2016-06-16 23:36:55 -07:00
Sainath Grandhi
1e5ee1dd37 Fixes #23596-returns empty string for NetworkID in response to /containers/json
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
(cherry picked from commit ad85d29906)
2016-06-16 23:36:55 -07:00
Stephen J Day
c3015a22cb api/client/service: list running services over replicas
To provide users a view of service status, list the number of running
task over the requested number of replicas.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit b86cb293ec)
2016-06-16 23:36:55 -07:00
Tonis Tiigi
01d26abd5c Add api tests for secret update
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit aed7667bee)
2016-06-16 23:36:55 -07:00
Victor Vieux
7f4bca0f90 use same hash for same secret
Signed-off-by: Victor Vieux <vieux@docker.com>
(cherry picked from commit a579ce8ed3)
2016-06-16 23:36:55 -07:00
Victor Vieux
7cc76facba fix docker swarm init/update --secret
Signed-off-by: Victor Vieux <vieux@docker.com>
(cherry picked from commit 085895342c)
2016-06-16 23:36:54 -07:00
Michael Crosby
e491dbb38a Set systemd KillMode
Change the kill mode to process so that systemd does not kill container
processes when the daemon is shutdown but only the docker daemon

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
(cherry picked from commit db435f526a)
2016-06-16 23:36:54 -07:00
Sebastiaan van Stijn
dd5573bc60 Update release script installation instructions
Instructions for installing the static binaries
has changed, so updated the instructions.

The comment on top already requires the steps
to be executed as root, so removing the 'sudo'

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit e233c8dd72)
2016-06-16 23:36:54 -07:00
Daniel Nephin
bb8996d62b Fix String() for some option types
and add unit tests for them.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit c26e7d8c91)
2016-06-16 23:36:54 -07:00
Adrian Moisey
2401c0223d Fix URL to issue
Signed-off-by: Adrian Moisey <adrian@changeover.za.net>
(cherry picked from commit 88d4da7f42)
2016-06-16 23:36:54 -07:00
Sven Dowideit
af3b1c7370 advisory can't be in the [menu] section
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
(cherry picked from commit bc033cb706)
2016-06-16 23:36:54 -07:00
Thomas Leonard
979ad07925 Remove out-of-date health test
The test was waiting for the container to exit after failing its
healthcheck. However, we no longer automatically terminate containers,
so this waited instead for the container to time-out by itself.

Signed-off-by: Thomas Leonard <thomas.leonard@docker.com>
(cherry picked from commit 18a59bb869)
2016-06-16 23:36:53 -07:00
Anusha Ragunathan
3e44703cae Add basic integration tests for plugins.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
(cherry picked from commit a2d48c9e4e)
2016-06-16 23:36:53 -07:00
Anusha Ragunathan
c82f23095a Add accept-permissions flag for install.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
(cherry picked from commit ec4857da48)
2016-06-16 23:36:53 -07:00
Arnaud Porterie (icecrime)
187b6607a4 Service --update-parallelism defauls to 0
The `--update-parallelism` flaag should default to 0, which is
interpreted by the backend as unlimited. In other words, by default all
services should update simultaneously.

Signed-off-by: Arnaud Porterie (icecrime) <arnaud.porterie@docker.com>
(cherry picked from commit f22d0174f3)
2016-06-16 23:36:53 -07:00
Tom Barlow
5e41ec703d Change 'invald' to 'invalid' in volume opts errors
Signed-off-by: Tom Barlow <tomwbarlow@gmail.com>
(cherry picked from commit bf988fc6ff)
2016-06-16 23:36:53 -07:00
Justin Cormack
ad28216987 Move mlock back into the default ungated seccomp profile
Do not gate with CAP_IPC_LOCK as unprivileged use is now
allowed in Linux. This returns it to how it was in 1.11.

Fixes #23587

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
(cherry picked from commit bdf01cf5de)
2016-06-16 23:36:53 -07:00
Anusha Ragunathan
d2a9560e71 Avoid back and forth conversion between strings and bytes.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
(cherry picked from commit d6d448aab8)
2016-06-16 23:36:53 -07:00
Daniel Nephin
41d72e28c3 Change SCALE to REPLICAS.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit 4df0349948)
2016-06-16 23:36:52 -07:00
Kenfe-Mickael Laventure
e324ec639b Fix TestRunWithRuntime* on arm
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
(cherry picked from commit bd6317031b)
2016-06-16 23:36:52 -07:00
Michael Crosby
cdb04519e2 Update libnetwork to 96d45528599c32354230480a1ebc0
This fixes an issue with hanging tests due to store.

Fixes #23560

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
(cherry picked from commit e927df7b4b)
2016-06-16 23:36:52 -07:00
Victoria Bialas
38305cb676 fixing links and merge conflicts
updated link to faqs/troubleshoot to point to new location /toolbox

fixed docker-for-mac link error

Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
(cherry picked from commit 1d80f8ca19)
2016-06-16 23:36:52 -07:00
Shoubhik Bose
2b36087597 Fixes #23376 Broken URL for Centos yum repo for docker changed to now have a hardcoded centos version 7
Signed-off-by: Shoubhik Bose <sbose78@gmail.com>
(cherry picked from commit d3fad80cc7)
2016-06-16 23:36:52 -07:00
Sven Dowideit
7af9b80f23 fix links for #23505
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
(cherry picked from commit fa94eb4604)
2016-06-16 23:36:52 -07:00
Madhu Venugopal
60a86590aa Use service alias and configure container's --net-alias
Signed-off-by: Madhu Venugopal <madhu@docker.com>
(cherry picked from commit 07e39e9e72)
2016-06-16 23:36:51 -07:00
Madhu Venugopal
588b76c2a1 Vendoring swarmkit 682e0b69be208176d6055cba855a5e9cf15c7cb4
Signed-off-by: Madhu Venugopal <madhu@docker.com>
(cherry picked from commit 5af8e2a9c0)
2016-06-16 23:36:51 -07:00
Madhu Venugopal
f1d5c3374c Vendoring libnetwork 0d517a9e4e5cbdb889b3257eebd2351addcd46d4
Signed-off-by: Madhu Venugopal <madhu@docker.com>
(cherry picked from commit f2f97f768e)
2016-06-16 23:36:51 -07:00
Tonis Tiigi
ca16a4c81d Fix hanging integration tests
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 22f827abab)
2016-06-16 23:36:51 -07:00
Antonio Murdaca
034d555d30 daemon: allow tmpfs to trump over VOLUME(s)
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
(cherry picked from commit 756f6cef4a)
2016-06-16 23:36:51 -07:00
Akihiro Suda
ce6211d252 Update experimental/README.md
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
(cherry picked from commit fec98ecca1)
2016-06-16 23:36:51 -07:00
Victoria Bialas
92ff142da2 surfacing Learn by example topics to top level of Docker Engine docs
fixing links after moving surfacing tutorials

fixing more links for the newly located tutorials

WIP: merging 3 getting started tutorials into one to cover all platforms, added new files

fixing broken images and links in 3-in-1 getting started, re-wrote story flow, linked to Toolbox, d4mac,d4win

Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
(cherry picked from commit 0254c12e1e)
2016-06-16 23:36:50 -07:00
Drew Erny
c816f2c905 Remove the node leader column, show leader as status.
Removes the leader column from node ls and shows whether a node is the
leader in the manager status column instead.

Signed-off-by: Drew Erny <drew.erny@docker.com>
(cherry picked from commit 4104c1dc13)
2016-06-16 23:36:50 -07:00
Michael Crosby
be67aae778 Merge pull request #23627 from mlaventure/update-runc-on-1.12
Update runc on 1.12
2016-06-16 14:30:54 -07:00
Kenfe-Mickael Laventure
301f3d776f Revert build-{deb,rpm} to cloning from opencontainers repository
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
2016-06-16 09:06:53 -07:00
Kenfe-Mickael Laventure
9eb6e049bd Vendor in runc cc29e3dded8e27ba8f65738f40d251c885030a28
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
(cherry picked from commit b675124cf5)
2016-06-16 08:46:23 -07:00
Tibor Vass
1f136c1f85 bump VERSION to v1.12.0-rc1
Signed-off-by: Tibor Vass <tibor@docker.com>
2016-06-15 00:36:32 -04:00
Michael Crosby
c293f64dc0 Merge pull request #23564 from tiborvass/fix-changelog
v1.12.0: fixed date in CHANGELOG to be in YYYY-MM-DD form
2016-06-14 21:35:39 -07:00
Tibor Vass
adbf43fe10 v1.12.0: fixed date in CHANGELOG to be in YYYY-MM-DD form
Signed-off-by: Tibor Vass <tibor@docker.com>
2016-06-14 21:33:17 -07:00
Arnaud Porterie
aab402731f Merge pull request #23563 from icecrime/i_trust_crosbymichael
Use runc from crosbymichael's fork
2016-06-15 04:14:13 +00:00
Arnaud Porterie (icecrime)
e2b7f648f4 Use runc from crosbymichael's fork
Signed-off-by: Arnaud Porterie (icecrime) <arnaud.porterie@docker.com>
2016-06-14 21:10:38 -07:00
Tibor Vass
427738d81f v1.12.0: first draft of CHANGELOG additions
Signed-off-by: Tibor Vass <tibor@docker.com>
2016-06-14 20:12:57 -07:00
183 changed files with 4071 additions and 1014 deletions

View File

@@ -5,6 +5,133 @@ information on the list of deprecated flags and APIs please have a look at
https://docs.docker.com/engine/deprecated/ where target removal dates can also
be found.
## 1.12.0 (2016-07-14)
### Builder
+ New `HEALTHCHECK` Dockerfile instruction to support user-defined healthchecks [#23218](https://github.com/docker/docker/pull/23218)
+ New `SHELL` Dockerfile instruction to specify the default shell when using the shell form for commands in a Dockerfile [#22489](https://github.com/docker/docker/pull/22489)
+ Add `#escape=` Dockerfile directive to support platform-specific parsing of file paths in Dockerfile [#22268](https://github.com/docker/docker/pull/22268)
+ Add support for comments in `.dockerignore` [#23111](https://github.com/docker/docker/pull/23111)
* Support for UTF-8 in Dockerfiles [#23372](https://github.com/docker/docker/pull/23372)
* Skip UTF-8 BOM bytes from `Dockerfile` and `.dockerignore` if exist [#23234](https://github.com/docker/docker/pull/23234)
* Windows: support for `ARG` to match Linux [#22508](https://github.com/docker/docker/pull/22508)
- Fix error message when building using a daemon with the bridge network disabled [#22932](https://github.com/docker/docker/pull/22932)
### Contrib
* Enable seccomp for Centos 7 and Oracle Linux 7 [#22344](https://github.com/docker/docker/pull/22344)
- Remove MountFlags in systemd unit to allow shared mount propagation [#22806](https://github.com/docker/docker/pull/22806)
### Distribution
+ Add `--max-concurrent-downloads` and `--max-concurrent-uploads` daemon flags useful for situations where network connections don't support multiple downloads/uploads [#22445](https://github.com/docker/docker/pull/22445)
* Registry operations now honor the `ALL_PROXY` environment variable [#22316](https://github.com/docker/docker/pull/22316)
* Provide more information to the user on `docker load` [#23377](https://github.com/docker/docker/pull/23377)
### Logging
+ Syslog logging driver now supports DGRAM sockets [#21613](https://github.com/docker/docker/pull/21613)
+ Add `--details` option to `docker logs` to also display log tags [#21889](https://github.com/docker/docker/pull/21889)
+ Enable syslog logger to have access to env and labels [#21724](https://github.com/docker/docker/pull/21724)
+ An additional syslog-format option `rfc5424micro` to allow microsecond resolution in syslog timestamp [#21844](https://github.com/docker/docker/pull/21844)
* Inherit the daemon log options when creating containers [#21153](https://github.com/docker/docker/pull/21153)
* Remove `docker/` prefix from log messages tag and replace it with `{{.DaemonName}}` so that users have the option of changing the prefix [#22384](https://github.com/docker/docker/pull/22384)
### Networking
+ Built-in Virtual-IP based internal and ingress load-balancing using IPVS [#23361](https://github.com/docker/docker/pull/23361)
+ Secured multi-host overlay networking using encrypted control-plane and Data-plane [#23361](https://github.com/docker/docker/pull/23361)
+ MacVlan driver is out of experimental [#23524](https://github.com/docker/docker/pull/23524)
+ Add `driver` filter to `network ls` [#22319](https://github.com/docker/docker/pull/22319)
+ Adding `network` filter to `docker ps --filter` [#23300](https://github.com/docker/docker/pull/23300)
+ Add `--link-local-ip` flag to `create`, `run` and `network connect` to specify a container's link-local address [#23415](https://github.com/docker/docker/pull/23415)
+ Add network label filter support [#21495](https://github.com/docker/docker/pull/21495)
* Removed dependency on external KV-Store for Overlay networking in Swarm-Mode [#23361](https://github.com/docker/docker/pull/23361)
* Add container's short-id as default network alias [#21901](https://github.com/docker/docker/pull/21901)
* `run` options `--dns` and `--net=host` are no longer mutually exclusive [#22408](https://github.com/docker/docker/pull/22408)
- Fix DNS issue when renaming containers with generated names [#22716](https://github.com/docker/docker/pull/22716)
- Allow both `network inspect -f {{.Id}}` and `network inspect -f {{.ID}}` to address inconsistency with inspect output [#23226](https://github.com/docker/docker/pull/23226)
### Plugins (experimental)
+ New `plugin` command to manager plugins with `install`, `enable`, `disable`, `rm`, `inspect`, `set` subcommands [#23446](https://github.com/docker/docker/pull/23446)
### Remote API (v1.24) & Client
+ Split the binary into two: `docker` (client) and `dockerd` (daemon) [#20639](https://github.com/docker/docker/pull/20639)
+ Add `before` and `since` filters to `docker images --filter` [#22908](https://github.com/docker/docker/pull/22908)
+ Add `--limit` option to `docker search` [#23107](https://github.com/docker/docker/pull/23107)
+ Add `--filter` option to `docker search` [#22369](https://github.com/docker/docker/pull/22369)
+ Add security options to `docker info` output [#21172](https://github.com/docker/docker/pull/21172) [#23520](https://github.com/docker/docker/pull/23520)
+ Add insecure registries to `docker info` output [#20410](https://github.com/docker/docker/pull/20410)
+ Extend Docker authorization with TLS user information [#21556](https://github.com/docker/docker/pull/21556)
+ devicemapper: expose Mininum Thin Pool Free Space through `docker info` [#21945](https://github.com/docker/docker/pull/21945)
* API now returns a JSON object when an error occurs making it more consistent [#22880](https://github.com/docker/docker/pull/22880)
- Prevent `docker run -i --restart` from hanging on exit [#22777](https://github.com/docker/docker/pull/22777)
- Fix API/CLI discrepancy on hostname validation [#21641](https://github.com/docker/docker/pull/21641)
- Fix discrepancy in the format of sizes in `stats` from HumanSize to BytesSize [#21773](https://github.com/docker/docker/pull/21773)
- authz: when request is denied return forbbiden exit code (403) [#22448](https://github.com/docker/docker/pull/22448)
### Runtime
+ Add `--live-restore` daemon flag to keep containers running when daemon shuts down, and regain control on startup [#23213](https://github.com/docker/docker/pull/23213)
+ Ability to add OCI-compatible runtimes (via `--add-runtime` daemon flag) and select one with `--runtime` on `create` and `run` [#22983](https://github.com/docker/docker/pull/22983)
+ New `overlay2` graphdriver for Linux 4.0+ with multiple lower directory support [#22126](https://github.com/docker/docker/pull/22126)
+ New load/save image events [#22137](https://github.com/docker/docker/pull/22137)
+ Add support for reloading daemon configuration through systemd [#22446](https://github.com/docker/docker/pull/22446)
+ Add disk quota support for btrfs [#19651](https://github.com/docker/docker/pull/19651)
+ Add disk quota support for zfs [#21946](https://github.com/docker/docker/pull/21946)
+ Add support for `docker run --pid=container:<id>` [#22481](https://github.com/docker/docker/pull/22481)
+ Align default seccomp profile with selected capabilities [#22554](https://github.com/docker/docker/pull/22554)
+ Add a `daemon reload` event when the daemon reloads its configuration [#22590](https://github.com/docker/docker/pull/22590)
+ Add `trace` capability in the pprof profiler to show execution traces in binary form [#22715](https://github.com/docker/docker/pull/22715)
+ Add a `detach` event [#22898](https://github.com/docker/docker/pull/22898)
+ Add support for setting sysctls with `--sysctl` [#19265](https://github.com/docker/docker/pull/19265)
+ Add `--storage-opt` flag to `create` and `run` allowing to set `size` on devicemapper [#19367](https://github.com/docker/docker/pull/19367)
* Undeprecate the `-c` short alias of `--cpu-shares` on `run`, `build`, `create`, `update` [#22621](https://github.com/docker/docker/pull/22621)
* Prevent from using aufs and overlay graphdrivers on an eCryptfs mount [#23121](https://github.com/docker/docker/pull/23121)
- Fix issues with tmpfs mount ordering [#22329](https://github.com/docker/docker/pull/22329)
- Created containers are no longer listed on `docker ps -a -f exited=0` [#21947](https://github.com/docker/docker/pull/21947)
- Fix an issue where containers are stuck in a "Removal In Progress" state [#22423](https://github.com/docker/docker/pull/22423)
- Fix bug that was returning an HTTP 500 instead of a 400 when not specifying a command on run/create [#22762](https://github.com/docker/docker/pull/22762)
- Fix bug with `--detach-keys` whereby input matching a prefix of the detach key was not preserved [#22943](https://github.com/docker/docker/pull/22943)
- SELinux labeling is now disabled when using `--privileged` mode [#22993](https://github.com/docker/docker/pull/22993)
- If volume-mounted into a container, `/etc/hosts`, `/etc/resolv.conf`, `/etc/hostname` are no longer SELinux-relabeled [#22993](https://github.com/docker/docker/pull/22993)
- Fix inconsistency in `--tmpfs` behavior regarding mount options [#22438](https://github.com/docker/docker/pull/22438)
- Fix an issue where daemon hangs at startup [#23148](https://github.com/docker/docker/pull/23148)
- Ignore SIGPIPE events to prevent journald restarts to crash docker in some cases [#22460](https://github.com/docker/docker/pull/22460)
- Containers are not removed from stats list on error [#20835](https://github.com/docker/docker/pull/20835)
- Fix `on-failure` restart policy when daemon restarts [#20853](https://github.com/docker/docker/pull/20853)
- Fix an issue with `stats` when a container is using another container's network [#21904](https://github.com/docker/docker/pull/21904)
### Swarm Mode
+ New `swarm` command to manage swarms with `init`, `join`, `leave`, `update` subcommands [#23361](https://github.com/docker/docker/pull/23361)
+ New `service` command to manage swarm-wide services with `create`, `inspect`, `update`, `remove`, `tasks` subcommands [#23361](https://github.com/docker/docker/pull/23361)
+ New `node` command to manage nodes with `accept`, `promote`, `demote`, `inspect`, `update`, `tasks`, `ls` and `rm` subcommands [#23361](https://github.com/docker/docker/pull/23361)
+ (experimental) New `stack` and `deploy` commands to manage and deploy multi-service applications [#23522](https://github.com/docker/docker/pull/23522)
### Volume
+ Add support for local and global volume scopes (analogous to network scopes) [#22077](https://github.com/docker/docker/pull/22077)
+ Allow volume drivers to provide a `Status` field [#21006](https://github.com/docker/docker/pull/21006)
+ Add name/driver filter support for volume [#21361](https://github.com/docker/docker/pull/21361)
* Mount/Unmount operations now receives an opaque ID to allow volume drivers to differentiate between two callers [#21015](https://github.com/docker/docker/pull/21015)
- Fix issue preventing to remove a volume in a corner case [#22103](https://github.com/docker/docker/pull/22103)
- Windows: Enable auto-creation of host-path to match Linux [#22094](https://github.com/docker/docker/pull/22094)
### DEPRECATION
* Environment variables `DOCKER_CONTENT_TRUST_OFFLINE_PASSPHRASE` and `DOCKER_CONTENT_TRUST_TAGGING_PASSPHRASE` have been renamed
to `DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE` and `DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE` respectively [#22574](https://github.com/docker/docker/pull/22574)
* Remove deprecated `syslog-tag`, `gelf-tag`, `fluentd-tag` log option in favor of the more generic `tag` one [#22620](https://github.com/docker/docker/pull/22620)
* Remove deprecated feature of passing HostConfig at API container start [#22570](https://github.com/docker/docker/pull/22570)
* Remove deprecated `-f`/`--force` flag on docker tag [#23090](https://github.com/docker/docker/pull/23090)
* Remove deprecated `/containers/<id|name>/copy` endpoint [#22149](https://github.com/docker/docker/pull/22149)
* Remove deprecated `docker ps` flags `--since` and `--before` [#22138](https://github.com/docker/docker/pull/22138)
* Deprecate the old 3-args form of `docker import` [#23273](https://github.com/docker/docker/pull/23273)
## 1.11.2 (2016-05-31)
### Networking
@@ -116,7 +243,7 @@ be found.
### Misc
+ When saving linked images together with `docker save` a subsequent `docker load` will correctly restore their parent/child relationship ([#21385](https://github.com/docker/docker/pull/c))
+ When saving linked images together with `docker save` a subsequent `docker load` will correctly restore their parent/child relationship ([#21385](https://github.com/docker/docker/pull/21385))
+ Support for building the Docker cli for OpenBSD was added ([#21325](https://github.com/docker/docker/pull/21325))
+ Labels can now be applied at network, volume and image creation ([#21270](https://github.com/docker/docker/pull/21270))
* The `dockremap` is now created as a system user ([#21266](https://github.com/docker/docker/pull/21266))

View File

@@ -233,10 +233,10 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT 5ce88a95f6cf218ba7f3309562f95464a968e890
ENV RUNC_COMMIT cc29e3dded8e27ba8f65738f40d251c885030a28
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/crosbymichael/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \

View File

@@ -180,10 +180,10 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT 5ce88a95f6cf218ba7f3309562f95464a968e890
ENV RUNC_COMMIT cc29e3dded8e27ba8f65738f40d251c885030a28
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/crosbymichael/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \

View File

@@ -189,10 +189,10 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT 5ce88a95f6cf218ba7f3309562f95464a968e890
ENV RUNC_COMMIT cc29e3dded8e27ba8f65738f40d251c885030a28
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/crosbymichael/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \

View File

@@ -74,10 +74,10 @@ WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
# Install runc
ENV RUNC_COMMIT 5ce88a95f6cf218ba7f3309562f95464a968e890
ENV RUNC_COMMIT cc29e3dded8e27ba8f65738f40d251c885030a28
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/crosbymichael/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \

View File

@@ -204,10 +204,10 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT 5ce88a95f6cf218ba7f3309562f95464a968e890
ENV RUNC_COMMIT cc29e3dded8e27ba8f65738f40d251c885030a28
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/crosbymichael/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="apparmor seccomp selinux" \

View File

@@ -161,7 +161,7 @@ RUN useradd --create-home --gid docker unprivilegeduser
VOLUME /var/lib/docker
WORKDIR /go/src/github.com/docker/docker
ENV DOCKER_BUILDTAGS apparmor selinux
ENV DOCKER_BUILDTAGS apparmor selinux seccomp
# Let us use a .bashrc file
RUN ln -sfv $PWD/.bashrc ~/.bashrc
@@ -197,10 +197,10 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install runc
ENV RUNC_COMMIT 5ce88a95f6cf218ba7f3309562f95464a968e890
ENV RUNC_COMMIT cc29e3dded8e27ba8f65738f40d251c885030a28
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/crosbymichael/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \

View File

@@ -57,10 +57,10 @@ ENV GOPATH /go:/go/src/github.com/docker/docker/vendor
ENV CGO_LDFLAGS -L/lib
# Install runc
ENV RUNC_COMMIT 5ce88a95f6cf218ba7f3309562f95464a968e890
ENV RUNC_COMMIT cc29e3dded8e27ba8f65738f40d251c885030a28
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/crosbymichael/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
&& cd "$GOPATH/src/github.com/opencontainers/runc" \
&& git checkout -q "$RUNC_COMMIT" \
&& make static BUILDTAGS="seccomp apparmor selinux" \

View File

@@ -1 +1 @@
1.12.0-dev
1.12.0-rc2

View File

@@ -4,8 +4,8 @@ package bundlefile
import (
"encoding/json"
"fmt"
"io"
"os"
)
// Bundlefile stores the contents of a bundlefile
@@ -34,19 +34,28 @@ type Port struct {
}
// LoadFile loads a bundlefile from a path to the file
func LoadFile(path string) (*Bundlefile, error) {
reader, err := os.Open(path)
if err != nil {
return nil, err
}
func LoadFile(reader io.Reader) (*Bundlefile, error) {
bundlefile := &Bundlefile{}
if err := json.NewDecoder(reader).Decode(bundlefile); err != nil {
decoder := json.NewDecoder(reader)
if err := decoder.Decode(bundlefile); err != nil {
switch jsonErr := err.(type) {
case *json.SyntaxError:
return nil, fmt.Errorf(
"JSON syntax error at byte %v: %s",
jsonErr.Offset,
jsonErr.Error())
case *json.UnmarshalTypeError:
return nil, fmt.Errorf(
"Unexpected type at byte %v. Expected %s but received %s.",
jsonErr.Offset,
jsonErr.Type,
jsonErr.Value)
}
return nil, err
}
return bundlefile, err
return bundlefile, nil
}
// Print writes the contents of the bundlefile to the output writer

View File

@@ -0,0 +1,79 @@
// +build experimental
package bundlefile
import (
"bytes"
"strings"
"testing"
"github.com/docker/docker/pkg/testutil/assert"
)
func TestLoadFileV01Success(t *testing.T) {
reader := strings.NewReader(`{
"Version": "0.1",
"Services": {
"redis": {
"Image": "redis@sha256:4b24131101fa0117bcaa18ac37055fffd9176aa1a240392bb8ea85e0be50f2ce",
"Networks": ["default"]
},
"web": {
"Image": "dockercloud/hello-world@sha256:fe79a2cfbd17eefc344fb8419420808df95a1e22d93b7f621a7399fd1e9dca1d",
"Networks": ["default"],
"User": "web"
}
}
}`)
bundle, err := LoadFile(reader)
assert.NilError(t, err)
assert.Equal(t, bundle.Version, "0.1")
assert.Equal(t, len(bundle.Services), 2)
}
func TestLoadFileSyntaxError(t *testing.T) {
reader := strings.NewReader(`{
"Version": "0.1",
"Services": unquoted string
}`)
_, err := LoadFile(reader)
assert.Error(t, err, "syntax error at byte 37: invalid character 'u'")
}
func TestLoadFileTypeError(t *testing.T) {
reader := strings.NewReader(`{
"Version": "0.1",
"Services": {
"web": {
"Image": "redis",
"Networks": "none"
}
}
}`)
_, err := LoadFile(reader)
assert.Error(t, err, "Unexpected type at byte 94. Expected []string but received string")
}
func TestPrint(t *testing.T) {
var buffer bytes.Buffer
bundle := &Bundlefile{
Version: "0.1",
Services: map[string]Service{
"web": {
Image: "image",
Command: []string{"echo", "something"},
},
},
}
assert.NilError(t, Print(&buffer, bundle))
output := buffer.String()
assert.Contains(t, output, "\"Image\": \"image\"")
assert.Contains(t, output,
`"Command": [
"echo",
"something"
]`)
}

View File

@@ -41,7 +41,8 @@ func runRestart(dockerCli *client.DockerCli, opts *restartOptions) error {
ctx := context.Background()
var errs []string
for _, name := range opts.containers {
if err := dockerCli.Client().ContainerRestart(ctx, name, time.Duration(opts.nSeconds)*time.Second); err != nil {
timeout := time.Duration(opts.nSeconds) * time.Second
if err := dockerCli.Client().ContainerRestart(ctx, name, &timeout); err != nil {
errs = append(errs, err.Error())
} else {
fmt.Fprintf(dockerCli.Out(), "%s\n", name)

View File

@@ -43,7 +43,8 @@ func runStop(dockerCli *client.DockerCli, opts *stopOptions) error {
var errs []string
for _, container := range opts.containers {
if err := dockerCli.Client().ContainerStop(ctx, container, time.Duration(opts.time)*time.Second); err != nil {
timeout := time.Duration(opts.time) * time.Second
if err := dockerCli.Client().ContainerStop(ctx, container, &timeout); err != nil {
errs = append(errs, err.Error())
} else {
fmt.Fprintf(dockerCli.Out(), "%s\n", container)

View File

@@ -155,6 +155,10 @@ func (ctx ContainerContext) Write() {
ctx.postformat(tmpl, &containerContext{})
}
func isDangling(image types.Image) bool {
return len(image.RepoTags) == 1 && image.RepoTags[0] == "<none>:<none>" && len(image.RepoDigests) == 1 && image.RepoDigests[0] == "<none>@<none>"
}
func (ctx ImageContext) Write() {
switch ctx.Format {
case tableFormatKey:
@@ -200,42 +204,98 @@ virtual_size: {{.Size}}
}
for _, image := range ctx.Images {
images := []*imageContext{}
if isDangling(image) {
images = append(images, &imageContext{
trunc: ctx.Trunc,
i: image,
repo: "<none>",
tag: "<none>",
digest: "<none>",
})
} else {
repoTags := map[string][]string{}
repoDigests := map[string][]string{}
repoTags := image.RepoTags
repoDigests := image.RepoDigests
if len(repoTags) == 1 && repoTags[0] == "<none>:<none>" && len(repoDigests) == 1 && repoDigests[0] == "<none>@<none>" {
// dangling image - clear out either repoTags or repoDigests so we only show it once below
repoDigests = []string{}
}
// combine the tags and digests lists
tagsAndDigests := append(repoTags, repoDigests...)
for _, repoAndRef := range tagsAndDigests {
repo := "<none>"
tag := "<none>"
digest := "<none>"
if !strings.HasPrefix(repoAndRef, "<none>") {
ref, err := reference.ParseNamed(repoAndRef)
for _, refString := range append(image.RepoTags) {
ref, err := reference.ParseNamed(refString)
if err != nil {
continue
}
repo = ref.Name()
switch x := ref.(type) {
case reference.Canonical:
digest = x.Digest().String()
case reference.NamedTagged:
tag = x.Tag()
if nt, ok := ref.(reference.NamedTagged); ok {
repoTags[ref.Name()] = append(repoTags[ref.Name()], nt.Tag())
}
}
imageCtx := &imageContext{
trunc: ctx.Trunc,
i: image,
repo: repo,
tag: tag,
digest: digest,
for _, refString := range append(image.RepoDigests) {
ref, err := reference.ParseNamed(refString)
if err != nil {
continue
}
if c, ok := ref.(reference.Canonical); ok {
repoDigests[ref.Name()] = append(repoDigests[ref.Name()], c.Digest().String())
}
}
for repo, tags := range repoTags {
digests := repoDigests[repo]
// Do not display digests as their own row
delete(repoDigests, repo)
if !ctx.Digest {
// Ignore digest references, just show tag once
digests = nil
}
for _, tag := range tags {
if len(digests) == 0 {
images = append(images, &imageContext{
trunc: ctx.Trunc,
i: image,
repo: repo,
tag: tag,
digest: "<none>",
})
continue
}
// Display the digests for each tag
for _, dgst := range digests {
images = append(images, &imageContext{
trunc: ctx.Trunc,
i: image,
repo: repo,
tag: tag,
digest: dgst,
})
}
}
}
// Show rows for remaining digest only references
for repo, digests := range repoDigests {
// If digests are displayed, show row per digest
if ctx.Digest {
for _, dgst := range digests {
images = append(images, &imageContext{
trunc: ctx.Trunc,
i: image,
repo: repo,
tag: "<none>",
digest: dgst,
})
}
} else {
images = append(images, &imageContext{
trunc: ctx.Trunc,
i: image,
repo: repo,
tag: "<none>",
})
}
}
}
for _, imageCtx := range images {
err = ctx.contextFormat(tmpl, imageCtx)
if err != nil {
return

View File

@@ -301,7 +301,6 @@ func TestImageContextWrite(t *testing.T) {
},
`REPOSITORY TAG IMAGE ID CREATED SIZE
image tag1 imageID1 24 hours ago 0 B
image <none> imageID1 24 hours ago 0 B
image tag2 imageID2 24 hours ago 0 B
<none> <none> imageID3 24 hours ago 0 B
`,
@@ -312,7 +311,7 @@ image tag2 imageID2 24 hours ago
Format: "table {{.Repository}}",
},
},
"REPOSITORY\nimage\nimage\nimage\n<none>\n",
"REPOSITORY\nimage\nimage\n<none>\n",
},
{
ImageContext{
@@ -322,7 +321,6 @@ image tag2 imageID2 24 hours ago
Digest: true,
},
`REPOSITORY DIGEST
image <none>
image sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
image <none>
<none> <none>
@@ -335,7 +333,7 @@ image <none>
Quiet: true,
},
},
"REPOSITORY\nimage\nimage\nimage\n<none>\n",
"REPOSITORY\nimage\nimage\n<none>\n",
},
{
ImageContext{
@@ -344,7 +342,7 @@ image <none>
Quiet: true,
},
},
"imageID1\nimageID1\nimageID2\nimageID3\n",
"imageID1\nimageID2\nimageID3\n",
},
{
ImageContext{
@@ -355,8 +353,7 @@ image <none>
Digest: true,
},
`REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
image tag1 <none> imageID1 24 hours ago 0 B
image <none> sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf imageID1 24 hours ago 0 B
image tag1 sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf imageID1 24 hours ago 0 B
image tag2 <none> imageID2 24 hours ago 0 B
<none> <none> <none> imageID3 24 hours ago 0 B
`,
@@ -369,7 +366,7 @@ image tag2 <none>
},
Digest: true,
},
"imageID1\nimageID1\nimageID2\nimageID3\n",
"imageID1\nimageID2\nimageID3\n",
},
// Raw Format
{
@@ -384,12 +381,6 @@ image_id: imageID1
created_at: %s
virtual_size: 0 B
repository: image
tag: <none>
image_id: imageID1
created_at: %s
virtual_size: 0 B
repository: image
tag: tag2
image_id: imageID2
@@ -402,7 +393,7 @@ image_id: imageID3
created_at: %s
virtual_size: 0 B
`, expectedTime, expectedTime, expectedTime, expectedTime),
`, expectedTime, expectedTime, expectedTime),
},
{
ImageContext{
@@ -413,13 +404,6 @@ virtual_size: 0 B
},
fmt.Sprintf(`repository: image
tag: tag1
digest: <none>
image_id: imageID1
created_at: %s
virtual_size: 0 B
repository: image
tag: <none>
digest: sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
image_id: imageID1
created_at: %s
@@ -439,7 +423,7 @@ image_id: imageID3
created_at: %s
virtual_size: 0 B
`, expectedTime, expectedTime, expectedTime, expectedTime),
`, expectedTime, expectedTime, expectedTime),
},
{
ImageContext{
@@ -449,7 +433,6 @@ virtual_size: 0 B
},
},
`image_id: imageID1
image_id: imageID1
image_id: imageID2
image_id: imageID3
`,
@@ -461,7 +444,7 @@ image_id: imageID3
Format: "{{.Repository}}",
},
},
"image\nimage\nimage\n<none>\n",
"image\nimage\n<none>\n",
},
{
ImageContext{
@@ -470,7 +453,7 @@ image_id: imageID3
},
Digest: true,
},
"image\nimage\nimage\n<none>\n",
"image\nimage\n<none>\n",
},
}

View File

@@ -40,7 +40,7 @@ func (r *IDResolver) get(ctx context.Context, t interface{}, id string) (string,
}
return id, nil
case swarm.Service:
service, err := r.client.ServiceInspect(ctx, id)
service, _, err := r.client.ServiceInspectWithRaw(ctx, id)
if err != nil {
return id, nil
}

View File

@@ -94,6 +94,10 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, "Default Runtime: %s\n", info.DefaultRuntime)
}
fmt.Fprintf(cli.out, "Security Options:")
ioutils.FprintfIfNotEmpty(cli.out, " %s", strings.Join(info.SecurityOptions, " "))
fmt.Fprintf(cli.out, "\n")
ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion)
ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem)
ioutils.FprintfIfNotEmpty(cli.out, "OSType: %s\n", info.OSType)

View File

@@ -33,7 +33,7 @@ func runAccept(dockerCli *client.DockerCli, flags *pflag.FlagSet, args []string)
}); err != nil {
return err
}
fmt.Println(id, "attempting to accept a node in the swarm.")
fmt.Fprintf(dockerCli.Out(), "Node %s accepted in the swarm.\n", id)
}
return nil

View File

@@ -33,7 +33,7 @@ func runDemote(dockerCli *client.DockerCli, flags *pflag.FlagSet, args []string)
}); err != nil {
return err
}
fmt.Println(id, "attempting to demote a manager in the swarm.")
fmt.Fprintf(dockerCli.Out(), "Manager %s demoted in the swarm.\n", id)
}
return nil

View File

@@ -16,7 +16,7 @@ import (
)
const (
listItemFmt = "%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
listItemFmt = "%s\t%s\t%s\t%s\t%s\t%s\n"
)
type listOptions struct {
@@ -74,7 +74,7 @@ func printTable(out io.Writer, nodes []swarm.Node, info types.Info) {
// Ignore flushing errors
defer writer.Flush()
fmt.Fprintf(writer, listItemFmt, "ID", "NAME", "MEMBERSHIP", "STATUS", "AVAILABILITY", "MANAGER STATUS", "LEADER")
fmt.Fprintf(writer, listItemFmt, "ID", "NAME", "MEMBERSHIP", "STATUS", "AVAILABILITY", "MANAGER STATUS")
for _, node := range nodes {
name := node.Spec.Name
availability := string(node.Spec.Availability)
@@ -84,14 +84,13 @@ func printTable(out io.Writer, nodes []swarm.Node, info types.Info) {
name = node.Description.Hostname
}
leader := ""
if node.ManagerStatus != nil && node.ManagerStatus.Leader {
leader = "Yes"
}
reachability := ""
if node.ManagerStatus != nil {
reachability = string(node.ManagerStatus.Reachability)
if node.ManagerStatus.Leader {
reachability = "Leader"
} else {
reachability = string(node.ManagerStatus.Reachability)
}
}
ID := node.ID
@@ -107,8 +106,7 @@ func printTable(out io.Writer, nodes []swarm.Node, info types.Info) {
client.PrettyPrint(membership),
client.PrettyPrint(string(node.Status.State)),
client.PrettyPrint(availability),
client.PrettyPrint(reachability),
leader)
client.PrettyPrint(reachability))
}
}

View File

@@ -33,7 +33,7 @@ func runPromote(dockerCli *client.DockerCli, flags *pflag.FlagSet, args []string
}); err != nil {
return err
}
fmt.Println(id, "attempting to promote a node to a manager in the swarm.")
fmt.Fprintf(dockerCli.Out(), "Node %s promoted to a manager in the swarm.\n", id)
}
return nil

View File

@@ -21,7 +21,11 @@ func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
Short: "Update a node",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runUpdate(dockerCli, args[0], mergeNodeUpdate(flags))
if err := runUpdate(dockerCli, args[0], mergeNodeUpdate(flags)); err != nil {
return err
}
fmt.Fprintln(dockerCli.Out(), args[0])
return nil
},
}
@@ -47,7 +51,6 @@ func runUpdate(dockerCli *client.DockerCli, nodeID string, mergeNode func(node *
return err
}
fmt.Fprintf(dockerCli.Out(), "%s\n", nodeID)
return nil
}

View File

@@ -3,21 +3,39 @@
package plugin
import (
"fmt"
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/reference"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
func newDisableCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "disable",
Use: "disable PLUGIN",
Short: "Disable a plugin",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return dockerCli.Client().PluginDisable(context.Background(), args[0])
return runDisable(dockerCli, args[0])
},
}
return cmd
}
func runDisable(dockerCli *client.DockerCli, name string) error {
named, err := reference.ParseNamed(name) // FIXME: validate
if err != nil {
return err
}
if reference.IsNameOnly(named) {
named = reference.WithDefaultTag(named)
}
ref, ok := named.(reference.NamedTagged)
if !ok {
return fmt.Errorf("invalid name: %s", named.String())
}
return dockerCli.Client().PluginDisable(context.Background(), ref.String())
}

View File

@@ -3,21 +3,39 @@
package plugin
import (
"fmt"
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/reference"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
func newEnableCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "enable",
Use: "enable PLUGIN",
Short: "Enable a plugin",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return dockerCli.Client().PluginEnable(context.Background(), args[0])
return runEnable(dockerCli, args[0])
},
}
return cmd
}
func runEnable(dockerCli *client.DockerCli, name string) error {
named, err := reference.ParseNamed(name) // FIXME: validate
if err != nil {
return err
}
if reference.IsNameOnly(named) {
named = reference.WithDefaultTag(named)
}
ref, ok := named.(reference.NamedTagged)
if !ok {
return fmt.Errorf("invalid name: %s", named.String())
}
return dockerCli.Client().PluginEnable(context.Background(), ref.String())
}

View File

@@ -4,16 +4,18 @@ package plugin
import (
"encoding/json"
"fmt"
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/reference"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
func newInspectCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "inspect",
Use: "inspect PLUGIN",
Short: "Inspect a plugin",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
@@ -25,7 +27,18 @@ func newInspectCommand(dockerCli *client.DockerCli) *cobra.Command {
}
func runInspect(dockerCli *client.DockerCli, name string) error {
p, err := dockerCli.Client().PluginInspect(context.Background(), name)
named, err := reference.ParseNamed(name) // FIXME: validate
if err != nil {
return err
}
if reference.IsNameOnly(named) {
named = reference.WithDefaultTag(named)
}
ref, ok := named.(reference.NamedTagged)
if !ok {
return fmt.Errorf("invalid name: %s", named.String())
}
p, err := dockerCli.Client().PluginInspect(context.Background(), ref.String())
if err != nil {
return err
}

View File

@@ -3,35 +3,52 @@
package plugin
import (
"bufio"
"fmt"
"strings"
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/reference"
"github.com/docker/docker/registry"
"github.com/docker/engine-api/types"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
type pluginOptions struct {
name string
grantPerms bool
disable bool
}
func newInstallCommand(dockerCli *client.DockerCli) *cobra.Command {
var options pluginOptions
cmd := &cobra.Command{
Use: "install",
Use: "install PLUGIN",
Short: "Install a plugin",
Args: cli.RequiresMinArgs(1), // TODO: allow for set args
RunE: func(cmd *cobra.Command, args []string) error {
return runInstall(dockerCli, args[0], args[1:])
options.name = args[0]
return runInstall(dockerCli, options)
},
}
flags := cmd.Flags()
flags.BoolVar(&options.grantPerms, "grant-all-permissions", false, "grant all permissions necessary to run the plugin")
flags.BoolVar(&options.disable, "disable", false, "do not enable the plugin on install")
return cmd
}
func runInstall(dockerCli *client.DockerCli, name string, args []string) error {
named, err := reference.ParseNamed(name) // FIXME: validate
func runInstall(dockerCli *client.DockerCli, opts pluginOptions) error {
named, err := reference.ParseNamed(opts.name) // FIXME: validate
if err != nil {
return err
}
named = reference.WithDefaultTag(named)
if reference.IsNameOnly(named) {
named = reference.WithDefaultTag(named)
}
ref, ok := named.(reference.NamedTagged)
if !ok {
return fmt.Errorf("invalid name: %s", named.String())
@@ -46,6 +63,34 @@ func runInstall(dockerCli *client.DockerCli, name string, args []string) error {
if err != nil {
return err
}
// TODO: pass acceptAllPermissions and noEnable flag
return dockerCli.Client().PluginInstall(ctx, ref.String(), encodedAuth, false, false, dockerCli.In(), dockerCli.Out())
registryAuthFunc := dockerCli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "plugin install")
options := types.PluginInstallOptions{
RegistryAuth: encodedAuth,
Disabled: opts.disable,
AcceptAllPermissions: opts.grantPerms,
AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.name),
// TODO: Rename PrivilegeFunc, it has nothing to do with privileges
PrivilegeFunc: registryAuthFunc,
}
return dockerCli.Client().PluginInstall(ctx, ref.String(), options)
}
func acceptPrivileges(dockerCli *client.DockerCli, name string) func(privileges types.PluginPrivileges) (bool, error) {
return func(privileges types.PluginPrivileges) (bool, error) {
fmt.Fprintf(dockerCli.Out(), "Plugin %q is requesting the following privileges:\n", name)
for _, privilege := range privileges {
fmt.Fprintf(dockerCli.Out(), " - %s: %v\n", privilege.Name, privilege.Value)
}
fmt.Fprint(dockerCli.Out(), "Do you grant the above permissions? [y/N] ")
reader := bufio.NewReader(dockerCli.In())
line, _, err := reader.ReadLine()
if err != nil {
return false, err
}
return strings.ToLower(string(line)) == "y", nil
}
}

View File

@@ -16,7 +16,7 @@ import (
func newPushCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "push",
Use: "push PLUGIN",
Short: "Push a plugin",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
@@ -31,7 +31,9 @@ func runPush(dockerCli *client.DockerCli, name string) error {
if err != nil {
return err
}
named = reference.WithDefaultTag(named)
if reference.IsNameOnly(named) {
named = reference.WithDefaultTag(named)
}
ref, ok := named.(reference.NamedTagged)
if !ok {
return fmt.Errorf("invalid name: %s", named.String())

View File

@@ -7,13 +7,14 @@ import (
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/reference"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
func newRemoveCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "rm",
Use: "rm PLUGIN",
Short: "Remove a plugin",
Aliases: []string{"remove"},
Args: cli.RequiresMinArgs(1),
@@ -28,8 +29,19 @@ func newRemoveCommand(dockerCli *client.DockerCli) *cobra.Command {
func runRemove(dockerCli *client.DockerCli, names []string) error {
var errs cli.Errors
for _, name := range names {
named, err := reference.ParseNamed(name) // FIXME: validate
if err != nil {
return err
}
if reference.IsNameOnly(named) {
named = reference.WithDefaultTag(named)
}
ref, ok := named.(reference.NamedTagged)
if !ok {
return fmt.Errorf("invalid name: %s", named.String())
}
// TODO: pass names to api instead of making multiple api calls
if err := dockerCli.Client().PluginRemove(context.Background(), name); err != nil {
if err := dockerCli.Client().PluginRemove(context.Background(), ref.String()); err != nil {
errs = append(errs, err)
continue
}

View File

@@ -3,16 +3,19 @@
package plugin
import (
"fmt"
"golang.org/x/net/context"
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/reference"
"github.com/spf13/cobra"
)
func newSetCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "set",
Use: "set PLUGIN key1=value1 [key2=value2...]",
Short: "Change settings for a plugin",
Args: cli.RequiresMinArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
@@ -24,5 +27,16 @@ func newSetCommand(dockerCli *client.DockerCli) *cobra.Command {
}
func runSet(dockerCli *client.DockerCli, name string, args []string) error {
return dockerCli.Client().PluginSet(context.Background(), name, args)
named, err := reference.ParseNamed(name) // FIXME: validate
if err != nil {
return err
}
if reference.IsNameOnly(named) {
named = reference.WithDefaultTag(named)
}
ref, ok := named.(reference.NamedTagged)
if !ok {
return fmt.Errorf("invalid name: %s", named.String())
}
return dockerCli.Client().PluginSet(context.Background(), ref.String(), args)
}

View File

@@ -13,6 +13,7 @@ import (
"github.com/docker/docker/pkg/ioutils"
apiclient "github.com/docker/engine-api/client"
"github.com/docker/engine-api/types/swarm"
"github.com/docker/go-units"
"github.com/spf13/cobra"
)
@@ -50,7 +51,7 @@ func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
ctx := context.Background()
getRef := func(ref string) (interface{}, []byte, error) {
service, err := client.ServiceInspect(ctx, ref)
service, _, err := client.ServiceInspectWithRaw(ctx, ref)
if err == nil || !apiclient.IsErrServiceNotFound(err) {
return service, nil, err
}
@@ -93,22 +94,61 @@ func printService(out io.Writer, service swarm.Service) {
}
if service.Spec.Mode.Global != nil {
fmt.Fprintln(out, "Mode:\t\tGLOBAL")
fmt.Fprintln(out, "Mode:\t\tGlobal")
} else {
fmt.Fprintln(out, "Mode:\t\tREPLICATED")
fmt.Fprintln(out, "Mode:\t\tReplicated")
if service.Spec.Mode.Replicated.Replicas != nil {
fmt.Fprintf(out, " Replicas:\t\t%d\n", *service.Spec.Mode.Replicated.Replicas)
fmt.Fprintf(out, " Replicas:\t%d\n", *service.Spec.Mode.Replicated.Replicas)
}
}
fmt.Fprintln(out, "Placement:")
fmt.Fprintln(out, " Strategy:\tSPREAD")
fmt.Fprintf(out, "UpateConfig:\n")
fmt.Fprintln(out, " Strategy:\tSpread")
if service.Spec.TaskTemplate.Placement != nil && len(service.Spec.TaskTemplate.Placement.Constraints) > 0 {
ioutils.FprintfIfNotEmpty(out, " Constraints\t: %s\n", strings.Join(service.Spec.TaskTemplate.Placement.Constraints, ", "))
}
fmt.Fprintf(out, "UpdateConfig:\n")
fmt.Fprintf(out, " Parallelism:\t%d\n", service.Spec.UpdateConfig.Parallelism)
if service.Spec.UpdateConfig.Delay.Nanoseconds() > 0 {
fmt.Fprintf(out, " Delay:\t\t%s\n", service.Spec.UpdateConfig.Delay)
}
fmt.Fprintf(out, "ContainerSpec:\n")
printContainerSpec(out, service.Spec.TaskTemplate.ContainerSpec)
if service.Spec.TaskTemplate.Resources != nil {
fmt.Fprintln(out, "Resources:")
printResources := func(out io.Writer, r *swarm.Resources) {
if r.NanoCPUs != 0 {
fmt.Fprintf(out, " CPU:\t\t%g\n", float64(r.NanoCPUs)/1e9)
}
if r.MemoryBytes != 0 {
fmt.Fprintf(out, " Memory:\t\t%s\n", units.BytesSize(float64(r.MemoryBytes)))
}
}
if service.Spec.TaskTemplate.Resources.Reservations != nil {
fmt.Fprintln(out, "Reservations:")
printResources(out, service.Spec.TaskTemplate.Resources.Reservations)
}
if service.Spec.TaskTemplate.Resources.Limits != nil {
fmt.Fprintln(out, "Limits:")
printResources(out, service.Spec.TaskTemplate.Resources.Limits)
}
}
if len(service.Spec.Networks) > 0 {
fmt.Fprintf(out, "Networks:")
for _, n := range service.Spec.Networks {
fmt.Fprintf(out, " %s", n.Target)
}
}
if len(service.Endpoint.Ports) > 0 {
fmt.Fprintln(out, "Ports:")
for _, port := range service.Endpoint.Ports {
fmt.Fprintf(out, " Name = %s\n", port.Name)
fmt.Fprintf(out, " Protocol = %s\n", port.Protocol)
fmt.Fprintf(out, " TargetPort = %d\n", port.TargetPort)
fmt.Fprintf(out, " PublishedPort = %d\n", port.PublishedPort)
}
}
}
func printContainerSpec(out io.Writer, containerSpec swarm.ContainerSpec) {
@@ -117,11 +157,20 @@ func printContainerSpec(out io.Writer, containerSpec swarm.ContainerSpec) {
fmt.Fprintf(out, " Command:\t%s\n", strings.Join(containerSpec.Command, " "))
}
if len(containerSpec.Args) > 0 {
fmt.Fprintf(out, " Args:\t%s\n", strings.Join(containerSpec.Args, " "))
fmt.Fprintf(out, " Args:\t\t%s\n", strings.Join(containerSpec.Args, " "))
}
if len(containerSpec.Env) > 0 {
fmt.Fprintf(out, " Env:\t\t%s\n", strings.Join(containerSpec.Env, " "))
}
ioutils.FprintfIfNotEmpty(out, " Dir\t\t%s\n", containerSpec.Dir)
ioutils.FprintfIfNotEmpty(out, " User\t\t%s\n", containerSpec.User)
if len(containerSpec.Mounts) > 0 {
fmt.Fprintln(out, " Mounts:")
for _, v := range containerSpec.Mounts {
fmt.Fprintf(out, " Target = %s\n", v.Target)
fmt.Fprintf(out, " Source = %s\n", v.Source)
fmt.Fprintf(out, " Writable = %v\n", v.Writable)
fmt.Fprintf(out, " Type = %v\n", v.Type)
}
}
}

View File

@@ -6,15 +6,15 @@ import (
"strings"
"text/tabwriter"
"golang.org/x/net/context"
"github.com/docker/docker/api/client"
"github.com/docker/docker/cli"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
"github.com/docker/engine-api/types/swarm"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
const (
@@ -47,11 +47,10 @@ func newListCommand(dockerCli *client.DockerCli) *cobra.Command {
}
func runList(dockerCli *client.DockerCli, opts listOptions) error {
ctx := context.Background()
client := dockerCli.Client()
services, err := client.ServiceList(
context.Background(),
types.ServiceListOptions{Filter: opts.filter.Value()})
services, err := client.ServiceList(ctx, types.ServiceListOptions{Filter: opts.filter.Value()})
if err != nil {
return err
}
@@ -60,31 +59,48 @@ func runList(dockerCli *client.DockerCli, opts listOptions) error {
if opts.quiet {
printQuiet(out, services)
} else {
printTable(out, services)
taskFilter := filters.NewArgs()
for _, service := range services {
taskFilter.Add("service", service.ID)
}
tasks, err := client.TaskList(ctx, types.TaskListOptions{Filter: taskFilter})
if err != nil {
return err
}
running := map[string]int{}
for _, task := range tasks {
if task.Status.State == "running" {
running[task.ServiceID]++
}
}
printTable(out, services, running)
}
return nil
}
func printTable(out io.Writer, services []swarm.Service) {
func printTable(out io.Writer, services []swarm.Service, running map[string]int) {
writer := tabwriter.NewWriter(out, 0, 4, 2, ' ', 0)
// Ignore flushing errors
defer writer.Flush()
fmt.Fprintf(writer, listItemFmt, "ID", "NAME", "SCALE", "IMAGE", "COMMAND")
fmt.Fprintf(writer, listItemFmt, "ID", "NAME", "REPLICAS", "IMAGE", "COMMAND")
for _, service := range services {
scale := ""
replicas := ""
if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil {
scale = fmt.Sprintf("%d", *service.Spec.Mode.Replicated.Replicas)
replicas = fmt.Sprintf("%d/%d", running[service.ID], *service.Spec.Mode.Replicated.Replicas)
} else if service.Spec.Mode.Global != nil {
scale = "global"
replicas = "global"
}
fmt.Fprintf(
writer,
listItemFmt,
stringid.TruncateID(service.ID),
service.Spec.Name,
scale,
replicas,
service.Spec.TaskTemplate.ContainerSpec.Image,
strings.Join(service.Spec.TaskTemplate.ContainerSpec.Args, " "))
}

View File

@@ -28,7 +28,7 @@ type int64Value interface {
type memBytes int64
func (m *memBytes) String() string {
return strconv.FormatInt(m.Value(), 10)
return units.BytesSize(float64(m.Value()))
}
func (m *memBytes) Set(value string) error {
@@ -48,7 +48,7 @@ func (m *memBytes) Value() int64 {
type nanoCPUs int64
func (c *nanoCPUs) String() string {
return strconv.FormatInt(c.Value(), 10)
return big.NewRat(c.Value(), 1e9).FloatString(3)
}
func (c *nanoCPUs) Set(value string) error {
@@ -177,7 +177,7 @@ func (m *MountOpt) Set(value string) error {
}
if len(parts) != 2 {
return fmt.Errorf("invald field '%s' must be a key=value pair", field)
return fmt.Errorf("invalid field '%s' must be a key=value pair", field)
}
key, value := parts[0], parts[1]
@@ -191,14 +191,14 @@ func (m *MountOpt) Set(value string) error {
case "writable":
mount.Writable, err = strconv.ParseBool(value)
if err != nil {
return fmt.Errorf("invald value for writable: %s", err.Error())
return fmt.Errorf("invalid value for writable: %s", value)
}
case "bind-propagation":
mount.BindOptions.Propagation = swarm.MountPropagation(strings.ToUpper(value))
case "volume-populate":
volumeOptions().Populate, err = strconv.ParseBool(value)
if err != nil {
return fmt.Errorf("invald value for populate: %s", err.Error())
return fmt.Errorf("invalid value for populate: %s", value)
}
case "volume-label":
setValueOnMap(volumeOptions().Labels, value)
@@ -235,7 +235,8 @@ func (m *MountOpt) Type() string {
func (m *MountOpt) String() string {
mounts := []string{}
for _, mount := range m.values {
mounts = append(mounts, fmt.Sprintf("%v", mount))
repr := fmt.Sprintf("%s %s %s", mount.Type, mount.Source, mount.Target)
mounts = append(mounts, repr)
}
return strings.Join(mounts, ", ")
}
@@ -456,7 +457,7 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
flags.StringSliceVar(&opts.constraints, flagConstraint, []string{}, "Placement constraints")
flags.Uint64Var(&opts.update.parallelism, flagUpdateParallelism, 1, "Maximum number of tasks updated simultaneously")
flags.Uint64Var(&opts.update.parallelism, flagUpdateParallelism, 0, "Maximum number of tasks updated simultaneously")
flags.DurationVar(&opts.update.delay, flagUpdateDelay, time.Duration(0), "Delay between updates")
flags.StringSliceVar(&opts.networks, flagNetwork, []string{}, "Network attachments")

View File

@@ -0,0 +1,115 @@
package service
import (
"testing"
"time"
"github.com/docker/docker/pkg/testutil/assert"
"github.com/docker/engine-api/types/swarm"
)
func TestMemBytesString(t *testing.T) {
var mem memBytes = 1048576
assert.Equal(t, mem.String(), "1 MiB")
}
func TestMemBytesSetAndValue(t *testing.T) {
var mem memBytes
assert.NilError(t, mem.Set("5kb"))
assert.Equal(t, mem.Value(), int64(5120))
}
func TestNanoCPUsString(t *testing.T) {
var cpus nanoCPUs = 6100000000
assert.Equal(t, cpus.String(), "6.100")
}
func TestNanoCPUsSetAndValue(t *testing.T) {
var cpus nanoCPUs
assert.NilError(t, cpus.Set("0.35"))
assert.Equal(t, cpus.Value(), int64(350000000))
}
func TestDurationOptString(t *testing.T) {
dur := time.Duration(300 * 10e8)
duration := DurationOpt{value: &dur}
assert.Equal(t, duration.String(), "5m0s")
}
func TestDurationOptSetAndValue(t *testing.T) {
var duration DurationOpt
assert.NilError(t, duration.Set("300s"))
assert.Equal(t, *duration.Value(), time.Duration(300*10e8))
}
func TestUint64OptString(t *testing.T) {
value := uint64(2345678)
opt := Uint64Opt{value: &value}
assert.Equal(t, opt.String(), "2345678")
opt = Uint64Opt{}
assert.Equal(t, opt.String(), "none")
}
func TestUint64OptSetAndValue(t *testing.T) {
var opt Uint64Opt
assert.NilError(t, opt.Set("14445"))
assert.Equal(t, *opt.Value(), uint64(14445))
}
func TestMountOptString(t *testing.T) {
mount := MountOpt{
values: []swarm.Mount{
{
Type: swarm.MountType("BIND"),
Source: "/home/path",
Target: "/target",
},
{
Type: swarm.MountType("VOLUME"),
Source: "foo",
Target: "/target/foo",
},
},
}
expected := "BIND /home/path /target, VOLUME foo /target/foo"
assert.Equal(t, mount.String(), expected)
}
func TestMountOptSetNoError(t *testing.T) {
var mount MountOpt
assert.NilError(t, mount.Set("type=bind,target=/target,source=/foo"))
mounts := mount.Value()
assert.Equal(t, len(mounts), 1)
assert.Equal(t, mounts[0], swarm.Mount{
Type: swarm.MountType("BIND"),
Source: "/foo",
Target: "/target",
})
}
func TestMountOptSetErrorNoType(t *testing.T) {
var mount MountOpt
assert.Error(t, mount.Set("target=/target,source=/foo"), "type is required")
}
func TestMountOptSetErrorNoTarget(t *testing.T) {
var mount MountOpt
assert.Error(t, mount.Set("type=VOLUME,source=/foo"), "target is required")
}
func TestMountOptSetErrorInvalidKey(t *testing.T) {
var mount MountOpt
assert.Error(t, mount.Set("type=VOLUME,bogus=foo"), "unexpected key 'bogus'")
}
func TestMountOptSetErrorInvalidField(t *testing.T) {
var mount MountOpt
assert.Error(t, mount.Set("type=VOLUME,bogus"), "invalid field 'bogus'")
}
func TestMountOptSetErrorInvalidWritable(t *testing.T) {
var mount MountOpt
assert.Error(t, mount.Set("type=VOLUME,writable=yes"), "invalid value for writable: yes")
}

View File

@@ -14,7 +14,7 @@ import (
func newScaleCommand(dockerCli *client.DockerCli) *cobra.Command {
return &cobra.Command{
Use: "scale SERVICE=SCALE [SERVICE=SCALE...]",
Use: "scale SERVICE=REPLICAS [SERVICE=REPLICAS...]",
Short: "Scale one or multiple services",
Args: scaleArgs,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -61,7 +61,8 @@ func runServiceScale(dockerCli *client.DockerCli, serviceID string, scale string
client := dockerCli.Client()
ctx := context.Background()
service, err := client.ServiceInspect(ctx, serviceID)
service, _, err := client.ServiceInspectWithRaw(ctx, serviceID)
if err != nil {
return err
}

View File

@@ -44,7 +44,7 @@ func runTasks(dockerCli *client.DockerCli, opts tasksOptions) error {
client := dockerCli.Client()
ctx := context.Background()
service, err := client.ServiceInspect(ctx, opts.serviceID)
service, _, err := client.ServiceInspectWithRaw(ctx, opts.serviceID)
if err != nil {
return err
}

View File

@@ -41,7 +41,7 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, serviceID stri
client := dockerCli.Client()
ctx := context.Background()
service, err := client.ServiceInspect(ctx, serviceID)
service, _, err := client.ServiceInspectWithRaw(ctx, serviceID)
if err != nil {
return err
}

View File

@@ -31,7 +31,12 @@ func loadBundlefile(stderr io.Writer, namespace string, path string) (*bundlefil
}
fmt.Fprintf(stderr, "Loading bundle from %s\n", path)
bundle, err := bundlefile.LoadFile(path)
reader, err := os.Open(path)
if err != nil {
return nil, err
}
bundle, err := bundlefile.LoadFile(reader)
if err != nil {
return nil, fmt.Errorf("Error reading %s: %v\n", path, err)
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/docker/docker/cli"
"github.com/docker/engine-api/types/swarm"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
type initOptions struct {
@@ -19,6 +20,7 @@ type initOptions struct {
}
func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
var flags *pflag.FlagSet
opts := initOptions{
listenAddr: NewNodeAddrOption(),
autoAccept: NewAutoAcceptOption(),
@@ -26,14 +28,14 @@ func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "init",
Short: "Initialize a Swarm.",
Short: "Initialize a Swarm",
Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runInit(dockerCli, opts)
return runInit(dockerCli, flags, opts)
},
}
flags := cmd.Flags()
flags = cmd.Flags()
flags.Var(&opts.listenAddr, "listen-addr", "Listen address")
flags.Var(&opts.autoAccept, "auto-accept", "Auto acceptance policy (worker, manager, or none)")
flags.StringVar(&opts.secret, "secret", "", "Set secret value needed to accept nodes into cluster")
@@ -41,7 +43,7 @@ func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
return cmd
}
func runInit(dockerCli *client.DockerCli, opts initOptions) error {
func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions) error {
client := dockerCli.Client()
ctx := context.Background()
@@ -50,8 +52,11 @@ func runInit(dockerCli *client.DockerCli, opts initOptions) error {
ForceNewCluster: opts.forceNewCluster,
}
req.Spec.AcceptancePolicy.Policies = opts.autoAccept.Policies(opts.secret)
if flags.Changed("secret") {
req.Spec.AcceptancePolicy.Policies = opts.autoAccept.Policies(&opts.secret)
} else {
req.Spec.AcceptancePolicy.Policies = opts.autoAccept.Policies(nil)
}
nodeID, err := client.SwarmInit(ctx, req)
if err != nil {
return err

View File

@@ -25,7 +25,7 @@ func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "join [OPTIONS] HOST:PORT",
Short: "Join a Swarm as a node and/or manager.",
Short: "Join a Swarm as a node and/or manager",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.remote = args[0]

View File

@@ -19,7 +19,7 @@ func newLeaveCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "leave",
Short: "Leave a Swarm.",
Short: "Leave a Swarm",
Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runLeave(dockerCli, opts)

View File

@@ -35,12 +35,12 @@ func (a *NodeAddrOption) String() string {
// Set the value for this flag
func (a *NodeAddrOption) Set(value string) error {
if !strings.Contains(value, ":") {
return fmt.Errorf("Invalud url, a host and port are required")
return fmt.Errorf("Invalid url, a host and port are required")
}
parts := strings.Split(value, ":")
if len(parts) != 2 {
return fmt.Errorf("Invalud url, too many colons")
return fmt.Errorf("Invalid url, too many colons")
}
a.addr = value
@@ -102,7 +102,7 @@ func (o *AutoAcceptOption) Type() string {
}
// Policies returns a representation of this option for the api
func (o *AutoAcceptOption) Policies(secret string) []swarm.Policy {
func (o *AutoAcceptOption) Policies(secret *string) []swarm.Policy {
policies := []swarm.Policy{}
for _, p := range defaultPolicies {
if len(o.values) != 0 {

View File

@@ -18,6 +18,7 @@ type updateOptions struct {
secret string
taskHistoryLimit int64
dispatcherHeartbeat time.Duration
nodeCertExpiry time.Duration
}
func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
@@ -26,7 +27,7 @@ func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "update",
Short: "update the Swarm.",
Short: "Update the Swarm",
Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runUpdate(dockerCli, flags, opts)
@@ -38,6 +39,7 @@ func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
flags.StringVar(&opts.secret, "secret", "", "Set secret value needed to accept nodes into cluster")
flags.Int64Var(&opts.taskHistoryLimit, "task-history-limit", 10, "Task history retention limit")
flags.DurationVar(&opts.dispatcherHeartbeat, "dispatcher-heartbeat", time.Duration(5*time.Second), "Dispatcher heartbeat period")
flags.DurationVar(&opts.nodeCertExpiry, "cert-expiry", time.Duration(90*24*time.Hour), "Validity period for node certificates")
return cmd
}
@@ -54,6 +56,7 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts updateOpt
if err != nil {
return err
}
err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec)
if err != nil {
return err
@@ -68,18 +71,17 @@ func mergeSwarm(swarm *swarm.Swarm, flags *pflag.FlagSet) error {
if flags.Changed("auto-accept") {
value := flags.Lookup("auto-accept").Value.(*AutoAcceptOption)
if len(spec.AcceptancePolicy.Policies) > 0 {
spec.AcceptancePolicy.Policies = value.Policies(spec.AcceptancePolicy.Policies[0].Secret)
} else {
spec.AcceptancePolicy.Policies = value.Policies("")
}
spec.AcceptancePolicy.Policies = value.Policies(nil)
}
var psecret *string
if flags.Changed("secret") {
secret, _ := flags.GetString("secret")
for _, policy := range spec.AcceptancePolicy.Policies {
policy.Secret = secret
}
psecret = &secret
}
for i := range spec.AcceptancePolicy.Policies {
spec.AcceptancePolicy.Policies[i].Secret = psecret
}
if flags.Changed("task-history-limit") {
@@ -92,5 +94,11 @@ func mergeSwarm(swarm *swarm.Swarm, flags *pflag.FlagSet) error {
}
}
if flags.Changed("cert-expiry") {
if v, err := flags.GetDuration("cert-expiry"); err == nil {
spec.CAConfig.NodeCertExpiry = v
}
}
return nil
}

View File

@@ -1,21 +1,20 @@
package cli
import "bytes"
import "strings"
// Errors is a list of errors.
// Useful in a loop if you don't want to return the error right away and you want to display after the loop,
// all the errors that happened during the loop.
type Errors []error
func (errs Errors) Error() string {
if len(errs) < 1 {
func (errList Errors) Error() string {
if len(errList) < 1 {
return ""
}
var buf bytes.Buffer
buf.WriteString(errs[0].Error())
for _, err := range errs[1:] {
buf.WriteString(", ")
buf.WriteString(err.Error())
out := make([]string, len(errList))
for i := range errList {
out[i] = errList[i].Error()
}
return buf.String()
return strings.Join(out, ", ")
}

View File

@@ -10,5 +10,5 @@ import (
)
func pluginInit(config *daemon.Config, remote libcontainerd.Remote, rs registry.Service) error {
return plugin.Init(config.Root, config.ExecRoot, remote, rs)
return plugin.Init(config.Root, config.ExecRoot, remote, rs, config.LiveRestore)
}

View File

@@ -823,7 +823,7 @@ func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epC
})
}
createOptions = append(createOptions, libnetwork.CreateOptionService(svcCfg.Name, svcCfg.ID, net.ParseIP(vip), portConfigs))
createOptions = append(createOptions, libnetwork.CreateOptionService(svcCfg.Name, svcCfg.ID, net.ParseIP(vip), portConfigs, svcCfg.Aliases[n.ID()]))
}
if !containertypes.NetworkMode(n.Name()).IsUserDefined() {

View File

@@ -54,7 +54,8 @@ func (container *Container) UnmountVolumes(forceSyscall bool, volumeEventLog fun
// TmpfsMounts returns the list of tmpfs mounts
func (container *Container) TmpfsMounts() []Mount {
return nil
var mounts []Mount
return mounts
}
// UpdateContainer updates configuration of a container

View File

@@ -1639,9 +1639,15 @@ _docker_swarm_join() {
}
_docker_swarm_update() {
case "$prev" in
--auto-accept|--cert-expiry|--dispatcher-heartbeat|--secret|--task-history-limit)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--auto-accept --dispatcher-heartbeat --help --secret --task-history-limit" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--auto-accept --cert-expiry --dispatcher-heartbeat --help --secret --task-history-limit" -- "$cur" ) )
;;
esac
}

View File

@@ -1,4 +1,4 @@
#compdef docker
#compdef docker dockerd
#
# zsh completion for docker (http://docker.com)
#
@@ -1410,6 +1410,13 @@ _docker() {
return ret
}
_dockerd() {
integer ret=1
words[1]='daemon'
__docker_subcommand && ret=0
return ret
}
_docker "$@"
# Local Variables:

View File

@@ -20,6 +20,8 @@ LimitCORE=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
[Install]
WantedBy=multi-user.target

View File

@@ -28,25 +28,28 @@ import (
const swarmDirName = "swarm"
const controlSocket = "control.sock"
const swarmConnectTimeout = 10 * time.Second
const swarmConnectTimeout = 20 * time.Second
const stateFile = "docker-state.json"
const (
initialReconnectDelay = 100 * time.Millisecond
maxReconnectDelay = 10 * time.Second
maxReconnectDelay = 30 * time.Second
)
// ErrNoManager is returned then a manager-only function is called on non-manager
var ErrNoManager = fmt.Errorf("this node is not participating as a Swarm manager")
var ErrNoManager = fmt.Errorf("This node is not participating as a Swarm manager")
// ErrNoSwarm is returned on leaving a cluster that was never initialized
var ErrNoSwarm = fmt.Errorf("this node is not part of Swarm")
var ErrNoSwarm = fmt.Errorf("This node is not part of Swarm")
// ErrSwarmExists is returned on initialize or join request for a cluster that has already been activated
var ErrSwarmExists = fmt.Errorf("this node is already part of a Swarm")
var ErrSwarmExists = fmt.Errorf("This node is already part of a Swarm cluster. Use \"docker swarm leave\" to leave this cluster and join another one.")
// ErrPendingSwarmExists is returned on initialize or join request for a cluster that is already processing a similar request but has not succeeded yet.
var ErrPendingSwarmExists = fmt.Errorf("This node is processing an existing join request that has not succeeded yet. Use \"docker swarm leave\" to cancel the current request.")
// ErrSwarmJoinTimeoutReached is returned when cluster join could not complete before timeout was reached.
var ErrSwarmJoinTimeoutReached = fmt.Errorf("timeout reached before node was joined")
var ErrSwarmJoinTimeoutReached = fmt.Errorf("Timeout was reached before node was joined. Attempt to join the cluster will continue in the background. Use \"docker info\" command to see the current Swarm status of your node.")
type state struct {
ListenAddr string
@@ -111,7 +114,7 @@ func New(config Config) (*Cluster, error) {
select {
case <-time.After(swarmConnectTimeout):
logrus.Errorf("swarm component could not be started before timeout was reached")
case <-n.Ready(context.Background()):
case <-n.Ready():
case <-ctx.Done():
}
if ctx.Err() != nil {
@@ -213,7 +216,7 @@ func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secre
go func() {
select {
case <-node.Ready(context.Background()):
case <-node.Ready():
c.Lock()
c.reconnectDelay = initialReconnectDelay
c.Unlock()
@@ -249,13 +252,14 @@ func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secre
// Init initializes new cluster from user provided request.
func (c *Cluster) Init(req types.InitRequest) (string, error) {
c.Lock()
if c.node != nil {
if node := c.node; node != nil {
c.Unlock()
if !req.ForceNewCluster {
return "", ErrSwarmExists
return "", errSwarmExists(node)
}
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
c.cancelReconnect()
if err := c.node.Stop(ctx); err != nil && !strings.Contains(err.Error(), "context canceled") {
return "", err
}
@@ -273,7 +277,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
c.Unlock()
select {
case <-n.Ready(context.Background()):
case <-n.Ready():
if err := initAcceptancePolicy(n, req.Spec.AcceptancePolicy); err != nil {
return "", err
}
@@ -297,9 +301,9 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
// Join makes current Cluster part of an existing swarm cluster.
func (c *Cluster) Join(req types.JoinRequest) error {
c.Lock()
if c.node != nil {
if node := c.node; node != nil {
c.Unlock()
return ErrSwarmExists
return errSwarmExists(node)
}
// todo: check current state existing
if len(req.RemoteAddrs) == 0 {
@@ -312,23 +316,29 @@ func (c *Cluster) Join(req types.JoinRequest) error {
}
c.Unlock()
select {
case <-time.After(swarmConnectTimeout):
go c.reconnectOnFailure(ctx)
if nodeid := n.NodeID(); nodeid != "" {
return fmt.Errorf("Timeout reached before node was joined. Your cluster settings may be preventing this node from automatically joining. To accept this node into cluster run `docker node accept %v` in an existing cluster manager", nodeid)
certificateRequested := n.CertificateRequested()
for {
select {
case <-certificateRequested:
if n.NodeMembership() == swarmapi.NodeMembershipPending {
return fmt.Errorf("Your node is in the process of joining the cluster but needs to be accepted by existing cluster member.\nTo accept this node into cluster run \"docker node accept %v\" in an existing cluster manager. Use \"docker info\" command to see the current Swarm status of your node.", n.NodeID())
}
certificateRequested = nil
case <-time.After(swarmConnectTimeout):
// attempt to connect will continue in background, also reconnecting
go c.reconnectOnFailure(ctx)
return ErrSwarmJoinTimeoutReached
case <-n.Ready():
go c.reconnectOnFailure(ctx)
return nil
case <-ctx.Done():
c.RLock()
defer c.RUnlock()
if c.err != nil {
return c.err
}
return ctx.Err()
}
return ErrSwarmJoinTimeoutReached
case <-n.Ready(context.Background()):
go c.reconnectOnFailure(ctx)
return nil
case <-ctx.Done():
c.RLock()
defer c.RUnlock()
if c.err != nil {
return c.err
}
return ctx.Err()
}
}
@@ -379,10 +389,11 @@ func (c *Cluster) Leave(force bool) error {
if err := node.Stop(ctx); err != nil && !strings.Contains(err.Error(), "context canceled") {
return err
}
nodeID := node.NodeID()
for _, id := range c.config.Backend.ListContainersForNode(nodeID) {
if err := c.config.Backend.ContainerRm(id, &apitypes.ContainerRmConfig{ForceRemove: true}); err != nil {
logrus.Errorf("error removing %v: %v", id, err)
if nodeID := node.NodeID(); nodeID != "" {
for _, id := range c.config.Backend.ListContainersForNode(nodeID) {
if err := c.config.Backend.ContainerRm(id, &apitypes.ContainerRmConfig{ForceRemove: true}); err != nil {
logrus.Errorf("error removing %v: %v", id, err)
}
}
}
c.Lock()
@@ -444,12 +455,12 @@ func (c *Cluster) Update(version uint64, spec types.Spec) error {
return ErrNoManager
}
swarmSpec, err := convert.SwarmSpecToGRPC(spec)
swarm, err := getSwarm(c.getRequestContext(), c.client)
if err != nil {
return err
}
swarm, err := getSwarm(c.getRequestContext(), c.client)
swarmSpec, err := convert.SwarmSpecToGRPCandMerge(spec, &swarm.Spec)
if err != nil {
return err
}
@@ -918,7 +929,7 @@ func populateNetworkID(ctx context.Context, c swarmapi.ControlClient, s *types.S
if err != nil {
return err
}
s.Networks[i] = types.NetworkAttachmentConfig{Target: apiNetwork.ID}
s.Networks[i].Target = apiNetwork.ID
}
return nil
}
@@ -1004,6 +1015,13 @@ func (c *Cluster) managerStats() (current bool, reachable int, unreachable int,
return
}
func errSwarmExists(node *swarmagent.Node) error {
if node.NodeMembership() != swarmapi.NodeMembershipAccepted {
return ErrPendingSwarmExists
}
return ErrSwarmExists
}
func initAcceptancePolicy(node *swarmagent.Node, acceptancePolicy types.AcceptancePolicy) error {
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
for conn := range node.ListenControlSocket(ctx) {
@@ -1030,7 +1048,7 @@ func initAcceptancePolicy(node *swarmagent.Node, acceptancePolicy types.Acceptan
}
spec := &cluster.Spec
if err := convert.SwarmSpecUpdateAcceptancePolicy(spec, acceptancePolicy); err != nil {
if err := convert.SwarmSpecUpdateAcceptancePolicy(spec, acceptancePolicy, nil); err != nil {
return fmt.Errorf("error updating cluster settings: %v", err)
}
_, err := client.UpdateCluster(ctx, &swarmapi.UpdateClusterRequest{

View File

@@ -148,17 +148,22 @@ func BasicNetworkFromGRPC(n swarmapi.Network) basictypes.NetworkResource {
}
}
return basictypes.NetworkResource{
nr := basictypes.NetworkResource{
ID: n.ID,
Name: n.Spec.Annotations.Name,
Scope: "swarm",
Driver: n.DriverState.Name,
EnableIPv6: spec.Ipv6Enabled,
IPAM: ipam,
Internal: spec.Internal,
Options: n.DriverState.Options,
Labels: n.Spec.Annotations.Labels,
}
if n.DriverState != nil {
nr.Driver = n.DriverState.Name
nr.Options = n.DriverState.Options
}
return nr
}
// BasicNetworkCreateToGRPC converts a NetworkCreateRequest to a grpc NetworkSpec.

View File

@@ -49,7 +49,8 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
Autoaccept: policy.Autoaccept,
}
if policy.Secret != nil {
p.Secret = string(policy.Secret.Data)
secret := string(policy.Secret.Data)
p.Secret = &secret
}
swarm.Spec.AcceptancePolicy.Policies = append(swarm.Spec.AcceptancePolicy.Policies, p)
}
@@ -57,8 +58,8 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
return swarm
}
// SwarmSpecToGRPC converts a Spec to a grpc ClusterSpec.
func SwarmSpecToGRPC(s types.Spec) (swarmapi.ClusterSpec, error) {
// SwarmSpecToGRPCandMerge converts a Spec to a grpc ClusterSpec and merge AcceptancePolicy from an existing grpc ClusterSpec if provided.
func SwarmSpecToGRPCandMerge(s types.Spec, existingSpec *swarmapi.ClusterSpec) (swarmapi.ClusterSpec, error) {
spec := swarmapi.ClusterSpec{
Annotations: swarmapi.Annotations{
Name: s.Name,
@@ -82,15 +83,18 @@ func SwarmSpecToGRPC(s types.Spec) (swarmapi.ClusterSpec, error) {
},
}
if err := SwarmSpecUpdateAcceptancePolicy(&spec, s.AcceptancePolicy); err != nil {
if err := SwarmSpecUpdateAcceptancePolicy(&spec, s.AcceptancePolicy, existingSpec); err != nil {
return swarmapi.ClusterSpec{}, err
}
return spec, nil
}
// SwarmSpecUpdateAcceptancePolicy updates a grpc ClusterSpec using AcceptancePolicy.
func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolicy types.AcceptancePolicy) error {
func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolicy types.AcceptancePolicy, oldSpec *swarmapi.ClusterSpec) error {
spec.AcceptancePolicy.Policies = nil
hashs := make(map[string][]byte)
for _, p := range acceptancePolicy.Policies {
role, ok := swarmapi.NodeRole_value[strings.ToUpper(string(p.Role))]
if !ok {
@@ -102,11 +106,24 @@ func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolic
Autoaccept: p.Autoaccept,
}
if p.Secret != "" {
hashPwd, _ := bcrypt.GenerateFromPassword([]byte(p.Secret), 0)
if p.Secret != nil {
if *p.Secret == "" { // if provided secret is empty, it means erase previous secret.
policy.Secret = nil
} else { // if provided secret is not empty, we generate a new one.
hashPwd, ok := hashs[*p.Secret]
if !ok {
hashPwd, _ = bcrypt.GenerateFromPassword([]byte(*p.Secret), 0)
hashs[*p.Secret] = hashPwd
}
policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{
Data: hashPwd,
Alg: "bcrypt",
}
}
} else if oldSecret := getOldSecret(oldSpec, policy.Role); oldSecret != nil { // else use the old one.
policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{
Data: hashPwd,
Alg: "bcrypt",
Data: oldSecret.Data,
Alg: oldSecret.Alg,
}
}
@@ -114,3 +131,15 @@ func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolic
}
return nil
}
func getOldSecret(oldSpec *swarmapi.ClusterSpec, role swarmapi.NodeRole) *swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret {
if oldSpec == nil {
return nil
}
for _, p := range oldSpec.AcceptancePolicy.Policies {
if p.Role == role {
return p.Secret
}
}
return nil
}

View File

@@ -39,7 +39,7 @@ func newContainerAdapter(b executorpkg.Backend, task *api.Task) (*containerAdapt
func (c *containerAdapter) pullImage(ctx context.Context) error {
// if the image needs to be pulled, the auth config will be retrieved and updated
encodedAuthConfig := c.container.task.ServiceAnnotations.Labels[fmt.Sprintf("%v.registryauth", systemLabelPrefix)]
encodedAuthConfig := c.container.spec().RegistryAuth
authConfig := &types.AuthConfig{}
if encodedAuthConfig != "" {
@@ -126,7 +126,6 @@ func (c *containerAdapter) create(ctx context.Context, backend executorpkg.Backe
if nc != nil {
for n, ep := range nc.EndpointsConfig {
logrus.Errorf("CONNECT %s : %v", n, ep.IPAMConfig.IPv4Address)
if err := backend.ConnectContainerToNetwork(cr.ID, n, ep); err != nil {
return err
}

View File

@@ -348,6 +348,7 @@ func (c *containerConfig) serviceConfig() *clustertypes.ServiceConfig {
log.Printf("Creating service config in agent for t = %+v", c.task)
svcCfg := &clustertypes.ServiceConfig{
Name: c.task.ServiceAnnotations.Name,
Aliases: make(map[string][]string),
ID: c.task.ServiceID,
VirtualAddresses: make(map[string]*clustertypes.VirtualAddress),
}
@@ -357,6 +358,9 @@ func (c *containerConfig) serviceConfig() *clustertypes.ServiceConfig {
// We support only IPv4 virtual IP for now.
IPv4: c.virtualIP(na.Network.ID),
}
if len(na.Aliases) > 0 {
svcCfg.Aliases[na.Network.ID] = na.Aliases
}
}
if c.task.Endpoint != nil {

View File

@@ -2,13 +2,13 @@ package container
import (
"fmt"
"strings"
executorpkg "github.com/docker/docker/daemon/cluster/executor"
"github.com/docker/engine-api/types"
"github.com/docker/swarmkit/agent/exec"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@@ -84,31 +84,32 @@ func (r *controller) Prepare(ctx context.Context) error {
return err
}
for {
if err := r.checkClosed(); err != nil {
return err
}
if err := r.adapter.create(ctx, r.backend); err != nil {
if isContainerCreateNameConflict(err) {
if _, err := r.adapter.inspect(ctx); err != nil {
return err
}
if err := r.adapter.pullImage(ctx); err != nil {
// NOTE(stevvooe): We always try to pull the image to make sure we have
// the most up to date version. This will return an error, but we only
// log it. If the image truly doesn't exist, the create below will
// error out.
//
// This gives us some nice behavior where we use up to date versions of
// mutable tags, but will still run if the old image is available but a
// registry is down.
//
// If you don't want this behavior, lock down your image to an
// immutable tag or digest.
log.G(ctx).WithError(err).Error("pulling image failed")
}
// container is already created. success!
return exec.ErrTaskPrepared
}
if !strings.Contains(err.Error(), "No such image") { // todo: better error detection
return err
}
if err := r.adapter.pullImage(ctx); err != nil {
if err := r.adapter.create(ctx, r.backend); err != nil {
if isContainerCreateNameConflict(err) {
if _, err := r.adapter.inspect(ctx); err != nil {
return err
}
continue // retry to create the container
// container is already created. success!
return exec.ErrTaskPrepared
}
break
return err
}
return nil
@@ -135,7 +136,7 @@ func (r *controller) Start(ctx context.Context) error {
}
if err := r.adapter.start(ctx); err != nil {
return err
return errors.Wrap(err, "starting container failed")
}
return nil

View File

@@ -31,6 +31,7 @@ type PortConfig struct {
type ServiceConfig struct {
ID string
Name string
Aliases map[string][]string
VirtualAddresses map[string]*VirtualAddress
ExposedPorts []*PortConfig
}

View File

@@ -179,7 +179,7 @@ func (daemon *Daemon) restore() error {
logrus.Errorf("Failed to restore with containerd: %q", err)
return
}
if !c.HostConfig.NetworkMode.IsContainer() {
if !c.HostConfig.NetworkMode.IsContainer() && c.IsRunning() {
options, err := daemon.buildSandboxOptions(c)
if err != nil {
logrus.Warnf("Failed build sandbox option to restore container %s: %v", c.ID, err)

View File

@@ -114,19 +114,10 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
backingFs = fsName
}
// check if they are running over btrfs, aufs, zfs or overlay
// check if they are running over btrfs, aufs, zfs, overlay, or ecryptfs
switch fsMagic {
case graphdriver.FsMagicBtrfs:
logrus.Error("'overlay' is not supported over btrfs.")
return nil, graphdriver.ErrIncompatibleFS
case graphdriver.FsMagicAufs:
logrus.Error("'overlay' is not supported over aufs.")
return nil, graphdriver.ErrIncompatibleFS
case graphdriver.FsMagicZfs:
logrus.Error("'overlay' is not supported over zfs.")
return nil, graphdriver.ErrIncompatibleFS
case graphdriver.FsMagicOverlay:
logrus.Error("'overlay' is not supported over overlay.")
case graphdriver.FsMagicBtrfs, graphdriver.FsMagicAufs, graphdriver.FsMagicZfs, graphdriver.FsMagicOverlay, graphdriver.FsMagicEcryptfs:
logrus.Errorf("'overlay2' is not supported over %s", backingFs)
return nil, graphdriver.ErrIncompatibleFS
}

View File

@@ -465,6 +465,7 @@ func (daemon *Daemon) transformContainer(container *container.Container, ctx *li
GlobalIPv6Address: network.GlobalIPv6Address,
GlobalIPv6PrefixLen: network.GlobalIPv6PrefixLen,
MacAddress: network.MacAddress,
NetworkID: network.NetworkID,
}
if network.IPAMConfig != nil {
networks[name].IPAMConfig = &networktypes.EndpointIPAMConfig{

View File

@@ -480,9 +480,10 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c
}
if m.Source == "tmpfs" {
data := c.HostConfig.Tmpfs[m.Destination]
options := []string{"noexec", "nosuid", "nodev", volume.DefaultPropagationMode}
if m.Data != "" {
options = append(options, strings.Split(m.Data, ",")...)
if data != "" {
options = append(options, strings.Split(data, ",")...)
}
merged, err := mount.MergeTmpfsOptions(options)

View File

@@ -129,7 +129,8 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo
return err
}
if binds[bind.Destination] {
_, tmpfsExists := hostConfig.Tmpfs[bind.Destination]
if binds[bind.Destination] || tmpfsExists {
return fmt.Errorf("Duplicate mount point '%s'", bind.Destination)
}

View File

@@ -16,7 +16,15 @@ import (
// /etc/resolv.conf, and if it is not, appends it to the array of mounts.
func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, error) {
var mounts []container.Mount
// TODO: tmpfs mounts should be part of Mountpoints
tmpfsMounts := make(map[string]bool)
for _, m := range c.TmpfsMounts() {
tmpfsMounts[m.Destination] = true
}
for _, m := range c.MountPoints {
if tmpfsMounts[m.Destination] {
continue
}
if err := daemon.lazyInitializeVolume(c.ID, m); err != nil {
return nil, err
}

42
docs/getstarted/index.md Normal file
View File

@@ -0,0 +1,42 @@
<!--[metadata]>
+++
aliases = [
"/mac/started/",
"/windows/started/",
"/linux/started/",
]
title = "Get Started with Docker"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker"]
[menu.main]
identifier = "getstart_all"
parent = "engine_use"
weight="-80"
+++
<![end-metadata]-->
# Get Started with Docker
This tutorial is a for non-technical users who are interested in learning more about Docker. By following these steps, you'll learn fundamental Docker features while working through some simple tasks. You'll learn how to:
* install Docker software for your platform
* run a software image in a container
* browse for an image on Docker Hub
* create your own image and run it in a container
* create a Docker Hub account and an image repository
* create an image of your own
* push your image to Docker Hub for others to use
The getting started was user tested to reduce the chance of users having problems. For the best chance of success, follow the steps as written the first time before exploring on your own. It takes approximately 45 minutes to complete.
### Make sure you understand...
This getting started uses Docker Engine CLI commands entered on the command line of a terminal window. You don't need to be a wizard at the command line, but you should be familiar with how to open your favorite shell or terminal, and run basic commands in that environment. It helps (but isn't required) to know how to navigate a directory tree, manipulate files, list running process, and so forth.
Go to [the next page to install](step_one.md).
&nbsp;

View File

@@ -0,0 +1,70 @@
<!--[metadata]>
+++
aliases = [
"/mac/last_page/",
"/windows/last_page/",
"/linux/last_page/",
]
title = "Learning more"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker"]
[menu.main]
identifier = "getstart_learn_more"
parent = "getstart_all"
weight = 7
+++
<![end-metadata]-->
# Learning more
This getting started provided very basic essentials for using Docker on Mac, Windows, and Linux. If you want to learn more with regard to end-to-end development, start with the full install instructions and feature overviews, then follow up with more advanced tutorials and user guides.
Depending on your interest, the Docker documentation contains a wealth of information. Here are some places to start:
<style type="text/css">
</style>
<table class="tutorial">
<tr>
<th class="tg-031e">If you are looking for</th>
<th class="tg-031e">Where to find it</th>
</tr>
<tr>
<td class="tg-031e">More about Docker for Mac, features, examples, FAQs, relationship to Docker Machine and Docker Toolbox, and how this fits in the Docker ecosystem</td>
<td class="tg-031e">[Getting Started with Docker for Mac](/docker-for-mac/index.md)</td>
</tr>
<tr>
<td class="tg-031e">More about Docker for Windows, More about Docker for Windows, features, examples, FAQs, relationship to Docker Machine and Docker Toolbox, and how this fits in the Docker ecosystem</td>
<td class="tg-031e">[Getting Started with Docker for Windows](/docker-for-mac/index.md)</td>
</tr>
<tr>
<td class="tg-031e">More about Docker Toolbox</td>
<td class="tg-031e">[Docker Toolbox Overview](/toolbox/overview.md)</td>
</tr>
<tr>
<td class="tg-031e">More about Docker for Linux distributions</td>
<td class="tg-031e">[Install Docker Engine on Linux](/engine/installation/linux/index.md)</td>
</tr>
<tr>
<td class="tg-031e">More advanced tutorials on running containers, building your own images, networking containers, managing data for containers, and storing images on Docker Hub</td>
<td class="tg-031e"> [Learn by example](/engine/tutorials/index.md)</a></td>
</tr>
<tr>
<td class="tg-031e">Information about the Docker product line</td>
<td class="tg-031e"><a href="http://www.docker.com/products/">The product explainer is a good place to start.</a></td>
</tr>
<tr>
<td class="tg-031e">How to set up an automated build on Docker Hub</td>
<td class="tg-031e"><a href="https://docs.docker.com/docker-hub/">Docker Hub documentation</a></td>
</tr>
<tr>
<td class="tg-031e">How to run a multi-container application with Compose</td>
<td class="tg-031e"> [Docker Compose documentation](/compose/overview.md)
</td>
</tr>
</table>
&nbsp;

View File

@@ -0,0 +1,44 @@
<!--[metadata]>
+++
aliases = ["/mac/started/"]
title = "Install Docker and run hello-world"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker, install"]
identifier = "getstart_linux_install"
parent = "getstart_all"
weight="-80"
+++
<![end-metadata]-->
# Example: Install Docker on Ubuntu Linux
This installation procedure for users who are unfamiliar with package
managers, and just want to try out the Getting Started tutorial while running Docker on Linux. If you are comfortable with package managers, prefer not to use
`curl`, or have problems installing and want to troubleshoot, please use our
`apt` and `yum` <a href="https://docs.docker.com/engine/installation/"
target="_blank">repositories instead for your installation</a>.
1. Log into your Ubuntu installation as a user with `sudo` privileges.
2. Verify that you have `curl` installed.
$ which curl
If `curl` isn't installed, install it after updating your manager:
$ sudo apt-get update
$ sudo apt-get install curl
3. Get the latest Docker package.
$ curl -fsSL https://get.docker.com/ | sh
The system prompts you for your `sudo` password. Then, it downloads and
installs Docker and its dependencies.
>**Note**: If your company is behind a filtering proxy, you may find that the
>`apt-key`
>command fails for the Docker repo during installation. To work around this,
>add the key directly using the following:
>
> $ curl -fsSL https://get.docker.com/gpg | sudo apt-key add -

View File

@@ -0,0 +1,78 @@
<!--[metadata]>
+++
aliases = [
"/mac/step_five/",
"/windows/step_five/",
"/linux/step_five/",
]
title = "Create a Docker Hub account & repository"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker"]
[menu.main]
identifier = "getstart_docker_hub"
parent = "getstart_all"
weight = 5
+++
<![end-metadata]-->
# Create a Docker Hub account & repository
You've built something really cool, you should share it. In this next section,
you'll do just that. You'll need a Docker Hub account. Then, you'll push your
image up to it so other people with Docker Engine can run it.
## Step 1: Sign up for an account
1. Use your browser to navigate to <a href="https://hub.docker.com/?utm_source=getting_started_guide&utm_medium=embedded_MacOSX&utm_campaign=create_docker_hub_account" target="_blank">the Docker Hub signup page</a>.
Your browser displays the page.
![Docker Hub signup](tutimg/hub_signup.png)
2. Fill out the form on the signup page.
Docker Hub is free. Docker does need a name, password, and email address.
3. Press **Signup**.
The browser displays the welcome to Docker Hub page.
## Step 2: Verify your email and add a repository
Before you can share anything on the hub, you need to verify your email address.
1. Open your email inbox.
2. Look for the email titled `Please confirm email for your Docker Hub account`.
If you don't see the email, check your Spam folder or wait a moment for the email to arrive.
2. Open the email and click the **Confirm Your Email** button.
The browser opens Docker Hub to your profile page.
4. Choose **Create Repository**.
The browser opens the **Create Repository** page.
5. Provide a Repository Name and Short Description.
6. Make sure Visibility is set to **Public**.
When you are done, your form should look similar to the following:
![Add repo](tutimg/add_repository.png)
6. Press **Create** when you are done.
Docker Hub creates your new repository.
## Where to go next
On this page, you opened an account on Docker Hub and created a new repository.
In the next section, you populate the repository [by tagging and pushing the
image you created earlier](step_six.md).
&nbsp;

View File

@@ -0,0 +1,225 @@
<!--[metadata]>
+++
aliases = [
"/mac/step_four/",
"/windows/step_four/",
"/linux/step_four/",
]
title = "Build your own image"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker"]
[menu.main]
identifier = "getstart_build_image"
parent = "getstart_all"
weight = 4
+++
<![end-metadata]-->
# Build your own image
The `whalesay` image could be improved. It would be nice if you didn't have to
think of something to say. And you type a lot to get `whalesay` to talk.
docker run docker/whalesay cowsay boo-boo
In this next section, you will improve the `whalesay` image by building a new version that "talks on its own" and requires fewer words to run.
## Step 1: Write a Dockerfile
In this step, you use your favorite text editor to write a short Dockerfile. A
Dockerfile describes the software that is "baked" into an image. It isn't just
ingredients tho, it can tell the software what environment to use or what
commands to run. Your recipe is going to be very short.
1. Go back to your command terminal window.
2. Make a new directory by typing `mkdir mydockerbuild` and pressing RETURN.
$ mkdir mydockerbuild
This directory serves as the "context" for your build. The context just means it contains all the things you need to build your image.
3. Change to your new directory.
$ cd mydockerbuild
Right now the directory is empty.
4. Create a Dockerfile in the directory by typing `touch Dockerfile` and pressing RETURN.
$ touch Dockerfile
The command appears to do nothing but it actually creates the Dockerfile in the current directory. Just type `ls Dockerfile` to see it.
$ ls Dockerfile
Dockerfile
5. Open the `Dockerfile` in a visual text editor like <a href="https://atom.io/" target="_blank">Atom</a> or <a href="https://www.sublimetext.com/" target="_blank">Sublime</a>, or a text based editor like `vi`, or `nano` (https://www.nano-editor.org/).
6. Add a line to the file like this:
FROM docker/whalesay:latest
The `FROM` keyword tells Docker which image your image is based on. Whalesay is cute and has the `cowsay` program already, so we'll start there.
7. Now, add the `fortunes` program to the image.
RUN apt-get -y update && apt-get install -y fortunes
The `fortunes` program has a command that prints out wise sayings for our whale to say. So, the first step is to install it. This line installs the software into the image.
8. Once the image has the software it needs, you instruct the software to run
when the image is loaded.
CMD /usr/games/fortune -a | cowsay
This line tells the `fortune` program to pass a nifty quote to the `cowsay` program.
9. Check your work, your file should look like this:
FROM docker/whalesay:latest
RUN apt-get -y update && apt-get install -y fortunes
CMD /usr/games/fortune -a | cowsay
10. Save and close your Dockerfile.
At this point, you have all your software ingredients and behaviors described in a Dockerfile. You are ready to build a new image.
## Step 2: Build an image from your Dockerfile
1. At the command line, make sure the Dockerfile is in the current directory by typing `cat Dockerfile`
$ cat Dockerfile
FROM docker/whalesay:latest
RUN apt-get -y update && apt-get install -y fortunes
CMD /usr/games/fortune -a | cowsay
2. Now, build your new image by typing the `docker build -t docker-whale .` command in your terminal (don't forget the . period).
$ docker build -t docker-whale .
Sending build context to Docker daemon 158.8 MB
...snip...
Removing intermediate container a8e6faa88df3
Successfully built 7d9495d03763
The command takes several seconds to run and reports its outcome. Before
you do anything with the new image, take a minute to learn about the
Dockerfile build process.
## Step 3: Learn about the build process
The `docker build -t docker-whale .` command takes the `Dockerfile` in the
current directory, and builds an image called `docker-whale` on your local
machine. The command takes about a minute and its output looks really long and
complex. In this section, you learn what each message means.
First Docker checks to make sure it has everything it needs to build.
Sending build context to Docker daemon 158.8 MB
Then, Docker loads with the `whalesay` image. It already has this image
locally as you might recall from the last page. So, Docker doesn't need to
download it.
Step 0 : FROM docker/whalesay:latest
---> fb434121fc77
Docker moves onto the next step which is to update the `apt-get` package
manager. This takes a lot of lines, no need to list them all again here.
Step 1 : RUN apt-get -y update && apt-get install -y fortunes
---> Running in 27d224dfa5b2
Ign http://archive.ubuntu.com trusty InRelease
Ign http://archive.ubuntu.com trusty-updates InRelease
Ign http://archive.ubuntu.com trusty-security InRelease
Hit http://archive.ubuntu.com trusty Release.gpg
....snip...
Get:15 http://archive.ubuntu.com trusty-security/restricted amd64 Packages [14.8 kB]
Get:16 http://archive.ubuntu.com trusty-security/universe amd64 Packages [134 kB]
Reading package lists...
---> eb06e47a01d2
Then, Docker installs the new `fortunes` software.
Removing intermediate container e2a84b5f390f
Step 2 : RUN apt-get install -y fortunes
---> Running in 23aa52c1897c
Reading package lists...
Building dependency tree...
Reading state information...
The following extra packages will be installed:
fortune-mod fortunes-min librecode0
Suggested packages:
x11-utils bsdmainutils
The following NEW packages will be installed:
fortune-mod fortunes fortunes-min librecode0
0 upgraded, 4 newly installed, 0 to remove and 3 not upgraded.
Need to get 1961 kB of archives.
After this operation, 4817 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ trusty/main librecode0 amd64 3.6-21 [771 kB]
...snip......
Setting up fortunes (1:1.99.1-7) ...
Processing triggers for libc-bin (2.19-0ubuntu6.6) ...
---> c81071adeeb5
Removing intermediate container 23aa52c1897c
Finally, Docker finishes the build and reports its outcome.
Step 3 : CMD /usr/games/fortune -a | cowsay
---> Running in a8e6faa88df3
---> 7d9495d03763
Removing intermediate container a8e6faa88df3
Successfully built 7d9495d03763
## Step 4: Run your new docker-whale
In this step, you verify the new images is on your computer and then you run your new image.
1. Open a command line terminal.
2. Type `docker images` and press RETURN.
This command, you might remember, lists the images you have locally.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
docker-whale latest 7d9495d03763 4 minutes ago 273.7 MB
docker/whalesay latest fb434121fc77 4 hours ago 247 MB
hello-world latest 91c95931e552 5 weeks ago 910 B
3. Run your new image by typing `docker run docker-whale` and pressing RETURN.
$ docker run docker-whale
_________________________________________
/ "He was a modest, good-humored boy. It \
\ was Oxford that made him insufferable." /
-----------------------------------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
As you can see, you've made the whale a lot smarter. It finds its own
things to say and the command line is a lot shorter! You may also notice
that Docker didn't have to download anything. That is because the image was
built locally and is already available.
## Where to go next
On this page, you learned to build an image by writing your own Dockerfile.
You ran your image in a container. You also just used Linux from your Mac yet
again. In the next section, you take the first step in sharing your image by
[creating a Docker Hub account](step_five.md).
&nbsp;

140
docs/getstarted/step_one.md Normal file
View File

@@ -0,0 +1,140 @@
<!--[metadata]>
+++
aliases = [
"/mac/step_one/",
"/windows/step_one/",
"/linux/step_one/",
]
title = "Install Docker and run hello-world"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker, install"]
[menu.main]
identifier = "getstart_all_install"
parent = "getstart_all"
weight = 1
+++
<![end-metadata]-->
# Install Docker
## Step 1: Get Docker
### Docker for Mac
Docker for Mac is our newest offering for the Mac. It runs as a native Mac application and uses <a href="https://github.com/mist64/xhyve/" target="_blank">xhyve</a> to virutalize the Docker Engine environment and Linux kernel-specific features for the Docker daemon.
<a class="button" href="https://download.docker.com/mac/beta/Docker.dmg">Get Docker for Mac</a>
#### Install Prequisites
- Mac must be a 2010 or newer model, with Intel's hardware support for memory management unit (MMU) virtualization; i.e., Extended Page Tables (EPT)
- OS X 10.10.3 Yosemite or newer
- At least 4GB of RAM
- VirtualBox prior to version 4.3.30 must NOT be installed (it is incompatible with Docker for Mac). Docker for Mac will error out on install in this case. Uninstall the older version of VirtualBox and re-try the install.
#### Docker Toolbox for the Mac
If you have an earlier Mac that doesn't meet the Docker for Mac prerequisites, <a href="https://www.docker.com/products/docker-toolbox" target="_blank">get Docker Toolbox</a> for the Mac.
See [Docker Toolbox Overview](/toolbox/overview.md) for help on installing Docker with Toolbox.
### Docker for Windows
Docker for Windows is our newest offering for PCs. It runs as a native Windows application and uses Hyper-V to virutalize the Docker Engine environment and Linux kernel-specific features for the Docker daemon.
<a class="button" href="https://download.docker.com/win/beta/InstallDocker.msi">Get Docker for Windows</a>
#### Install Prequisites
* 64bit Windows 10 Pro, Enterprise and Education (1511 November update, Build 10586 or later). In the future we will support more versions of Windows 10.
* The Hyper-V package must be enabled. The Docker for Windows installer will enable it for you, if needed. (This requires a reboot).
#### Docker Toolbox for Windows
If you have an earlier Windows system that doesn't meet the Docker for Windows prerequisites, <a href="https://www.docker.com/products/docker-toolbox" target="_blank">get Docker Toolbox</a>.
See [Docker Toolbox Overview](/toolbox/overview.md) for help on installing Docker with Toolbox.
### Docker for Linux
Docker Engine runs navitvely on Linux distributions.
For full instructions on getting Docker for various Linux distributions, see [Install Docker Engine](/engine/installation/index.md).
## Step 2: Install Docker
* For install instructions for Docker for Mac, see [Getting Started with Docker for Mac](/docker-for-mac/index.md).
* For install instructions for Docker for Windows, see [Getting Started with Docker for Windows](/docker-for-windows/index.md).
* For install instructions for Docker Toolbox, see [Docker Toolbox Overview](/toolbox/overview.md).
* For a simple example of installing Docker on Ubuntu Linux so that you can work through this tutorial, see [Installing Docker on Ubuntu Linux (Example)](linux_install_help.md).
For full install instructions for Docker on Linux, see [Install Docker Engine](/engine/installation/index.md) and select the flavor of Linux you want to use.
## Step 3: Verify your installation
1. Open a command-line terminal, and run some Docker commands to verify that Docker is working as expected.
Some good commands to try are `docker version` to check that you have the latest release installed and `docker ps` to see if you have any running containers. (Probably not, since you just started.)
2. Type the `docker run hello-world` command and press RETURN.
The command does some work for you, if everything runs well, the command's
output looks like this:
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
535020c3e8ad: Pull complete
af340544ed62: Pull complete
Digest: sha256:a68868bfe696c00866942e8f5ca39e3e31b79c1e50feaee4ce5e28df2f051d5c
Status: Downloaded newer image for hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker Engine CLI client contacted the Docker Engine daemon.
2. The Docker Engine daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker Engine daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker Engine daemon streamed that output to the Docker Engine CLI client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker Hub account:
https://hub.docker.com
For more examples and ideas, visit:
https://docs.docker.com/userguide/
3. Run `docker ps -a` to show all containers on the system.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
592376ff3eb8 hello-world "/hello" 25 seconds ago Exited (0) 24 seconds ago prickly_wozniak
You should see your `hello-world` container listed in the output for the `docker ps -a` command.
The command `docker ps` shows only currently running containers. Since `hello-world` already ran and exited, it wouldn't show up with a `docker ps`.
## Looking for troubleshooting help?
Typically, the above steps work out-of-the-box, but some scenarios can cause problems. If your `docker run hello-world` didn't work and resulted in errors, check out [Troubleshooting](/toolbox/faqs/troubleshoot.md) for quick fixes to common problems.
## Where to go next
At this point, you have successfully installed the Docker software. Leave the
Docker Quickstart Terminal window open. Now, go to the next page to [read a very
short introduction Docker images and containers](step_two.md).
&nbsp;

205
docs/getstarted/step_six.md Normal file
View File

@@ -0,0 +1,205 @@
<!--[metadata]>
+++
aliases = [
"/mac/step_six/",
"/windows/step_six/",
"/linux/step_six/",
]
title = "Tag, push, & pull your image"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker"]
[menu.main]
identifier = "getstart_tag_push_pull"
parent = "getstart_all"
weight = 6
+++
<![end-metadata]-->
# Tag, push, and pull your image
In this section, you tag and push your `docker-whale` image to your newly
created repository. When you are done, you test the repository by pulling your
new image.
## Step 1: Tag and push the image
If you don't already have a terminal open, open one now:
1. Go back to your command line terminal.
2. At the prompt, type `docker images` to list the images you currently have:
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
docker-whale latest 7d9495d03763 38 minutes ago 273.7 MB
<none> <none> 5dac217f722c 45 minutes ago 273.7 MB
docker/whalesay latest fb434121fc77 4 hours ago 247 MB
hello-world latest 91c95931e552 5 weeks ago 910 B
5. Find the `IMAGE ID` for your `docker-whale` image.
In this example, the id is `7d9495d03763`.
Notice that currently, the `REPOSITORY` shows the repo name `docker-whale`
but not the namespace. You need to include the `namespace` for Docker Hub to
associate it with your account. The `namespace` is the same as your Docker
Hub account name. You need to rename the image to
`YOUR_DOCKERHUB_NAME/docker-whale`.
6. Use `IMAGE ID` and the `docker tag` command to tag your `docker-whale` image.
The command you type looks like this:
![Docker tag command](tutimg/tagger.png)
Of course, your account name will be your own. So, you type the command with
your image's ID and your account name and press RETURN.
$ docker tag 7d9495d03763 maryatdocker/docker-whale:latest
7. Type the `docker images` command again to see your newly tagged image.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
maryatdocker/docker-whale latest 7d9495d03763 5 minutes ago 273.7 MB
docker-whale latest 7d9495d03763 2 hours ago 273.7 MB
<none> <none> 5dac217f722c 5 hours ago 273.7 MB
docker/whalesay latest fb434121fc77 5 hours ago 247 MB
hello-world latest 91c95931e552 5 weeks ago 910 B
8. Use the `docker login` command to log into the Docker Hub from the command line.
The format for the login command is:
docker login --username=yourhubusername --email=youremail@company.com
When prompted, enter your password and press enter. So, for example:
$ docker login --username=maryatdocker --email=mary@docker.com
Password:
WARNING: login credentials saved in C:\Users\sven\.docker\config.json
Login Succeeded
9. Type the `docker push` command to push your image to your new repository.
$ docker push maryatdocker/docker-whale
The push refers to a repository [maryatdocker/docker-whale] (len: 1)
7d9495d03763: Image already exists
c81071adeeb5: Image successfully pushed
eb06e47a01d2: Image successfully pushed
fb434121fc77: Image successfully pushed
5d5bd9951e26: Image successfully pushed
99da72cfe067: Image successfully pushed
1722f41ddcb5: Image successfully pushed
5b74edbcaa5b: Image successfully pushed
676c4a1897e6: Image successfully pushed
07f8e8c5e660: Image successfully pushed
37bea4ee0c81: Image successfully pushed
a82efea989f9: Image successfully pushed
e9e06b06e14c: Image successfully pushed
Digest: sha256:ad89e88beb7dc73bf55d456e2c600e0a39dd6c9500d7cd8d1025626c4b985011
10. Return to your profile on Docker Hub to see your new image.
![Docker tag command](tutimg/new_image.png)
## Step 2: Pull your new image
In this last section, you'll pull the image you just pushed to hub. Before you
do that though, you'll need to remove the original image from your local
machine. If you left the original image on your machine. Docker would not pull
from the hub &mdash; why would it? The two images are identical.
1. Make sure Docker is running, and open a command line terminal.
2. At the prompt, type `docker images` to list the images you currently have on your local machine.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
maryatdocker/docker-whale latest 7d9495d03763 5 minutes ago 273.7 MB
docker-whale latest 7d9495d03763 2 hours ago 273.7 MB
<none> <none> 5dac217f722c 5 hours ago 273.7 MB
docker/whalesay latest fb434121fc77 5 hours ago 247 MB
hello-world latest 91c95931e552 5 weeks ago 910 B
To make a good test, you need to remove the `maryatdocker/docker-whale` and
`docker-whale` images from your local system. Removing them forces the next
`docker pull` to get the image from your repository.
3. Use the `docker rmi` to remove the `maryatdocker/docker-whale` and `docker-whale`
images.
You can use an ID or the name to remove an image.
$ docker rmi -f 7d9495d03763
$ docker rmi -f docker-whale
4. Pull and load a new image from your repository using the `docker run` command.
The command you type should include your username from Docker Hub.
docker run yourusername/docker-whale
Since the image is no longer available on your local system, Docker downloads it.
$ docker run maryatdocker/docker-whale
Unable to find image 'maryatdocker/docker-whale:latest' locally
latest: Pulling from maryatdocker/docker-whale
eb06e47a01d2: Pull complete
c81071adeeb5: Pull complete
7d9495d03763: Already exists
e9e06b06e14c: Already exists
a82efea989f9: Already exists
37bea4ee0c81: Already exists
07f8e8c5e660: Already exists
676c4a1897e6: Already exists
5b74edbcaa5b: Already exists
1722f41ddcb5: Already exists
99da72cfe067: Already exists
5d5bd9951e26: Already exists
fb434121fc77: Already exists
Digest: sha256:ad89e88beb7dc73bf55d456e2c600e0a39dd6c9500d7cd8d1025626c4b985011
Status: Downloaded newer image for maryatdocker/docker-whale:latest
________________________________________
/ Having wandered helplessly into a \
| blinding snowstorm Sam was greatly |
| relieved to see a sturdy Saint Bernard |
| dog bounding toward him with the |
| traditional keg of brandy strapped to |
| his collar. |
| |
| "At last," cried Sam, "man's best |
\ friend -- and a great big dog, too!" /
----------------------------------------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
## Where to go next
You've done a lot, you've done all of the following fundamental Docker tasks.
* installed Docker
* run a software image in a container
* located an interesting image on Docker Hub
* run the image on your own machine
* modified an image to create your own and run it
* create a Docker Hub account and repository
* pushed your image to Docker Hub for others to share
<a href="https://twitter.com/intent/tweet?button_hashtag=dockerdocs&text=Just%20ran%20a%20container%20with%20an%20image%20I%20built.%20Find%20it%20on%20%23dockerhub.%20Build%20your%20own%3A%20http%3A%2F%2Fgoo.gl%2FMUi7cA" class="twitter-hashtag-button" data-size="large" data-related="docker" target="_blank">Tweet your accomplishment!</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
You've only scratched the surface of what Docker can do. Go to the next page to [learn more](last_page.md).
&nbsp;

View File

@@ -0,0 +1,143 @@
<!--[metadata]>
+++
aliases = [
"/mac/step_three/",
"/windows/step_three/",
"/linux/step_three/",
]
title = "Find & run the whalesay image"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker"]
[menu.main]
identifier = "getstart_locate"
parent = "getstart_all"
weight = 3
+++
<![end-metadata]-->
# Find and run the whalesay image
People all over the world create Docker images. You can find these images by
browsing the Docker Hub. In this next section, you'll search for and find the
image you'll use in the rest of this getting started.
## Step 1: Locate the whalesay image
1. Open your browser and <a href="https://hub.docker.com/?utm_source=getting_started_guide&utm_medium=embedded_MacOSX&utm_campaign=find_whalesay" target=_blank> browse to the Docker Hub</a>.
![Browse Docker Hub](tutimg/browse_and_search.png)
The Docker Hub contains images from individuals like you and official images
from organizations like RedHat, IBM, Google, and a whole lot more.
2. Click **Browse & Search**.
The browser opens the search page.
3. Enter the word `whalesay` in the search bar.
![Browse Docker Hub](tutimg/image_found.png)
4. Click on the **docker/whalesay** image in the results.
The browser displays the repository for the **whalesay** image.
![Browse Docker Hub](tutimg/whale_repo.png)
Each image repository contains information about an image. It should
include information such as what kind of software the image contains and
how to use it. You may notice that the **whalesay** image is based on a
Linux distribution called Ubuntu. In the next step, you run the **whalesay** image on your machine.
## Step 2: Run the whalesay image
Make sure Docker is running. On Docker for Mac and Docker for Windows, this is indicated by the Docker whale showing in the status bar.
1. Open a command-line terminal.
2. Type the `docker run docker/whalesay cowsay boo` command and press RETURN.
This command runs the **whalesay** image in a container. Your terminal should look like the following:
$ docker run docker/whalesay cowsay boo
Unable to find image 'docker/whalesay:latest' locally
latest: Pulling from docker/whalesay
e9e06b06e14c: Pull complete
a82efea989f9: Pull complete
37bea4ee0c81: Pull complete
07f8e8c5e660: Pull complete
676c4a1897e6: Pull complete
5b74edbcaa5b: Pull complete
1722f41ddcb5: Pull complete
99da72cfe067: Pull complete
5d5bd9951e26: Pull complete
fb434121fc77: Already exists
Digest: sha256:d6ee73f978a366cf97974115abe9c4099ed59c6f75c23d03c64446bb9cd49163
Status: Downloaded newer image for docker/whalesay:latest
_____
< boo >
-----
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
The first time you run a software image, the `docker` command looks for it
on your local system. If the image isn't there, then `docker` gets it from
the hub.
5. While still in the command line terminal, type `docker images` command and press RETURN.
The command lists all the images on your local system. You should see
`docker/whalesay` in the list.
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
docker/whalesay latest fb434121fc77 3 hours ago 247 MB
hello-world latest 91c95931e552 5 weeks ago 910 B
When you run an image in a container, Docker downloads the image to your
computer. This local copy of the image saves you time. Docker only
downloads the image again if the image's source changes on the hub. You
can, of course, delete the image yourself. You'll learn more about that
later. Let's leave the image there for now because we are going to use it
later.
6. Take a moment to play with the **whalesay** container a bit.
Try running the `whalesay` image again with a word or phrase. Try a long or
short phrase. Can you break the cow?
$ docker run docker/whalesay cowsay boo-boo
_________
< boo-boo >
---------
\
\
\
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
## Where to go next
On this page, you learned to search for images on Docker Hub. You used your
command line to run an image. Think about it, effectively you ran a piece of
Linux software on your Mac computer. You learned that running an image copies
it on your computer. Now, you are ready to create your own Docker image.
Go on to the next part [to build your own image](step_four.md).
&nbsp;

View File

@@ -0,0 +1,46 @@
<!--[metadata]>
+++
aliases = [
"/mac/step_two/",
"/windows/step_two/",
"/linux/step_two/",
]
title = "Understand images & containers"
description = "Getting started with Docker"
keywords = ["beginner, getting started, Docker"]
[menu.main]
identifier = "getstart_understand"
parent = "getstart_all"
weight = 2
+++
<![end-metadata]-->
# Learn about images & containers
Docker Engine provides the core Docker technology that enables images and
containers. As the last step in your installation, you ran the
`docker run hello-world` command. The command you ran had three parts.
![Container Explainer](tutimg/container_explainer.png)
An *image* is a filesystem and parameters to use at runtime. It doesn't have
state and never changes. A *container* is a running instance of an image.
When you ran the command, Docker Engine:
* checked to see if you had the `hello-world` software image
* downloaded the image from the Docker Hub (more about the hub later)
* loaded the image into the container and "ran" it
Depending on how it was built, an image might run a simple, single command and then exit. This is what `Hello-World` did.
A Docker image, though, is capable of much more. An image can start software as complex as a database, wait for you (or someone else) to add data, store the data for later use, and then wait for the next person.
Who built the `hello-world` software image though? In this case, Docker did but anyone can. Docker Engine lets people (or companies) create and share software through Docker images. Using Docker Engine, you don't have to worry about whether your computer can run the software in a Docker image &mdash; a Docker container *can always run it*.
## Where to go next
See, that was quick wasn't it? Now, you are ready to do some really fun stuff with Docker.
Go on to the next part [to find and run the whalesay image](step_three.md).
&nbsp;

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

View File

@@ -57,7 +57,7 @@ package manager.
$ sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg

View File

@@ -45,19 +45,22 @@ storage driver and a node that is part of a 2 node Swarm cluster:
Paused: 1
Stopped: 10
Images: 52
Server Version: 1.11.1
Server Version: 1.12.0-dev
Storage Driver: overlay
Backing Filesystem: extfs
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge null host
Network: bridge null host overlay
Swarm:
NodeID: 0gac67oclbxq7
IsManager: YES
Managers: 2
Nodes: 2
Runtimes: default
Default Runtime: default
Security Options: apparmor seccomp
Kernel Version: 4.4.0-21-generic
Operating System: Ubuntu 16.04 LTS
OSType: linux

View File

@@ -30,17 +30,17 @@ Example output:
$ docker node inspect swarm-manager
[
{
"ID": "0gac67oclbxq7",
{
"ID": "e216jshn25ckzbvmwlnh5jr3g",
"Version": {
"Index": 2028
"Index": 10
},
"CreatedAt": "2016-06-06T20:49:32.720047494Z",
"UpdatedAt": "2016-06-07T00:23:31.207632893Z",
"CreatedAt": "2016-06-16T22:52:44.9910662Z",
"UpdatedAt": "2016-06-16T22:52:45.230878043Z",
"Spec": {
"Role": "MANAGER",
"Membership": "ACCEPTED",
"Availability": "ACTIVE"
"Role": "manager",
"Membership": "accepted",
"Availability": "active"
},
"Description": {
"Hostname": "swarm-manager",
@@ -50,38 +50,55 @@ Example output:
},
"Resources": {
"NanoCPUs": 1000000000,
"MemoryBytes": 1044250624
"MemoryBytes": 1039843328
},
"Engine": {
"EngineVersion": "1.12.0",
"Labels": {
"provider": "virtualbox"
}
"Plugins": [
{
"Type": "Volume",
"Name": "local"
},
{
"Type": "Network",
"Name": "overlay"
},
{
"Type": "Network",
"Name": "null"
},
{
"Type": "Network",
"Name": "host"
},
{
"Type": "Network",
"Name": "bridge"
},
{
"Type": "Network",
"Name": "overlay"
}
]
}
},
"Status": {
"State": "READY"
"State": "ready"
},
"Manager": {
"Raft": {
"RaftID": 2143745093569717375,
"Addr": "192.168.99.118:4500",
"Status": {
"Leader": true,
"Reachability": "REACHABLE"
}
}
},
"Attachment": {},
}
"ManagerStatus": {
"Leader": true,
"Reachability": "reachable",
"Addr": "168.0.32.137:2377"
}
}
]
$ docker node inspect --format '{{ .Manager.Raft.Status.Leader }}' self
$ docker node inspect --format '{{ .ManagerStatus.Leader }}' self
false
$ docker node inspect --pretty self
ID: 2otfhz83efcc7
Hostname: ad960a848573
ID: e216jshn25ckzbvmwlnh5jr3g
Hostname: swarm-manager
Status:
State: Ready
Availability: Active

View File

@@ -29,10 +29,10 @@ Lists all the nodes that the Docker Swarm manager knows about. You can filter us
Example output:
$ docker node ls
ID NAME STATUS AVAILABILITY MANAGER STATUS LEADER
0gac67oclbxq swarm-master Ready Active Reachable Yes
0pwvm3ve66q7 swarm-node-02 Ready Active
15xwihgw71aw * swarm-node-01 Ready Active Reachable
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER
1bcef6utixb0l0ca7gxuivsj0 swarm-worker2 Accepted Ready Active
38ciaotwjuritcdtn9npbnkuz swarm-worker1 Accepted Ready Active
e216jshn25ckzbvmwlnh5jr3g * swarm-manager1 Accepted Ready Active Reachable Yes
## Filtering
@@ -49,22 +49,21 @@ The currently supported filters are:
### name
The `name` filter matches on all or part of a tasks's name.
The `name` filter matches on all or part of a node name.
The following filter matches the node with a name equal to `swarm-master` string.
$ docker node ls -f name=swarm-master
ID NAME STATUS AVAILABILITY MANAGER STATUS LEADER
0gac67oclbxq * swarm-master Ready Active Reachable Yes
$ docker node ls -f name=swarm-manager1
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER
e216jshn25ckzbvmwlnh5jr3g * swarm-manager1 Accepted Ready Active Reachable Yes
### id
The `id` filter matches all or part of a node's id.
$ docker node ls -f id=0
ID NAME STATUS AVAILABILITY MANAGER STATUS LEADER
0gac67oclbxq * swarm-master Ready Active Reachable Yes
0pwvm3ve66q7 swarm-node-02 Ready Active
$ docker node ls -f id=1
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER
1bcef6utixb0l0ca7gxuivsj0 swarm-worker2 Accepted Ready Active
#### label
@@ -76,8 +75,8 @@ The following filter matches nodes with the `usage` label regardless of its valu
```bash
$ docker node ls -f "label=foo"
ID NAME STATUS AVAILABILITY MANAGER STATUS LEADER
15xwihgw71aw * swarm-node-01 Ready Active Reachable
ID NAME MEMBERSHIP STATUS AVAILABILITY MANAGER STATUS LEADER
1bcef6utixb0l0ca7gxuivsj0 swarm-worker2 Accepted Ready Active
```

View File

@@ -26,13 +26,13 @@ Lists all the tasks on a Node that Docker knows about. You can filter using the
Example output:
$ docker node tasks swarm-master
ID NAME SERVICE IMAGE DESIRED STATE LAST STATE NODE
dx2g0fe3zsdb6y6q453f8dqw2 redis.1 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
f33pcf8lwhs4c1t4kq8szwzta redis.4 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
5v26yzixl3one3ptjyqqbd0ro redis.5 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
adcaphlhsfr30d47lby6walg6 redis.8 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
chancjvk9tex6768uzzacslq2 redis.9 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
$ docker node tasks swarm-manager1
ID NAME SERVICE IMAGE LAST STATE DESIRED STATE NODE
7q92v0nr1hcgts2amcjyqg3pq redis.1 redis redis:3.0.6 Running 5 hours Running swarm-manager1
b465edgho06e318egmgjbqo4o redis.6 redis redis:3.0.6 Running 29 seconds Running swarm-manager1
bg8c07zzg87di2mufeq51a2qp redis.7 redis redis:3.0.6 Running 5 seconds Running swarm-manager1
dkkual96p4bb3s6b10r7coxxt redis.9 redis redis:3.0.6 Running 5 seconds Running swarm-manager1
0tgctg8h8cech4w0k0gwrmr23 redis.10 redis redis:3.0.6 Running 5 seconds Running swarm-manager1
## Filtering
@@ -53,22 +53,22 @@ The `name` filter matches on all or part of a task's name.
The following filter matches all tasks with a name containing the `redis` string.
$ docker node tasks -f name=redis swarm-master
ID NAME SERVICE IMAGE DESIRED STATE LAST STATE NODE
dx2g0fe3zsdb6y6q453f8dqw2 redis.1 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
f33pcf8lwhs4c1t4kq8szwzta redis.4 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
5v26yzixl3one3ptjyqqbd0ro redis.5 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
adcaphlhsfr30d47lby6walg6 redis.8 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
chancjvk9tex6768uzzacslq2 redis.9 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
$ docker node tasks -f name=redis swarm-manager1
ID NAME SERVICE IMAGE LAST STATE DESIRED STATE NODE
7q92v0nr1hcgts2amcjyqg3pq redis.1 redis redis:3.0.6 Running 5 hours Running swarm-manager1
b465edgho06e318egmgjbqo4o redis.6 redis redis:3.0.6 Running 29 seconds Running swarm-manager1
bg8c07zzg87di2mufeq51a2qp redis.7 redis redis:3.0.6 Running 5 seconds Running swarm-manager1
dkkual96p4bb3s6b10r7coxxt redis.9 redis redis:3.0.6 Running 5 seconds Running swarm-manager1
0tgctg8h8cech4w0k0gwrmr23 redis.10 redis redis:3.0.6 Running 5 seconds Running swarm-manager1
### id
The `id` filter matches a task's id.
$ docker node tasks -f id=f33pcf8lwhs4c1t4kq8szwzta swarm-master
ID NAME SERVICE IMAGE DESIRED STATE LAST STATE NODE
f33pcf8lwhs4c1t4kq8szwzta redis.4 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
$ docker node tasks -f id=bg8c07zzg87di2mufeq51a2qp swarm-manager1
ID NAME SERVICE IMAGE LAST STATE DESIRED STATE NODE
bg8c07zzg87di2mufeq51a2qp redis.7 redis redis:3.0.6 Running 5 seconds Running swarm-manager1
#### label
@@ -80,9 +80,9 @@ The following filter matches tasks with the `usage` label regardless of its valu
```bash
$ docker node tasks -f "label=usage"
ID NAME SERVICE IMAGE DESIRED STATE LAST STATE NODE
dx2g0fe3zsdb6y6q453f8dqw2 redis.1 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
f33pcf8lwhs4c1t4kq8szwzta redis.4 redis redis:3.0.6 RUNNING RUNNING 2 hours swarm-master
ID NAME SERVICE IMAGE LAST STATE DESIRED STATE NODE
b465edgho06e318egmgjbqo4o redis.6 redis redis:3.0.6 Running 10 minutes Running swarm-manager1
bg8c07zzg87di2mufeq51a2qp redis.7 redis redis:3.0.6 Running 9 minutes Running swarm-manager1
```

View File

@@ -16,6 +16,12 @@ parent = "smn_cli"
Update a node
Options:
--availability string Availability of the node (active/pause/drain)
--help Print usage
--membership string Membership of the node (accepted/rejected)
--role string Role of the node (worker/manager)
## Related information

View File

@@ -3,9 +3,9 @@
title = "plugin disable"
description = "the plugin disable command description and usage"
keywords = ["plugin, disable"]
advisory = "experimental"
[menu.main]
parent = "smn_cli"
advisory = "experimental"
+++
<![end-metadata]-->

View File

@@ -3,9 +3,9 @@
title = "plugin enable"
description = "the plugin enable command description and usage"
keywords = ["plugin, enable"]
advisory = "experimental"
[menu.main]
parent = "smn_cli"
advisory = "experimental"
+++
<![end-metadata]-->

View File

@@ -3,9 +3,9 @@
title = "plugin inspect"
description = "The plugin inspect command description and usage"
keywords = ["plugin, inspect"]
advisory = "experimental"
[menu.main]
parent = "smn_cli"
advisory = "experimental"
+++
<![end-metadata]-->

View File

@@ -3,9 +3,9 @@
title = "plugin install"
description = "the plugin install command description and usage"
keywords = ["plugin, install"]
advisory = "experimental"
[menu.main]
parent = "smn_cli"
advisory = "experimental"
+++
<![end-metadata]-->

View File

@@ -3,9 +3,9 @@
title = "plugin ls"
description = "The plugin ls command description and usage"
keywords = ["plugin, list"]
advisory = "experimental"
[menu.main]
parent = "smn_cli"
advisory = "experimental"
+++
<![end-metadata]-->

View File

@@ -3,9 +3,9 @@
title = "plugin rm"
description = "the plugin rm command description and usage"
keywords = ["plugin, rm"]
advisory = "experimental"
[menu.main]
parent = "smn_cli"
advisory = "experimental"
+++
<![end-metadata]-->

View File

@@ -22,6 +22,7 @@ parent = "smn_cli"
--help Print usage
--secret string Set secret value needed to accept nodes into cluster
--task-history-limit int Task history retention limit (default 10)
--cert-expiry duration Validity period for node certificates (default 2160h0m0s)
Updates a Swarm cluster with new parameter values. This command must target a manager node.

View File

@@ -3,11 +3,11 @@
title = "Swarm overview"
description = "Docker Swarm overview"
keywords = ["docker, container, cluster, swarm"]
advisory = "rc"
[menu.main]
identifier="swarm_overview"
parent="engine_swarm"
weight="1"
advisory = "rc"
+++
<![end-metadata]-->
# Docker Swarm overview

View File

@@ -3,11 +3,11 @@
title = "Swarm key concepts"
description = "Introducing key concepts for Docker Swarm"
keywords = ["docker, container, cluster, swarm"]
advisory = "rc"
[menu.main]
identifier="swarm-concepts"
parent="engine_swarm"
weight="2"
advisory = "rc"
+++
<![end-metadata]-->
# Docker Swarm key concepts

View File

@@ -3,11 +3,11 @@
title = "Manage a Swarm (1.12 RC)"
description = "How to use Docker Swarm to create and manage Docker Engine clusters"
keywords = [" docker, documentation, developer, "]
advisory = "rc"
[menu.main]
identifier = "engine_swarm"
parent = "engine_use"
weight = 0
advisory = "rc"
+++
<![end-metadata]-->

View File

@@ -3,11 +3,11 @@
title = "Add nodes to the Swarm"
description = "Add nodes to the Swarm"
keywords = ["tutorial, cluster management, swarm"]
advisory = "rc"
[menu.main]
identifier="add-nodes"
parent="swarm-tutorial"
weight=13
advisory = "rc"
+++
<![end-metadata]-->

View File

@@ -3,11 +3,11 @@
title = "Create a Swarm"
description = "Initialize the Swarm"
keywords = ["tutorial, cluster management, swarm"]
advisory = "rc"
[menu.main]
identifier="initialize-swarm"
parent="swarm-tutorial"
weight=12
advisory = "rc"
+++
<![end-metadata]-->

View File

@@ -3,11 +3,11 @@
title = "Delete the service"
description = "Remove the service on the Swarm"
keywords = ["tutorial, cluster management, swarm, service"]
advisory = "rc"
[menu.main]
identifier="swarm-tutorial-delete-service"
parent="swarm-tutorial"
weight=19
advisory = "rc"
+++
<![end-metadata]-->

View File

@@ -3,11 +3,11 @@
title = "Deploy a service"
description = "Deploy the application"
keywords = ["tutorial, cluster management, swarm"]
advisory = "rc"
[menu.main]
identifier="deploy-application"
parent="swarm-tutorial"
weight=16
advisory = "rc"
+++
<![end-metadata]-->
@@ -39,8 +39,8 @@ example, the tutorial uses a machine named `manager1`.
```
$ docker service ls
ID NAME SCALE IMAGE COMMAND
2zs4helqu64f helloworld 1 alpine ping docker.com
ID NAME REPLICAS IMAGE COMMAND
2zs4helqu64f helloworld 1 alpine ping docker.com
```
## What's next?

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