Compare commits

..

961 commits

Author SHA1 Message Date
Joffrey F
aa8fb8f708 Merge pull request #4499 from xulike666/function-name-modification
function-name-modification for tests/*
2017-02-16 11:59:36 -08:00
Joffrey F
b49f42f9b7 Merge pull request #4496 from xulike666/quick-easy-typo-fix
fix a typo in script/release/utils.sh
2017-02-16 11:59:17 -08:00
Joffrey F
afd3bcfbf4 Merge pull request #4484 from shin-/4425-sys-path-fix
Reinitialize sys.path after it's been potentially modified by pip
2017-02-16 11:39:54 -08:00
Aaron.L.Xu
d20e3f3342 function-name-modification for tests/*
Signed-off-by: Aaron.L.Xu <likexu@harmonycloud.cn>
2017-02-16 15:25:20 +08:00
Aaron.L.Xu
27297fd1af fix a typo in script/release/utils.sh
Signed-off-by: Aaron.L.Xu <likexu@harmonycloud.cn>
2017-02-16 11:14:49 +08:00
Joffrey F
66f4a795a2 Don't import pip inside Compose
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-15 16:31:50 -08:00
Joffrey F
40c26ca676 Merge pull request #4480 from shin-/4479-merge-secrets
Fix `config` command output with service.secrets section
2017-02-14 17:08:18 -08:00
Joffrey F
abce83ef25 Fix config command output with service.secrets section
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-13 16:51:50 -08:00
Joffrey F
bb5d7b2433 Merge pull request #4473 from Vehsamrak/patch-1
Compose file reference link fix in README.md
2017-02-13 13:03:39 -08:00
Petr Karmashev
252699c1d1 Compose file reference link fix in README.md
Signed-off-by: Petr Karmashev <smonkl@bk.ru>
2017-02-12 02:10:34 +03:00
Joffrey F
ad0e6d219b Merge pull request #4469 from dnephin/fix_secrets_config
Fixes secrets config loading
2017-02-10 18:39:53 -08:00
Daniel Nephin
dc5b3f3b3e Fix secrets config.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-02-10 17:11:24 -05:00
Joffrey F
1fe2443735 Merge pull request #4438 from fate-grand-order/master
fix typo in CHANGELOG.md
2017-02-09 16:35:35 -08:00
Joffrey F
27e0f31275 Merge pull request #4443 from xulike666/fix-accessibility
Referencing the right segment of code in compose/bundle.py
2017-02-09 16:34:48 -08:00
Joffrey F
2f13201b9e Merge pull request #4453 from kevinetc123/patch-typo
fix typo in project.py
2017-02-09 16:33:07 -08:00
Joffrey F
276db7231a Merge pull request #4455 from dnephin/fix_3.1
Fix version 3.1
2017-02-09 12:38:29 -08:00
Daniel Nephin
c092fa37de Fix version 3.1
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-02-09 12:39:57 -05:00
kevinetc123
47e4442722 fix typo in project.py
Signed-off-by: kevinetc123 <kaiwentan@harmonycloud.cn>
2017-02-09 19:10:26 +08:00
Joffrey F
b306e843d3 Merge pull request #4448 from shin-/1.11-release
1.11 release-master realign
2017-02-08 13:54:12 -08:00
Joffrey F
fc7b74d7f9 Bump to next dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-08 13:47:08 -08:00
Joffrey F
2cd6cb9a47 Bump 1.10.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-08 13:45:25 -08:00
Joffrey F
01d1895a35 Bump 1.11.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-08 13:44:40 -08:00
Joffrey F
979a0d53f7 Bump 1.11.0-rc1
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-08 13:44:31 -08:00
Aaron.L.Xu
f083526829 referencing right segment of code
Signed-off-by: Aaron.L.Xu <likexu@harmonycloud.cn>
2017-02-08 18:50:26 +08:00
fate-grand-order
b392b6e12e fix typo in CHANGELOG.md
Signed-off-by: fate-grand-order <chenjg@harmonycloud.cn>
2017-02-07 15:59:34 +08:00
Joffrey F
165eb9c91a Merge pull request #3558 from shin-/1135-pyinstaller-update
Use newer version of PyInstaller to fix prelinking issues
2017-02-06 15:00:39 -08:00
Joffrey F
1636985a7a Merge pull request #4426 from shin-/4392-context-mgr
Close the open file handle using context manager
2017-02-06 13:30:49 -08:00
Kevin Jing Qiu
a3a9d8944a Close the open file handle using context manager
Signed-off-by: Kevin Jing Qiu <kevin.qiu@points.com>
2017-02-03 14:50:40 -08:00
Joffrey F
951497c0f2 Merge pull request #4419 from shin-/4418-healthcheck-extends
Don't re-parse healthcheck values coming from extended services
2017-02-03 12:24:53 -08:00
Joffrey F
e22164ec9f Merge pull request #4035 from urda/urda/compose-top
Added `top` to `docker-compose` to display running processes
2017-02-02 15:41:14 -08:00
Joffrey F
f106d23776 Merge pull request #4414 from shin-/4184-merge-pids
Add missing comma in DOCKER_CONFIG_KEYS list
2017-02-02 14:51:42 -08:00
Joffrey F
cf43e6edf7 Don't re-parse healthcheck values coming from extended services
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-02 14:50:53 -08:00
Joffrey F
7e8958e6ca Add missing comma in DOCKER_CONFIG_KEYS list
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-01 16:40:43 -08:00
Joffrey F
11038c455b Merge pull request #4334 from muicoder/master
add IMAGE_EVENTS: load/save
2017-02-01 15:49:03 -08:00
Peter Urda
a67500ee57
Added top to docker-compose to display running processes.
This commit allows `docker-compose` to access `top` for containers
much like running `docker top` directly on a given container.

This commit includes:

* `docker-compose` CLI changes to expose `top`
* Completions for `bash` and `zsh`
* Required testing for the new `top` command

Signed-off-by: Peter Urda <peter.urda@gmail.com>
2017-02-01 15:42:30 -08:00
Joffrey F
1f39b33357 Merge pull request #3989 from mattjbray/patch-1
Zsh completion: permit multiple --file arguments
2017-02-01 15:08:39 -08:00
Joffrey F
67e1111806 Merge pull request #4410 from shin-/4408-colors-no-tty
Don't strip ANSI color codes when output is not a TTY
2017-02-01 14:20:10 -08:00
Joffrey F
84774cacd2 Upgrade python and pip versions in Dockerfile
Add libbz2 dependency

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-02-01 14:12:41 -08:00
Joffrey F
c9eb9380ed Merge pull request #4368 from dnephin/secrets-using-bind-mounts
Secrets using bind mounts
2017-02-01 14:11:20 -08:00
Joffrey F
c16cd77737 Merge pull request #4406 from shin-/bump_docker_py
Bump docker SDK version
2017-01-31 15:36:30 -08:00
Joffrey F
8efb7e6e8b Don't strip ANSI color codes when output is not a TTY
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-31 12:51:46 -08:00
Daniel Nephin
59d1847d9b Fix some test failures.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-01-31 09:53:40 -05:00
Daniel Nephin
3a2735abb9 Rebase compose v3.1 on the latest v3
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-01-31 09:53:16 -05:00
Daniel Nephin
0d609b68ac Add a warning for unsupported secret fields.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-01-31 09:53:16 -05:00
Daniel Nephin
4053adc7d3 Add an integration test for secrets using bind mounts.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-01-31 09:53:16 -05:00
Daniel Nephin
e0c6397999 Implement secrets using bind mounts
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-01-31 09:53:16 -05:00
Daniel Nephin
add56ce818 Read service secrets as a type.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-01-31 09:53:16 -05:00
Daniel Nephin
a82de8863e Add v3.1 with secrets.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-01-31 09:53:16 -05:00
Joffrey F
2593366a3e Bump docker SDK version
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 16:49:05 -08:00
Joffrey F
22249add84 Use newer version of PyInstaller to fix prelinking issues
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-30 13:52:27 -08:00
Joffrey F
76d4f5bea6 Merge pull request #4383 from shin-/4344-detect-docker-py
Detect conflicting version of the docker python SDK
2017-01-30 12:14:27 -08:00
Joffrey F
5895d8bbc9 Detect conflicting version of the docker python SDK and prevent execution
until issue is fixed

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-26 17:12:41 -08:00
Joffrey F
e05a9f4e62 Merge pull request #4389 from shin-/4372-normalize-time-values
Convert time data back to string values when serializing config
2017-01-26 13:47:34 -08:00
Joffrey F
e10d1140b9 Convert time data back to string values when serializing config
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-26 11:59:22 -08:00
Joffrey F
56e01f25ea Merge pull request #4367 from dnephin/add-missing-network-internal-to-v3
Add missing network.internal to v3 schema.
2017-01-25 13:41:41 -08:00
Joffrey F
c86faab4ec Merge pull request #4370 from shin-/4357-win32-unicode-paths
Don't encode build context path on Windows
2017-01-23 12:04:42 -08:00
Joffrey F
20d6f450b5 Don't encode build context path on Windows
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-20 15:05:53 -08:00
Daniel Nephin
644e1716c3 Add missing network.internal to v3 schema.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2017-01-20 12:55:59 -05:00
Joffrey F
9a0962dacb Merge pull request #4361 from shin-/4348-serialize-ext-volumes
Remove external_name from volume def in config output
2017-01-19 17:41:08 -08:00
Joffrey F
263b9e9317 Merge pull request #4360 from shin-/4359-volume-labels
Fix volume definition in v3 schema
2017-01-19 17:40:29 -08:00
Joffrey F
d83d31889e Remove external_name from volume def in config output
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-19 16:05:13 -08:00
Joffrey F
5c2165eaaf Fix volume definition in v3 schema
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-19 15:41:31 -08:00
Joffrey F
8a27a0f059 Merge pull request #4350 from shin-/fix-invalid-depends-on-merge
depends_on merge now retains condition information when present
2017-01-19 14:50:29 -08:00
Joffrey F
b47c97e94e Merge pull request #4358 from shin-/1.11-dev
1.11.0dev
2017-01-19 14:50:10 -08:00
Joffrey F
a482c138d8 Merge pull request #4353 from xulike666/fight-for-readability
Fix typo in script/test/versions.py
2017-01-19 14:49:05 -08:00
Joffrey F
1c46525c2b 1.11.0dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-19 14:47:31 -08:00
Aaron.L.Xu
169289c8b6 find a fishbone
Signed-off-by: Aaron.L.Xu <likexu@harmonycloud.cn>
2017-01-20 00:52:19 +08:00
Joffrey F
1a02121ab5 depends_on merge now retains condition information when present
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-18 17:52:03 -08:00
Joffrey F
708c4f9534 Merge pull request #4339 from shin-/4328-catch-healthcheck-exception
Catch healthcheck exceptions in parallel_execute
2017-01-17 14:16:37 -08:00
Joffrey F
56a1b02aac Catch healthcheck exceptions in parallel_execute
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-17 13:22:16 -08:00
muicoder
931027c598 add IMAGE_EVENTS: load/save
Signed-off-by: muicoder <muicoder@gmail.com>
2017-01-16 10:53:40 +08:00
Joffrey F
5ade097d74 Merge pull request #4324 from shin-/4321-v3-depends-on
Provide valid serialization of depends_on when format is not 2.1
2017-01-12 11:52:15 -08:00
Joffrey F
62cdd25b7d Merge pull request #4323 from shin-/fix-push-release-script
Use correct wheel file name in twine upload command
2017-01-12 11:52:05 -08:00
Joffrey F
2df31bb13c Provide valid serialization of depends_on when format is not 2.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-11 16:25:40 -08:00
Joffrey F
29b46d5b26 Use correct wheel file name in twine upload command
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-11 15:39:48 -08:00
Joffrey F
2091149fee Merge pull request #4317 from shin-/release-script-fixes
Fix docker image build script when using universal wheels
2017-01-10 17:21:27 -08:00
Joffrey F
19190ea0df Fix docker image build script when using universal wheels
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-10 16:43:26 -08:00
Joffrey F
1c1fe89e43 Merge pull request #4316 from shin-/update-setup-py
Update setup.py extra_requires
2017-01-10 15:50:11 -08:00
Joffrey F
52792b7a96 Update setup.py extra_requires
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-10 14:59:11 -08:00
Joffrey F
9f6778aa73 Merge pull request #4172 from graingert/enable-universal-wheels
enable universal wheels
2017-01-10 14:57:22 -08:00
Joffrey F
545153f117 Merge pull request #4288 from tntC4stl3/fix_404_issue
Fix 404 issue, change APIError to more accureate ImageNotFound
2017-01-09 16:43:57 -08:00
Joffrey F
3f7b3fbf0a Merge pull request #4304 from shin-/4302-dockerignore-windows
Use docker SDK patch
2017-01-09 16:14:57 -08:00
Joffrey F
88294b46dd Merge pull request #4294 from shin-/4240-compose-convert-false
Ensure falsy values in COMPOSE_CONVERT_WINDOWS_PATHS are properly recognized
2017-01-09 15:49:44 -08:00
Joffrey F
2c157e8fa9 Use docker SDK 2.0.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-09 15:27:20 -08:00
Joffrey F
b570cba965 Merge pull request #3961 from ankon/patch-1
Fix typo
2017-01-09 12:15:04 -08:00
Joffrey F
3bb8a7d178 Merge pull request #4297 from shin-/4271-fix-schemas
Fix config schemas (misplaced "additionalProperties")
2017-01-06 12:10:22 -08:00
Joffrey F
45c7ee4466 Merge pull request #4279 from dnephin/fix-schema-typo
Fix schema typo
2017-01-05 17:15:39 -08:00
Joffrey F
e063c5739f Fix config schemas (misplaced "additionalProperties")
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-05 11:18:21 -08:00
Joffrey F
534b4ed820 Falsy values in COMPOSE_CONVERT_WINDOWS_PATHS are properly recognized
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-04 15:45:11 -08:00
Joffrey F
27d91bba01 Merge pull request #4293 from shin-/stop_timeout_v2.1
Add support for stop_grace_period in v2
2017-01-04 15:14:18 -08:00
Joffrey F
1be41f59c9 Add support for stop_grace_period in v2
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-04 14:30:20 -08:00
Joffrey F
838bdd71f3 Merge pull request #4291 from shin-/unify-healthcheck-def-v2v3
Unify healthcheck spec definition in v2 and v3
2017-01-04 13:53:39 -08:00
Joffrey F
47b672e393 Merge pull request #4051 from shin-/update-release-process
Update release process document to account for recent changes.
2017-01-04 13:15:49 -08:00
Joffrey F
8145429399 Unify healthcheck spec definition in v2 and v3
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-04 13:14:23 -08:00
Joffrey F
be88bb0e6c Merge pull request #4267 from shin-/3754-depends-on-healthcheck
Allow service dependencies to wait on healthy containers
2017-01-04 13:00:19 -08:00
Joffrey F
bef2308530 Fix condition name in config tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-04 11:28:30 -08:00
Joffrey F
04394b1d0a Expand depends_on to allow different conditions (service_start, service_healthy)
Rework "up" and "start" to wait on conditional state of dependent services
Add integration tests

Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-04 11:28:30 -08:00
Joffrey F
f6edd610f3 Add 3.0 schema to docker-compose.spec
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-04 11:26:45 -08:00
Joffrey F
0edfe08bf0 Add healthchecks to 2.1 schema. Update depends_on
Signed-off-by: Joffrey F <joffrey@docker.com>
2017-01-04 11:26:45 -08:00
Thomas Grainger
2648af6807
enable universal wheels
Signed-off-by: Thomas Grainger <tom.grainger@procensus.com>
2017-01-04 18:33:58 +00:00
Jun Guo
c73fc26824 Fix 404 issue, change APIError to more accureate ImageNotFound
Signed-off-by: Jun Guo <blackhumour.gj@gmail.com>
2017-01-04 15:42:31 +08:00
Daniel Nephin
a74b2f2f70 Fix schema typo.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-12-28 15:16:53 -05:00
Joffrey F
09690e1758 Merge pull request #4220 from shin-/4211-default_network_labels
Add default labels to networks and volumes created by Compose
2016-12-20 02:34:57 -08:00
Joffrey F
3058e39407 Merge pull request #4268 from shin-/jtakkala-3765-sysctl-support
Add sysctl option support when creating service
2016-12-20 02:34:02 -08:00
Joffrey F
e1ebb0df22 Merge pull request #4070 from shin-/use-colorama
Use colorama to enable colored output on Windows
2016-12-20 02:32:51 -08:00
Joffrey F
ba47fb99ba Add default labels to networks and volumes created by Compose
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-19 20:43:35 -08:00
Joffrey F
346802715d Use colorama to enable colored output on Windows
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-19 20:40:47 -08:00
Joffrey F
eb6441c8e3 Add sysctls option to 3.0 schema
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-19 20:35:09 -08:00
Joffrey F
82230071d5 Merge branch '3765-sysctl-support' of https://github.com/jtakkala/compose into jtakkala-3765-sysctl-support
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-19 20:33:54 -08:00
Joffrey F
e6b2949edc Merge pull request #4216 from lawliet89/userns_mode
Implement `userns_mode` HostConfig for services
2016-12-19 18:12:15 -08:00
Joffrey F
ea7b565009 Merge pull request #4232 from shin-/attachable_networks
Make created networks attachable for file format >=2.1
2016-12-16 13:06:57 -08:00
Joffrey F
e736151ee4 Make created networks attachable for file format >=2.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-16 12:23:24 -08:00
Joffrey F
fb165d9c15 Add v3_only marker to healthcheck test
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-16 12:21:59 -08:00
Joffrey F
9cb6a70b6f Merge pull request #4219 from shin-/dockerpy_2.0
Use docker SDK 2.0
2016-12-14 16:19:34 -08:00
Joffrey F
04e5925a23 Use docker SDK 2.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-14 15:36:08 -08:00
Joffrey F
635a281777 Merge pull request #4163 from aanand/add-healthcheck
Implement 'healthcheck' option
2016-12-14 15:35:05 -08:00
Aanand Prasad
599b29e405 Merge pull request #4213 from shin-/4212-interactive-connect
Win32 interactive run - Connect container to networks before starting
2016-12-08 13:41:33 +00:00
Aanand Prasad
30eac9f1ae Merge pull request #4226 from dnephin/update-api-version-for-v3
Increase minimum version for compose format v3
2016-12-07 16:59:28 +00:00
Daniel Nephin
e04a12b5ca Increase minimum version for v3.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-12-07 11:16:40 -05:00
Joffrey F
b453ee46e8 Merge pull request #4228 from shin-/bump_version
Bump master version to 1.10.0dev
2016-12-06 17:50:44 -08:00
Joffrey F
4d0575355c Bump master version to 1.10.0dev
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-06 17:14:05 -08:00
Yong Wen Chua
62f8b1402e Implement userns_mode HostConfig for services
Fixes #3349

This allows the key `userns_mode` to be used in service definitions.
Since `userns_mode` requires API version > 1.23, this is only available
in 2.1 and 3.0 versions of compose file

Signed-off-by: Yong Wen Chua <me@yongwen.xyz>
2016-12-05 14:25:56 +08:00
Joffrey F
6aacf51427 Win32 interactive run - Connect container to networks before starting
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-12-02 16:10:15 -08:00
Joffrey F
9bfb855b89 Merge pull request #4187 from ijc25/pull-urxvt-corruption
progress_stream: Avoid undefined ANSI escape codes
2016-12-02 13:54:08 -08:00
Ian Campbell
dc9184a90f progress_stream: Avoid undefined ANSI escape codes
The ANSI escape codes \e[0A (cursor up 0 lines) and \e[0B (cursor down 0 lines)
are not well defined and are treated differently by different terminals. In
particular xterm treats 0 as a missing parameter and therefore defaults to 1,
whereas rxvt-unicode treats these escapes as a request to move 0 lines.

However the use of these codes is unnecessary and were really just hiding the
fact that we were not correctly computing diff when adding a new line. Having
added the new line to the ids map and output the corresponding \n the correct
diff would be 1 and not 0 (which xterm interprets as 1) as currently.

Rather than changing the hardcoded 0 to a 1 pull the diff calculation out and
always do it since it produces the correct answer in both cases.

This fixes similar corruption when compose is pulling an image to that seen
with `docker pull` and rxvt-unicode (and likely other terminals in that family)
seen in docker/docker#28111.

This is the same as the fix made to Docker's pkg/jsonmessage in
https://github.com/docker/docker/pull/28238 (and I have shamelessly ripped off
most of this commit message from there).

Signed-off-by: Ian Campbell <ian.campbell@docker.com>
2016-11-25 10:16:37 +00:00
Joffrey F
def150a129 Merge pull request #4173 from graingert/case-pypi-correctly
case PyPI correctly
2016-11-22 18:15:10 -08:00
Aanand Prasad
af894b4dff Merge pull request #4170 from dnephin/warn-on-deploy
Update messages about docker stack deploy
2016-11-22 17:07:13 +00:00
Thomas Grainger
024b5dd6da
case PyPI correctly
Signed-off-by: Thomas Grainger <tom.grainger@procensus.com>
2016-11-22 11:15:21 +00:00
Daniel Nephin
c26a2afaf3 Update messages about docker stack deploy.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-11-21 16:34:49 -05:00
Aanand Prasad
716a6baa59 Implement 'healthcheck' option
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-11-18 14:47:02 +00:00
Joffrey F
f5ad3e7577 Merge pull request #4165 from shin-/changelog_update
Changelog update
2016-11-17 13:29:32 -08:00
Joffrey F
b93211881b Changelog update
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-16 13:35:29 -08:00
Aanand Prasad
466ebb6cc1 Merge pull request #4146 from dnephin/add-stop-grace-period
Add stop grace period to v3
2016-11-16 17:56:20 +00:00
Daniel Nephin
079c95c340 Use stop grace period for container stop.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-11-16 12:12:28 -05:00
Daniel Nephin
6cac48c056 Add a vendored and modified pytimeparse
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-11-16 12:10:32 -05:00
Aanand Prasad
586443ba5d Merge pull request #4147 from aanand/version-3.0
Support version 3.0 of the Compose file format
2016-11-16 16:34:50 +00:00
Aanand Prasad
f75ef6862f Warn if any services use 'deploy'
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-11-16 16:07:02 +00:00
Aanand Prasad
d717c88b6e Support version 3.0 of the Compose file format
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-11-16 16:07:02 +00:00
Joffrey F
721bf89447 Merge pull request #4134 from shin-/fix_none_opts_network_check
Avoid breaking when remote driver options are null
2016-11-15 15:01:24 -08:00
Joffrey F
09540339e0 Merge pull request #4131 from aanand/test-environment-overrides-env-file
Test that values in 'environment' override env files
2016-11-15 14:18:54 -08:00
Joffrey F
7f60ff5ae6 Avoid breaking when remote driver options are null.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-15 12:00:52 -08:00
Joffrey F
3d0747017a Merge pull request #4151 from shin-/fix_ignore_pull_failure_behavior_1.13
Handle new pull failures behavior in Engine 1.13
2016-11-15 12:00:19 -08:00
Joffrey F
efb4ed1b9e Handle new pull failures behavior in Engine 1.13
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-15 11:30:52 -08:00
Joffrey F
d7e9748501 Merge pull request #4150 from shin-/test_only_ubuntu_host
Limit testing pool to Ubuntu hosts to avoid errors with dind
2016-11-14 18:04:30 -08:00
Joffrey F
0291d9ade5 Limit testing pool to Ubuntu hosts to avoid errors with dind not
starting properly.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-14 17:23:25 -08:00
Jari Takkala
91620ae97b Add sysctl option support when creating service
Closes #3765

Signed-off-by: Jari Takkala <jtakkala@gmail.com>
2016-11-10 16:41:16 -05:00
Aanand Prasad
ba249e5179 Test that values in 'environment' override env files
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-11-09 15:10:27 +00:00
Joffrey F
0e28163ccb Merge pull request #4115 from shin-/fix_overlay_options_mismatch
Call check_remote_network_config from Network.ensure
2016-11-08 15:35:38 -08:00
Aanand Prasad
0902edef43 Merge pull request #4113 from shin-/4103-merge-empty-logging
Fix logging dict merging
2016-11-08 14:56:27 +00:00
Joffrey F
4aa7d15d97 Call check_remote_network_config from Network.ensure
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-04 10:51:14 -07:00
Joffrey F
10417eebd7 Fix logging dict merging
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-03 17:22:31 -07:00
Joffrey F
9046e33ab2 Merge pull request #4112 from mikedougherty/rm-docs-checker
Remove docs checker from Jenkinsfile and use cleanWorkspace option on wrappedNode
2016-11-03 17:22:05 -07:00
Mike Dougherty
da1508051d Remove docs checker from Jenkinsfile and use cleanWorkspace option on wrappedNode
Signed-off-by: Mike Dougherty <mike.dougherty@docker.com>
2016-11-03 14:00:17 -07:00
Joffrey F
969abca47f Merge pull request #4098 from shin-/fix_overlay_options_mismatch
Add whitelisted driver option added by the overlay driver
2016-11-03 11:43:11 -07:00
Joffrey F
d525dd1846 Merge pull request #4104 from shin-/bump_docker_py
Bump docker-py
2016-11-03 11:43:04 -07:00
Joffrey F
7a430dbe96 Updated docker-py dependency to latest version
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-02 16:56:45 -07:00
Joffrey F
3b46a62f36 Merge pull request #4073 from mikedougherty/jenkinsfile
Update Jenkinsfile to run "janky" tasks
2016-11-02 14:55:11 -07:00
Joffrey F
ba43d08fbd Add whitelisted driver option added by the overlay driver to avoid breakage
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-11-01 11:47:12 -07:00
Joffrey F
ed71391f66 Merge pull request #4062 from strayobject/patch-1
fix(docs): updated documentation links
2016-10-28 11:55:58 -07:00
Joffrey F
e563b58595 Merge pull request #4071 from NiR-/fix/run-as-container
Fix path of the parent dir of COMPOSE_FILE
2016-10-27 15:03:54 -07:00
Aanand Prasad
62c9ed93d0 Merge pull request #4084 from shin-/bump_docker_py
Bump docker-py version to include latest patch
2016-10-27 12:53:44 -07:00
Joffrey F
046144e8f4 Bump docker-py version to include latest patch
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-27 12:13:32 -07:00
Mike Dougherty
4871523d5e Update Jenkinsfile to perform existing jenkins tasks
Signed-off-by: Mike Dougherty <mike.dougherty@docker.com>
2016-10-25 11:51:02 -07:00
Aanand Prasad
505c785c5c Merge pull request #4066 from shin-/fix-schema-divergence
Fix schema divergence - add missing fields to compose 2.1 schema
2016-10-25 11:20:51 -07:00
Albin Kerouanton
99343fd76c Fix path of the parent dir of COMPOSE_FILE
Signed-off-by: Albin Kerouanton <albin.kerouanton@knplabs.com>
2016-10-25 11:09:45 +02:00
Aanand Prasad
8b5782ba9f Merge pull request #4067 from shin-/portable-find-exe
Replace "which" calls with the portable find_executable function
2016-10-24 16:15:21 -07:00
Aanand Prasad
d586328812 Merge pull request #4065 from shin-/refine-swarm-warning
Do not print Swarm mode warning when connecting to a UCP server
2016-10-24 16:15:14 -07:00
Aanand Prasad
021bb41fc6 Merge pull request #4069 from shin-/project_tests_robustness
Improve robustness of a couple integration tests with occasional failures
2016-10-24 15:35:52 -07:00
Joffrey F
60d005b055 Improve robustness of a couple integration tests with occasional failures
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-24 13:58:45 -07:00
Joffrey F
d2fb146913 Replace "which" calls with the portable find_executable function
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-24 13:22:52 -07:00
Joffrey F
43e29b41c0 Fix schema divergence - add missing fields to compose 2.1 schema
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-24 11:51:45 -07:00
Joffrey F
a652b6818c Merge pull request #4064 from shin-/missing-2.1-spec
Add missing config schema to docker-compose.spec
2016-10-24 11:43:17 -07:00
Joffrey F
ea68be3441 Do not print Swarm mode warning when connecting to a UCP server
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-24 11:36:44 -07:00
Joffrey F
2c24bc3a08 Add missing config schema to docker-compose.spec
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-24 10:55:04 -07:00
Michal Zdrojewski
3d8dc6f47a fix(docs): updated documentation links
Signed-off-by: Michal Zdrojewski <code@strayobject.co.uk>
2016-10-24 15:41:31 +01:00
Joffrey F
f039c8b43c Update release process document to account for recent changes.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-20 17:47:07 -07:00
Joffrey F
3147090fb4 Merge pull request #4030 from shin-/npipe-fixes
Bump docker-py dependency (includes several npipe fixes)
2016-10-19 11:44:52 -07:00
Joffrey F
de15ec835a Merge pull request #3980 from aanand/shell-out-attach
Attach interactively on Windows by shelling out
2016-10-19 11:14:36 -07:00
Joffrey F
2d3c76950f Merge pull request #3972 from shin-/fix-contributors-script
Fix the contributors script
2016-10-18 15:25:55 -07:00
Joffrey F
932b3cc10a Merge pull request #4026 from shin-/3923-windows-volumes
Do not normalize volume paths on Windows by default
2016-10-18 14:41:52 -07:00
Joffrey F
db5d2bcb10 Merge pull request #3990 from shin-/fix-osx-build
Fix openssl dependency in OSX binary build
2016-10-18 14:14:30 -07:00
Joffrey F
cd94c37f5d Fix merge error (missing Network.labels attribute)
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-18 14:09:31 -07:00
Joffrey F
efb09af271 Do not normalize volume paths on Windows by default
Add environment variable to enable normalization if needed.
Do not normalize internal paths

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-18 12:17:56 -07:00
Joffrey F
f60c60205b Merge branch 'dbdd4us-master' 2016-10-17 14:09:40 -07:00
Joffrey F
14716bc2da Merge branch 'master' of https://github.com/dbdd4us/compose into dbdd4us-master 2016-10-17 14:09:09 -07:00
Joffrey F
882084932d Upgrade docker-py to latest version
Adjust required requests version

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-17 14:03:21 -07:00
Joffrey F
a5c1e4b0cd Merge pull request #3991 from shin-/3906-isolation-config
Add support for "isolation" in config
2016-10-17 11:02:11 -07:00
Joffrey F
95c6cc0420 Merge pull request #3994 from shin-/3430-enable-ipv6
Add support for enable_ipv6 in network definition.
2016-10-17 11:02:00 -07:00
Joffrey F
50faddb683 Merge pull request #4034 from realab/fix-restart-with-null-string
fix serialize restart spec with null string
2016-10-14 14:34:35 -07:00
Aanand Prasad
925915eb25 Show clear error when docker binary can't be found
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-10-14 17:31:21 +01:00
Aanand Prasad
8314a48a2e Attach interactively on Windows by shelling out
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-10-14 17:31:21 +01:00
Aanand Prasad
8b383ad795 Refactor "docker not found" message generation, add Windows message
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-10-14 17:31:21 +01:00
realityone
22d91f60be
fix serialize restart spec with null string
Signed-off-by: realityone <realityone@me.com>
2016-10-14 18:20:55 +08:00
dbdd
bdcce13f4a add support for creating volume and network with label definition
Signed-off-by: dbdd <wangtong2712@gmail.com>
2016-10-12 10:35:14 +08:00
Joffrey F
e4bb9bde30 Merge pull request #3964 from shin-/3963-unicode-env
Don't break when interpolating environment with unicode characters
2016-10-11 12:00:36 -07:00
Joffrey F
7f1606545d Merge pull request #4004 from shin-/4000-extend-logging
Properly merge logging dictionaries in overriding configs
2016-10-11 12:00:06 -07:00
Joffrey F
0603b445e2 Properly merge logging dictionaries in overriding configs
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-10 15:39:05 -07:00
Joffrey F
9248298a4a Merge pull request #4016 from shin-/4008-unicode-formatter
Handle formatter case where logrecord message is binary containing unicode
2016-10-06 16:49:03 -07:00
Joffrey F
bc3ed6dead Merge pull request #3992 from shin-/3701-npipe-windows-default
Use docker-py's default behavior when no explicit host on Windows
2016-10-06 16:48:35 -07:00
Joffrey F
e5ded6ff9b Add support for enable_ipv6 in network definition.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-06 15:49:08 -07:00
Joffrey F
804555bc4d Merge pull request #4015 from dnephin/fix-inline-defaults
Support non-alphanumeric default values.
2016-10-06 15:46:35 -07:00
Joffrey F
17c5b45641 Handle formatter case where logrecord message is binary containing
unicode characters.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-06 15:39:47 -07:00
Daniel Nephin
2bce81508e Support non-alphanumeric default values.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-10-06 17:04:19 -04:00
Victoria Bialas
8f636d8279 Merge pull request #4010 from londoncalling/add-vnext-info
updated README per vnext branch plan
2016-10-05 18:47:00 -07:00
Joffrey F
b50b14f937 Fix openssl dependency in OSX binary build
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-10-05 17:08:14 -07:00
Victoria Bialas
a8ff4285d1 updated README per vnext branch plan
Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-10-05 16:19:09 -07:00
Joffrey F
eac01a7cd5 Merge pull request #3108 from dnephin/inplace_var_defaults
Support inline default values for interpolation
2016-10-05 14:22:02 -07:00
John Mulhausen
85d6d7955f Merge pull request #4005 from johndmulhausen/master
Remove old documentation source, add README on migration
2016-10-04 19:08:36 -07:00
John Mulhausen
1a4e81920b Remove old documentation source, add README on migration
Signed-off-by: John Mulhausen <john@docker.com>
2016-10-04 17:58:44 -07:00
Matt Bray
a37d99f201 Zsh completion: change --file description text
Signed-off-by: Matt Bray <mattjbray@gmail.com>
2016-09-30 00:45:46 +01:00
Daniel Nephin
fe08be698d Support inline default values.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-09-29 12:46:11 -04:00
Joffrey F
007cf96452 Use docker-py's default behavior when no explicit host on Windows
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-28 15:36:57 -07:00
Joffrey F
dc8a39f70d Add support for "isolation" in config
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-28 15:31:58 -07:00
Matthew Bray
90356b7040 Zsh completion: permit multiple --file arguments
Before this change:

```
$ docker-compose --file docker-compose.yml -<TAB>
 -- option --
--help                 -h  -- Get help
--host                 -H  -- Daemon socket to connect to
--project-name         -p  -- Specify an alternate project name (default: directory name)
--skip-hostname-check      -- Don't check the daemon's hostname against the name specified in the client certificate (for example if your docker host is an IP address)
--tls                      -- Use TLS; implied by --tlsverify
--tlscacert                -- Trust certs signed only by this CA
--tlscert                  -- Path to TLS certificate file
--tlskey                   -- Path to TLS key file
--tlsverify                -- Use TLS and verify the remote
--verbose                  -- Show more output
--version              -v  -- Print version and exit
```

(Note the `--file` argument is no longer available to complete.)

After this change:

```
docker-compose --file docker-compose.yml -<TAB>
 -- option --
--file                 -f  -- Specify an alternate docker-compose file (default: docker-compose.yml)
--help                 -h  -- Get help
--host                 -H  -- Daemon socket to connect to
--project-name         -p  -- Specify an alternate project name (default: directory name)
--skip-hostname-check      -- Don't check the daemon's hostname against the name specified in the client certificate (for example if your docker host is an IP address)
--tls                      -- Use TLS; implied by --tlsverify
--tlscacert                -- Trust certs signed only by this CA
--tlscert                  -- Path to TLS certificate file
--tlskey                   -- Path to TLS key file
--tlsverify                -- Use TLS and verify the remote
--verbose                  -- Show more output
--version              -v  -- Print version and exit
```

Signed-off-by: Matt Bray <mattjbray@gmail.com>
2016-09-28 12:04:13 +01:00
Joffrey F
5667de87e8 Fix the contributors script to show only contributors on the current branch
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-22 12:34:59 -07:00
Joffrey F
f65f89ad8c Merge pull request #3653 from shin-/3637-link-local-ips
Add support for link-local IPs in service.networks definition
2016-09-22 11:58:29 -07:00
Daniel Nephin
5b27389571 Merge pull request #3956 from shin-/update_dockerpy_version
Bump docker-py dependency
2016-09-21 10:08:48 -04:00
Joffrey F
53fa44c01e Don't break when interpolating environment with unicode characters
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-20 18:05:59 -07:00
Joffrey F
7687412e03 Merge pull request #3922 from shin-/3897-volumespec_parse_win32
Improve volumespec parsing on windows platforms
2016-09-20 13:09:37 -07:00
Joffrey F
33424189d4 Denormalize function defaults to latest version
Minor docs fix

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-20 11:47:14 -07:00
Joffrey F
7911659266 Improve volumespec parsing on windows platforms
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-20 11:24:24 -07:00
Andreas Kohn
cb3bf869f4 Fix typo
Signed-off-by: Andreas Kohn <andreas.kohn@gmail.com>
2016-09-20 13:59:17 +02:00
Joffrey F
1648a3e257 Merge pull request #3709 from Knetic/groupadd
Supported group_add
2016-09-19 17:18:06 -07:00
Joffrey F
fc6791f3f0 Bump docker-py dependency
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-16 14:12:15 -07:00
Joffrey F
1d03baa9b1 Merge pull request #3954 from shin-/windows_tcp_default
Force default host on windows to the default TCP host (instead of npipe)
2016-09-16 14:09:10 -07:00
Joffrey F
64517e31fc Force default host on windows to the default TCP host (instead of npipe)
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-16 11:43:25 -07:00
Joffrey F
66b395d950 Include docker-py link-local fix and improve integration test
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-15 14:55:42 -07:00
Joffrey F
fd254caa68 Add support for link-local IPs in service.networks definition
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-15 14:55:14 -07:00
Joffrey F
651283eef9 Merge pull request #3941 from shin-/3888-recover-apierror-logs
Catch APIError while printing container logs
2016-09-13 12:58:40 -07:00
Joffrey F
f065ce0f73 Merge pull request #3942 from shin-/3873-syslog-logs-error
Only allow log streaming if logdriver is json-file
2016-09-13 12:28:27 -07:00
Joffrey F
3fcd648ba2 Catch APIError while printing container logs
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-13 12:10:41 -07:00
Joffrey F
7dd2e33057 Only allow log streaming if logdriver is json-file or journald
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-13 11:56:26 -07:00
Joffrey F
1b2354c6f4 Merge pull request #3943 from aanand/fix-integration-test-on-docker-for-mac
Fix integration test on Docker for Mac
2016-09-13 11:54:16 -07:00
Daniel Nephin
ac9198e638 Merge pull request #3930 from shin-/update_dockerpy_version
Update docker-py dependency to latest release
2016-09-13 10:35:56 -04:00
Daniel Nephin
9faa852d41 Merge pull request #3921 from shin-/3890-pull-services
Fix command hint in bundle to pull services instead of images
2016-09-13 10:32:14 -04:00
Aanand Prasad
9759f27fa6 Fix integration test on Docker for Mac
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-09-13 14:50:37 +01:00
Joffrey F
b64bd07f22 Update docker-py dependency to latest release
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-12 14:34:07 -07:00
George Lester
dada36f732 Supported group_add
Signed-off-by: George Lester <glester491@gmail.com>
2016-09-11 23:10:49 -07:00
Joffrey F
817c76c8e9 Fix command hint in bundle to pull services instead of images
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-09-08 11:17:39 -07:00
Joffrey F
3dec600d82 Merge pull request #3830 from shin-/3534-machine-config-args
Remove surrounding quotes from TLS paths, if present
2016-09-07 18:35:43 -07:00
Ben Firshman
c197e02ecc Merge pull request #3814 from aanand/disambiguate-swarm
Disambiguate 'Swarm' in integration doc
2016-09-07 10:46:14 +01:00
Joffrey F
267a243f80 Merge pull request #3799 from aanand/handle-connection-error-on-project-init
Handle connection errors on project initialization
2016-09-06 10:25:48 -07:00
Sven Dowideit
08179fc7e3 Merge pull request #3865 from SvenDowideit/add-jenkinsfile
Add docs checking Jenkinsfile
2016-08-24 15:01:36 +10:00
Sven Dowideit
bf91c64983 Add docs checking Jenkinsfile
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2016-08-22 12:18:07 +10:00
Ben Firshman
acfe100686 Merge pull request #3542 from jfroche/add_swappiness
Add support for swappiness constraint
2016-08-16 13:58:33 +01:00
Jean-François Roche
d824cb9b06 Add support for swappiness constraint
Run a service using `docker run --memory-swappiness=0` (see
https://docs.docker.com/engine/reference/run/)

refs #2383

Signed-off-by: Jean-François Roche <jfroche@affinitic.be>
2016-08-16 11:02:51 +02:00
Joffrey F
13bcd85eb3 Merge pull request #3808 from jgsqware/patch-1
Update rm.md
2016-08-09 15:16:48 -07:00
Joffrey F
c0305024f5 Remove surrounding quotes from TLS paths, if present
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-09 15:13:01 -07:00
JG²
17f46f8999 Update rm.md
Receiving this message when using the -a flag : `--all flag is obsolete. This is now the default behavior of `docker-compose rm`, I proposed to mark it in the docs but I don't know which way is the best

Signed-off-by: jgsqware <garciagonzalez.julien@gmail.com>
2016-08-05 13:41:20 +02:00
Aanand Prasad
4cba653eeb Disambiguate 'Swarm' in integration doc
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-08-04 15:19:02 +01:00
Aanand Prasad
d29f8e1022 Merge pull request #3789 from shin-/3788-json-splitter-fix
json_splitter: Don't break when buffer contains leading whitespace.
2016-08-03 13:23:52 +01:00
Joffrey F
9abbe1b7f8 Catchable error for parse failures in split_buffer
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-08-02 12:48:32 -07:00
Aanand Prasad
b3a4d76d4f Handle connection errors on project initialization
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-08-02 11:44:25 +01:00
Victoria
589fb4925e Merge pull request #3797 from aanand/note-about-experimental-build
Add note to bundle docs about requiring an experimental Engine build
2016-08-01 12:25:38 -07:00
Aanand Prasad
48258e2b46 Add note to bundle docs about requiring an experimental Engine build
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-08-01 12:25:49 +01:00
Joffrey F
6ce066274e Merge pull request #3784 from aanand/fix-timeout-error
Fix stacktrace when handling timeout error
2016-07-29 14:09:21 -07:00
Joffrey F
6f4be1cffc json_splitter: Don't break when buffer contains leading whitespace.
Add error logging with detailed output for decode errors

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-29 14:05:59 -07:00
Aanand Prasad
5aeeecb6f2 Fix stacktrace when handling timeout error
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-29 17:12:46 +01:00
Daniel Nephin
dec2c83014 Merge pull request #3778 from shin-/1.8.0-release-master-changes
1.8.0 release master changes
2016-07-27 18:04:43 -04:00
Joffrey F
d5765b7856 Merge pull request #3771 from aanand/shell-completion-for-push-images
Shell completion for --push-images
2016-07-27 13:35:05 -07:00
Joffrey F
6ab0607e61 Switch back to dev version
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-27 13:30:52 -07:00
Joffrey F
1110af1bae Bump 1.8.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-27 13:30:06 -07:00
Aanand Prasad
7fafd72c1e Bump 1.8.0-rc3
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-27 13:22:20 -07:00
Aanand Prasad
60622026fa Bump 1.8.0-rc2
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-27 13:22:07 -07:00
Joffrey F
22c0779a49 Bump 1.8.0-rc1
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-27 13:21:47 -07:00
Joffrey F
647f260b0a Merge pull request #3774 from aanand/fix-tls-version-error-message
Fix error message for unrecognised TLS version
2016-07-27 10:35:21 -07:00
Aanand Prasad
ec825af3d3 Fix error message for unrecognised TLS version
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-27 18:26:40 +01:00
Aanand Prasad
6633f1962c Shell completion for --push-images
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-27 16:00:53 +01:00
Aanand Prasad
e9d62e8404 Merge pull request #3676 from aanand/warn-for-swarm-mode
Show a warning when engine is in swarm mode
2016-07-27 15:38:09 +01:00
Aanand Prasad
ef4ad93d1e Merge pull request #3760 from bfirsh/useragent
Add user agent to API calls
2016-07-27 14:55:18 +01:00
Aanand Prasad
69b91ef6ba Merge pull request #3636 from dnephin/add_missing_ref_docs
Add missing reference docs for push and bundle
2016-07-27 14:30:17 +01:00
Ben Firshman
1877a41b92
Add user agent to API calls
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-07-27 14:26:15 +01:00
Aanand Prasad
5f0186e008 Merge pull request #3769 from shin-/upgrade-dockerpy-1.9.0
Update to docker-py 1.9.0
2016-07-27 11:56:13 +01:00
Joffrey F
7f3375c2ce Update docker-py requirement to the latest release
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-07-26 13:07:38 -07:00
Daniel Nephin
2fec6966d4 Add reference docs for push and bundle.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-07-26 15:18:09 -04:00
Ben Firshman
4a8b88bc2e Merge pull request #3763 from aanand/remove-experimental-networking-doc
Remove doc on experimental networking support
2016-07-26 14:24:04 +01:00
Aanand Prasad
8ffbe8e083 Remove note about .dsb
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-26 11:59:04 +01:00
Aanand Prasad
28e6508f4a Add note about missing volume mount support
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-26 11:51:30 +01:00
Aanand Prasad
8924f6c05c Fix example image hash
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-26 11:51:16 +01:00
Aanand Prasad
4598dfc79f Merge pull request #3762 from aanand/pull-flag-on-bundle
Rename --fetch-digests to --push-images and remove auto-pull
2016-07-26 11:01:32 +01:00
Aanand Prasad
887ed8d1b6 Rename --fetch-digests to --push-images and remove auto-pull
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-25 17:36:24 +01:00
Aanand Prasad
583bbb4635 Copy experimental bundle docs into Compose docs so URL is stable
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-25 13:46:56 +01:00
Aanand Prasad
2c9e46f60f Show a warning when engine is in swarm mode
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-25 13:46:56 +01:00
Aanand Prasad
07e2426d89 Remove doc on experimental networking support
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-25 13:38:04 +01:00
Daniel Nephin
619bf4c4df Merge pull request #3705 from aanand/fix-timeout-message
Fix timeout value in error message
2016-07-22 10:57:41 -04:00
Daniel Nephin
10749e187c Merge pull request #3718 from aanand/fix-run-entrypoint
Fix bugs with entrypoint/command in docker-compose run
2016-07-22 10:55:25 -04:00
Aanand Prasad
7f65caa97b Merge pull request #3747 from aanand/clarify-env-docs
Clarify environment, env_file and build.args docs
2016-07-21 16:14:26 +01:00
Daniel Nephin
a9b5e5abe0 Merge pull request #3751 from ijc25/master
Tidy up remaining lingering docker.client.Client objects in test suite
2016-07-21 11:13:29 -04:00
Ian Campbell
d6f70dddc7 Call the superclass tearDown in VolumeTest
Currently it doesn't actually seem to make any practical difference that this
is missing, but it seems like good practice to do so anyway, to be robust
against future test case changes which might require cleanup done in the super
class.

Signed-off-by: Ian Campbell <ian.campbell@docker.com>
2016-07-21 13:17:53 +01:00
Ian Campbell
3124fec01a tearDown tmp_volumes array itself in VolumeTest
Each volume in the array holds a reference to a docker.client.Client object and
therefore a connection pool which leaves fds open once the test has completed.

Signed-off-by: Ian Campbell <ian.campbell@docker.com>
2016-07-21 13:17:53 +01:00
Ian Campbell
5cdf30fc12 Teardown project and db in ResilienceTest
These hold a reference to a docker.client.Client object and therefore a
connection pool which leaves fds open once the test has completed.

Signed-off-by: Ian Campbell <ian.campbell@docker.com>
2016-07-21 13:17:53 +01:00
Aanand Prasad
26b819ca67 Merge pull request #3748 from ijc25/master
tearDown the project override at the end of each test case
2016-07-20 16:28:45 +01:00
Ian Campbell
0483bcb472 delete DockerClientTestCase.client class attribute on tearDownClass
This is a docker.client.Client and therefore contains a connection pool, so
each subclass of DockerClientTestCase can end up holding on to up to 10 Unix
socket file descriptors after the tests contained in the sub-class are
complete.

Before this by the end of a test run I was seeing ~100 open file descriptors,
~80 of which were Unix domain sockets. By cleaning these up only 15 Unix
sockets remain at the end (out of ~25 fds, the rest of which are the Python
interpretter, opened libraries etc).

Signed-off-by: Ian Campbell <ian.campbell@docker.com>
2016-07-20 15:51:22 +01:00
Ian Campbell
6649e9aba3 tearDown the project override at the end of each test case
self._project.client is a docker.client.Client, so creating a new self._project
leaks (via the embedded connection pool) a bunch of Unix socket file
descriptors for each test which overrides self.project using this mechanism.

In my tests I observed the test harness using 800-900 file descriptor, which is
OK on Linux with the default limit of 1024 but breaks on OSX (e.g. with
Docker4Mac) where the default limit is only 256. The failure can be provoked on
Linux too with `ulimit -n 256`.

With this fix I have observed the process ending with ~100 file descriptors
open, including 83 Unix sockets, so I think there is likely at least one more
leak lurking.

Signed-off-by: Ian Campbell <ian.campbell@docker.com>
2016-07-20 14:34:12 +01:00
Aanand Prasad
425303992c Reorder/clarify args docs
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-20 12:47:47 +01:00
Jarrod Pooler
9ab1d55d06 Updating arg docs in the proper place
Signed-off-by: Jarrod Pooler <jarrod.pooler@homesite.com>
2016-07-20 12:45:11 +01:00
Aanand Prasad
907b0690e6 Clarify environment and env_file docs
Add note to say that environment variables will not be automatically
made available at build time, and point to the `args` documentation.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-20 12:23:51 +01:00
Aanand Prasad
d7db15ce94 Merge pull request #3364 from TomasTomecek/3355-detailed-error-messages
service: detailed error messages for create and start
2016-07-11 16:29:35 -04:00
Aanand Prasad
593d1aeb09 Fix bugs with entrypoint/command in docker-compose run
- When no command is passed but `--entrypoint` is, set Cmd to `[]`
- When command is a single empty string, set Cmd to `[""]`

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-11 16:15:13 -04:00
Aanand Prasad
1e60030b94 Merge pull request #3488 from jgiannuzzi/internal_networks
Add support for creating internal networks
2016-07-11 15:24:29 -04:00
Jonathan Giannuzzi
83f35e132b Add support for creating internal networks
Signed-off-by: Jonathan Giannuzzi <jonathan@giannuzzi.be>
2016-07-11 11:34:01 +02:00
Tomas Tomecek
fea970dff3 service: detailed error messages for create and start
Fixes: #3355

Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-07-11 10:45:27 +02:00
Aanand Prasad
c3fd6a8f4d Merge pull request #3704 from aanand/update-install-and-changelog-for-1.7.1
Update install.md and CHANGELOG.md for 1.7.1
2016-07-07 16:01:55 -07:00
Aanand Prasad
4207d43b85 Fix timeout value in error message
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-07 12:08:47 -07:00
Aanand Prasad
576a2ee7ae Stop checking the deprecated DOCKER_CLIENT_TIMEOUT variable
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-07 11:58:10 -07:00
Aanand Prasad
49d4fd2795 Update install.md and CHANGELOG.md for 1.7.1
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-07 11:41:11 -07:00
Joffrey F
79ddf06267 Merge pull request #3662 from albers/completion-bundle--fetch-digests
bash completion for `docker-compose bundle --fetch-digests`
2016-07-07 10:39:18 -07:00
Aanand Prasad
89c9aed339 Merge pull request #3697 from aanand/pin-alpine-base-image
Pin base image to alpine:3.4 in Dockerfile.run
2016-07-06 18:04:47 -07:00
Aanand Prasad
08127625a0 Pin base image to alpine:3.4 in Dockerfile.run
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-06 18:01:27 -07:00
Aanand Prasad
1e176b58c5 Merge pull request #3592 from stakodiak/fix-privilege-typo
Fix a typo in a test's name.
2016-07-06 15:22:05 -07:00
Aanand Prasad
98818d4e50 Merge pull request #3591 from staticshock/togather
Fix a typo (togather -> together)
2016-07-06 11:45:22 -07:00
Aanand Prasad
554dc2496a Merge pull request #3590 from Knetic/oomscore
Added support for oom_score_adj
2016-07-06 11:45:09 -07:00
Aanand Prasad
dcc09b677b Merge pull request #3691 from aanand/fix-alias-tests-on-1.11
Fix alias tests on 1.11
2016-07-06 11:03:54 -07:00
Aanand Prasad
949b88fff9 Fix alias tests on 1.11
The fix in 8e04582052 caused a regression
when testing against 1.11.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-07-06 09:56:25 -07:00
Aanand Prasad
e659cd139b Merge pull request #3689 from bfirsh/docker-mac-not-running-error
Suggest to run Docker for Mac if it isn't running
2016-07-06 09:55:19 -07:00
Ben Firshman
5dabc81c16 Suggest to run Docker for Mac if it isn't running
Instead of suggesting docker-machine.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-07-06 15:43:22 +01:00
George Lester
6fe5d2b543 Implemented oom_score_adj
Signed-off-by: George Lester <glester491@gmail.com>
2016-07-05 23:43:32 -07:00
Aanand Prasad
967dce5807 Merge pull request #3671 from dnephin/fix_pip_version_osx
Update pip in travis osx build
2016-07-05 16:08:51 -07:00
Aanand Prasad
edd3637b9b Merge pull request #3669 from chrisclark/master
Docs: Typo leading to possible extreme agony
2016-07-05 16:08:08 -07:00
Ben Firshman
f9f151a51f Merge pull request #3679 from allencloud/make-output-consistent-typo
make-output-consistent-typo
2016-07-05 17:36:59 +01:00
allencloud
931b01acf9 make-output-consistent-typo
Signed-off-by: allencloud <allen.sun@daocloud.io>
2016-07-02 23:33:13 +08:00
Aanand Prasad
f1974f6c5e Merge pull request #3670 from aanand/3343-run-with-env-values-from-system
[Carry #3373] Unset env vars behavior in 'run' mirroring engine
2016-07-01 12:12:29 -07:00
Daniel Nephin
3d0a1de023 Upgrade pip on osx
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-06-30 20:52:15 -04:00
Aanand Prasad
50d5aab8ad Fix test: check container's Env array instead of the output of 'env'
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-06-30 17:00:30 -07:00
Aanand Prasad
10ae81f8cf Post-merge fix - restore Environment import in main.py
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-06-30 15:49:16 -07:00
Joffrey F
5d244ef6d8 Unset env vars behavior in 'run' mirroring engine
Unset env vars passed to `run` via command line options take the
value of the system's var with the same name.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-30 15:48:23 -07:00
Chris Clark
a62739b906 Signed-off-by: Chris Clark <chris@untrod.com>
The postgres image expects a specific volume path. The docs had a typo in that path. This can cause a lot of agony. This is not hypothetical agony, but very real agony that was very recently experienced :)
2016-06-30 15:30:22 -07:00
Daniel Nephin
3d20e25bf8 Merge pull request #3661 from dnephin/fix_requirements
Add missing deps to requirements.txt
2016-06-30 18:21:40 -04:00
Aanand Prasad
bc0939dcf0 Merge pull request #3645 from leonhartX/zsh-completion-bundle
add zsh completion support for bundle
2016-06-30 10:32:44 -07:00
Aanand Prasad
c0237a487b Merge pull request #3221 from aeriksson/fix-zsh-autocomplete
Fix zsh autocomplete
2016-06-29 11:08:08 -07:00
Aanand Prasad
3c8fdb8752 Merge pull request #3615 from shin-/docker-py-bump190
Update docker-py version in requirements
2016-06-29 10:49:59 -07:00
Harald Albers
622de27c1e bash completion for docker-compose bundle --fetch-digests
Signed-off-by: Harald Albers <github@albersweb.de>
2016-06-29 08:45:36 -07:00
Daniel Nephin
2b6ea847b9 Update requirements.txt
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-06-29 10:38:01 -04:00
Ben Firshman
da2aae2a29 Merge pull request #3570 from davidjb/patch-1
Fix minor YAML typo
2016-06-29 15:20:16 +01:00
Ke Xu
edd28f09d1 change dsb to dab
Signed-off-by: Ke Xu <leonhartx.k@gmail.com>
2016-06-29 11:01:50 +09:00
Joffrey F
93cc2675c8 Merge pull request #3625 from albers/completion-bundle
bash completion for `docker-compose bundle`
2016-06-28 15:52:37 -07:00
Joffrey F
3649df83ab Merge pull request #3626 from albers/completion-push
bash completion for `docker-compose push`
2016-06-28 15:52:14 -07:00
Joffrey F
b89dc99e8e Merge pull request #3646 from leonhartX/zsh-completion-push
add zsh completion for push
2016-06-28 15:50:32 -07:00
Joffrey F
a822406eb0 Update docker-py version in requirements
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-28 15:49:06 -07:00
Aanand Prasad
72d3d5d84b Merge pull request #3612 from dnephin/tests_for_bundle
Add some unit tests and an acceptance test for bundle
2016-06-28 14:47:29 -07:00
Aanand Prasad
55e20d1727 Merge pull request #3652 from aanand/fix-tests-for-1.12
Fix tests to accommodate short-id container alias
2016-06-28 13:27:40 -07:00
Daniel Nephin
7c06f60573 Merge pull request #3563 from adamchainz/readthedocs.io
Convert readthedocs links for their .org -> .io migration for hosted projects
2016-06-28 12:35:19 -04:00
Daniel Nephin
00decf8677 Merge pull request #3638 from aanand/update-bundle-extension
Update bundle extension
2016-06-28 11:43:58 -04:00
Daniel Nephin
5640bd42a8 Add an acceptance test for bundle.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-06-28 10:18:59 -04:00
Daniel Nephin
95207561bb Add some unit tests for new bundle and push commands.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-06-28 10:18:20 -04:00
Aanand Prasad
8e04582052 Fix tests to accommodate short-id container alias
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-06-27 16:21:19 -07:00
Aanand Prasad
058a7659ba Update bundle extension
It's now .dab, for Distributed Application Bundle

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-06-27 14:16:44 -07:00
Aanand Prasad
fe0654603c Merge pull request #3619 from jgiannuzzi/fix_tests
Fix assertion that was always true
2016-06-27 14:16:00 -07:00
Andre Eriksson
c3247e7af8 zsh autocomplete: update misleading comment
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:07:59 -07:00
Andre Eriksson
b3d4e9c9d7 zsh autocomplete: break out duplicated flag messages into variables
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
0058b4ba0c zsh autocomplete: replace use of sed with cut
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
612d263d74 zsh autocomplete: fix issue when filtering on already selected services
Previously, the filtering on already selected services would break when
one service was a substring of another.

This commit fixes that.

Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
048408af48 zsh autocomplete: fix missing services issue for build/pull commands
Previously, the autocomplete for the build/pull commands would only add
services for which build/image were the _first_ keys, respectively, in
the docker-compose file.

This commit fixes this, so the appropriate services are listed
regardless of the order in which they appear

Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
d990f7899c zsh autocomplete: pass all relevant flags to docker-compose/docker
For autocomplete to work properly, we need to pass along some flags when
calling docker (--host, --tls, …) and docker-compose (--file, --tls, …).

Previously flags would only be passed to docker-compose, and the only
flags passed were --file and --project-name.

This commit makes sure that all relevant flags are passed to both
docker-compose and docker.

Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
97ba14c82a zsh autocomplete: use two underscores for all function names
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
1b5a94f4e4 zsh autocomplete: bring flag help texts up to date
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
8d2fbe3a55 zsh autocomplete: add 'build' flag for 'create' and 'up'
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
eb10f41d13 zsh autocomplete: fix incorrect flag exclusions for 'create' and 'up'
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
73a1b60ced zsh autocomplete: add missing 'remove-orphans' flag for 'up' and 'down'
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
b3d9652cc3 zsh autocomplete: add missing docker-compose base flags
Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Andre Eriksson
cbb44b1a14 fix broken zsh autocomplete for version 2 docker-compose files
This has the added benefit of making autocompletion work when the
docker-compose config file is in a parent directory.

Signed-off-by: Andre Eriksson <aepubemail@gmail.com>
2016-06-27 11:00:17 -07:00
Ke Xu
a0a90b2352 add zsh completion for push
Signed-off-by: Ke Xu <leonhartx.k@gmail.com>
2016-06-27 18:00:52 +09:00
Ke Xu
aa7f522ab0 add zsh completion support for bundle
Signed-off-by: Ke Xu <leonhartx.k@gmail.com>
2016-06-27 17:48:14 +09:00
Sven Dowideit
5c1abe2e29 Merge pull request #3631 from jamesottaway/patch-1
Document `tmpfs` being v2 only
2016-06-27 11:50:15 +10:00
James Ottaway
f77dbc06cc Document tmpfs being v2 only
Signed-off-by: James Ottaway <git@james.ottaway.io>
2016-06-24 10:54:51 +10:00
Harald Albers
f49b624d95 bash completion for docker-compose push
Signed-off-by: Harald Albers <github@albersweb.de>
2016-06-22 17:19:20 +02:00
Harald Albers
e5c5dc09f8 bash completion for docker-compose bundle
Signed-off-by: Harald Albers <github@albersweb.de>
2016-06-22 17:06:30 +02:00
Jonathan Giannuzzi
3c77db709f Fix assertion that was always true
Signed-off-by: Jonathan Giannuzzi <jonathan@giannuzzi.be>
2016-06-20 14:48:45 +02:00
Anton Backer
80af26d2bb togather -> together
Signed-off-by: Anton Backer <anton.backer@newsela.com>
2016-06-15 15:55:45 -07:00
Aanand Prasad
352cdf0a80 Merge pull request #3601 from aanand/warn-on-missing-digests
Warn on missing digests, don't push/pull by default
2016-06-15 14:28:49 -07:00
Aanand Prasad
020d46ff21 Warn on missing digests, don't push/pull by default
Add a --fetch-digests flag to automatically push/pull

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-06-14 16:37:32 -07:00
Joffrey F
317cd98c0d Merge pull request #3599 from shin-/tls-version-unavailable-test
Skip TLS version test if TLSv1_2 is not available on platform
2016-06-14 12:34:43 -07:00
Victoria
f8f582f349 Merge pull request #3600 from londoncalling/fix-broken-links-PR-23492
fixes broken links in 3 Compose docs files due to topic re-org in PR#…

Merging to address broken links. One more to go in (DTR).
2016-06-14 12:30:41 -07:00
Victoria Bialas
a56e44f96e fixes broken links in 3 Compose docs files due to topic re-org in PR#23492
Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-06-14 12:24:30 -07:00
Joffrey F
ee68a51e28 Skip TLS version test if TLSv1_2 is not available on platform
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-14 12:23:04 -07:00
Joffrey F
0fe82614a6 Merge pull request #3595 from dnephin/add-push-and-bundle
Add docker-compose push and docker-compose bundle
2016-06-14 10:57:32 -07:00
Aanand Prasad
8f8c17bf66 Merge pull request #3549 from shin-/KalleDK-master
Add support for COMPOSE_TLS_VERSION config option
2016-06-14 10:57:12 -07:00
Daniel Nephin
9b7bd69cfc Support entrypoint, labels, and user in the bundle.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-06-14 13:00:12 -04:00
Aanand Prasad
1ea9dda1d3 Implement 'docker-compose push' and 'docker-compose bundle'
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-06-14 12:06:14 -04:00
Aanand Prasad
21f20cbc9b Merge pull request #3449 from Andrey9kin/ready/3281
Fix #3281: Unexpected result when using build args with default values
2016-06-14 08:05:07 -07:00
alex
68d73183eb Fix a typo in a test's name. 2016-06-13 23:36:34 -04:00
Aanand Prasad
2123906586 Merge pull request #3577 from sanmai-NL/3576-byte_str_fix
Fix byte/str typing error
2016-06-14 01:58:27 +01:00
Aanand Prasad
59e96fea4f Merge pull request #3588 from shin-/3285-root-mount
Fix split_path_mapping behavior when mounting "/"
2016-06-14 01:45:20 +01:00
Joffrey F
60f7e021ad Fix split_path_mapping behavior when mounting "/"
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-13 15:32:10 -07:00
Sander Maijers
61324ef308
Fix byte/str typing error
Signed-off-by: Sander Maijers <S.N.Maijers@gmail.com>
2016-06-10 16:30:46 +02:00
David Beitey
0287486b14 Fix minor YAML typo
Signed-off-by: David Beitey <david@davidjb.com>
2016-06-09 17:00:31 +10:00
Adam Chainz
9ddb7f3c90 Convert readthedocs links for their .org -> .io migration for hosted projects
As per [their blog post of the 27th April](https://blog.readthedocs.com/securing-subdomains/) ‘Securing subdomains’:

> Starting today, Read the Docs will start hosting projects from subdomains on the domain readthedocs.io, instead of on readthedocs.org. This change addresses some security concerns around site cookies while hosting user generated data on the same domain as our dashboard.

Test Plan: Manually visited all the links I’ve modified.

Signed-off-by: Adam Chainz <adam@adamj.eu>
2016-06-08 03:52:12 +01:00
Aanand Prasad
e502417df2 Merge pull request #3475 from shin-/3429-networks-config-serialize
Output valid config in config command
2016-06-07 18:01:39 +02:00
Ben Firshman
6e2d1eb80e Merge pull request #3516 from albers/completion-rm--all
remove command completion for `docker-compose rm --a`
2016-06-06 22:23:56 +01:00
Joffrey F
ea640f3821 Remove external_name from serialized config output
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-03 12:10:09 -07:00
Joffrey F
427ec899df Merge pull request #3504 from denismakogon/issue-3503
Issue-3503: Improve timestamp validation in tests
2016-06-03 11:57:55 -07:00
Joffrey F
e7a8b2fed5 Update TLS version configuration code. Tests.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-06-03 11:45:22 -07:00
Sven Dowideit
17b219454f Merge pull request #3522 from SvenDowideit/fix-links
Fix links
2016-05-31 16:36:29 -07:00
Sven Dowideit
dd3590180d more fixes
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2016-05-31 21:18:42 +00:00
Andrey Devyatkin
a67ba5536d Fix #3281: Unexpected result when using build args with default values
Fix the issue when build arg is set to None instead of empty string. Usecase:

cat docker-compose.yml
  .... args:
  - http_proxy
  - https_proxy
  - no_proxy

If http_proxy, https_proxy, no_proxy environment variables are not defined then http_proxy,
https_proxy, no_proxy build args will be set to string None which breaks all downloads

With this change undefined build args will be set to empty string instead of string None

Signed-off-by: Andrey Devyatkin <andrey.a.devyatkin@gmail.com>
2016-05-28 11:39:41 +02:00
Sven Dowideit
90fba58df9 Fix links
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2016-05-27 21:29:47 +00:00
Andrey Devyatkin
c148849f0e Fix #3281: Unexpected result when using build args with default values
Fix the issue when build arg is set to None instead of empty string. Usecase:

cat docker-compose.yml
.... args:
- http_proxy
- https_proxy
- no_proxy

If http_proxy, https_proxy, no_proxy environment variables are not defined then http_proxy,
https_proxy, no_proxy build args will be set to string None which breaks all downloads

With this change undefined build args will be set to empty string instead of string None

Signed-off-by: Andrey Devyatkin <andrey.a.devyatkin@gmail.com>
2016-05-27 20:16:52 +02:00
Denis Makogon
1298b9aa5d Issue-3503: Improve timestamp validation in tests
CLITestCase.test_events_human_readable fails due to
 wrong assumption that host where tests were launched
 will have the same date time as Docker daemon.

 This fix introduces internal method for validating
 timestamp in Docker logs

Signed-off-by: Denys Makogon <lildee1991@gmail.com>
2016-05-27 14:50:13 +03:00
Andrey Devyatkin
e3e8a619cc Fix #3281: Unexpected result when using build args with default values
Fix the issue when build arg is set to None instead of empty string.
Usecase:

cat docker-compose.yml
....
args:
- http_proxy
- https_proxy
- no_proxy

If http_proxy, https_proxy, no_proxy environment variables are not defined
then http_proxy, https_proxy, no_proxy build args will be set to string None which breaks all downloads

With this change build args will not passed to docker engine if they are equal to string None

Signed-off-by: Andrey Devyatkin <andrey.a.devyatkin@gmail.com>
2016-05-27 07:48:13 +02:00
Harald Albers
c46737ed02 remove command completion for docker-compose rm --a
As `--all|-a` is deprecated, there's no use to suggest it any
more in command completion.

Signed-off-by: Harald Albers <github@albersweb.de>
2016-05-26 12:48:53 -07:00
Aanand Prasad
86b5ed1a84 Merge pull request #3473 from shin-/3461-merge-port-mappings
Eliminate duplicates when merging port mappings from config files
2016-05-26 16:57:43 +01:00
Joffrey F
4bb80c25d3 Merge pull request #3483 from aanand/env-disambiguation
Add "disambiguation" page for environment variables
2016-05-24 13:29:22 -07:00
Joffrey F
048360d1ed Merge pull request #3489 from aanand/update-openssl-mac
Use latest OpenSSL version when building Mac binary on Travis
2016-05-23 13:52:51 -07:00
Aanand Prasad
a34cd5ed54 Add "disambiguation" page for environment variables
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-05-23 15:03:25 +01:00
Joffrey F
c4229b469a Improve merging for several service config attributes
All uniqueItems lists in the config now receive the same treatment removing
duplicates.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-05-20 15:29:04 -07:00
Joffrey F
842e372258 Eliminate duplicates when merging port mappings from config files
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-05-20 15:28:35 -07:00
Aanand Prasad
33bed5c706 Use latest OpenSSL version (1.0.2h) when building Mac binary on Travis
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-05-20 12:04:37 +01:00
Aanand Prasad
7763122ecb Merge pull request #3459 from shin-/2487-split-volume-path
Always use the Windows version of splitdrive when parsing volume mappings
2016-05-20 11:42:43 +01:00
Joffrey F
2b5b665d3a Add test for path mapping with Windows containers
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-05-19 14:53:37 -07:00
Joffrey F
9a39208741 Merge pull request #3482 from aanand/fix-prompt-buffering
Fix bug where confirmation prompt doesn't show due to line buffering
2016-05-19 08:52:34 -07:00
Aanand Prasad
ce8df9e789 Merge pull request #3466 from shin-/3330-rm-all-default
Update rm command to always remove one-off containers.
2016-05-19 16:46:31 +01:00
Aanand Prasad
0c8aeb9e05 Fix bug where confirmation prompt doesn't show due to line buffering
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-05-19 15:44:17 +01:00
Joffrey F
db0a6cf2bb Always use the Windows version of splitdrive when parsing volume mappings
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-05-17 16:33:59 -07:00
Joffrey F
844b7d463f Update rm command to always remove one-off containers.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-05-16 14:59:33 -07:00
Joffrey F
ca3aef0c84 Merge pull request #3436 from shin-/3374-exec-windows
Fail gracefully when -d is not provided for exec command on Win32
2016-05-12 15:14:15 -07:00
Joffrey F
e5645595e3 Fail gracefully when -d is not provided for exec command on Win32
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-05-12 14:00:54 -07:00
Joffrey F
c9fe8920c9 Merge pull request #3457 from dnephin/fix_versions_script
Skip invalid git tags in versions.py
2016-05-12 13:52:20 -07:00
Daniel Nephin
4bf5271ae2 Skip invalid git tags in versions.py
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-05-12 14:41:40 -04:00
Aanand Prasad
72f6a5c8d3 Merge pull request #3433 from anton44eg/issue_3432
add msg attribute to ProjectError class
2016-05-12 16:55:11 +01:00
Joffrey F
dc88e54010 Merge pull request #3399 from yorkedork/fix/env-file-validation
Adds additional validation to 'env_vars_from_file'.
2016-05-12 08:53:25 -07:00
Anton Simernia
4b01f6dcd6 add msg attribute to ProjectError class
Signed-off-by: Anton Simernia <anton.simernya@gmail.com>
2016-05-09 18:26:20 +07:00
Sven Dowideit
f1603a3ee2 Merge pull request #3092 from wenchma/service_image
Update image format for service conf reference
2016-05-09 10:16:37 +10:00
Sven Dowideit
5fa81c4044 Merge pull request #3417 from spectralsun/patch-1
Small typo
2016-05-09 10:15:56 +10:00
Garrett Seward
3b7191f246 Small typo
Signed-off-by: spectralsun <garrett@spectralsun.com>
2016-05-04 10:47:01 -07:00
Daniel Nephin
3bf75b7330 Merge pull request #3398 from shin-/docker-py-1.8.1
Require latest docker-py version
2016-05-03 15:47:47 -04:00
Sven Dowideit
c1c8c70800 Merge pull request #3392 from SvenDowideit/use-docs-base-oss
convert docs Dockerfiles to use docs/base:oss
2016-05-03 10:47:00 +10:00
Joffrey F
94bcbd1fb6 Merge pull request #3388 from andrerom/patch-1
Clarify env-file doc that .env is read from cwd
2016-05-02 16:04:03 -07:00
Joffrey F
3e11a95056 Merge pull request #3400 from shin-/3333-raise-up-errors
Properly handle APIError failures in Project.up
2016-05-02 14:34:12 -07:00
Joffrey F
310b3d9441 Properly handle APIError failures in Project.up
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-05-02 13:42:05 -07:00
Thom Linton
28fb91b344 Adds additional validation to 'env_vars_from_file'.
The 'env_file' directive and feature precludes the use of the name
'.env' in the path shared with 'docker-config.yml', regardless of
whether or not it is enabled.

This change adds an additional validation to allow the use of this
path provided it is not a file.

Signed-off-by: Thom Linton <thom.linton@gmail.com>
2016-04-29 17:53:31 -07:00
Joffrey F
c41f30c3ff Merge pull request #3385 from shin-/3316-skip-statusless-events
Skip event objects that don't contain a status field
2016-04-29 17:50:32 -07:00
Joffrey F
fe17e0f948 Skip event objects that don't contain a status field
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-29 16:39:42 -07:00
Joffrey F
bd7ec24e25 Merge pull request #3384 from shin-/3264-shorthand-host-support
Support combination of shorthand flag and equal sign for host option
2016-04-29 16:39:16 -07:00
Joffrey F
e4bb678875 Require latest docker-py version
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-29 16:37:26 -07:00
André R
84aa39e978 Clarify env-file doc that .env is read from cwd
Closes #3381

Signed-off-by: André R <ar@ez.no>
2016-04-28 23:14:06 +02:00
Joffrey F
8cc7d68a00 Merge pull request #3390 from aronahl/master
Add missing log event filter when using docker-compose logs.
2016-04-28 12:53:04 -07:00
Joffrey F
0b24883cef Support combination of shorthand flag and equal sign for host option
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-28 12:52:00 -07:00
Aaron Nall
2efcec776c Add missing log event filter when using docker-compose logs.
Signed-off-by: Aaron Nall <aronahl@hotmail.com>
2016-04-28 15:14:44 +00:00
Daniel Nephin
61794ba97c Merge pull request #3377 from shin-/3372-windowserror
Define WindowsError on non-win32 platforms
2016-04-28 10:33:18 -04:00
Sven Dowideit
87ee38ed2c convert docs Dockerfiles to use docs/base:oss
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2016-04-28 12:57:02 +00:00
Aanand Prasad
7ad7eb71ca Merge pull request #3164 from aanand/fix-config-v1
WIP: Fix output of 'config' for v1 files
2016-04-26 20:34:18 +01:00
Joffrey F
d3e645488a Define WindowsError on non-win32 platforms
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-26 11:40:31 -07:00
Aanand Prasad
756ef14edc Fix format of 'restart' option in 'config' output
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-26 19:21:03 +01:00
Aanand Prasad
6064d200f9 Fix output of 'config' for v1 files
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-26 19:21:03 +01:00
Aanand Prasad
84a3e2fe79 Check full error message in test_up_with_net_is_invalid
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-26 19:21:03 +01:00
Aanand Prasad
a4d3dd6197 Remove v2_only decorators on config tests
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-26 19:21:03 +01:00
Joffrey F
0cd35913c3 Merge pull request #3382 from dnephin/upgrade_pip
Upgade pip to latest - attempt to fix jenkins builds
2016-04-26 09:38:12 -07:00
Daniel Nephin
26fe8213aa Upgade pip to latest
Hopefully fixes our builds.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-04-26 11:58:41 -04:00
Daniel Nephin
ac82597ac1 Merge pull request #3360 from bfirsh/better-validation-error-messages
Make validation errors less robotic
2016-04-21 11:32:23 -04:00
Daniel Nephin
1988dfeaf0 Merge pull request #3359 from bfirsh/clarify-compose-file-networks-documentation
Clarify service networks documentation
2016-04-21 11:19:32 -04:00
Joffrey F
da1d603463 Merge pull request #3351 from shin-/3342-setup-requirements
Force docker-py 1.8.0 or above
2016-04-20 17:40:51 -07:00
Joffrey F
75bcc382d9 Force docker-py 1.8.0 or above
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-20 16:56:48 -07:00
Ben Firshman
b67f110620 Explain the explanation about file versions
This explanation looked like it was part of the error. Added an
extra new line and a bit of copy to explain the explanation.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-04-20 16:40:16 -07:00
Ben Firshman
27628f8655 Make validation error less robotic
"ERROR: Validation failed in file './docker-compose.yml', reason(s):"

is now:

"ERROR: The Compose file './docker-compose.yml' is invalid because:"

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-04-20 16:38:09 -07:00
Ben Firshman
55fcd1c3e3 Clarify service networks documentation
When jumping straight to this bit of the docs, it's not clear
that these are options under a service rather than the top-level
`networks` key. Added a service to make this super clear.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-04-20 15:58:12 -07:00
Ben Firshman
a0aea42f75 Merge pull request #3326 from CRogers/patch-1
Readme should use new docker compose format instead of the old one
2016-04-20 23:06:35 +01:00
Ben Firshman
6ff3c47630 Merge pull request #3222 from jonlemmon/patch-1
Rails Docs: Add nodejs to apt-get install command
2016-04-20 22:57:50 +01:00
Daniel Nephin
8a34ee0eaa Merge pull request #3356 from metal3d/fix-help-acceptance-test
Fix the tests from jenkins
2016-04-20 12:18:20 -04:00
Patrice FERLET
ba10f1cd55 Fix the tests from jenkins
Acceptance tests didn't set "help" command to return "0" EXIT_CODE.

close #3354
related #3263

Signed-off-by: Patrice Ferlet <metal3d@gmail.com>
2016-04-20 13:23:37 +02:00
Aanand Prasad
cafe1315b2 Merge pull request #3334 from werehuman/fix-config-hash-change
Fix #3248: Accidental config_hash change
2016-04-19 12:42:19 +01:00
Aanand Prasad
984f839d33 Merge pull request #3263 from twitherspoon/3191_2_help_cli_feature
Added code to support no argument help command
2016-04-19 12:14:24 +01:00
Aanand Prasad
d21e1c5a30 Merge pull request #3335 from johnharris85/master
Fix CLI docstring to reflect Docopt behaviour.
2016-04-19 12:13:20 +01:00
Aanand Prasad
52fa010ac7 Merge pull request #3337 from dnephin/check_for_short_id_alias
Check for short id alias, and don't disconnect if it already exists
2016-04-19 12:12:43 +01:00
Daniel Nephin
d4bebbb1ba Merge pull request #3340 from johnharris85/2922-config-does-not-catch-missing-links
Fix #2922: Config does not catch missing links
2016-04-18 10:13:47 -04:00
johnharris85
6d2805917c Account for aliased links
Fix failing tests
Signed-off-by: John Harris <john@johnharris.io>
2016-04-17 15:25:06 -04:00
johnharris85
377be5aa1f Adding tests
Signed-off-by: John Harris <john@johnharris.io>
2016-04-17 14:01:06 -04:00
johnharris85
68272b0216 Config now catches undefined service links
Fixes issue #2922
Signed-off-by: John Harris <john@johnharris.io>
2016-04-17 14:00:07 -04:00
Daniel Nephin
56c6e29819 Unit test for skipping network disconnect.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-04-15 16:28:59 -04:00
Vladimir Lagunov
4702703615 Fix #3248: Accidental config_hash change
Signed-off-by: Vladimir Lagunov <lagunov.vladimir@gmail.com>
2016-04-15 15:34:30 +03:00
johnharris85
ad306f0479 Fix CLI docstring to reflect Docopt behaviour.
Signed-off-by: John Harris <john@johnharris.io>
2016-04-15 13:30:13 +01:00
Daniel Nephin
e1356e1f6f Set networking_config when creating a container.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-04-14 18:09:06 -04:00
Daniel Nephin
abb5ae7fe4 Only disconnect if we don't already have the short id alias.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-04-14 16:05:14 -04:00
Callum Rogers
e71c62b8d1 Readme should use new docker compose format instead of the old one
Signed-off-by: Callum Rogers <callumrogers@hotmail.co.uk>
2016-04-14 10:49:10 +01:00
Aanand Prasad
e2cb7b0237 Merge pull request #3299 from dannyprout/2096-only-show-port-clash-warning-when-starting-multiple-containers
Only show port clash warning if multiple containers are about to be started
2016-04-14 10:40:02 +01:00
Aanand Prasad
aebb3d5d0a Merge pull request #3320 from dnephin/make_it_dev_again
Update release notes and set version to 1.8.0dev
2016-04-14 10:22:01 +01:00
Daniel Nephin
50287722f2 Update release notes and set version to 1.8.0dev
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-04-13 13:27:18 -04:00
Danyal Prout
339ebc0483 Fixes #2096: Only show multiple port clash warning if multiple containers
are about to be started.

Signed-off-by: Danyal Prout <me@dany.al>
2016-04-12 20:58:21 +01:00
Tony Witherspoon
ae46bf8907 Updated StringIO import to support io module
Signed-off-by: Tony Witherspoon <tony.witherspoon@gmail.com>
2016-04-12 12:29:59 -04:00
Tony Witherspoon
276738f733 Updated cli_test.py to validate against the updated help command conditions
Signed-off-by: Tony Witherspoon <tony.witherspoon@gmail.com>
2016-04-12 11:47:15 -04:00
Daniel Nephin
f10bc8072e Merge pull request #3310 from aanand/fix-logs-test
Attempt to fix flaky logs test
2016-04-12 10:44:04 -04:00
Aanand Prasad
7781f62ddf Attempt to fix flaky logs test
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-12 12:07:13 +01:00
Aanand Prasad
3d3f331404 Merge pull request #3303 from aanand/clarify-rm-and-down
Clarify behaviour of rm and down
2016-04-12 11:31:22 +01:00
Daniel Nephin
d05feb1a4d Merge pull request #3302 from aanand/feed-queue-refactor
feed_queue() refactor
2016-04-11 12:58:11 -04:00
Aanand Prasad
7cfb5e7bc9 Fix race condition
If processing of all objects finishes before the queue is drained,
parallel_execute_iter() returns prematurely.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-11 17:05:52 +01:00
Aanand Prasad
3722bb38c6 Clarify behaviour of rm and down
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-11 16:31:27 +01:00
Aanand Prasad
15c5bc2e6c Rename a couple of functions in parallel.py
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-11 13:05:30 +01:00
Aanand Prasad
0671b8b8c3 Document parallel helper functions
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-11 12:51:27 +01:00
Aanand Prasad
0e3db185cf Small refactor to feed_queue()
Put the event tuple into the results queue rather than yielding it from
the function.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-11 12:37:00 +01:00
Victoria
97467c7dec Merge pull request #3295 from londoncalling/docs-format-followup-PR3275
added some formatting on the Wordress steps, and made heading levels …
2016-04-08 16:56:57 -07:00
Victoria Bialas
4192a009da added some formatting on the Wordress steps, and made heading levels in these sample app topics consistent
Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-04-08 16:40:07 -07:00
Victoria
80614cff9b Merge pull request #3275 from activatedgeek/patch-1
Updated Wordpress tutorial
2016-04-08 16:12:44 -07:00
Sanyam Kapoor
d4e9a3b6b1 Updated Wordpress tutorial
The new tutorial now uses official Wordpress Docker Image.

Signed-off-by: Sanyam Kapoor <1sanyamkapoor@gmail.com>
2016-04-09 02:05:45 +05:30
Daniel Nephin
3ca8858897 Merge pull request #3292 from dnephin/fix_up_build
Remove extra ensure_image_exists() which causes duplicate builds.
2016-04-08 15:45:37 -04:00
Daniel Nephin
83df95d511 Remove extra ensure_image_exists() which causes duplicate builds.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-04-08 15:21:12 -04:00
Daniel Nephin
e5443717fb Merge pull request #3291 from aanand/parallel-execute-refactor
Parallel execution refactor/fixes
2016-04-08 15:15:41 -04:00
Daniel Nephin
91a545813a Merge pull request #3276 from shin-/bump_docker_py
Use docker-py 1.8.0
2016-04-08 15:15:01 -04:00
Aanand Prasad
be27e266da Reduce queue timeout
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-08 19:07:40 +01:00
Aanand Prasad
5450a67c2d Hold state in an object
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-08 19:06:07 +01:00
Aanand Prasad
54b6fc4219 Refactor so there's only one queue
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-08 18:54:02 +01:00
Aanand Prasad
ffab27c049 Test events coming out of parallel_execute_stream in error case
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-08 18:53:16 +01:00
Aanand Prasad
3720b50c3b Extract get_deps test helper
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-08 18:48:07 +01:00
Aanand Prasad
af9526fb82 Move queue logic out of parallel_execute()
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-08 18:30:28 +01:00
Aanand Prasad
141b96bb31 Abort operations if their dependencies fail
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-08 17:51:09 +01:00
Aanand Prasad
bcdf541c8c Refactor setup_queue()
- Stop sharing set objects across threads
- Use a second queue to signal when producer threads are done
- Use a single consumer thread to check dependencies and kick off new
  producers

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-04-08 16:24:29 +01:00
Tony Witherspoon
f5b80640fe Merge branch '3191_2_help_cli_feature' of https://github.com/twitherspoon/compose into 3191_2_help_cli_feature 2016-04-07 12:46:27 -04:00
twitherspoon
9f47e43b5c Merge branch 'master' into 3191_2_help_cli_feature 2016-04-07 12:43:34 -04:00
Tony Witherspoon
5d0aab4a8e updated cli_test.py to no longer expect raised SystemExit exceptions
Signed-off-by: Tony Witherspoon <tony.witherspoon@gmail.com>
2016-04-07 12:42:14 -04:00
Joffrey F
3ef6b17bfc Use docker-py 1.8.0
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-04-06 13:28:45 -07:00
Daniel Nephin
958f96c78a Merge pull request #3269 from dnephin/fix_logs_and_scale_down
Prevent unnecessary inspection of containers
2016-04-06 12:45:46 -04:00
Daniel Nephin
b33d7b3dd8 Prevent unnecessary inspection of containers when created from an inspect.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-04-06 11:14:42 -04:00
Tony Witherspoon
129fb5b356 Added code to output the top level command options if docker-compose help with no command options provided
Signed-off-by: Tony Witherspoon <tony.witherspoon@gmail.com>
2016-04-04 13:15:28 -04:00
Aanand Prasad
86530287d6 Merge pull request #2627 from bfirsh/update-roadmap
Update roadmap
2016-04-04 12:52:54 +01:00
Ben Firshman
c1026e815a Update roadmap
Bring it inline with current plans:

- Use in production is not necessarily about the command-line
  tool, but also improving file format, integrations, new tools,
  etc.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-04-01 12:55:16 -07:00
Ben Firshman
c72d62f96d Merge pull request #3187 from bfirsh/update-wordpress-example-to-use-official-images
Update wordpress example to use official images
2016-04-01 20:53:37 +01:00
Daniel Nephin
a63a05964b Merge pull request #3249 from aanand/better-env-substitution-example
Better variable substitution example
2016-04-01 15:12:18 -04:00
Joffrey F
9509508f3e Merge pull request #3226 from shin-/3210-assert-hostname
Fix assert_hostname logic in tls_config_from_options
2016-04-01 10:32:13 -07:00
Joffrey F
1a7a65f84d Include docker-py requirements fix
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-31 18:01:51 -07:00
Aanand Prasad
3034803258 Better variable substitution example
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-31 15:45:14 +01:00
Joffrey F
78a8be07ad Re-enabling assert_hostname when instantiating docker_client from the
environment.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-30 11:11:19 -07:00
Joffrey F
d27b82207c Remove obsolete assert_hostname tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-30 10:58:15 -07:00
Joffrey F
71c86acaa4 Update docker-py version to include match_hostname fix
Removed unnecessary assert_hostname computation in tls_config_from_options

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-29 18:01:27 -07:00
Aanand Prasad
85e2fb63b3 Merge pull request #3218 from sdurrheimer/zsh-completion-run-workdir
Add zsh completion for 'docker-compose run -w --workdir'
2016-03-29 16:50:12 +01:00
Aanand Prasad
024a810617 Merge pull request #3217 from sdurrheimer/zsh-completion-up-build
Add zsh completion for 'docker-compose up --build'
2016-03-29 16:49:49 +01:00
Aanand Prasad
668d45c7cc Merge pull request #3216 from sdurrheimer/zsh-completion-logs
Add zsh completion for 'docker-compose logs -f --follow --tail -t --t…
2016-03-29 16:49:36 +01:00
Aanand Prasad
09ea74245d Merge pull request #3215 from sdurrheimer/zsh-completion-exec-command
Add zsh completion for 'docker-compose exec' command
2016-03-29 16:49:15 +01:00
Aanand Prasad
386edd892c Merge pull request #3214 from sdurrheimer/zsh-completion-rm-all
Add zsh completion for 'docker-compose rm -a --all'
2016-03-29 16:48:53 +01:00
Joffrey F
7116aefe43 Fix assert_hostname logic in tls_config_from_options
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-28 17:39:20 -07:00
Jon Lemmon
93901ec480 Rails Docs: Add nodejs to apt-get install command
When using the latest version of Rails, the tutorial currently errors when running `docker-compose up` with the following error:

```
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.11.2/lib/bundler/runtime.rb:80:in `rescue in block (2 levels) in require': There was an error while trying to load the gem 'uglifier'. (Bundler::GemRequireError)
```

Installing nodejs in the build fixes the issue.

Signed-off-by: Jon Lemmon <jon.lemmon@enspiral.com>
2016-03-28 13:31:40 +13:00
Steve Durrheimer
8ae8f7ed4b Add zsh completion for 'docker-compose run -w --workdir'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-03-25 19:25:33 +01:00
Steve Durrheimer
9729c0d3c7 Add zsh completion for 'docker-compose up --build'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-03-25 19:15:34 +01:00
Steve Durrheimer
9d58b19ecc Add zsh completion for 'docker-compose logs -f --follow --tail -t --timestamps'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-03-25 19:09:53 +01:00
Steve Durrheimer
63b448120a Add zsh completion for 'docker-compose exec' command
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-03-25 19:03:36 +01:00
Steve Durrheimer
0f1fb42326 Add zsh completion for 'docker-compose rm -a --all'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-03-25 18:52:28 +01:00
Daniel Nephin
aa50023507 Merge pull request #3057 from shin-/2636-env-file
Add support for a default environment file
2016-03-24 14:26:03 -04:00
Joffrey F
12ad3ff301 Injecting os.environ in Environment instance happens outside of init method
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:28 -07:00
Joffrey F
1506f997de Better windows support for Environment class
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:28 -07:00
Joffrey F
b99037b4a6 Add support for DOCKER_* variables in .env file
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:28 -07:00
Joffrey F
c7afe16419 Account for case-insensitive env on windows platform
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
36f1b4589c Limit occurrences of creating an environment object.
.env file is always read from the project_dir

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
0ff53d9668 Less verbose environment invocation
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
dcdcf4869b Mention environment file in envvars.md
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
21aa7a0448 Documentation for .env file
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
f48da96e8b Test get_project_name from env file
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
d55fc85fea Added default env file test.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
1801f83bb8 Environment class cleanup
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
fd020ed2cf Tests use updated get_config_paths_from_options signature
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
5831b869e8 Update tests for new environment handling
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
b9ca5188a2 Remove Environment singleton, instead carry instance during config processing
Project name and compose file detection also updated

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
bf8e501b5e Fix pre-commit config
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Joffrey F
c69d8a3bd2 Implement environment singleton to be accessed throughout the code
Load and parse environment file from working dir

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:57:01 -07:00
Daniel Nephin
d1d8df7f72 Merge pull request #3192 from shin-/use-dockerpy-1.8
Require docker-py 1.8.0rc2
2016-03-24 13:55:59 -04:00
Joffrey F
d78b013bb0 Merge pull request #3204 from albers/completion-rm--all
bash completion for `docker-compose rm --all`
2016-03-24 10:44:36 -07:00
Joffrey F
aabeb56527 Merge pull request #3206 from albers/completion-exec
bash completion for `docker-compose exec`
2016-03-24 10:44:19 -07:00
Joffrey F
60470fb9f1 Require docker-py 1.8.0rc2
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-24 10:13:56 -07:00
Daniel Nephin
84a2e634a8 Merge pull request #3200 from dnephin/disable_broken_test
Disable a test that is failing against 1.11.0rc1.
2016-03-24 13:09:35 -04:00
Harald Albers
c9b02b7b34 bash completion for docker-compose exec
Signed-off-by: Harald Albers <github@albersweb.de>
2016-03-24 18:02:12 +01:00
Joffrey F
87231a25be Merge pull request #3202 from albers/completion-logs
bash completion for new `docker logs` options
2016-03-24 09:56:12 -07:00
Joffrey F
353c4deb19 Merge pull request #3203 from albers/completion-up--build
bash completion for `docker-compose up --build`
2016-03-24 09:55:58 -07:00
Daniel Nephin
732531b722 Disable a test that is failing against 1.11.0rc1.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-24 12:32:13 -04:00
Harald Albers
b030c3928a bash completion for docker-compose rm --all
Signed-off-by: Harald Albers <github@albersweb.de>
2016-03-24 17:29:04 +01:00
Harald Albers
5416e4c99b bash completion for docker-compose up --build
Signed-off-by: Harald Albers <github@albersweb.de>
2016-03-24 17:21:56 +01:00
Harald Albers
d8fb9d8831 bash completion for new docker logs options
Signed-off-by: Harald Albers <github@albersweb.de>
2016-03-24 17:11:10 +01:00
Aanand Prasad
2b063d332e Merge pull request #3196 from albers/completion-daemon-options
bash completion for new TLS options
2016-03-24 15:11:55 +00:00
Daniel Nephin
b09b6e390f Merge pull request #3199 from aanand/add-tls-flags-to-overview
Add TLS flags to CLI reference
2016-03-24 10:48:50 -04:00
Aanand Prasad
8282bb1b24 Add TLS flags to CLI reference
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-24 14:41:51 +00:00
Harald Albers
5b2c2e332f bash completion for TLS options
Signed-off-by: Harald Albers <github@albersweb.de>
2016-03-24 12:06:10 +01:00
Harald Albers
9094c4d97d prepare bash completion for new TLS options
Up to now there were two special top-level options that required special
treatment: --project-name and --file (and their short forms).
For 1.7.0, several TLS related options were added that have to be passed
to secondary docker-compose invocations as well.
This commit introduces a scalable treatment of those options.

Signed-off-by: Harald Albers <github@albersweb.de>
2016-03-24 12:05:59 +01:00
Victoria
2a09fb02db Merge pull request #3182 from londoncalling/docs-fix-links-build-errors
fixed links showing as build errors per PR #3180
2016-03-23 15:08:25 -07:00
Victoria Bialas
d1ea4d72ac fixed links showing as build errors per PR #3180
fixed links per build errors

Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-03-23 14:58:45 -07:00
Aanand Prasad
c3eca82749 Merge pull request #3128 from dnephin/add_network_settings_to_config_hash
Include network settings as part of the service config hash.
2016-03-23 17:01:32 +00:00
Ben Firshman
a53b29467a Update wordpress example to use official images
The orchardup images are very old and not maintained.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-03-22 17:19:50 -07:00
Daniel Nephin
2be2029791 Merge pull request #3139 from shin-/1716-tls-flags-support
Add support for TLS config command-line options
2016-03-22 18:24:52 -04:00
Joffrey F
2cc87555cb tls_config_from_options unit tests
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-22 11:57:45 -07:00
Joffrey F
4727115317 Bump docker-py version to include tcp host fix
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-22 11:47:53 -07:00
Joffrey F
442dff72b4 Improve assert_hostname setting in tls_config_from_options
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-22 11:47:53 -07:00
Joffrey F
26f3861791 Specifying --tls no longer overrides all other TLS options
Add an option to skip hostname verification

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-22 11:47:53 -07:00
Joffrey F
7166408d2a Fixed typos + simplified TLSConfig creation process.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-22 11:47:53 -07:00
Joffrey F
1ac33ea7e5 Add support for TLS config command-line options
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-22 11:47:53 -07:00
Aanand Prasad
4f5123bda9 Merge pull request #3168 from dnephin/fix_tty_timeout
Handle all timeout errors consistently
2016-03-22 10:14:52 +00:00
Aanand Prasad
aaa7b09369 Merge pull request #3181 from dnephin/fix_partial_change_test_failure
Fix flaky partial_change state test
2016-03-22 10:14:28 +00:00
Aanand Prasad
a20b84e6d2 Merge pull request #3178 from aanand/2774-off-one-offs
Remove one-off containers in `rm` and `down`
2016-03-22 10:12:21 +00:00
Daniel Nephin
5c968f9e15 Fix flaky partial_change state test.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-21 19:07:50 -04:00
Daniel Nephin
6718e82966 Merge pull request #3179 from dnephin/fix_tmpfs_test_failure
Only allow tmpfs with the v2 format
2016-03-21 18:40:51 -04:00
Daniel Nephin
be1476f24b Only allow tmpfs on v2.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-21 14:41:28 -04:00
Aanand Prasad
2bf5e46857 Stop and remove still-running one-off containers in 'down'
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-21 18:08:07 +00:00
Aanand Prasad
a2317dfac2 Remove one-off containers in 'docker-compose down'
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-21 16:15:49 +00:00
Aanand Prasad
81f6d86ad9 Warn when --all is not passed to rm
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-21 15:14:31 +00:00
Aanand Prasad
1bc9469674 Don't allow boolean values for one_off in Project methods
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-21 14:42:57 +00:00
Joffrey F
5826a2147b Use enum to represent 3 possible states of the one_off filter
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-21 12:12:52 +00:00
Joffrey F
187ea4cd81 Add --all option to rm command - remove one-off containers
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-21 12:12:52 +00:00
Aanand Prasad
28120148f4 Merge pull request #3137 from dnephin/add_tmpfs_to_config
Add support for docker run --tmpfs flag.
2016-03-21 12:10:12 +00:00
Kalle Møller
7fc40dd7cc Adding ssl_version to docker_clients kwargs
Select tls version based of COMPOSE_TLS_VERSION

Changed from SSL to TLS

Also did docs - missing default value

Using getattr and raises AttributeError in case of unsupported version

Signed-off-by: Kalle Møller <github.com@k-moeller.dk>
2016-03-19 01:15:03 +01:00
Daniel Nephin
dfac48f3f5 Make a new flaky test less flaky.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-18 18:20:03 -04:00
Daniel Nephin
089ec66522 Include network settings as part of the service config hash.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-18 18:20:03 -04:00
Philip Walls
85c7d3e5ce Add support for docker run --tmpfs flag.
Signed-off-by: Philip Walls <pawalls@rabidgeek.com>
2016-03-18 18:19:48 -04:00
Daniel Nephin
f1dce50b3d Handle all timeout errors consistently.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-18 18:19:35 -04:00
Daniel Nephin
25cbc2aae9 Fix flaky network test.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-18 18:19:16 -04:00
Daniel Nephin
d5ef0dfa92 Merge pull request #3162 from albers/completion-workdir
bash completion for `docker-compose run --workdir`
2016-03-18 11:25:41 -04:00
Harald Albers
e3c1b5886a bash completion for docker-compose run --workdir
Signed-off-by: Harald Albers <github@albersweb.de>
2016-03-18 10:47:17 +01:00
Daniel Nephin
3a63a0815d Merge pull request #3158 from aanand/windows-install-docs
Windows install docs
2016-03-17 14:40:22 -04:00
Aanand Prasad
50fe014ba9 Remove hardcoded host from Engine install URLs
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-17 18:10:32 +00:00
Aanand Prasad
10dfd54ebe Update install page with link to Windows Toolbox install instructions
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-17 18:09:38 +00:00
Aanand Prasad
72ed4d3f97 Merge pull request #3152 from aanand/update-mac-install-url
Update Mac Engine install URL in error message
2016-03-17 17:56:34 +00:00
Joffrey F
312d764c9c Merge pull request #3156 from graingert/fix-type-error-in-exc-handling
Fix TypeError in Exception handling
2016-03-17 08:51:33 -07:00
Daniel Nephin
b2b58402b3 Merge pull request #3154 from aanand/move-ip-docs-to-reference
Move ipv4_address/ipv6_address docs to reference section
2016-03-17 11:44:42 -04:00
Thomas Grainger
20bf05a6e3 Fix TypeError in Exception handling
Traceback (most recent call last):
  File "/tmp/tmp.02tgGaAGtW/docker-compose/bin/docker-compose", line 11, in <module>
    sys.exit(main())
  File "/tmp/tmp.02tgGaAGtW/docker-compose/lib/python3.4/site-packages/compose/cli/main.py", line 68, in main
    log_api_error(e)
  File "/tmp/tmp.02tgGaAGtW/docker-compose/lib/python3.4/site-packages/compose/cli/main.py", line 89, in log_api_error
    if 'client is newer than server' in e.explanation:
TypeError: 'str' does not support the buffer interface

Signed-off-by: Thomas Grainger <tagrain@gmail.com>
2016-03-17 15:13:01 +00:00
Aanand Prasad
7424938fc8 Move ipv4_address/ipv6_address docs to reference section
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-17 11:32:36 +00:00
Aanand Prasad
92d69b0cb6 Update Mac Engine install URL in error message
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-17 09:56:44 +00:00
Aanand Prasad
371ea479f5 Merge pull request #3075 from dnephin/reactive_logs
Display logs for new containers started after the command is run
2016-03-16 21:03:25 +00:00
Aanand Prasad
abddabfb0a Merge pull request #3135 from dnephin/fix_down_idempotency
Make down idempotent, continue to remove resources if one is missing
2016-03-16 20:26:18 +00:00
Joffrey F
dd40331b44 Merge pull request #3102 from shin-/1477-a-modest-proposal
Add flag to up/down to remove orphaned containers
2016-03-16 10:58:15 -07:00
Aanand Prasad
1696506ff4 Merge pull request #3136 from dnephin/add_workdir_to_run
Add workdir to run
2016-03-16 12:45:00 +00:00
Joffrey F
20c29f7e47 Add flag to up/down to remove orphaned containers
Add --remove-orphans to CLI reference docs
Add --remove-orphans to bash completion file
Test orphan warning and remove_orphan option in up

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-15 16:11:49 -07:00
Daniel Nephin
52b791a264 Split off build_container_options() to reduce the complexity of run
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 15:29:24 -04:00
Simon van der Veldt
658803edf8 Add -w or --workdir to compose run to override workdir from commandline
Signed-off-by: Simon van der Veldt <simon.vanderveldt@gmail.com>
2016-03-15 15:28:32 -04:00
Daniel Nephin
bf96edfe11 Reduce the args of some functions by including presenters as part of the thread_args.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 15:15:00 -04:00
Daniel Nephin
e5529a89e1 Make down idempotent, continue to remove resources if one is missing.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:26:29 -04:00
Daniel Nephin
e8a93821d4 Fix race condition where a container stopping and starting again would cause logs to miss logs.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:17:11 -04:00
Daniel Nephin
8d9adc0902 Fix flaky log test by using container status, instead of boolean state.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:17:10 -04:00
Daniel Nephin
3f7e5bf768 Filter logs by service names.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:17:10 -04:00
Daniel Nephin
48ed68eeaa Fix geneartors for python3.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:17:10 -04:00
Daniel Nephin
4312c93eae Add an acceptance test to show logs behaves properly for stopped containers.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:17:10 -04:00
Daniel Nephin
4cad2a0c5f Handle events for removed containers.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:17:10 -04:00
Daniel Nephin
44c1747127 Add tests for reactive log printing.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:17:10 -04:00
Daniel Nephin
65797558f8 Refactor log printing to support containers that are started later.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-15 13:17:10 -04:00
Aanand Prasad
94b1862579 Merge pull request #2679 from IlyaSkriblovsky/dependency-ordered-start-stop
Parallel up/start/stop
2016-03-15 11:51:44 +00:00
Ilya Skriblovsky
34de1f0a4c Removed unused parallel.parallel_stop
Signed-off-by: Ilya Skriblovsky <IlyaSkriblovsky@gmail.com>
2016-03-14 22:56:58 +03:00
Ilya Skriblovsky
5df774bd10 Fixed testing error handling by up
Signed-off-by: Ilya Skriblovsky <IlyaSkriblovsky@gmail.com>
2016-03-14 22:55:42 +03:00
Ilya Skriblovsky
f933381a12 Dependency-ordered start/stop/up
Signed-off-by: Ilya Skriblovsky <IlyaSkriblovsky@gmail.com>
2016-03-14 22:55:42 +03:00
Aanand Prasad
e5cd869c61 Merge pull request #3095 from dnephin/refactor_command_dispatch
Refactor command dispatch and fix api version mismatch error
2016-03-14 16:18:29 +00:00
Aanand Prasad
9853b876af Merge pull request #3101 from bfirsh/less-scary-swarm-compose-docs
Better Compose in production docs
2016-03-14 16:12:46 +00:00
Ben Firshman
1485a56c75 Better Compose in production docs
The Compose/Swarm integration has been working really well for
users, so it seems pretty safe to remove the scary warnings about
it not being ready.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-03-10 08:55:07 -08:00
Daniel Nephin
99d68be815 Merge pull request #3011 from mdaue/2804
Fix #2804: Add ipv4 and ipv6 static addressing
2016-03-09 16:28:15 -08:00
Matt Daue
ee136446a2 Fix #2804: Add ipv4 and ipv6 static addressing
- Added ipv4_network and ipv6_network to the networks section in the
  service section for each configured network
- Added feature documentation
- Added unit tests

Signed-off-by: Matt Daue <mattdaue@gmail.com>
2016-03-09 18:37:52 -05:00
Daniel Nephin
8a86e204a0 Merge pull request #3063 from albers/completion-multiple-compose-files
add support for multiple compose files to bash completion
2016-03-09 11:12:34 -08:00
Joffrey F
7a30fc0983 Merge pull request #3089 from ltiao/patch-1
Fixed indentation level in example.
2016-03-09 10:56:50 -08:00
Joffrey F
7033042656 Merge pull request #3039 from dbonev/3020-build-arguments-object-syntax
Allowing null for build args
2016-03-09 10:55:05 -08:00
Daniel Nephin
7de9b08ca5 Merge pull request #3066 from shin-/3062-dont-log-noop-volume-create
Don't call create on existing volumes
2016-03-08 15:04:59 -08:00
Daniel Nephin
0a091055d2 Improve handling of connection errors and error messages.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-08 15:39:11 -05:00
Daniel Nephin
886328640f Convert some cli tests to pytest.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-08 14:42:51 -05:00
Daniel Nephin
9f9dcc098a Make TopLevelCommand use the project field.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-08 14:36:53 -05:00
Daniel Nephin
53bea8a720 Refactor command dispatch to improve unit testing and support better error messages.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-08 14:23:27 -05:00
Daniel Nephin
a6649b308e Merge pull request #3094 from aanand/fix-version-in-docs-example
Fix version in aliases example
2016-03-08 11:18:45 -08:00
Aanand Prasad
e700d7ca6a Fix version in docs example
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-08 18:15:18 +01:00
wenchma
000eaee16a Update image format for service conf reference
Signed-off-by: Wen Cheng Ma <wenchma@cn.ibm.com>
2016-03-08 17:14:38 +08:00
Louis Tiao
88a719b4b6 Fixed indentation level in example.
Signed-off-by: Louis Tiao <louistiao@gmail.com>
2016-03-08 15:53:55 +11:00
Joffrey F
d2b065e615 Don't raise ConfigurationError for volume driver mismatch
when driver is unspecified

Add testcase

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-07 18:07:41 -08:00
Joffrey F
698998c410 Don't call create on existing volumes
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-03-07 18:00:27 -08:00
Dimitar Bonev
81b7fba33e Allowing null for build args
Signed-off-by: Dimitar Bonev <dimitar.bonev@gmail.com>
2016-03-05 15:57:06 +02:00
Aanand Prasad
9e242cdc75 Merge pull request #3032 from dnephin/multiple_files_from_env_var
Support multiple files in COMPOSE_FILE env var
2016-03-03 17:23:22 +00:00
Aanand Prasad
4ae71f41dd Merge pull request #2832 from aanand/refactor-cli-unit-tests
Refactor CLI initialization and unit tests
2016-03-02 16:10:44 -08:00
Daniel Nephin
53a3d14046 Support multiple files in COMPOSE_FILE env var.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-02 18:47:58 -05:00
Aanand Prasad
20caf02bf6 Create real Project objects in CLI unit tests
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-02 15:11:34 -08:00
Aanand Prasad
4644f2c0f9 Remove environment-overriding unit test for 'run'
There's already an acceptance test for it

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-02 15:11:32 -08:00
Aanand Prasad
575b48749d Remove unused global_options arg from dispatch()
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-02 15:09:48 -08:00
Aanand Prasad
2c75a8fdf5 Extract helper methods for building config objects from dicts
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-02 15:09:48 -08:00
Aanand Prasad
f75408923e Merge pull request #3053 from dnephin/handle_booleans_in_mappings
Don't allow booleans for mapping types
2016-03-02 15:04:20 -08:00
Aanand Prasad
3f98c0716e Merge pull request #3052 from dnephin/merge_v1_logging
Fix merging of logging options in v1 config
2016-03-02 15:03:36 -08:00
Aanand Prasad
f84ebf9b18 Merge pull request #3048 from dnephin/osx_bin_from_travis
Build OSX binary on Travis
2016-03-02 15:02:57 -08:00
Aanand Prasad
1655be6c5b Merge pull request #2601 from dnephin/dont_build_on_up
Only build as part of `up` if `--build` flag is set
2016-03-02 15:02:18 -08:00
Daniel Nephin
e1b87d7be0 Update reference docs for the new flag.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-02 15:32:51 -05:00
Daniel Nephin
b7fb3a6d9b Add --build flag for up and create
Also adds a warning when up builds an image without the --build flag
so that users know it wont happen on the next up.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-02 15:32:51 -05:00
Harald Albers
0049743615 add support for multiple compose files to bash completion
Since 1.6.0, Compose supports multiple compose files specified with `-f`.
These need to be passed to the docker invocations done by the
completion.

Signed-off-by: Harald Albers <github@albersweb.de>
2016-03-02 21:18:33 +01:00
Aanand Prasad
3f3c05e465 Merge pull request #3049 from aanand/clarify-depends-on
Clarify depends_on logic
2016-03-02 11:59:06 -08:00
Aanand Prasad
aa7b862f4c Clarify depends_on logic
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-03-02 10:29:24 -08:00
Aanand Prasad
0b3561a7d5 Merge pull request #2720 from seguins/2227-improvements-logs
Add flags on logs
2016-03-01 17:41:31 -08:00
Aanand Prasad
af12c78915 Merge pull request #3056 from dnephin/fix_shutdown_errors
Fix signal handling with pyinstaller.
2016-03-01 14:56:27 -08:00
Daniel Nephin
ed4473c849 Fix signal handling with pyinstaller.
Raise a ShutdownException instead of a KeyboardInterupt when a thread.error
is caught. This thread.error is only raised when run from a pyinstaller
binary (for reasons unknown).

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-01 16:39:43 -05:00
Stéphane Seguin
038da4eea3 Logs args of LogPrinter as a dictionary
Signed-off-by: Stéphane Seguin <stephseguin93@gmail.com>
2016-03-01 20:24:15 +01:00
Stéphane Seguin
9b36dc5c54 Add --tail flag as option on logs.
Closes #265
Signed-off-by: Stéphane Seguin <stephseguin93@gmail.com>
2016-03-01 20:23:46 +01:00
Stéphane Seguin
d9b4286f91 Add -t, --timestamps flag as option on logs.
Signed-off-by: Stéphane Seguin <stephseguin93@gmail.com>
2016-03-01 20:23:46 +01:00
Stéphane Seguin
82632098a3 Add -f, --follow flag as option on logs.
Closes #2187
Signed-off-by: Stéphane Seguin <stephseguin93@gmail.com>
2016-03-01 20:23:43 +01:00
Aanand Prasad
7684604830 Merge pull request #3023 from londoncalling/fix-note-3019
WIP: updated note format for dockerfile per Aanand's comments on PR #…
2016-03-01 11:11:55 -08:00
Daniel Nephin
18510b4024 Don't allow booleans for mapping types.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-01 11:57:35 -05:00
Daniel Nephin
b726f508a6 Fix merging of logging options in v1 config.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-01 11:43:26 -05:00
Daniel Nephin
04877d47aa Build osx binary on travis and upload to bintray.
This requires a change to the make-branch script, to have it push the bump branch
to the docker remote instead of the user remote. Pushing to the docker remote
triggers the travis build, which builds the binary.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-03-01 11:34:54 -05:00
Aanand Prasad
fc99c7ee19 Merge pull request #2584 from mjgpy3/patch-1
Update `volumes_from` docs to state default
2016-02-29 15:37:46 -08:00
Aanand Prasad
210856179d Merge pull request #3036 from JesusTinoco/master
Display in the log output the name of those containers created using …
2016-02-29 15:17:14 -08:00
Daniel Nephin
f5ce31d43e Merge pull request #3024 from aanand/update-build-image-docs
Update docs about using build and image together
2016-02-29 14:03:54 -08:00
Daniel Nephin
4db1fef58c Merge pull request #3022 from aanand/update-build-image-extends-note
Update note about build + image with extends
2016-02-29 14:03:28 -08:00
Daniel Nephin
8d24af92e0 Merge pull request #3030 from aanand/document-startup-order-workarounds
Document ways to make services wait for dependencies
2016-02-29 13:01:32 -08:00
Aanand Prasad
97c9c12660 Merge pull request #2023 from TomasTomecek/593-implement-exec
implement exec
2016-02-29 12:21:41 -08:00
Aanand Prasad
6b947ee478 Document ways to make services wait for dependencies
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-29 11:24:58 -08:00
Jesus
6bfb23baaa Display containers name when scale a container
Display in the log output the name of those containers created using the scale command and
change the test_scale_with_api_error test to support the containers name when scale

Signed-off-by: Jesus Rodriguez Tinoco <jesus.rodriguez.tinoco@gmail.com>
2016-02-29 20:19:03 +01:00
Tomas Tomecek
d28c5dda92 implement exec
Resolves #593

Signed-off-by: Tomas Tomecek <ttomecek@redhat.com>
2016-02-29 10:50:09 +01:00
Aanand Prasad
62fb6b99eb Update FAQ regarding long stop times
- It happens on recreate, not just stop

- We now support `stop_signal`, which can help in some cases

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-26 14:34:44 -08:00
Aanand Prasad
1502c5a14d Merge pull request #3025 from aanand/release-notes-1.6.2
Add release notes for 1.6.2
2016-02-26 10:36:26 -08:00
Aanand Prasad
c72e9b3843 Add release notes for 1.6.2
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-25 17:55:04 -08:00
Aanand Prasad
5be48ba1ed Update docs about using build and image together
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-25 17:19:58 -08:00
Aanand Prasad
adb8de367e Merge pull request #2388 from dnephin/fix_long_lines
Wrap long lines
2016-02-25 16:52:33 -08:00
Aanand Prasad
42f4d814d7 Merge pull request #2880 from dnephin/merge_jsonschemas
Merge jsonschemas to a single schema file per version
2016-02-25 16:51:56 -08:00
Victoria Bialas
5cc420e727 WIP: updated note format for dockerfile per Aanand's comments on PR #3019
Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-02-25 16:47:46 -08:00
Aanand Prasad
c2c8c41ef2 Merge pull request #2608 from dnephin/more_cyclomatic_reduction
More cyclomatic complexity reduction
2016-02-25 16:41:49 -08:00
Aanand Prasad
2cd1b94dd3 Update note about build + image with extends
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-25 15:15:18 -08:00
Aanand Prasad
5111d0862c Merge pull request #2672 from dnephin/organize_scripts
Organize scripts into directories
2016-02-25 14:09:03 -08:00
Daniel Nephin
11dc720752 Move test scripts to script/test.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 16:24:13 -08:00
Daniel Nephin
ec6bb1660d Move run scripts to script/run
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 16:24:13 -08:00
Daniel Nephin
a87d482a3b Move all build scripts to script/build
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 16:24:13 -08:00
Daniel Nephin
dc3a5ce624 Refactor config validation to support constraints in the same jsonschema
Reworked the two schema validation functions to read from the same schema but
use different parts of it. Error handling is now split as well by the
schema that is being used to validate.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 16:20:17 -08:00
Daniel Nephin
43ecf8793a Address old TODO, and small refactor of container name logic in service.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 16:19:38 -08:00
Daniel Nephin
cdda616d6b Reduce complexity of sort_service_dicts.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 16:19:38 -08:00
Daniel Nephin
84a1822e40 Reduce complexity of _get_container_create_options
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 16:19:38 -08:00
Daniel Nephin
be554c3a74 Merge v1 config jsonschemas into a single file.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 15:59:10 -08:00
Daniel Nephin
adb64ef8d5 Merge v2 config jsonschemas into a single file.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-24 15:59:10 -08:00
Daniel Nephin
38dd342b7b Merge pull request #3009 from dnephin/update_release_notes
Add release notes for 1.6.1
2016-02-23 16:02:18 -08:00
Joffrey F
f48d321b5b Merge pull request #3008 from shin-/update_dockerpy_version
Update docker-py version in requirements to 1.7.2
2016-02-23 15:41:11 -08:00
Daniel Nephin
49ef8a271d Add release notes for 1.6.1
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-23 15:13:01 -08:00
Daniel Nephin
0467bc3dcf Merge pull request #2998 from londoncalling/docs-wordpress-example
updated Wordpress example to be easier to follow, added/updated images
2016-02-23 15:10:11 -08:00
Joffrey F
97bbee19b7 Update docker-py version in requirements to 1.7.2
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-23 14:55:06 -08:00
Victoria Bialas
e6797e1166 updated Wordpress example to be easier to follow, added/updated images
docs update per Mary's comments on the PR

Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-02-23 11:59:19 -08:00
Daniel Nephin
f2ccbeff76 Merge pull request #2997 from dnephin/fix_env_var_without_value
Fix env var without value
2016-02-23 11:58:30 -08:00
Daniel Nephin
d451578152 Make environment variables without a value the same as docker-cli.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-23 11:14:59 -08:00
Daniel Nephin
4b04280db8 Revert "Change special case from '_', None to ()"
This reverts commit 677c50650c.

Revert "Modify service_test.py::ServiceTest::test_resolve_env to reflect new behavior"

This reverts commit 0019037712.

Revert "Mangle the tests. They pass for better or worse!"

This reverts commit 7ab9509ce6.

Revert "If an env var is passthrough but not defined on the host don't set it."

This reverts commit 6540efb3d3.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-23 11:13:57 -08:00
Daniel Nephin
1d67e6f0f0 Merge pull request #2995 from dnephin/fix_warning_about_bools
Fix warning about boolean values
2016-02-23 11:11:54 -08:00
Daniel Nephin
ba799d2e86 Merge pull request #2996 from dnephin/fix_abort_on_container_exit
Fix abort on container exit
2016-02-23 10:52:12 -08:00
Joffrey F
a7fd578b14 Merge pull request #2962 from shin-/2960-volume-driver
Update docs for volume_driver option
2016-02-22 17:23:07 -08:00
Joffrey F
176b966486 Update documentation for volume_driver option.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-22 16:51:33 -08:00
Daniel Nephin
7e3d756a18 Merge pull request #2992 from shin-/update_dockerpy_version
Use docker-py 1.7.1
2016-02-22 16:50:36 -08:00
Daniel Nephin
15b2094bad Stop other containers if the flag is set.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-22 16:48:46 -08:00
Richard Bann
bf2bf21720 Add failing test for --abort-on-container-exit
Handle --abort-on-container-exit. Fixes #2940

Signed-off-by: Richard Bann <richardbann@gmail.com>
2016-02-22 16:39:40 -08:00
Daniel Nephin
0a06d827fa Fix warning about boolean values.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-22 14:56:01 -08:00
Joffrey F
ba39d4cc77 Use docker-py 1.7.1
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-22 12:56:54 -08:00
Daniel Nephin
d5514965d5 Merge pull request #2975 from dnephin/fix_crash_on_none_in_config
Fix validation message when there are multiple nested oneOf validations.
2016-02-19 15:53:26 -05:00
Daniel Nephin
02535f0cf1 Fix validation message when there are multiple ested oneOf validations.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-19 14:22:55 -05:00
Daniel Nephin
c7ceacfeae Merge pull request #2948 from dnephin/validate_top_level
Validate that each section of the config is a mapping
2016-02-19 13:41:50 -05:00
Aanand Prasad
bed0cfeb32 Merge pull request #2807 from aanand/swarm-doc
Update Swarm integration guide and make it an official part of the docs
2016-02-19 10:25:28 -08:00
Daniel Nephin
0d218c34c7 Make config validation error messages more consistent.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-19 13:12:57 -05:00
Daniel Nephin
4b2a666231 Validate that each section of the config is a mapping before running interpolation.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-19 12:38:52 -05:00
Aanand Prasad
520c695bf4 Update Swarm integration guide and make it an official part of the docs
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-19 09:32:43 -08:00
Aanand Prasad
1f2c2942d7 Merge pull request #2963 from londoncalling/docs-alias-repr2829
corrected description of network aliases, added real-world example pe…
2016-02-19 09:26:40 -08:00
Victoria Bialas
753c953870 Merge branch 'docs-alias-repr2829' of github.com:londoncalling/compose into docs-alias-repr2829
Fixed file format of one word, legacy, adding signature to that commit.

Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-02-18 18:32:44 -08:00
Victoria Bialas
eb4a98c0d1 corrected description of network aliases, added real-world example per #2907
copyedit to make  show as file format

Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-02-18 18:05:52 -08:00
Victoria Bialas
630a50295b copyedit to make show as file format
Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-02-18 18:05:30 -08:00
Victoria Bialas
068a56eb97 corrected description of network aliases, added real-world example per #2907
Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-02-18 17:49:28 -08:00
Joffrey F
5fc0df4be2 Merge pull request #2907 from shin-/2829-net-alias
Allow user to specify custom network aliases
2016-02-18 16:01:30 -08:00
Joffrey F
0cb8ba3775 Use modern set notation in _get_aliases
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 15:28:12 -08:00
Joffrey F
7152f7ea76 Handle mismatched network formats in config files
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 15:24:41 -08:00
Joffrey F
825a0941f0 Network aliases are now part of the network dictionary
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 15:23:47 -08:00
Joffrey F
4b99b32ffb Add v2_only decorator to network aliases test
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 15:23:47 -08:00
Joffrey F
41e399be98 Fix network list serialization in py3
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 15:23:47 -08:00
Joffrey F
7801cfc5d1 Document network_aliases config
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 15:23:47 -08:00
Joffrey F
633e349ab9 Test network_aliases feature
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 15:23:46 -08:00
Joffrey F
2b5d3f51cb Allow user to specify custom network aliases
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 15:23:46 -08:00
Joffrey F
d3a95c2892 Merge pull request #2938 from shin-/2927-buildargs-types
Constraint build argument types. Numbers are cast into strings.
2016-02-18 15:07:09 -08:00
Joffrey F
93a02e497d Apply driver_opts processing to network configs
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-18 10:53:40 -08:00
Aanand Prasad
85ba08bb13 Merge pull request #2932 from AvdN/patch-1
reset colors after warning
2016-02-18 09:25:02 -08:00
Aanand Prasad
50dc27aed7 Merge pull request #2913 from clkao/container-install-fixes
A few fixes to the container-based install, which is broken on:
2016-02-18 09:24:10 -08:00
Aanand Prasad
bd72670947 Merge pull request #2894 from dnephin/only_set_constraint_with_volumes
Only set a container affinity if there are volumes to copy over
2016-02-18 08:46:29 -08:00
Daniel Nephin
4f7530c480 Only set a container affinity if there are volumes to copy over.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-17 22:35:14 -05:00
Joffrey F
1952b52392 Constraint build argument types. Numbers are cast into strings
Numerical driver_opts are also valid and typecast into strings.
Additional config tests.

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-17 11:53:29 -08:00
Joffrey F
706062ad16 Merge pull request #2934 from dnephin/fix_volume_copy
Fix copying of volumes by using the name of the volume
2016-02-17 11:52:18 -08:00
Daniel Nephin
d4f2f54cf8 Merge pull request #2936 from dnephin/update_docs_for_161
Update docs, fix broken link, use v2 compose file format
2016-02-17 13:34:39 -05:00
Daniel Nephin
4a09da43ea Fix copying of volumes by using the name of the volume instead of the host path.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-17 13:34:14 -05:00
Joffrey F
89108f2a0f Merge pull request #2939 from AvdN/patch-2
for 1.6.0 the version value needs to be a string
2016-02-17 09:42:41 -08:00
Anthon van der Neut
1512793b30 for 1.6.0 the version value needs to be a string
After conversion a file would immediately not load in docker-compose 1.6.0 with the message:

  ERROR: Version in "./converted.yml" is invalid - it should be a string.

Signed-off-by: Anthon van der Neut anthon@mnt.org
Signed-off-by: Anthon van der Neut <a.van.der.neut@ruamel.eu>
2016-02-17 10:01:16 +01:00
Daniel Nephin
471264239f Update guides to use v2 config format.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-16 16:43:26 -05:00
Daniel Nephin
4de12ad7a1 Update link to docker volume create docs.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-16 16:43:22 -05:00
Joffrey F
ec3af7d491 Merge pull request #2920 from londoncalling/docs-examples
update to description of files generated from examples, which are no …
2016-02-16 11:51:14 -08:00
Victoria Bialas
8af0a0f85b update to description of files generated from examples, which are no longer owned by root w/new release
updated descriptions of changing file ownership and images per Seb's comments

fixed line wraps

fixed line breaks per Joffrey's comments

Signed-off-by: Victoria Bialas <victoria.bialas@docker.com>
2016-02-16 11:34:59 -08:00
moxiegirl
b8c35e1298 Merge pull request #2884 from moxiegirl/remove-tutorials
Updating Dockerfile
2016-02-16 08:09:49 -08:00
Anthon van der Neut
69d0154718 reset colors after warning
If a warning is shown, and you happen to have no color setting in your (bash) prompt, the \033[37m setting, stays active. With the message hardly readable (light grey on my default light yellow background), that means the prompt is barely visible and you need to do `tput reset`.
Would probably be better if the background color was set as well in case you have dark on light theme by default in your terminal.

Signed-off-by: Anthon van der Neut <a.van.der.neut@ruamel.eu>
2016-02-16 15:42:43 +01:00
Chia-liang Kao
2204b642ef Quote argv as they are
Signed-off-by: Chia-liang Kao <clkao@clkao.org>
2016-02-14 01:57:04 +08:00
Chia-liang Kao
e6a675f338 Detect -t and -i separately
Signed-off-by: Chia-liang Kao <clkao@clkao.org>
2016-02-14 01:56:26 +08:00
Chia-liang Kao
dd55415d4f Don't mount pwd if it is /
Signed-off-by: Chia-liang Kao <clkao@clkao.org>
2016-02-14 01:56:17 +08:00
Daniel Nephin
74dc1b1411 Merge pull request #2893 from shin-/2833-run-dependencies
Bring up all dependencies when running a single service.
2016-02-12 16:33:01 -05:00
Daniel Nephin
16200b0bce Merge pull request #2903 from shin-/2899-invalid-driver-opts
driver_opts can only be of type string
2016-02-12 14:41:05 -05:00
Joffrey F
a8fda480e3 driver_opts can only be of type string
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-12 10:51:11 -08:00
Joffrey F
367fabdbfa Bring up all dependencies when running a single service.
Added test for running a depends_on service

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-12 09:46:10 -08:00
Joffrey F
e1d67ad68a Merge pull request #2882 from shin-/2715-old-server-error
Detailed error message when daemon version is too old.
2016-02-11 16:03:20 -08:00
Daniel Nephin
b6812b8600 Merge pull request #2877 from dnephin/fix_merging_build
Fix build section without context
2016-02-11 18:53:23 -05:00
Joffrey F
79f993f52c Detailed error message when daemon version is too old.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-11 15:20:32 -08:00
Joffrey F
77cf67ba8a Merge pull request #2888 from dnephin/upgrade_pyinstaller
Upgrade pyinstaller.
2016-02-11 12:11:57 -08:00
Joffrey F
5eb45a31e6 Merge pull request #2883 from shin-/2849-log-volume-creation
Add logging when initializing a volume.
2016-02-11 12:11:28 -08:00
Joffrey F
e225f12551 Add logging when initializing a volume.
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-02-11 11:40:22 -08:00
Joffrey F
830a9fc118 Merge pull request #2889 from dnephin/fix_test_broken_on_master
Shm_size requires docker 1.10
2016-02-11 11:18:45 -08:00
Daniel Nephin
532dffd688 Fix build section without context.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-11 14:12:02 -05:00
Daniel Nephin
1e7dd2e740 Upgrade pyinstaller.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-11 13:50:41 -05:00
Daniel Nephin
740329a131 Shm_size requires docker 1.10.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-11 13:50:23 -05:00
Daniel Nephin
7bae4cdbb2 Merge pull request #2875 from aanand/fix-version-in-install-guide
Fix version in install guide
2016-02-11 12:43:51 -05:00
Aanand Prasad
23ab2c7e44 Merge pull request #2878 from dnephin/merge_build_args
Merge build.args when merging services
2016-02-11 17:41:41 +00:00
Aanand Prasad
b8f7bbb84e Merge pull request #2830 from nubs/master
Add support for shm_size.  Fixes #2823.
2016-02-11 17:34:44 +00:00
Joffrey F
a5d95612e0 Merge pull request #2881 from humitos/patch-1
Typo fixed
2016-02-11 09:28:08 -08:00
Mary Anthony
643166ae98 Updating Dockerfile
Signed-off-by: Mary Anthony <mary@docker.com>
2016-02-10 20:47:15 -08:00
Manuel Kaufmann
ac14642d94 Typo fixed
Signed-off-by: Manuel Kaufmann <humitos@gmail.com>
2016-02-10 19:00:17 -05:00
Spencer Rinehart
ab40d389d0 Fix sorting of DOCKER_START_KEYS.
Make sure it's sorted!

Signed-off-by: Spencer Rinehart <anubis@overthemonkey.com>
2016-02-10 15:25:18 -06:00
Spencer Rinehart
5e6dc3521c Add support for shm_size. Fixes #2823.
shm_size controls the size of /dev/shm in the container and requires
Docker 1.10 or newer (API version 1.22).  This requires docker-py 1.8.0
(docker/docker-py#923).

Similar to fields like `mem_limit`, `shm_size` may be specified as
either an integer or a string (e.g., `64M`).

Updating docker-py to the master branch in order to get the unreleased
dependency on `shm_size` there in place.

Signed-off-by: Spencer Rinehart <anubis@overthemonkey.com>
2016-02-10 15:25:18 -06:00
Daniel Nephin
37564a73c3 Merge build.args when merging services.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-10 13:54:40 -05:00
Aanand Prasad
7b5bad6050 Merge pull request #2851 from cr7pt0gr4ph7/2839-fix-networks-merging
Fix merge behavior for 'networks' and 'network_mode'.
2016-02-10 17:51:01 +00:00
Aanand Prasad
c43b25b0cf Merge pull request #2827 from loic/patch-1
Fixed typo in compose-file.md
2016-02-10 15:58:54 +00:00
Aanand Prasad
ab9d82b400 Merge pull request #2842 from michael-k/links
Fixed broken links on pypi
2016-02-10 15:58:39 +00:00
Aanand Prasad
88b11afde2 Merge pull request #2858 from dnephin/fix_upgrading_url_in_changelog
Fix upgrading url in changelog
2016-02-10 15:58:02 +00:00
Aanand Prasad
28689a57a7 Merge pull request #2871 from yograterol/patch-1
Typo into the doc with `networks` in yaml
2016-02-10 15:57:45 +00:00
Aanand Prasad
ab6e07da7d Fix version in install guide
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-10 15:56:50 +00:00
Yohan Graterol
59a2920758 Typo into the doc with networks in yaml
Signed-off-by: Yohan Graterol <yohangraterol92@gmail.com>
2016-02-09 18:45:04 -05:00
Daniel Nephin
6f06b3bd30 Merge pull request #2853 from dnephin/fix_short_id_alias
Use 12 characters for the short id
2016-02-09 14:56:24 -05:00
Michael Käufl
481caa8e48 Used absolute links in readme
This prevents links being broken on pypi
(e.g. https://pypi.python.org/pypi/docs/index.md#features)

Signed-off-by: Michael Käufl <docker-compose@c.michael-kaeufl.de>
2016-02-09 13:29:14 +01:00
Daniel Nephin
63870fbccd Fix upgrading url.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-08 18:15:21 -05:00
cr7pt0gr4ph7
582de19a5a Simplify unit tests in config/config_test.py by using class variables instead of methods for parametrizing tests.
Signed-off-by: cr7pt0gr4ph7 <cr7pt0gr4ph7@gmail.com>
2016-02-08 21:57:15 +01:00
Daniel Nephin
859cc2348c Merge pull request #2744 from aanand/pytest-ini
Add pytest.ini
2016-02-08 14:19:40 -05:00
Joffrey F
fdf4a2e89e Merge pull request #2734 from jrabbit/empty-env-var-2359
Empty env var #2359
2016-02-08 11:17:54 -08:00
Daniel Nephin
421981e7d2 Use 12 characters for the short id to match docker and fix backwards compatibility.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-08 12:18:48 -05:00
Lukas Waslowski
5bd88f634f Handle the 'network_mode' key when merging multiple compose files.
Fixes docker/compose#2840.

Signed-off-by: Lukas Waslowski <cr7pt0gr4ph7@gmail.com>
2016-02-08 15:33:26 +01:00
Lukas Waslowski
5a3a10d43b Correctly merge the 'services/<service>/networks' key in the case of multiple compose files.
Fixes docker/compose#2839.

Signed-off-by: Lukas Waslowski <cr7pt0gr4ph7@gmail.com>
2016-02-08 15:17:21 +01:00
Lukas Waslowski
e929086c49 Separate MergePortsTest from MergeListsTest and add MergeNetworksTest.
Signed-off-by: Lukas Waslowski <cr7pt0gr4ph7@gmail.com>
2016-02-08 14:29:03 +01:00
jrabbit
677c50650c Change special case from '_', None to ()
Signed-off-by: jrabbit <jackjrabbit@gmail.com>
2016-02-06 02:54:06 -05:00
Aanand Prasad
8acb5e17e8 Add pytest section to tox.ini
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-05 13:07:01 +00:00
Loïc Bistuer
b635647105 Fixed typo in compose-file.md
Signed-off-by: Loïc Bistuer <loic.bistuer@gmail.com>
2016-02-05 09:50:22 +07:00
Daniel Nephin
57fc85b457 Wrap long lines and restrict lines to 105 characters.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-04 19:05:39 -05:00
Daniel Nephin
28e652daec Merge pull request #2826 from aanand/bump-1.7.0dev
Bump 1.7.0dev
2016-02-04 18:56:27 -05:00
Aanand Prasad
869e815213 Bump 1.7.0dev
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-04 23:46:41 +00:00
Aanand Prasad
422ff623b4 Merge pull request #2819 from bfirsh/improve-names-in-compose-file-2-example
Improve names in Compose file 2 example
2016-02-04 19:42:22 +00:00
Aanand Prasad
c2db1a24bf Merge pull request #2822 from aanand/update-docker-py-and-dockerpty
Update docker-py and dockerpty
2016-02-04 19:40:41 +00:00
Aanand Prasad
be236d8801 Update docker-py and dockerpty
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-04 19:16:01 +00:00
Aanand Prasad
93426cec4c Merge pull request #2824 from dnephin/docs_version_is_a_string
Update docs for version being a string
2016-02-04 17:20:32 +00:00
Daniel Nephin
a7c2987991 Update docs for version being a string.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-04 12:19:43 -05:00
Aanand Prasad
386974f831 Merge pull request #2814 from nubs/patch-1
Fix example formatting for depends_on.
2016-02-04 15:56:27 +00:00
Daniel Nephin
80d02e84e2 Merge pull request #2808 from aanand/connect-before-start
Connect container to networks before starting it
2016-02-03 23:49:56 -05:00
Ben Firshman
bdddbe3a73 Improve names in Compose file 2 example
Just makes it a bit clearer what's going on.

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
2016-02-03 17:42:57 -08:00
Spencer Rinehart
f612bc98d9 Fix example formatting for depends_on.
Markdown was acting against expectations here by merging the example indented YAML into the previous list item instead of treating it as a code block.

I decided that a better way of handling this would be to add a "Simple example:" line that is also used elsewhere in this file.  It resets the markdown indentation in a way that works.

Signed-off-by: Spencer Rinehart <anubis@overthemonkey.com>
2016-02-03 14:36:46 -06:00
Daniel Nephin
89c5b800e6 Merge pull request #2782 from dbonev/2772-compose-project-name-empty
Falling back to default project name on empty COMPOSE_PROJECT_NAME
2016-02-02 20:37:38 -05:00
Sven Dowideit
bd1c8973ab Merge pull request #2809 from moxiegirl/fixing-dup-identifier
Fixing duplicate identifiers for 1.10
2016-02-02 15:43:09 -08:00
Mary Anthony
a713447e0b Fixing duplicate identifiers
Signed-off-by: Mary Anthony <mary@docker.com>
2016-02-02 12:04:13 -08:00
Aanand Prasad
2651c00f0c Connect container to networks before starting it
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-02 19:31:49 +00:00
Daniel Nephin
4c4e94bc19 Merge pull request #2785 from dnephin/depends_on_with_extends
Fix list options when used with extends and multiple files
2016-02-02 13:36:46 -05:00
Daniel Nephin
1cb67b781c Merge pull request #2777 from dnephin/reorder_docs
Re-order docs in menu, fix menu title capitalization, cleanup command reference
2016-02-02 11:26:26 -05:00
Daniel Nephin
c290e560cb Merge pull request #2786 from dnephin/refactor_project
Fix a few bugs around networking and project initilization
2016-02-02 11:19:34 -05:00
Aanand Prasad
7a197e5a69 Merge pull request #2802 from dnephin/appveyor_to_bintray_deploy
Deploying to bintray from appveyor using the new bintray support
2016-02-02 16:13:07 +00:00
Daniel Nephin
c81cc24e72 Merge pull request #2806 from aanand/run-tests-with-tty
Run test containers in TTY mode
2016-02-02 10:56:21 -05:00
Daniel Nephin
3d3388d59b Extract volume init and removal from project.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:53:04 -05:00
Daniel Nephin
e551988616 Include networks in the config_hash.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:52:03 -05:00
Daniel Nephin
0810eeba10 Don't initialize networks that aren't used by any services.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:52:03 -05:00
Daniel Nephin
8e838968fe Refactor project network initlization.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:51:31 -05:00
Daniel Nephin
3ec87adccc Update merge docs with depends_on, and correction about how links and volumes_from are merged.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:49:43 -05:00
Daniel Nephin
e32863f89e Make links unique-by-alias when merging
Factor out MergeDict from merge_service_dicts to reduce complexity below limit.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:48:47 -05:00
Daniel Nephin
bf6a5d3e49 Fix merging of lists with multiple files.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:48:18 -05:00
Ryan Taylor Long
c70c72f49a Add depends_on to ALLOWED_KEYS
This ensures and already existing `depends_on` is not deleted when the service on which it is defined also employs `extends`.

Signed-off-by: Ryan Taylor Long <ryan@rtlong.com>
2016-02-02 10:48:18 -05:00
Daniel Nephin
7b03de7d01 Move command reference to overview.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:46:52 -05:00
Daniel Nephin
cf24c36c55 Rename the old environment variable page to link environment variables.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:46:29 -05:00
Daniel Nephin
2df5593e8f Cleanup command-line reference docs by renaming overview to envvars.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:46:28 -05:00
Daniel Nephin
5e30f089e3 Use the same capitalization for all menu items in the docs.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:46:28 -05:00
Daniel Nephin
4f92004d9a Re-order compose docs so that quickstart guides come before other documentation.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-02 10:46:28 -05:00
Aanand Prasad
60a5b39f6f Merge pull request #2783 from aanand/fix-validation-v2
Fix validation and version checking
2016-02-02 15:19:50 +00:00
Aanand Prasad
1152c5b25b Tweak and test warning shown when version is a dict
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-02 13:58:34 +00:00
Aanand Prasad
ef8db3650a Improve error messages for invalid versions
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-02 13:58:34 +00:00
Aanand Prasad
aeef61fcd8 Make 'version' a string
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-02 13:58:34 +00:00
Aanand Prasad
a8de582425 Remove redundant check - self.config should never be None
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-02 13:47:44 +00:00
Aanand Prasad
4ac004059a Normalise/fix config field designators in validation messages
- Instead of "Service 'web' configuration key 'image'", just say
  "web.image"

- Fix the "Service 'services'" bug in the v2 file format

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-02 13:47:43 +00:00
Aanand Prasad
d40bc6e4a0 Convert validation error tests to pytest style
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-02 13:47:43 +00:00
Aanand Prasad
e8756905ba Run test containers in TTY mode
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-02-02 13:31:28 +00:00
Daniel Nephin
6928c24323 Deploying to bintray from appveyor using the new bintray support.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-02-01 16:44:45 -05:00
Daniel Nephin
9c6c50c607 Merge pull request #2796 from mustafau/patch-1
Update link to "Common Use Cases" title
2016-02-01 11:24:18 -05:00
Aanand Prasad
1816147d57 Merge pull request #2740 from albers/completion-create
bash completion for `docker-compose create`
2016-02-01 15:44:07 +00:00
Aanand Prasad
c1cb75cc4f Merge pull request #2741 from sdurrheimer/zsh-completion-create-command
Add zsh completion for 'docker-compose create'
2016-02-01 15:43:47 +00:00
Aanand Prasad
b912b306f1 Merge pull request #2784 from dnephin/signal_race
Fix race condition with up and setting signal handlers
2016-02-01 15:15:59 +00:00
Mustafa Ulu
0b7877d82a Update link to "Common Use Cases" title
It is now under overview.md

Signed-off-by: Mustafa Ulu <mustafau@sabanciuniv.edu>
2016-02-01 00:17:18 +02:00
Dimitar Bonev
34ccb90d7e Falling back to default project name when COMPOSE_PROJECT_NAME is set to empty
Signed-off-by: Dimitar Bonev <dimitar.bonev@gmail.com>
2016-01-30 10:14:45 +02:00
Daniel Nephin
b4868d0259 Fix race condition with up and setting signal handlers.
Also print stdout on wait_for_container().

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-29 13:04:04 -05:00
Daniel Nephin
40d69675f3 Merge pull request #2745 from albers/completion-services
Fix computation of service lists in bash completion
2016-01-28 16:08:46 -05:00
Daniel Nephin
517d3a581c Merge pull request #2768 from aanand/fix-make-branch
Fixes to make-branch script
2016-01-28 15:05:21 -05:00
Daniel Nephin
883e45626f Merge pull request #2706 from dnephin/dont_copy_host_volumes
Don't copy host volumes on recreate
2016-01-28 15:02:53 -05:00
Aanand Prasad
12af889e26 Merge pull request #2737 from moxiegirl/new-navigation
New navigation for 1.10 release
2016-01-28 12:38:28 +00:00
Mary Anthony
3fc72038c5 New navigation for 1.10 release
Updating with Joffrey's comments

Signed-off-by: Mary Anthony <mary@docker.com>
2016-01-27 12:05:56 -08:00
Aanand Prasad
634ae7daa5 Let the user specify any repo as their fork
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-27 15:40:28 +00:00
Aanand Prasad
3547c55523 Default to vim if EDITOR is not set
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-27 15:40:28 +00:00
Aanand Prasad
8c250e220c Merge pull request #2754 from aanand/upgrading-improvements
Improvements to upgrade guide and script
2016-01-27 13:48:23 +00:00
Aanand Prasad
888f4b43c9 Merge pull request #2762 from aanand/remove-links-warnings
Remove outdated warnings about links from docs
2016-01-27 13:08:15 +00:00
Aanand Prasad
d3a1cea170 Remove outdated warnings about links from docs
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-27 02:34:59 +00:00
Aanand Prasad
3aa545eb8e Merge pull request #2755 from aanand/fix-rebase-script
Fix rebase-bump-commit script
2016-01-27 02:05:24 +00:00
Aanand Prasad
ca81672b82 Merge pull request #2761 from aanand/fix-bridge-plus-host
Remove ability to join bridge network + user-defined networks
2016-01-27 01:41:07 +00:00
Aanand Prasad
650b0cec38 Remove ability to join bridge network + user-defined networks
Containers connected to the bridge network can't have aliases, so it's
simpler to rule that they can *either* be connected to the bridge
network (via `network_mode: bridge`) *or* be connected to user-defined
networks (via `networks` or the default network).

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-27 00:42:09 +00:00
Joffrey F
e69ef1c456 Bump docker-py version to latest RC
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-01-27 00:36:38 +00:00
Aanand Prasad
d3d09ceb08 Merge pull request #2756 from aanand/external-links-v2
Add back external links in v2
2016-01-27 00:34:17 +00:00
Aanand Prasad
cd4cc8b8c6 Merge pull request #2760 from aanand/fix-docs-whitespace
Fix trailing whitespace in docker-compose.md
2016-01-26 23:39:59 +00:00
Aanand Prasad
b84da7c78b Fix trailing whitespace in docker-compose.md
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 23:22:21 +00:00
Aanand Prasad
0ba02b4a18 Add back external links in v2
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 18:48:43 +00:00
Aanand Prasad
e40a46349f Fix rebase-bump-commit script
Trim whitespace from wc's output before constructing arguments to `git rebase`

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 17:42:44 +00:00
Aanand Prasad
bacc2b730e Merge pull request #2748 from schmunk42/master
fixed documentation about traversing yml files
2016-01-26 17:20:40 +00:00
Aanand Prasad
7d403d09cf Extract helper methods
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 16:08:34 +00:00
Aanand Prasad
aa4d43af0b Create declarations for named volumes
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 16:07:26 +00:00
Aanand Prasad
f86fe11825 Make sure version line is at the top of the file
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 15:54:18 +00:00
Aanand Prasad
47b22e90f9 Make warnings a bit more readable
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 15:53:25 +00:00
Aanand Prasad
4736b4409a Update for links, external_links, network_mode
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 15:53:02 +00:00
Aanand Prasad
c39d5a3f06 Add note about named volumes to upgrade guide
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-26 15:51:09 +00:00
Joffrey F
4b84d088e0 Merge pull request #2743 from aanand/network-mode
Implement network_mode option
2016-01-25 18:26:35 -08:00
Aanand Prasad
ed1b204804 Rename 'net' to 'network mode' in various classes/methods
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-25 23:55:20 +00:00
Aanand Prasad
a9c623fdf2 Test that net can be extended
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-25 23:55:20 +00:00
Aanand Prasad
e566a4dc1c Implement network_mode in v2
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-25 23:24:55 +00:00
Aanand Prasad
a267d8fe3c Merge pull request #2728 from shin-/2709_service_volumes
Match named volumes in service definitions with declared volumes
2016-01-25 23:24:09 +00:00
Joffrey F
af6b18cad8 Merge pull request #2746 from aanand/alias-containers-by-short-id
Alias containers by short id
2016-01-25 13:55:30 -08:00
Tobias Munk
5fe0b57e5c fixed documentation about traversing yml files
Signed-off-by: Tobias Munk <schmunk@usrbin.de>
2016-01-25 19:33:39 +01:00
Aanand Prasad
313c584185 Alias containers by short id
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-25 16:14:21 +00:00
Harald Albers
73a0d83075 Fix computation of service list in bash completion
The previous approach assumed that the service list could be extracted
from a single file. It did not follow extends and overrides.

Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-25 15:51:58 +01:00
Aanand Prasad
3fff286e1a Merge pull request #2727 from dbonev/2703-strict-validation-of-networks
Network fields schema validation
2016-01-25 14:39:54 +00:00
Steve Durrheimer
381d58bc66 Add zsh completion for 'docker-compose create'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-25 10:27:21 +01:00
Harald Albers
7f3a319ecc bash completion for docker-compose create
Signed-off-by: Harald Albers <github@albersweb.de>
2016-01-25 10:15:14 +01:00
jrabbit
0019037712 Modify service_test.py::ServiceTest::test_resolve_env to reflect new behavior
Signed-off-by: jrabbit <jackjrabbit@gmail.com>
2016-01-24 15:25:06 -05:00
jrabbit
7ab9509ce6 Mangle the tests. They pass for better or worse!
Signed-off-by: jrabbit <jackjrabbit@gmail.com>
2016-01-23 16:19:17 -05:00
jrabbit
6540efb3d3 If an env var is passthrough but not defined on the host don't set it.
This doesn't change too much code and keeps the generators.

Signed-off-by: jrabbit <jackjrabbit@gmail.com>
2016-01-23 15:58:06 -05:00
Joffrey F
139c7f7830 Move named volumes matching to config validation phase
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-01-22 17:42:24 -08:00
Joffrey F
48377a354f is_named_volume also tests for home paths ~
Fix bug with VolumeSpec not being updated
Fix integration test

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-01-22 16:05:21 -08:00
Dimitar Bonev
3a72edb906 Network fields schema validation
Signed-off-by: Dimitar Bonev <dimitar.bonev@gmail.com>
2016-01-22 16:42:10 +02:00
Aanand Prasad
35788f47ff Merge pull request #2729 from shin-/bump_docker_py
Use latest docker-py rc
2016-01-22 11:40:35 +00:00
Aanand Prasad
49c83b16c2 Merge pull request #2726 from aanand/no-logs-on-interactive-run
Pass logs=False to dockerpty
2016-01-22 11:37:58 +00:00
Joffrey F
9e67eae311 Match named volumes in service definitions with declared volumes
Raise ConfigurationError for undeclared named volumes
Test new behavior

Signed-off-by: Joffrey F <joffrey@docker.com>
2016-01-21 18:10:53 -08:00
Joffrey F
77b435f4fe Use latest docker-py rc
Signed-off-by: Joffrey F <joffrey@docker.com>
2016-01-21 18:07:14 -08:00
Daniel Nephin
963ec1ceda Merge pull request #2707 from dnephin/add_stop_signal_to_docs
Add stop signal to the docs
2016-01-21 18:41:28 -05:00
Aanand Prasad
da2b6329ae Add test for logs=False
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>

Conflicts:
	compose/cli/main.py
2016-01-21 19:20:50 +00:00
Alf Lervag
6e73fb38ea Fixes #2448
Signed-off-by: Alf Lervag <alf.lervag@bouvet.no>

Conflicts:
	compose/cli/main.py
	requirements.txt
2016-01-21 19:19:37 +00:00
Aanand Prasad
8662ce8e21 Merge pull request #2723 from aanand/fix-run-with-networking
Fix 'run' behaviour with networks
2016-01-21 19:07:53 +00:00
Aanand Prasad
730c33b28c Merge pull request #2699 from aanand/update-compose-file-docs
Update Compose file documentation for version 2
2016-01-21 18:57:16 +00:00
Joffrey F
fec8cc9f80 Update documentation for external param
Signed-off-by: Joffrey F <joffrey@docker.com>

Conflicts:
	docs/compose-file.md
2016-01-21 18:51:28 +00:00
Aanand Prasad
59493dd7aa Add links to networks key references
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 18:51:28 +00:00
Aanand Prasad
2f41f3aa7e Update documentation for links
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 18:51:28 +00:00
Aanand Prasad
9a3378930f Document depends_on
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 18:50:44 +00:00
Aanand Prasad
0554c6e6fd Update Compose file documentation for version 2
- Explain each version in its own section
- Explain how to upgrade from version 1 to 2
- Note which keys are restricted to particular versions
- A few corrections to the docs for version-specific keys

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 18:50:44 +00:00
Aanand Prasad
f3e55568d1 Fix interactive run with networking
Make sure we connect the container to all required networks *after*
starting the container and *before* hijacking the terminal.

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 18:42:59 +00:00
Aanand Prasad
09dbc7b4cb Stop connecting to all networks on container creation
This relies on an Engine behaviour which is a bug, not an intentional
feature - we have to connect to networks one at a time

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 18:04:50 +00:00
Aanand Prasad
a14906fd35 Fix 'run' behaviour with networks
- Test that one-off containers join all networks
- Don't set any aliases

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 17:28:55 +00:00
Aanand Prasad
1e51b7e88b Merge pull request #2722 from aanand/fix-scale-race-condition
Fix scale race condition
2016-01-21 17:08:15 +00:00
Aanand Prasad
013c5ea3f9 Merge pull request #2713 from aanand/links-v2
Support links in v2 files
2016-01-21 17:08:05 +00:00
Aanand Prasad
7a4fdfd034 Merge pull request #2712 from jzvelc/fix_v2_service_extend
Fix `extends` when using v2 config format
2016-01-21 17:06:21 +00:00
Aanand Prasad
642e71b4c7 Stop and remove containers in parallel when scaling down
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 15:28:40 +00:00
Aanand Prasad
755c49b500 Fix scale when containers exit immediately
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 15:19:55 +00:00
Aanand Prasad
ee63075a34 Support links in v2 files
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 14:34:26 +00:00
Aanand Prasad
5a249bd9f5 Fix Windows build failures when installing dependencies from git
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-21 11:39:08 +00:00
Jure Žvelc
907c3ce42b Fix for extending services written in v2 format.
Signed-off-by: Jure Žvelc <jzvelc@gmail.com>
2016-01-20 18:46:16 +01:00
Aanand Prasad
e35bf47a7f Merge pull request #2708 from dnephin/implement_depends_on
Implement depends_on
2016-01-20 17:46:10 +00:00
Aanand Prasad
fd6b7d1747 Merge pull request #2693 from dnephin/migrate_v1_to_v2
Add a migration script for v1 to v2 compose format
2016-01-20 17:45:01 +00:00
Daniel Nephin
3b1a0e6fc9 Add stop signal to the docs.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-19 21:33:04 -05:00
Daniel Nephin
5aadf5a187 Update tests in sort_services_test.py to use pytest.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-19 15:52:17 -05:00
Daniel Nephin
146587643c Move ulimits validation to validation.py and improve the error message.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-19 15:47:57 -05:00
Daniel Nephin
0bce467782 Implement depends_on to define an order for services in the v2 format.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-19 15:41:45 -05:00
Daniel Nephin
85619842be Add migration script.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-19 14:50:41 -05:00
Daniel Nephin
c39489f540 Don't copy over volumes that were previously host volumes, and are now container volumes.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-19 14:41:21 -05:00
Daniel Nephin
c47aea9c12 Merge pull request #2698 from aanand/fix-name-is-reserved
Fix "name is reserved" with Engine 1.10 RC1
2016-01-19 10:15:06 -05:00
Daniel Nephin
1be147f775 Merge pull request #2696 from aanand/test-external-default
Test that you can set the default network to be external
2016-01-19 10:09:42 -05:00
Aanand Prasad
2106481c23 Fix "name is reserved" with Engine 1.10 RC1
Ensure link aliases are unique (this deduping was previously performed
on the server).

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-19 11:27:27 +00:00
Aanand Prasad
5b2b4cbb07 Merge pull request #2692 from aanand/fix-tls-paramater-error
Catch TLSParameterErrors from docker-py
2016-01-19 11:25:21 +00:00
Aanand Prasad
746033ed9d Test that you can set the default network to be external
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-19 10:57:12 +00:00
Aanand Prasad
413cdbcb81 Merge pull request #2675 from sdurrheimer/zsh-completion-up-abort-on-container-exit
Add zsh completion for 'docker-compose up --abort-on-container-exit'
2016-01-19 10:41:08 +00:00
Aanand Prasad
683c8b0067 Merge pull request #2676 from sdurrheimer/zsh-completion-down-command
Add zsh completion for 'docker-compose down'
2016-01-19 10:40:29 +00:00
Aanand Prasad
9d2e1f58d9 Merge pull request #2677 from sdurrheimer/zsh-completion-fix-invalid-commands-cache
Fix zsh completion to ensure we have enough commands to store in the …
2016-01-19 10:40:03 +00:00
Aanand Prasad
adedbee41b Merge pull request #2694 from dnephin/release_script_fixes
Fix some bugs in release scripts
2016-01-19 10:39:06 +00:00
Aanand Prasad
9ccef1ea91 Catch TLSParameterErrors from docker-py
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-18 21:48:12 +00:00
Daniel Nephin
66dd9ae9a4 Fix some bugs in release scripts.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-18 15:59:40 -05:00
Aanand Prasad
341fa58b21 Merge pull request #2690 from aanand/ipam-config
Allow custom ipam config
2016-01-18 19:44:07 +00:00
Aanand Prasad
b863fe5723 Merge pull request #2687 from aanand/update-networking-docs
Update networking docs
2016-01-18 18:59:33 +00:00
Aanand Prasad
afae365050 Allow custom ipam config
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-18 18:56:18 +00:00
Aanand Prasad
6b105a6e92 Update networking docs
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-18 18:45:29 +00:00
Aanand Prasad
da490f5b0a Merge pull request #2686 from aanand/fix-custom-default-network
Allow overriding of config for the default network
2016-01-18 17:08:25 +00:00
Aanand Prasad
e7673bf920 Allow overriding of config for the default network
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-18 16:17:39 +00:00
Aanand Prasad
53d56ea245 Quote network names in error messages
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2016-01-18 16:15:52 +00:00
Steve Durrheimer
d54190167a Fix zsh completion to ensure we have enough commands to store in the cache
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-16 13:53:16 +01:00
Steve Durrheimer
f6561f1290 Add zsh completion for 'docker-compose down'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-16 13:47:48 +01:00
Steve Durrheimer
e7180982aa Add zsh completion for 'docker-compose up --abort-on-container-exit'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-01-16 13:22:02 +01:00
Joffrey F
a677a2c1f0 Merge pull request #2674 from dnephin/use-1.10-rc1
Test against docker 1.10.0-rc1
2016-01-15 17:13:56 -08:00
Daniel Nephin
ab927b986f Test against 1.10rc1.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-15 19:04:01 -05:00
Daniel Nephin
cce3b29688 Merge pull request #2665 from dnephin/check_extends_use_same_version
Validate that an extended config file has the same version as the base
2016-01-15 18:07:56 -05:00
Daniel Nephin
0f1a798f28 Increase the timeout for all acceptance tests.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-15 10:14:55 -05:00
Daniel Nephin
dc1104649f Validate that an extended config file has the same version as the base.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2016-01-14 22:28:20 -05:00
Michael Gilliland
39af6b653b Update volumes_from docs to state default
[Proof of read-write](cfb1b37da2/compose/config/types.py (L26)).

I found myself wondering what the default was a couple of times, and finally decided to change it :)

Signed-off-by: Michael Gilliland <gillilandmj@upmc.edu>
2015-12-28 16:44:31 -05:00
190 changed files with 9449 additions and 6174 deletions

View file

@ -10,7 +10,7 @@
- id: end-of-file-fixer
- id: flake8
- id: name-tests-test
exclude: 'tests/integration/testcases.py'
exclude: 'tests/(integration/testcases\.py|helpers\.py)'
- id: requirements-txt-fixer
- id: trailing-whitespace
- repo: git://github.com/asottile/reorder_python_imports

View file

@ -25,3 +25,5 @@ deploy:
key: '$BINTRAY_API_KEY'
file: ./bintray.json
skip_cleanup: true
on:
all_branches: true

View file

@ -1,6 +1,398 @@
Change log
==========
1.11.0 (2017-02-08)
-------------------
### New Features
#### Compose file version 3.1
- Introduced version 3.1 of the `docker-compose.yml` specification. This
version requires Docker Engine 1.13.0 or above. It introduces support
for secrets. See the documentation for more information
#### Compose file version 2.0 and up
- Introduced the `docker-compose top` command that displays processes running
for the different services managed by Compose.
### Bugfixes
- Fixed a bug where extending a service defining a healthcheck dictionary
would cause `docker-compose` to error out.
- Fixed an issue where the `pid` entry in a service definition was being
ignored when using multiple Compose files.
1.10.1 (2017-02-01)
------------------
### Bugfixes
- Fixed an issue where presence of older versions of the docker-py
package would cause unexpected crashes while running Compose
- Fixed an issue where healthcheck dependencies would be lost when
using multiple compose files for a project
- Fixed a few issues that made the output of the `config` command
invalid
- Fixed an issue where adding volume labels to v3 Compose files would
result in an error
- Fixed an issue on Windows where build context paths containing unicode
characters were being improperly encoded
- Fixed a bug where Compose would occasionally crash while streaming logs
when containers would stop or restart
1.10.0 (2017-01-18)
-------------------
### New Features
#### Compose file version 3.0
- Introduced version 3.0 of the `docker-compose.yml` specification. This
version requires to be used with Docker Engine 1.13 or above and is
specifically designed to work with the `docker stack` commands.
#### Compose file version 2.1 and up
- Healthcheck configuration can now be done in the service definition using
the `healthcheck` parameter
- Containers dependencies can now be set up to wait on positive healthchecks
when declared using `depends_on`. See the documentation for the updated
syntax.
**Note:** This feature will not be ported to version 3 Compose files.
- Added support for the `sysctls` parameter in service definitions
- Added support for the `userns_mode` parameter in service definitions
- Compose now adds identifying labels to networks and volumes it creates
#### Compose file version 2.0 and up
- Added support for the `stop_grace_period` option in service definitions.
### Bugfixes
- Colored output now works properly on Windows.
- Fixed a bug where docker-compose run would fail to set up link aliases
in interactive mode on Windows.
- Networks created by Compose are now always made attachable
(Compose files v2.1 and up).
- Fixed a bug where falsy values of `COMPOSE_CONVERT_WINDOWS_PATHS`
(`0`, `false`, empty value) were being interpreted as true.
- Fixed a bug where forward slashes in some .dockerignore patterns weren't
being parsed correctly on Windows
1.9.0 (2016-11-16)
-----------------
**Breaking changes**
- When using Compose with Docker Toolbox/Machine on Windows, volume paths are
no longer converted from `C:\Users` to `/c/Users`-style by default. To
re-enable this conversion so that your volumes keep working, set the
environment variable `COMPOSE_CONVERT_WINDOWS_PATHS=1`. Users of
Docker for Windows are not affected and do not need to set the variable.
New Features
- Interactive mode for `docker-compose run` and `docker-compose exec` is
now supported on Windows platforms. Please note that the `docker` binary
is required to be present on the system for this feature to work.
- Introduced version 2.1 of the `docker-compose.yml` specification. This
version requires to be used with Docker Engine 1.12 or above.
- Added support for setting volume labels and network labels in
`docker-compose.yml`.
- Added support for the `isolation` parameter in service definitions.
- Added support for link-local IPs in the service networks definitions.
- Added support for shell-style inline defaults in variable interpolation.
The supported forms are `${FOO-default}` (fall back if FOO is unset) and
`${FOO:-default}` (fall back if FOO is unset or empty).
- Added support for the `group_add` and `oom_score_adj` parameters in
service definitions.
- Added support for the `internal` and `enable_ipv6` parameters in network
definitions.
- Compose now defaults to using the `npipe` protocol on Windows.
- Overriding a `logging` configuration will now properly merge the `options`
mappings if the `driver` values do not conflict.
Bug Fixes
- Fixed several bugs related to `npipe` protocol support on Windows.
- Fixed an issue with Windows paths being incorrectly converted when
using Docker on Windows Server.
- Fixed a bug where an empty `restart` value would sometimes result in an
exception being raised.
- Fixed an issue where service logs containing unicode characters would
sometimes cause an error to occur.
- Fixed a bug where unicode values in environment variables would sometimes
raise a unicode exception when retrieved.
- Fixed an issue where Compose would incorrectly detect a configuration
mismatch for overlay networks.
1.8.1 (2016-09-22)
-----------------
Bug Fixes
- Fixed a bug where users using a credentials store were not able
to access their private images.
- Fixed a bug where users using identity tokens to authenticate
were not able to access their private images.
- Fixed a bug where an `HttpHeaders` entry in the docker configuration
file would cause Compose to crash when trying to build an image.
- Fixed a few bugs related to the handling of Windows paths in volume
binding declarations.
- Fixed a bug where Compose would sometimes crash while trying to
read a streaming response from the engine.
- Fixed an issue where Compose would crash when encountering an API error
while streaming container logs.
- Fixed an issue where Compose would erroneously try to output logs from
drivers not handled by the Engine's API.
- Fixed a bug where options from the `docker-machine config` command would
not be properly interpreted by Compose.
- Fixed a bug where the connection to the Docker Engine would
sometimes fail when running a large number of services simultaneously.
- Fixed an issue where Compose would sometimes print a misleading
suggestion message when running the `bundle` command.
- Fixed a bug where connection errors would not be handled properly by
Compose during the project initialization phase.
- Fixed a bug where a misleading error would appear when encountering
a connection timeout.
1.8.0 (2016-06-14)
-----------------
**Breaking Changes**
- As announced in 1.7.0, `docker-compose rm` now removes containers
created by `docker-compose run` by default.
- Setting `entrypoint` on a service now empties out any default
command that was set on the image (i.e. any `CMD` instruction in the
Dockerfile used to build it). This makes it consistent with
the `--entrypoint` flag to `docker run`.
New Features
- Added `docker-compose bundle`, a command that builds a bundle file
to be consumed by the new *Docker Stack* commands in Docker 1.12.
- Added `docker-compose push`, a command that pushes service images
to a registry.
- Compose now supports specifying a custom TLS version for
interaction with the Docker Engine using the `COMPOSE_TLS_VERSION`
environment variable.
Bug Fixes
- Fixed a bug where Compose would erroneously try to read `.env`
at the project's root when it is a directory.
- `docker-compose run -e VAR` now passes `VAR` through from the shell
to the container, as with `docker run -e VAR`.
- Improved config merging when multiple compose files are involved
for several service sub-keys.
- Fixed a bug where volume mappings containing Windows drives would
sometimes be parsed incorrectly.
- Fixed a bug in Windows environment where volume mappings of the
host's root directory would be parsed incorrectly.
- Fixed a bug where `docker-compose config` would output an invalid
Compose file if external networks were specified.
- Fixed an issue where unset buildargs would be assigned a string
containing `'None'` instead of the expected empty value.
- Fixed a bug where yes/no prompts on Windows would not show before
receiving input.
- Fixed a bug where trying to `docker-compose exec` on Windows
without the `-d` option would exit with a stacktrace. This will
still fail for the time being, but should do so gracefully.
- Fixed a bug where errors during `docker-compose up` would show
an unrelated stacktrace at the end of the process.
- `docker-compose create` and `docker-compose start` show more
descriptive error messages when something goes wrong.
1.7.1 (2016-05-04)
-----------------
Bug Fixes
- Fixed a bug where the output of `docker-compose config` for v1 files
would be an invalid configuration file.
- Fixed a bug where `docker-compose config` would not check the validity
of links.
- Fixed an issue where `docker-compose help` would not output a list of
available commands and generic options as expected.
- Fixed an issue where filtering by service when using `docker-compose logs`
would not apply for newly created services.
- Fixed a bug where unchanged services would sometimes be recreated in
in the up phase when using Compose with Python 3.
- Fixed an issue where API errors encountered during the up phase would
not be recognized as a failure state by Compose.
- Fixed a bug where Compose would raise a NameError because of an undefined
exception name on non-Windows platforms.
- Fixed a bug where the wrong version of `docker-py` would sometimes be
installed alongside Compose.
- Fixed a bug where the host value output by `docker-machine config default`
would not be recognized as valid options by the `docker-compose`
command line.
- Fixed an issue where Compose would sometimes exit unexpectedly while
reading events broadcasted by a Swarm cluster.
- Corrected a statement in the docs about the location of the `.env` file,
which is indeed read from the current directory, instead of in the same
location as the Compose file.
1.7.0 (2016-04-13)
------------------
**Breaking Changes**
- `docker-compose logs` no longer follows log output by default. It now
matches the behaviour of `docker logs` and exits after the current logs
are printed. Use `-f` to get the old default behaviour.
- Booleans are no longer allows as values for mappings in the Compose file
(for keys `environment`, `labels` and `extra_hosts`). Previously this
was a warning. Boolean values should be quoted so they become string values.
New Features
- Compose now looks for a `.env` file in the directory where it's run and
reads any environment variables defined inside, if they're not already
set in the shell environment. This lets you easily set defaults for
variables used in the Compose file, or for any of the `COMPOSE_*` or
`DOCKER_*` variables.
- Added a `--remove-orphans` flag to both `docker-compose up` and
`docker-compose down` to remove containers for services that were removed
from the Compose file.
- Added a `--all` flag to `docker-compose rm` to include containers created
by `docker-compose run`. This will become the default behavior in the next
version of Compose.
- Added support for all the same TLS configuration flags used by the `docker`
client: `--tls`, `--tlscert`, `--tlskey`, etc.
- Compose files now support the `tmpfs` and `shm_size` options.
- Added the `--workdir` flag to `docker-compose run`
- `docker-compose logs` now shows logs for new containers that are created
after it starts.
- The `COMPOSE_FILE` environment variable can now contain multiple files,
separated by the host system's standard path separator (`:` on Mac/Linux,
`;` on Windows).
- You can now specify a static IP address when connecting a service to a
network with the `ipv4_address` and `ipv6_address` options.
- Added `--follow`, `--timestamp`, and `--tail` flags to the
`docker-compose logs` command.
- `docker-compose up`, and `docker-compose start` will now start containers
in parallel where possible.
- `docker-compose stop` now stops containers in reverse dependency order
instead of all at once.
- Added the `--build` flag to `docker-compose up` to force it to build a new
image. It now shows a warning if an image is automatically built when the
flag is not used.
- Added the `docker-compose exec` command for executing a process in a running
container.
Bug Fixes
- `docker-compose down` now removes containers created by
`docker-compose run`.
- A more appropriate error is shown when a timeout is hit during `up` when
using a tty.
- Fixed a bug in `docker-compose down` where it would abort if some resources
had already been removed.
- Fixed a bug where changes to network aliases would not trigger a service
to be recreated.
- Fix a bug where a log message was printed about creating a new volume
when it already existed.
- Fixed a bug where interrupting `up` would not always shut down containers.
- Fixed a bug where `log_opt` and `log_driver` were not properly carried over
when extending services in the v1 Compose file format.
- Fixed a bug where empty values for build args would cause file validation
to fail.
1.6.2 (2016-02-23)
------------------
- Fixed a bug where connecting to a TLS-enabled Docker Engine would fail with
a certificate verification error.
1.6.1 (2016-02-23)
------------------
@ -228,7 +620,7 @@ Bug Fixes:
if at least one container is using the network.
- When printings logs during `up` or `logs`, flush the output buffer after
each line to prevent buffering issues from hideing logs.
each line to prevent buffering issues from hiding logs.
- Recreate a container if one of its dependencies is being created.
Previously a container was only recreated if it's dependencies already
@ -517,7 +909,7 @@ Fig has been renamed to Docker Compose, or just Compose for short. This has seve
- The command you type is now `docker-compose`, not `fig`.
- You should rename your fig.yml to docker-compose.yml.
- If youre installing via PyPi, the package is now `docker-compose`, so install it with `pip install docker-compose`.
- If youre installing via PyPI, the package is now `docker-compose`, so install it with `pip install docker-compose`.
Besides that, theres a lot of new stuff in this release:

View file

@ -35,7 +35,7 @@ that should get you started.
This step is optional, but recommended. Pre-commit hooks will run style checks
and in some cases fix style issues for you, when you commit code.
Install the git pre-commit hooks using [tox](https://tox.readthedocs.org) by
Install the git pre-commit hooks using [tox](https://tox.readthedocs.io) by
running `tox -e pre-commit` or by following the
[pre-commit install guide](http://pre-commit.com/#install).
@ -50,22 +50,22 @@ See Docker's [basic contribution workflow](https://docs.docker.com/opensource/wo
Use the test script to run linting checks and then the full test suite against
different Python interpreters:
$ script/test
$ script/test/default
Tests are run against a Docker daemon inside a container, so that we can test
against multiple Docker versions. By default they'll run against only the latest
Docker version - set the `DOCKER_VERSIONS` environment variable to "all" to run
against all supported versions:
$ DOCKER_VERSIONS=all script/test
$ DOCKER_VERSIONS=all script/test/default
Arguments to `script/test` are passed through to the `nosetests` executable, so
Arguments to `script/test/default` are passed through to the `tox` executable, so
you can specify a test directory, file, module, class or method:
$ script/test tests/unit
$ script/test tests/unit/cli_test.py
$ script/test tests/unit/config_test.py::ConfigTest
$ script/test tests/unit/config_test.py::ConfigTest::test_load
$ script/test/default tests/unit
$ script/test/default tests/unit/cli_test.py
$ script/test/default tests/unit/config_test.py::ConfigTest
$ script/test/default tests/unit/config_test.py::ConfigTest::test_load
## Finding things to work on

View file

@ -13,6 +13,7 @@ RUN set -ex; \
ca-certificates \
curl \
libsqlite3-dev \
libbz2-dev \
; \
rm -rf /var/lib/apt/lists/*
@ -20,40 +21,32 @@ RUN curl https://get.docker.com/builds/Linux/x86_64/docker-1.8.3 \
-o /usr/local/bin/docker && \
chmod +x /usr/local/bin/docker
# Build Python 2.7.9 from source
# Build Python 2.7.13 from source
RUN set -ex; \
curl -L https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz | tar -xz; \
cd Python-2.7.9; \
curl -L https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz | tar -xz; \
cd Python-2.7.13; \
./configure --enable-shared; \
make; \
make install; \
cd ..; \
rm -rf /Python-2.7.9
rm -rf /Python-2.7.13
# Build python 3.4 from source
RUN set -ex; \
curl -L https://www.python.org/ftp/python/3.4.3/Python-3.4.3.tgz | tar -xz; \
cd Python-3.4.3; \
curl -L https://www.python.org/ftp/python/3.4.6/Python-3.4.6.tgz | tar -xz; \
cd Python-3.4.6; \
./configure --enable-shared; \
make; \
make install; \
cd ..; \
rm -rf /Python-3.4.3
rm -rf /Python-3.4.6
# Make libpython findable
ENV LD_LIBRARY_PATH /usr/local/lib
# Install setuptools
RUN set -ex; \
curl -L https://bootstrap.pypa.io/ez_setup.py | python
# Install pip
RUN set -ex; \
curl -L https://pypi.python.org/packages/source/p/pip/pip-7.0.1.tar.gz | tar -xz; \
cd pip-7.0.1; \
python setup.py install; \
cd ..; \
rm -rf pip-7.0.1
curl -L https://bootstrap.pypa.io/get-pip.py | python
# Python3 requires a valid locale
RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen

View file

@ -1,5 +1,6 @@
FROM alpine:edge
FROM alpine:3.4
ARG version
RUN apk -U add \
python \
py-pip
@ -7,7 +8,7 @@ RUN apk -U add \
COPY requirements.txt /code/requirements.txt
RUN pip install -r /code/requirements.txt
ADD dist/docker-compose-release.tar.gz /code/docker-compose
RUN pip install --no-deps /code/docker-compose/docker-compose-*
COPY dist/docker_compose-${version}-py2.py3-none-any.whl /code/
RUN pip install --no-deps /code/docker_compose-${version}-py2.py3-none-any.whl
ENTRYPOINT ["/usr/bin/docker-compose"]

64
Jenkinsfile vendored Normal file
View file

@ -0,0 +1,64 @@
#!groovy
def image
def buildImage = { ->
wrappedNode(label: "ubuntu && !zfs", cleanWorkspace: true) {
stage("build image") {
checkout(scm)
def imageName = "dockerbuildbot/compose:${gitCommit()}"
image = docker.image(imageName)
try {
image.pull()
} catch (Exception exc) {
image = docker.build(imageName, ".")
image.push()
}
}
}
}
def runTests = { Map settings ->
def dockerVersions = settings.get("dockerVersions", null)
def pythonVersions = settings.get("pythonVersions", null)
if (!pythonVersions) {
throw new Exception("Need Python versions to test. e.g.: `runTests(pythonVersions: 'py27,py34')`")
}
if (!dockerVersions) {
throw new Exception("Need Docker versions to test. e.g.: `runTests(dockerVersions: 'all')`")
}
{ ->
wrappedNode(label: "ubuntu && !zfs", cleanWorkspace: true) {
stage("test python=${pythonVersions} / docker=${dockerVersions}") {
checkout(scm)
def storageDriver = sh(script: 'docker info | awk -F \': \' \'$1 == "Storage Driver" { print $2; exit }\'', returnStdout: true).trim()
echo "Using local system's storage driver: ${storageDriver}"
sh """docker run \\
-t \\
--rm \\
--privileged \\
--volume="\$(pwd)/.git:/code/.git" \\
--volume="/var/run/docker.sock:/var/run/docker.sock" \\
-e "TAG=${image.id}" \\
-e "STORAGE_DRIVER=${storageDriver}" \\
-e "DOCKER_VERSIONS=${dockerVersions}" \\
-e "BUILD_NUMBER=\$BUILD_TAG" \\
-e "PY_TEST_VERSIONS=${pythonVersions}" \\
--entrypoint="script/ci" \\
${image.id} \\
--verbose
"""
}
}
}
}
buildImage()
// TODO: break this out into meaningful "DOCKER_VERSIONS" values instead of all
parallel(
failFast: true,
all_py27: runTests(pythonVersions: "py27", dockerVersions: "all"),
all_py34: runTests(pythonVersions: "py34", dockerVersions: "all"),
)

View file

@ -6,11 +6,11 @@ Compose is a tool for defining and running multi-container Docker applications.
With Compose, you use a Compose file to configure your application's services.
Then, using a single command, you create and start all the services
from your configuration. To learn more about all the features of Compose
see [the list of features](https://github.com/docker/compose/blob/release/docs/overview.md#features).
see [the list of features](https://github.com/docker/docker.github.io/blob/master/compose/overview.md#features).
Compose is great for development, testing, and staging environments, as well as
CI workflows. You can learn more about each case in
[Common Use Cases](https://github.com/docker/compose/blob/release/docs/overview.md#common-use-cases).
[Common Use Cases](https://github.com/docker/docker.github.io/blob/master/compose/overview.md#common-use-cases).
Using Compose is basically a three-step process.
@ -22,19 +22,20 @@ they can be run together in an isolated environment:
A `docker-compose.yml` looks like this:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
links:
- redis
redis:
image: redis
version: '2'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: redis
For more information about the Compose file, see the
[Compose file reference](https://github.com/docker/compose/blob/release/docs/compose-file.md)
[Compose file reference](https://github.com/docker/docker.github.io/blob/master/compose/compose-file/compose-versioning.md)
Compose has commands for managing the whole lifecycle of your application:

View file

@ -1,13 +1,21 @@
# Roadmap
## An even better tool for development environments
Compose is a great tool for development environments, but it could be even better. For example:
- It should be possible to define hostnames for containers which work from the host machine, e.g. “mywebcontainer.local”. This is needed by apps comprising multiple web services which generate links to one another (e.g. a frontend website and a separate admin webapp)
## More than just development environments
Over time we will extend Compose's remit to cover test, staging and production environments. This is not a simple task, and will take many incremental improvements such as:
Compose currently works really well in development, but we want to make the Compose file format better for test, staging, and production environments. To support these use cases, there will need to be improvements to the file format, improvements to the command-line tool, integrations with other tools, and perhaps new tools altogether.
Some specific things we are considering:
- Compose currently will attempt to get your application into the correct state when running `up`, but it has a number of shortcomings:
- It should roll back to a known good state if it fails.
- It should allow a user to check the actions it is about to perform before running them.
- It should be possible to partially modify the config file for different environments (dev/test/staging/prod), passing in e.g. custom ports or volume mount paths. ([#1377](https://github.com/docker/compose/issues/1377))
- It should be possible to partially modify the config file for different environments (dev/test/staging/prod), passing in e.g. custom ports, volume mount paths, or volume drivers. ([#1377](https://github.com/docker/compose/issues/1377))
- Compose should recommend a technique for zero-downtime deploys.
- It should be possible to continuously attempt to keep an application in the correct state, instead of just performing `up` a single time.
@ -22,10 +30,3 @@ The current state of integration is documented in [SWARM.md](SWARM.md).
Compose works well for applications that are in a single repository and depend on services that are hosted on Docker Hub. If your application depends on another application within your organisation, Compose doesn't work as well.
There are several ideas about how this could work, such as [including external files](https://github.com/docker/fig/issues/318).
## An even better tool for development environments
Compose is a great tool for development environments, but it could be even better. For example:
- [Compose could watch your code and automatically kick off builds when something changes.](https://github.com/docker/fig/issues/184)
- It should be possible to define hostnames for containers which work from the host machine, e.g. “mywebcontainer.local”. This is needed by apps comprising multiple web services which generate links to one another (e.g. a frontend website and a separate admin webapp)

View file

@ -9,20 +9,16 @@ install:
# Build the binary after tests
build: false
environment:
BINTRAY_USER: "docker-compose-roleuser"
BINTRAY_PATH: "docker-compose/master/windows/master/docker-compose-Windows-x86_64.exe"
test_script:
- "tox -e py27,py34 -- tests/unit"
- ps: ".\\script\\build-windows.ps1"
deploy_script:
- "curl -sS
-u \"%BINTRAY_USER%:%BINTRAY_API_KEY%\"
-X PUT \"https://api.bintray.com/content/%BINTRAY_PATH%?override=1&publish=1\"
--data-binary @dist\\docker-compose-Windows-x86_64.exe"
- ps: ".\\script\\build\\windows.ps1"
artifacts:
- path: .\dist\docker-compose-Windows-x86_64.exe
name: "Compose Windows binary"
deploy:
- provider: Environment
name: master-builds
on:
branch: master

View file

@ -1,4 +1,4 @@
from __future__ import absolute_import
from __future__ import unicode_literals
__version__ = '1.6.1'
__version__ = '1.12.0dev'

258
compose/bundle.py Normal file
View file

@ -0,0 +1,258 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import json
import logging
import six
from docker.utils import split_command
from docker.utils.ports import split_port
from .cli.errors import UserError
from .config.serialize import denormalize_config
from .network import get_network_defs_for_service
from .service import format_environment
from .service import NoSuchImageError
from .service import parse_repository_tag
log = logging.getLogger(__name__)
SERVICE_KEYS = {
'working_dir': 'WorkingDir',
'user': 'User',
'labels': 'Labels',
}
IGNORED_KEYS = {'build'}
SUPPORTED_KEYS = {
'image',
'ports',
'expose',
'networks',
'command',
'environment',
'entrypoint',
} | set(SERVICE_KEYS)
VERSION = '0.1'
class NeedsPush(Exception):
def __init__(self, image_name):
self.image_name = image_name
class NeedsPull(Exception):
def __init__(self, image_name, service_name):
self.image_name = image_name
self.service_name = service_name
class MissingDigests(Exception):
def __init__(self, needs_push, needs_pull):
self.needs_push = needs_push
self.needs_pull = needs_pull
def serialize_bundle(config, image_digests):
return json.dumps(to_bundle(config, image_digests), indent=2, sort_keys=True)
def get_image_digests(project, allow_push=False):
digests = {}
needs_push = set()
needs_pull = set()
for service in project.services:
try:
digests[service.name] = get_image_digest(
service,
allow_push=allow_push,
)
except NeedsPush as e:
needs_push.add(e.image_name)
except NeedsPull as e:
needs_pull.add(e.service_name)
if needs_push or needs_pull:
raise MissingDigests(needs_push, needs_pull)
return digests
def get_image_digest(service, allow_push=False):
if 'image' not in service.options:
raise UserError(
"Service '{s.name}' doesn't define an image tag. An image name is "
"required to generate a proper image digest for the bundle. Specify "
"an image repo and tag with the 'image' option.".format(s=service))
_, _, separator = parse_repository_tag(service.options['image'])
# Compose file already uses a digest, no lookup required
if separator == '@':
return service.options['image']
try:
image = service.image()
except NoSuchImageError:
action = 'build' if 'build' in service.options else 'pull'
raise UserError(
"Image not found for service '{service}'. "
"You might need to run `docker-compose {action} {service}`."
.format(service=service.name, action=action))
if image['RepoDigests']:
# TODO: pick a digest based on the image tag if there are multiple
# digests
return image['RepoDigests'][0]
if 'build' not in service.options:
raise NeedsPull(service.image_name, service.name)
if not allow_push:
raise NeedsPush(service.image_name)
return push_image(service)
def push_image(service):
try:
digest = service.push()
except:
log.error(
"Failed to push image for service '{s.name}'. Please use an "
"image tag that can be pushed to a Docker "
"registry.".format(s=service))
raise
if not digest:
raise ValueError("Failed to get digest for %s" % service.name)
repo, _, _ = parse_repository_tag(service.options['image'])
identifier = '{repo}@{digest}'.format(repo=repo, digest=digest)
# only do this if RepoDigests isn't already populated
image = service.image()
if not image['RepoDigests']:
# Pull by digest so that image['RepoDigests'] is populated for next time
# and we don't have to pull/push again
service.client.pull(identifier)
log.info("Stored digest for {}".format(service.image_name))
return identifier
def to_bundle(config, image_digests):
if config.networks:
log.warn("Unsupported top level key 'networks' - ignoring")
if config.volumes:
log.warn("Unsupported top level key 'volumes' - ignoring")
config = denormalize_config(config)
return {
'Version': VERSION,
'Services': {
name: convert_service_to_bundle(
name,
service_dict,
image_digests[name],
)
for name, service_dict in config['services'].items()
},
}
def convert_service_to_bundle(name, service_dict, image_digest):
container_config = {'Image': image_digest}
for key, value in service_dict.items():
if key in IGNORED_KEYS:
continue
if key not in SUPPORTED_KEYS:
log.warn("Unsupported key '{}' in services.{} - ignoring".format(key, name))
continue
if key == 'environment':
container_config['Env'] = format_environment({
envkey: envvalue for envkey, envvalue in value.items()
if envvalue
})
continue
if key in SERVICE_KEYS:
container_config[SERVICE_KEYS[key]] = value
continue
set_command_and_args(
container_config,
service_dict.get('entrypoint', []),
service_dict.get('command', []))
container_config['Networks'] = make_service_networks(name, service_dict)
ports = make_port_specs(service_dict)
if ports:
container_config['Ports'] = ports
return container_config
# See https://github.com/docker/swarmkit/blob/agent/exec/container/container.go#L95
def set_command_and_args(config, entrypoint, command):
if isinstance(entrypoint, six.string_types):
entrypoint = split_command(entrypoint)
if isinstance(command, six.string_types):
command = split_command(command)
if entrypoint:
config['Command'] = entrypoint + command
return
if command:
config['Args'] = command
def make_service_networks(name, service_dict):
networks = []
for network_name, network_def in get_network_defs_for_service(service_dict).items():
for key in network_def.keys():
log.warn(
"Unsupported key '{}' in services.{}.networks.{} - ignoring"
.format(key, name, network_name))
networks.append(network_name)
return networks
def make_port_specs(service_dict):
ports = []
internal_ports = [
internal_port
for port_def in service_dict.get('ports', [])
for internal_port in split_port(port_def)[0]
]
internal_ports += service_dict.get('expose', [])
for internal_port in internal_ports:
spec = make_port_spec(internal_port)
if spec not in ports:
ports.append(spec)
return ports
def make_port_spec(value):
components = six.text_type(value).partition('/')
return {
'Protocol': components[2] or 'tcp',
'Port': int(components[0]),
}

View file

@ -0,0 +1,37 @@
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import subprocess
import sys
# Attempt to detect https://github.com/docker/compose/issues/4344
try:
# We don't try importing pip because it messes with package imports
# on some Linux distros (Ubuntu, Fedora)
# https://github.com/docker/compose/issues/4425
# https://github.com/docker/compose/issues/4481
# https://github.com/pypa/pip/blob/master/pip/_vendor/__init__.py
s_cmd = subprocess.Popen(
['pip', 'freeze'], stderr=subprocess.PIPE, stdout=subprocess.PIPE
)
packages = s_cmd.communicate()[0].splitlines()
dockerpy_installed = len(
list(filter(lambda p: p.startswith(b'docker-py=='), packages))
) > 0
if dockerpy_installed:
from .colors import red
print(
red('ERROR:'),
"Dependency conflict: an older version of the 'docker-py' package "
"is polluting the namespace. "
"Run the following command to remedy the issue:\n"
"pip uninstall docker docker-py; pip install docker",
file=sys.stderr
)
sys.exit(1)
except OSError:
# pip command is not available, which indicates it's probably the binary
# distribution of Compose which is not affected
pass

View file

@ -1,5 +1,8 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import colorama
NAMES = [
'grey',
'red',
@ -30,6 +33,7 @@ def make_color_fn(code):
return lambda s: ansi_color(code, s)
colorama.init(strip=False)
for (name, code) in get_pairs():
globals()[name] = make_color_fn(code)

View file

@ -1,69 +1,87 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import contextlib
import logging
import os
import re
import ssl
import six
from requests.exceptions import ConnectionError
from requests.exceptions import SSLError
from . import errors
from . import verbose_proxy
from .. import config
from ..config.environment import Environment
from ..const import API_VERSIONS
from ..project import Project
from .docker_client import docker_client
from .utils import call_silently
from .docker_client import tls_config_from_options
from .utils import get_version_info
from .utils import is_mac
from .utils import is_ubuntu
log = logging.getLogger(__name__)
@contextlib.contextmanager
def friendly_error_message():
try:
yield
except SSLError as e:
raise errors.UserError('SSL error: %s' % e)
except ConnectionError:
if call_silently(['which', 'docker']) != 0:
if is_mac():
raise errors.DockerNotFoundMac()
elif is_ubuntu():
raise errors.DockerNotFoundUbuntu()
else:
raise errors.DockerNotFoundGeneric()
elif call_silently(['which', 'docker-machine']) == 0:
raise errors.ConnectionErrorDockerMachine()
else:
raise errors.ConnectionErrorGeneric(get_client().base_url)
def project_from_options(base_dir, options):
def project_from_options(project_dir, options):
environment = Environment.from_env_file(project_dir)
host = options.get('--host')
if host is not None:
host = host.lstrip('=')
return get_project(
base_dir,
get_config_path_from_options(options),
project_dir,
get_config_path_from_options(project_dir, options, environment),
project_name=options.get('--project-name'),
verbose=options.get('--verbose'),
host=host,
tls_config=tls_config_from_options(options),
environment=environment
)
def get_config_path_from_options(options):
def get_config_from_options(base_dir, options):
environment = Environment.from_env_file(base_dir)
config_path = get_config_path_from_options(
base_dir, options, environment
)
return config.load(
config.find(base_dir, config_path, environment)
)
def get_config_path_from_options(base_dir, options, environment):
file_option = options.get('--file')
if file_option:
return file_option
config_file = os.environ.get('COMPOSE_FILE')
return [config_file] if config_file else None
config_files = environment.get('COMPOSE_FILE')
if config_files:
return config_files.split(os.pathsep)
return None
def get_client(verbose=False, version=None):
client = docker_client(version=version)
def get_tls_version(environment):
compose_tls_version = environment.get('COMPOSE_TLS_VERSION', None)
if not compose_tls_version:
return None
tls_attr_name = "PROTOCOL_{}".format(compose_tls_version)
if not hasattr(ssl, tls_attr_name):
log.warn(
'The "{}" protocol is unavailable. You may need to update your '
'version of Python or OpenSSL. Falling back to TLSv1 (default).'
.format(compose_tls_version)
)
return None
return getattr(ssl, tls_attr_name)
def get_client(environment, verbose=False, version=None, tls_config=None, host=None,
tls_version=None):
client = docker_client(
version=version, tls_config=tls_config, host=host,
environment=environment, tls_version=get_tls_version(environment)
)
if verbose:
version_info = six.iteritems(client.version())
log.info(get_version_info('full'))
@ -74,24 +92,36 @@ def get_client(verbose=False, version=None):
return client
def get_project(base_dir, config_path=None, project_name=None, verbose=False):
config_details = config.find(base_dir, config_path)
project_name = get_project_name(config_details.working_dir, project_name)
def get_project(project_dir, config_path=None, project_name=None, verbose=False,
host=None, tls_config=None, environment=None):
if not environment:
environment = Environment.from_env_file(project_dir)
config_details = config.find(project_dir, config_path, environment)
project_name = get_project_name(
config_details.working_dir, project_name, environment
)
config_data = config.load(config_details)
api_version = os.environ.get(
api_version = environment.get(
'COMPOSE_API_VERSION',
API_VERSIONS[config_data.version])
client = get_client(verbose=verbose, version=api_version)
return Project.from_config(project_name, config_data, client)
client = get_client(
verbose=verbose, version=api_version, tls_config=tls_config,
host=host, environment=environment
)
with errors.handle_connection_errors(client):
return Project.from_config(project_name, config_data, client)
def get_project_name(working_dir, project_name=None):
def get_project_name(working_dir, project_name=None, environment=None):
def normalize_name(name):
return re.sub(r'[^a-z0-9]', '', name.lower())
project_name = project_name or os.environ.get('COMPOSE_PROJECT_NAME')
if not environment:
environment = Environment.from_env_file(working_dir)
project_name = project_name or environment.get('COMPOSE_PROJECT_NAME')
if project_name:
return normalize_name(project_name)

View file

@ -2,36 +2,73 @@ from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import os
from docker import Client
from docker import APIClient
from docker.errors import TLSParameterError
from docker.tls import TLSConfig
from docker.utils import kwargs_from_env
from ..const import HTTP_TIMEOUT
from .errors import UserError
from .utils import generate_user_agent
from .utils import unquote_path
log = logging.getLogger(__name__)
def docker_client(version=None):
def tls_config_from_options(options):
tls = options.get('--tls', False)
ca_cert = unquote_path(options.get('--tlscacert'))
cert = unquote_path(options.get('--tlscert'))
key = unquote_path(options.get('--tlskey'))
verify = options.get('--tlsverify')
skip_hostname_check = options.get('--skip-hostname-check', False)
advanced_opts = any([ca_cert, cert, key, verify])
if tls is True and not advanced_opts:
return True
elif advanced_opts: # --tls is a noop
client_cert = None
if cert or key:
client_cert = (cert, key)
return TLSConfig(
client_cert=client_cert, verify=verify, ca_cert=ca_cert,
assert_hostname=False if skip_hostname_check else None
)
return None
def docker_client(environment, version=None, tls_config=None, host=None,
tls_version=None):
"""
Returns a docker-py client configured using environment variables
according to the same logic as the official Docker client.
"""
if 'DOCKER_CLIENT_TIMEOUT' in os.environ:
log.warn('The DOCKER_CLIENT_TIMEOUT environment variable is deprecated. Please use COMPOSE_HTTP_TIMEOUT instead.')
try:
kwargs = kwargs_from_env(assert_hostname=False)
kwargs = kwargs_from_env(environment=environment, ssl_version=tls_version)
except TLSParameterError:
raise UserError(
'TLS configuration is invalid - make sure your DOCKER_TLS_VERIFY and DOCKER_CERT_PATH are set correctly.\n'
'You might need to run `eval "$(docker-machine env default)"`')
"TLS configuration is invalid - make sure your DOCKER_TLS_VERIFY "
"and DOCKER_CERT_PATH are set correctly.\n"
"You might need to run `eval \"$(docker-machine env default)\"`")
if host:
kwargs['base_url'] = host
if tls_config:
kwargs['tls'] = tls_config
if version:
kwargs['version'] = version
kwargs['timeout'] = HTTP_TIMEOUT
timeout = environment.get('COMPOSE_HTTP_TIMEOUT')
if timeout:
kwargs['timeout'] = int(timeout)
else:
kwargs['timeout'] = HTTP_TIMEOUT
return Client(**kwargs)
kwargs['user_agent'] = generate_user_agent()
return APIClient(**kwargs)

View file

@ -1,7 +1,6 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import sys
from inspect import getdoc
from docopt import docopt
@ -15,24 +14,21 @@ def docopt_full_help(docstring, *args, **kwargs):
raise SystemExit(docstring)
class DocoptCommand(object):
def docopt_options(self):
return {'options_first': True}
class DocoptDispatcher(object):
def sys_dispatch(self):
self.dispatch(sys.argv[1:], None)
def __init__(self, command_class, options):
self.command_class = command_class
self.options = options
def dispatch(self, argv, global_options):
self.perform_command(*self.parse(argv, global_options))
def parse(self, argv, global_options):
options = docopt_full_help(getdoc(self), argv, **self.docopt_options())
def parse(self, argv):
command_help = getdoc(self.command_class)
options = docopt_full_help(command_help, argv, **self.options)
command = options['COMMAND']
if command is None:
raise SystemExit(getdoc(self))
raise SystemExit(command_help)
handler = self.get_handler(command)
handler = get_handler(self.command_class, command)
docstring = getdoc(handler)
if docstring is None:
@ -41,13 +37,18 @@ class DocoptCommand(object):
command_options = docopt_full_help(docstring, options['ARGS'], options_first=True)
return options, handler, command_options
def get_handler(self, command):
command = command.replace('-', '_')
if not hasattr(self, command):
raise NoSuchCommand(command, self)
def get_handler(command_class, command):
command = command.replace('-', '_')
# we certainly want to have "exec" command, since that's what docker client has
# but in python exec is a keyword
if command == "exec":
command = "exec_command"
return getattr(self, command)
if not hasattr(command_class, command):
raise NoSuchCommand(command, command_class)
return getattr(command_class, command)
class NoSuchCommand(Exception):

View file

@ -1,10 +1,30 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import contextlib
import logging
import socket
from distutils.spawn import find_executable
from textwrap import dedent
from docker.errors import APIError
from requests.exceptions import ConnectionError as RequestsConnectionError
from requests.exceptions import ReadTimeout
from requests.exceptions import SSLError
from requests.packages.urllib3.exceptions import ReadTimeoutError
from ..const import API_VERSION_TO_ENGINE_VERSION
from .utils import is_docker_for_mac_installed
from .utils import is_mac
from .utils import is_ubuntu
from .utils import is_windows
log = logging.getLogger(__name__)
class UserError(Exception):
def __init__(self, msg):
self.msg = dedent(msg).strip()
@ -14,44 +34,104 @@ class UserError(Exception):
__str__ = __unicode__
class DockerNotFoundMac(UserError):
def __init__(self):
super(DockerNotFoundMac, self).__init__("""
Couldn't connect to Docker daemon. You might need to install docker-osx:
https://github.com/noplay/docker-osx
""")
class ConnectionError(Exception):
pass
class DockerNotFoundUbuntu(UserError):
def __init__(self):
super(DockerNotFoundUbuntu, self).__init__("""
Couldn't connect to Docker daemon. You might need to install Docker:
https://docs.docker.com/engine/installation/ubuntulinux/
""")
@contextlib.contextmanager
def handle_connection_errors(client):
try:
yield
except SSLError as e:
log.error('SSL error: %s' % e)
raise ConnectionError()
except RequestsConnectionError as e:
if e.args and isinstance(e.args[0], ReadTimeoutError):
log_timeout_error(client.timeout)
raise ConnectionError()
exit_with_error(get_conn_error_message(client.base_url))
except APIError as e:
log_api_error(e, client.api_version)
raise ConnectionError()
except (ReadTimeout, socket.timeout) as e:
log_timeout_error(client.timeout)
raise ConnectionError()
class DockerNotFoundGeneric(UserError):
def __init__(self):
super(DockerNotFoundGeneric, self).__init__("""
Couldn't connect to Docker daemon. You might need to install Docker:
https://docs.docker.com/engine/installation/
""")
def log_timeout_error(timeout):
log.error(
"An HTTP request took too long to complete. Retry with --verbose to "
"obtain debug information.\n"
"If you encounter this issue regularly because of slow network "
"conditions, consider setting COMPOSE_HTTP_TIMEOUT to a higher "
"value (current value: %s)." % timeout)
class ConnectionErrorDockerMachine(UserError):
def __init__(self):
super(ConnectionErrorDockerMachine, self).__init__("""
Couldn't connect to Docker daemon - you might need to run `docker-machine start default`.
""")
def log_api_error(e, client_version):
if b'client is newer than server' not in e.explanation:
log.error(e.explanation)
return
version = API_VERSION_TO_ENGINE_VERSION.get(client_version)
if not version:
# They've set a custom API version
log.error(e.explanation)
return
log.error(
"The Docker Engine version is less than the minimum required by "
"Compose. Your current project requires a Docker Engine of "
"version {version} or greater.".format(version=version))
class ConnectionErrorGeneric(UserError):
def __init__(self, url):
super(ConnectionErrorGeneric, self).__init__("""
Couldn't connect to Docker daemon at %s - is it running?
def exit_with_error(msg):
log.error(dedent(msg).strip())
raise ConnectionError()
If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
""" % url)
def get_conn_error_message(url):
if find_executable('docker') is None:
return docker_not_found_msg("Couldn't connect to Docker daemon.")
if is_docker_for_mac_installed():
return conn_error_docker_for_mac
if find_executable('docker-machine') is not None:
return conn_error_docker_machine
return conn_error_generic.format(url=url)
def docker_not_found_msg(problem):
return "{} You might need to install Docker:\n\n{}".format(
problem, docker_install_url())
def docker_install_url():
if is_mac():
return docker_install_url_mac
elif is_ubuntu():
return docker_install_url_ubuntu
elif is_windows():
return docker_install_url_windows
else:
return docker_install_url_generic
docker_install_url_mac = "https://docs.docker.com/engine/installation/mac/"
docker_install_url_ubuntu = "https://docs.docker.com/engine/installation/ubuntulinux/"
docker_install_url_windows = "https://docs.docker.com/engine/installation/windows/"
docker_install_url_generic = "https://docs.docker.com/engine/installation/"
conn_error_docker_machine = """
Couldn't connect to Docker daemon - you might need to run `docker-machine start default`.
"""
conn_error_docker_for_mac = """
Couldn't connect to Docker daemon. You might need to start Docker for Mac.
"""
conn_error_generic = """
Couldn't connect to Docker daemon at {url} - is it running?
If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.
"""

View file

@ -4,6 +4,7 @@ from __future__ import unicode_literals
import logging
import os
import six
import texttable
from compose.cli import colors
@ -44,5 +45,7 @@ class ConsoleWarningFormatter(logging.Formatter):
return ''
def format(self, record):
if isinstance(record.msg, six.binary_type):
record.msg = record.msg.decode('utf-8')
message = super(ConsoleWarningFormatter, self).format(record)
return self.get_level_message(record) + message
return '{0}{1}'.format(self.get_level_message(record), message)

View file

@ -2,60 +2,153 @@ from __future__ import absolute_import
from __future__ import unicode_literals
import sys
from collections import namedtuple
from itertools import cycle
from threading import Thread
from docker.errors import APIError
from six.moves import _thread as thread
from six.moves.queue import Empty
from six.moves.queue import Queue
from . import colors
from .multiplexer import Multiplexer
from compose import utils
from compose.cli.signals import ShutdownException
from compose.utils import split_buffer
class LogPrinter(object):
"""Print logs from many containers to a single output stream."""
class LogPresenter(object):
def __init__(self, containers, output=sys.stdout, monochrome=False, cascade_stop=False):
self.containers = containers
self.output = utils.get_output_stream(output)
self.monochrome = monochrome
self.cascade_stop = cascade_stop
def __init__(self, prefix_width, color_func):
self.prefix_width = prefix_width
self.color_func = color_func
def run(self):
if not self.containers:
return
prefix_width = max_name_width(self.containers)
generators = list(self._make_log_generators(self.monochrome, prefix_width))
for line in Multiplexer(generators, cascade_stop=self.cascade_stop).loop():
self.output.write(line)
self.output.flush()
def _make_log_generators(self, monochrome, prefix_width):
def no_color(text):
return text
if monochrome:
color_funcs = cycle([no_color])
else:
color_funcs = cycle(colors.rainbow())
for color_func, container in zip(color_funcs, self.containers):
generator_func = get_log_generator(container)
prefix = color_func(build_log_prefix(container, prefix_width))
yield generator_func(container, prefix, color_func)
def present(self, container, line):
prefix = container.name_without_project.ljust(self.prefix_width)
return '{prefix} {line}'.format(
prefix=self.color_func(prefix + ' |'),
line=line)
def build_log_prefix(container, prefix_width):
return container.name_without_project.ljust(prefix_width) + ' | '
def build_log_presenters(service_names, monochrome):
"""Return an iterable of functions.
Each function can be used to format the logs output of a container.
"""
prefix_width = max_name_width(service_names)
def no_color(text):
return text
for color_func in cycle([no_color] if monochrome else colors.rainbow()):
yield LogPresenter(prefix_width, color_func)
def max_name_width(containers):
def max_name_width(service_names, max_index_width=3):
"""Calculate the maximum width of container names so we can make the log
prefixes line up like so:
db_1 | Listening
web_1 | Listening
"""
return max(len(container.name_without_project) for container in containers)
return max(len(name) for name in service_names) + max_index_width
class LogPrinter(object):
"""Print logs from many containers to a single output stream."""
def __init__(self,
containers,
presenters,
event_stream,
output=sys.stdout,
cascade_stop=False,
log_args=None):
self.containers = containers
self.presenters = presenters
self.event_stream = event_stream
self.output = utils.get_output_stream(output)
self.cascade_stop = cascade_stop
self.log_args = log_args or {}
def run(self):
if not self.containers:
return
queue = Queue()
thread_args = queue, self.log_args
thread_map = build_thread_map(self.containers, self.presenters, thread_args)
start_producer_thread((
thread_map,
self.event_stream,
self.presenters,
thread_args))
for line in consume_queue(queue, self.cascade_stop):
remove_stopped_threads(thread_map)
if not line:
if not thread_map:
# There are no running containers left to tail, so exit
return
# We got an empty line because of a timeout, but there are still
# active containers to tail, so continue
continue
self.output.write(line)
self.output.flush()
def remove_stopped_threads(thread_map):
for container_id, tailer_thread in list(thread_map.items()):
if not tailer_thread.is_alive():
thread_map.pop(container_id, None)
def build_thread(container, presenter, queue, log_args):
tailer = Thread(
target=tail_container_logs,
args=(container, presenter, queue, log_args))
tailer.daemon = True
tailer.start()
return tailer
def build_thread_map(initial_containers, presenters, thread_args):
return {
container.id: build_thread(container, next(presenters), *thread_args)
for container in initial_containers
}
class QueueItem(namedtuple('_QueueItem', 'item is_stop exc')):
@classmethod
def new(cls, item):
return cls(item, None, None)
@classmethod
def exception(cls, exc):
return cls(None, None, exc)
@classmethod
def stop(cls):
return cls(None, True, None)
def tail_container_logs(container, presenter, queue, log_args):
generator = get_log_generator(container)
try:
for item in generator(container, log_args):
queue.put(QueueItem.new(presenter.present(container, item)))
except Exception as e:
queue.put(QueueItem.exception(e))
return
if log_args.get('follow'):
queue.put(QueueItem.new(presenter.color_func(wait_on_exit(container))))
queue.put(QueueItem.stop())
def get_log_generator(container):
@ -64,30 +157,81 @@ def get_log_generator(container):
return build_no_log_generator
def build_no_log_generator(container, prefix, color_func):
def build_no_log_generator(container, log_args):
"""Return a generator that prints a warning about logs and waits for
container to exit.
"""
yield "{} WARNING: no logs are available with the '{}' log driver\n".format(
prefix,
yield "WARNING: no logs are available with the '{}' log driver\n".format(
container.log_driver)
yield color_func(wait_on_exit(container))
def build_log_generator(container, prefix, color_func):
def build_log_generator(container, log_args):
# if the container doesn't have a log_stream we need to attach to container
# before log printer starts running
if container.log_stream is None:
stream = container.attach(stdout=True, stderr=True, stream=True, logs=True)
line_generator = split_buffer(stream)
stream = container.logs(stdout=True, stderr=True, stream=True, **log_args)
else:
line_generator = split_buffer(container.log_stream)
stream = container.log_stream
for line in line_generator:
yield prefix + line
yield color_func(wait_on_exit(container))
return split_buffer(stream)
def wait_on_exit(container):
exit_code = container.wait()
return "%s exited with code %s\n" % (container.name, exit_code)
try:
exit_code = container.wait()
return "%s exited with code %s\n" % (container.name, exit_code)
except APIError as e:
return "Unexpected API error for %s (HTTP code %s)\nResponse body:\n%s\n" % (
container.name, e.response.status_code,
e.response.text or '[empty]'
)
def start_producer_thread(thread_args):
producer = Thread(target=watch_events, args=thread_args)
producer.daemon = True
producer.start()
def watch_events(thread_map, event_stream, presenters, thread_args):
for event in event_stream:
if event['action'] == 'stop':
thread_map.pop(event['id'], None)
if event['action'] != 'start':
continue
if event['id'] in thread_map:
if thread_map[event['id']].is_alive():
continue
# Container was stopped and started, we need a new thread
thread_map.pop(event['id'], None)
thread_map[event['id']] = build_thread(
event['container'],
next(presenters),
*thread_args)
def consume_queue(queue, cascade_stop):
"""Consume the queue by reading lines off of it and yielding them."""
while True:
try:
item = queue.get(timeout=0.1)
except Empty:
yield None
continue
# See https://github.com/docker/compose/issues/189
except thread.error:
raise ShutdownException()
if item.exc:
raise item.exc
if item.is_stop:
if cascade_stop:
raise StopIteration
else:
continue
yield item.item

File diff suppressed because it is too large Load diff

View file

@ -1,65 +0,0 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from threading import Thread
from six.moves import _thread as thread
try:
from Queue import Queue, Empty
except ImportError:
from queue import Queue, Empty # Python 3.x
STOP = object()
class Multiplexer(object):
"""
Create a single iterator from several iterators by running all of them in
parallel and yielding results as they come in.
"""
def __init__(self, iterators, cascade_stop=False):
self.iterators = iterators
self.cascade_stop = cascade_stop
self._num_running = len(iterators)
self.queue = Queue()
def loop(self):
self._init_readers()
while self._num_running > 0:
try:
item, exception = self.queue.get(timeout=0.1)
if exception:
raise exception
if item is STOP:
if self.cascade_stop is True:
break
else:
self._num_running -= 1
else:
yield item
except Empty:
pass
# See https://github.com/docker/compose/issues/189
except thread.error:
raise KeyboardInterrupt()
def _init_readers(self):
for iterator in self.iterators:
t = Thread(target=_enqueue_output, args=(iterator, self.queue))
t.daemon = True
t.start()
def _enqueue_output(iterator, queue):
try:
for item in iterator:
queue.put((item, None))
queue.put((STOP, None))
except Exception as e:
queue.put((None, e))

View file

@ -6,11 +6,19 @@ import os
import platform
import ssl
import subprocess
import sys
import docker
from six.moves import input
import compose
from ..const import IS_WINDOWS_PLATFORM
# WindowsError is not defined on non-win32 platforms. Avoid runtime errors by
# defining it as OSError (its parent class) if missing.
try:
WindowsError
except NameError:
WindowsError = OSError
def yesno(prompt, default=None):
@ -35,6 +43,16 @@ def yesno(prompt, default=None):
return None
def input(prompt):
"""
Version of input (raw_input in Python 2) which forces a flush of sys.stdout
to avoid problems where the prompt fails to appear due to line buffering
"""
sys.stdout.write(prompt)
sys.stdout.flush()
return sys.stdin.readline().rstrip('\n')
def call_silently(*args, **kwargs):
"""
Like subprocess.call(), but redirects stdout and stderr to /dev/null.
@ -56,6 +74,10 @@ def is_ubuntu():
return platform.system() == 'Linux' and platform.linux_distribution()[0] == 'Ubuntu'
def is_windows():
return IS_WINDOWS_PLATFORM
def get_version_info(scope):
versioninfo = 'docker-compose version {}, build {}'.format(
compose.__version__,
@ -86,3 +108,30 @@ def get_build_version():
with open(filename) as fh:
return fh.read().strip()
def is_docker_for_mac_installed():
return is_mac() and os.path.isdir('/Applications/Docker.app')
def generate_user_agent():
parts = [
"docker-compose/{}".format(compose.__version__),
"docker-py/{}".format(docker.__version__),
]
try:
p_system = platform.system()
p_release = platform.release()
except IOError:
pass
else:
parts.append("{}/{}".format(p_system, p_release))
return " ".join(parts)
def unquote_path(s):
if not s:
return s
if s[0] == '"' and s[-1] == '"':
return s[1:-1]
return s

View file

@ -2,6 +2,7 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from . import environment
from .config import ConfigurationError
from .config import DOCKER_CONFIG_KEYS
from .config import find

View file

@ -1,10 +1,8 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import codecs
import functools
import logging
import operator
import os
import string
import sys
@ -14,9 +12,18 @@ import six
import yaml
from cached_property import cached_property
from . import types
from ..const import COMPOSEFILE_V1 as V1
from ..const import COMPOSEFILE_V2_0 as V2_0
from ..const import COMPOSEFILE_V2_1 as V2_1
from ..const import COMPOSEFILE_V3_0 as V3_0
from ..const import COMPOSEFILE_V3_1 as V3_1
from ..utils import build_string_dict
from ..utils import parse_nanoseconds_int
from ..utils import splitdrive
from .environment import env_vars_from_file
from .environment import Environment
from .environment import split_env
from .errors import CircularReference
from .errors import ComposeFileNotFound
from .errors import ConfigurationError
@ -31,12 +38,13 @@ from .types import ServiceLink
from .types import VolumeFromSpec
from .types import VolumeSpec
from .validation import match_named_volumes
from .validation import validate_against_fields_schema
from .validation import validate_against_service_schema
from .validation import validate_against_config_schema
from .validation import validate_config_section
from .validation import validate_depends_on
from .validation import validate_extends_file_path
from .validation import validate_links
from .validation import validate_network_mode
from .validation import validate_service_constraints
from .validation import validate_top_level_object
from .validation import validate_ulimits
@ -58,7 +66,9 @@ DOCKER_CONFIG_KEYS = [
'env_file',
'environment',
'extra_hosts',
'group_add',
'hostname',
'healthcheck',
'image',
'ipc',
'labels',
@ -66,17 +76,23 @@ DOCKER_CONFIG_KEYS = [
'mac_address',
'mem_limit',
'memswap_limit',
'mem_swappiness',
'net',
'oom_score_adj',
'pid',
'ports',
'privileged',
'read_only',
'restart',
'secrets',
'security_opt',
'shm_size',
'stdin_open',
'stop_signal',
'sysctls',
'tty',
'user',
'userns_mode',
'volume_driver',
'volumes',
'volumes_from',
@ -87,6 +103,8 @@ ALLOWED_KEYS = DOCKER_CONFIG_KEYS + [
'build',
'container_name',
'dockerfile',
'log_driver',
'log_opt',
'logging',
'network_mode',
]
@ -110,13 +128,21 @@ DEFAULT_OVERRIDE_FILENAME = 'docker-compose.override.yml'
log = logging.getLogger(__name__)
class ConfigDetails(namedtuple('_ConfigDetails', 'working_dir config_files')):
class ConfigDetails(namedtuple('_ConfigDetails', 'working_dir config_files environment')):
"""
:param working_dir: the directory to use for relative paths in the config
:type working_dir: string
:param config_files: list of configuration files to load
:type config_files: list of :class:`ConfigFile`
:param environment: computed environment values for this project
:type environment: :class:`environment.Environment`
"""
def __new__(cls, working_dir, config_files, environment=None):
if environment is None:
environment = Environment.from_env_file(working_dir)
return super(ConfigDetails, cls).__new__(
cls, working_dir, config_files, environment
)
class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
@ -157,10 +183,8 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
if version == '2':
version = V2_0
if version != V2_0:
raise ConfigurationError(
'Version in "{}" is unsupported. {}'
.format(self.filename, VERSION_EXPLANATION))
if version == '3':
version = V3_0
return version
@ -176,8 +200,11 @@ class ConfigFile(namedtuple('_ConfigFile', 'filename config')):
def get_networks(self):
return {} if self.version == V1 else self.config.get('networks', {})
def get_secrets(self):
return {} if self.version < V3_1 else self.config.get('secrets', {})
class Config(namedtuple('_Config', 'version services volumes networks')):
class Config(namedtuple('_Config', 'version services volumes networks secrets')):
"""
:param version: configuration version
:type version: int
@ -204,11 +231,13 @@ class ServiceConfig(namedtuple('_ServiceConfig', 'working_dir filename name conf
config)
def find(base_dir, filenames):
def find(base_dir, filenames, environment):
if filenames == ['-']:
return ConfigDetails(
os.getcwd(),
[ConfigFile(None, yaml.safe_load(sys.stdin))])
[ConfigFile(None, yaml.safe_load(sys.stdin))],
environment
)
if filenames:
filenames = [os.path.join(base_dir, f) for f in filenames]
@ -218,7 +247,9 @@ def find(base_dir, filenames):
log.debug("Using configuration files: {}".format(",".join(filenames)))
return ConfigDetails(
os.path.dirname(filenames[0]),
[ConfigFile.from_filename(f) for f in filenames])
[ConfigFile.from_filename(f) for f in filenames],
environment
)
def validate_config_version(config_files):
@ -286,7 +317,7 @@ def load(config_details):
validate_config_version(config_details.config_files)
processed_files = [
process_config_file(config_file)
process_config_file(config_file, config_details.environment)
for config_file in config_details.config_files
]
config_details = config_details._replace(config_files=processed_files)
@ -298,16 +329,22 @@ def load(config_details):
networks = load_mapping(
config_details.config_files, 'get_networks', 'Network'
)
service_dicts = load_services(
config_details.working_dir,
main_file,
[file.get_service_dicts() for file in config_details.config_files])
secrets = load_secrets(config_details.config_files, config_details.working_dir)
service_dicts = load_services(config_details, main_file)
if main_file.version != V1:
for service_dict in service_dicts:
match_named_volumes(service_dict, volumes)
return Config(main_file.version, service_dicts, volumes, networks)
services_using_deploy = [s for s in service_dicts if s.get('deploy')]
if services_using_deploy:
log.warn(
"Some services ({}) use the 'deploy' key, which will be ignored. "
"Compose does not support deploy configuration - use "
"`docker stack deploy` to deploy to a swarm."
.format(", ".join(sorted(s['name'] for s in services_using_deploy))))
return Config(main_file.version, service_dicts, volumes, networks, secrets)
def load_mapping(config_files, get_func, entity_type):
@ -321,38 +358,66 @@ def load_mapping(config_files, get_func, entity_type):
external = config.get('external')
if external:
if len(config.keys()) > 1:
raise ConfigurationError(
'{} {} declared as external but specifies'
' additional attributes ({}). '.format(
entity_type,
name,
', '.join([k for k in config.keys() if k != 'external'])
)
)
validate_external(entity_type, name, config)
if isinstance(external, dict):
config['external_name'] = external.get('name')
else:
config['external_name'] = name
mapping[name] = config
if 'driver_opts' in config:
config['driver_opts'] = build_string_dict(
config['driver_opts']
)
if 'labels' in config:
config['labels'] = parse_labels(config['labels'])
return mapping
def load_services(working_dir, config_file, service_configs):
def validate_external(entity_type, name, config):
if len(config.keys()) <= 1:
return
raise ConfigurationError(
"{} {} declared as external but specifies additional attributes "
"({}).".format(
entity_type, name, ', '.join(k for k in config if k != 'external')))
def load_secrets(config_files, working_dir):
mapping = {}
for config_file in config_files:
for name, config in config_file.get_secrets().items():
mapping[name] = config or {}
if not config:
continue
external = config.get('external')
if external:
validate_external('Secret', name, config)
if isinstance(external, dict):
config['external_name'] = external.get('name')
else:
config['external_name'] = name
if 'file' in config:
config['file'] = expand_path(working_dir, config['file'])
return mapping
def load_services(config_details, config_file):
def build_service(service_name, service_dict, service_names):
service_config = ServiceConfig.with_abs_paths(
working_dir,
config_details.working_dir,
config_file.filename,
service_name,
service_dict)
resolver = ServiceExtendsResolver(service_config, config_file)
resolver = ServiceExtendsResolver(
service_config, config_file, environment=config_details.environment
)
service_dict = process_service(resolver.run())
service_config = service_config._replace(config=service_dict)
@ -360,7 +425,8 @@ def load_services(working_dir, config_file, service_configs):
service_dict = finalize_service(
service_config,
service_names,
config_file.version)
config_file.version,
config_details.environment)
return service_dict
def build_services(service_config):
@ -380,6 +446,10 @@ def load_services(working_dir, config_file, service_configs):
for name in all_service_names
}
service_configs = [
file.get_service_dicts() for file in config_details.config_files
]
service_config = service_configs[0]
for next_config in service_configs[1:]:
service_config = merge_services(service_config, next_config)
@ -387,34 +457,45 @@ def load_services(working_dir, config_file, service_configs):
return build_services(service_config)
def interpolate_config_section(filename, config, section):
validate_config_section(filename, config, section)
return interpolate_environment_variables(config, section)
def interpolate_config_section(config_file, config, section, environment):
validate_config_section(config_file.filename, config, section)
return interpolate_environment_variables(
config_file.version,
config,
section,
environment
)
def process_config_file(config_file, service_name=None):
def process_config_file(config_file, environment, service_name=None):
services = interpolate_config_section(
config_file.filename,
config_file,
config_file.get_service_dicts(),
'service')
'service',
environment)
if config_file.version == V2_0:
if config_file.version in (V2_0, V2_1, V3_0, V3_1):
processed_config = dict(config_file.config)
processed_config['services'] = services
processed_config['volumes'] = interpolate_config_section(
config_file.filename,
config_file,
config_file.get_volumes(),
'volume')
'volume',
environment)
processed_config['networks'] = interpolate_config_section(
config_file.filename,
config_file,
config_file.get_networks(),
'network')
if config_file.version == V1:
'network',
environment)
elif config_file.version == V1:
processed_config = services
else:
raise ConfigurationError(
'Version in "{}" is unsupported. {}'
.format(config_file.filename, VERSION_EXPLANATION))
config_file = config_file._replace(config=processed_config)
validate_against_fields_schema(config_file)
validate_against_config_schema(config_file)
if service_name and service_name not in services:
raise ConfigurationError(
@ -425,11 +506,12 @@ def process_config_file(config_file, service_name=None):
class ServiceExtendsResolver(object):
def __init__(self, service_config, config_file, already_seen=None):
def __init__(self, service_config, config_file, environment, already_seen=None):
self.service_config = service_config
self.working_dir = service_config.working_dir
self.already_seen = already_seen or []
self.config_file = config_file
self.environment = environment
@property
def signature(self):
@ -459,8 +541,8 @@ class ServiceExtendsResolver(object):
extends_file = ConfigFile.from_filename(config_path)
validate_config_version([self.config_file, extends_file])
extended_file = process_config_file(
extends_file,
service_name=service_name)
extends_file, self.environment, service_name=service_name
)
service_config = extended_file.get_service(service_name)
return config_path, service_config, service_name
@ -473,7 +555,9 @@ class ServiceExtendsResolver(object):
service_name,
service_dict),
self.config_file,
already_seen=self.already_seen + [self.signature])
already_seen=self.already_seen + [self.signature],
environment=self.environment
)
service_config = resolver.run()
other_service_dict = process_service(service_config)
@ -502,7 +586,7 @@ class ServiceExtendsResolver(object):
return filename
def resolve_environment(service_dict):
def resolve_environment(service_dict, environment=None):
"""Unpack any environment variables from an env_file, if set.
Interpolate environment values if set.
"""
@ -511,12 +595,12 @@ def resolve_environment(service_dict):
env.update(env_vars_from_file(env_file))
env.update(parse_environment(service_dict.get('environment')))
return dict(resolve_env_var(k, v) for k, v in six.iteritems(env))
return dict(resolve_env_var(k, v, environment) for k, v in six.iteritems(env))
def resolve_build_args(build):
def resolve_build_args(build, environment):
args = parse_build_arguments(build.get('args'))
return dict(resolve_env_var(k, v) for k, v in six.iteritems(args))
return dict(resolve_env_var(k, v, environment) for k, v in six.iteritems(args))
def validate_extended_service_dict(service_dict, filename, service):
@ -547,12 +631,13 @@ def validate_extended_service_dict(service_dict, filename, service):
def validate_service(service_config, service_names, version):
service_dict, service_name = service_config.config, service_config.name
validate_against_service_schema(service_dict, service_name, version)
validate_service_constraints(service_dict, service_name, version)
validate_paths(service_dict)
validate_ulimits(service_config)
validate_network_mode(service_config, service_names)
validate_depends_on(service_config, service_names)
validate_links(service_config, service_names)
if not service_dict.get('image') and has_uppercase(service_name):
raise ConfigurationError(
@ -588,18 +673,67 @@ def process_service(service_config):
if 'extra_hosts' in service_dict:
service_dict['extra_hosts'] = parse_extra_hosts(service_dict['extra_hosts'])
for field in ['dns', 'dns_search']:
if 'sysctls' in service_dict:
service_dict['sysctls'] = build_string_dict(parse_sysctls(service_dict['sysctls']))
service_dict = process_depends_on(service_dict)
for field in ['dns', 'dns_search', 'tmpfs']:
if field in service_dict:
service_dict[field] = to_list(service_dict[field])
service_dict = process_healthcheck(service_dict, service_config.name)
return service_dict
def finalize_service(service_config, service_names, version):
def process_depends_on(service_dict):
if 'depends_on' in service_dict and not isinstance(service_dict['depends_on'], dict):
service_dict['depends_on'] = dict([
(svc, {'condition': 'service_started'}) for svc in service_dict['depends_on']
])
return service_dict
def process_healthcheck(service_dict, service_name):
if 'healthcheck' not in service_dict:
return service_dict
hc = {}
raw = service_dict['healthcheck']
if raw.get('disable'):
if len(raw) > 1:
raise ConfigurationError(
'Service "{}" defines an invalid healthcheck: '
'"disable: true" cannot be combined with other options'
.format(service_name))
hc['test'] = ['NONE']
elif 'test' in raw:
hc['test'] = raw['test']
if 'interval' in raw:
if not isinstance(raw['interval'], six.integer_types):
hc['interval'] = parse_nanoseconds_int(raw['interval'])
else: # Conversion has been done previously
hc['interval'] = raw['interval']
if 'timeout' in raw:
if not isinstance(raw['timeout'], six.integer_types):
hc['timeout'] = parse_nanoseconds_int(raw['timeout'])
else: # Conversion has been done previously
hc['timeout'] = raw['timeout']
if 'retries' in raw:
hc['retries'] = raw['retries']
service_dict['healthcheck'] = hc
return service_dict
def finalize_service(service_config, service_names, version, environment):
service_dict = dict(service_config.config)
if 'environment' in service_dict or 'env_file' in service_dict:
service_dict['environment'] = resolve_environment(service_dict)
service_dict['environment'] = resolve_environment(service_dict, environment)
service_dict.pop('env_file', None)
if 'volumes_from' in service_dict:
@ -610,7 +744,10 @@ def finalize_service(service_config, service_names, version):
if 'volumes' in service_dict:
service_dict['volumes'] = [
VolumeSpec.parse(v) for v in service_dict['volumes']]
VolumeSpec.parse(
v, environment.get_boolean('COMPOSE_CONVERT_WINDOWS_PATHS')
) for v in service_dict['volumes']
]
if 'net' in service_dict:
network_mode = service_dict.pop('net')
@ -626,7 +763,12 @@ def finalize_service(service_config, service_names, version):
if 'restart' in service_dict:
service_dict['restart'] = parse_restart_spec(service_dict['restart'])
normalize_build(service_dict, service_config.working_dir)
if 'secrets' in service_dict:
service_dict['secrets'] = [
types.ServiceSecret.parse(s) for s in service_dict['secrets']
]
normalize_build(service_dict, service_config.working_dir, environment)
service_dict['name'] = service_config.name
return normalize_v1_service_format(service_dict)
@ -699,7 +841,7 @@ class MergeDict(dict):
merged = parse_sequence_func(self.base.get(field, []))
merged.update(parse_sequence_func(self.override.get(field, [])))
self[field] = [item.repr() for item in merged.values()]
self[field] = [item.repr() for item in sorted(merged.values())]
def merge_scalar(self, field):
if self.needs_merge(field):
@ -713,23 +855,25 @@ def merge_service_dicts(base, override, version):
md.merge_mapping('labels', parse_labels)
md.merge_mapping('ulimits', parse_ulimits)
md.merge_mapping('networks', parse_networks)
md.merge_mapping('sysctls', parse_sysctls)
md.merge_mapping('depends_on', parse_depends_on)
md.merge_sequence('links', ServiceLink.parse)
md.merge_sequence('secrets', types.ServiceSecret.parse)
for field in ['volumes', 'devices']:
md.merge_field(field, merge_path_mappings)
for field in [
'depends_on',
'expose',
'external_links',
'ports',
'volumes_from',
'ports', 'cap_add', 'cap_drop', 'expose', 'external_links',
'security_opt', 'volumes_from',
]:
md.merge_field(field, operator.add, default=[])
md.merge_field(field, merge_unique_items_lists, default=[])
for field in ['dns', 'dns_search', 'env_file']:
for field in ['dns', 'dns_search', 'env_file', 'tmpfs']:
md.merge_field(field, merge_list_or_string)
md.merge_field('logging', merge_logging, default={})
for field in set(ALLOWED_KEYS) - set(md):
md.merge_scalar(field)
@ -741,6 +885,10 @@ def merge_service_dicts(base, override, version):
return dict(md)
def merge_unique_items_lists(base, override):
return sorted(set().union(base, override))
def merge_build(output, base, override):
def to_dict(service):
build_config = service.get('build', {})
@ -755,6 +903,16 @@ def merge_build(output, base, override):
return dict(md)
def merge_logging(base, override):
md = MergeDict(base, override)
md.merge_scalar('driver')
if md.get('driver') == base.get('driver') or base.get('driver') is None:
md.merge_mapping('options', lambda m: m or {})
else:
md['options'] = override.get('options')
return dict(md)
def legacy_v1_merge_image_or_build(output, base, override):
output.pop('image', None)
output.pop('build', None)
@ -774,20 +932,11 @@ def merge_environment(base, override):
return env
def split_env(env):
if isinstance(env, six.binary_type):
env = env.decode('utf-8', 'replace')
if '=' in env:
return env.split('=', 1)
def split_kv(kvpair):
if '=' in kvpair:
return kvpair.split('=', 1)
else:
return env, None
def split_label(label):
if '=' in label:
return label.split('=', 1)
else:
return label, ''
return kvpair, ''
def parse_dict_or_list(split_func, type_name, arguments):
@ -808,8 +957,12 @@ def parse_dict_or_list(split_func, type_name, arguments):
parse_build_arguments = functools.partial(parse_dict_or_list, split_env, 'build arguments')
parse_environment = functools.partial(parse_dict_or_list, split_env, 'environment')
parse_labels = functools.partial(parse_dict_or_list, split_label, 'labels')
parse_labels = functools.partial(parse_dict_or_list, split_kv, 'labels')
parse_networks = functools.partial(parse_dict_or_list, lambda k: (k, None), 'networks')
parse_sysctls = functools.partial(parse_dict_or_list, split_kv, 'sysctls')
parse_depends_on = functools.partial(
parse_dict_or_list, lambda k: (k, {'condition': 'service_started'}), 'depends_on'
)
def parse_ulimits(ulimits):
@ -820,30 +973,15 @@ def parse_ulimits(ulimits):
return dict(ulimits)
def resolve_env_var(key, val):
def resolve_env_var(key, val, environment):
if val is not None:
return key, val
elif key in os.environ:
return key, os.environ[key]
elif environment and key in environment:
return key, environment[key]
else:
return key, None
def env_vars_from_file(filename):
"""
Read in a line delimited file of environment variables.
"""
if not os.path.exists(filename):
raise ConfigurationError("Couldn't find env file: %s" % filename)
env = {}
for line in codecs.open(filename, 'r', 'utf-8'):
line = line.strip()
if line and not line.startswith('#'):
k, v = split_env(line)
env[k] = v
return env
def resolve_volume_paths(working_dir, service_dict):
return [
resolve_volume_path(working_dir, volume)
@ -863,7 +1001,7 @@ def resolve_volume_path(working_dir, volume):
return container_path
def normalize_build(service_dict, working_dir):
def normalize_build(service_dict, working_dir, environment):
if 'build' in service_dict:
build = {}
@ -873,7 +1011,9 @@ def normalize_build(service_dict, working_dir):
else:
build.update(service_dict['build'])
if 'args' in build:
build['args'] = build_string_dict(resolve_build_args(build))
build['args'] = build_string_dict(
resolve_build_args(build, environment)
)
service_dict['build'] = build
@ -923,7 +1063,7 @@ def dict_from_path_mappings(path_mappings):
def path_mappings_from_dict(d):
return [join_path_mapping(v) for v in d.items()]
return [join_path_mapping(v) for v in sorted(d.items())]
def split_path_mapping(volume_path):
@ -932,12 +1072,7 @@ def split_path_mapping(volume_path):
path. Using splitdrive so windows absolute paths won't cause issues with
splitting on ':'.
"""
# splitdrive has limitations when it comes to relative paths, so when it's
# relative, handle special case to set the drive to ''
if volume_path.startswith('.') or volume_path.startswith('~'):
drive, volume_config = '', volume_path
else:
drive, volume_config = os.path.splitdrive(volume_path)
drive, volume_config = splitdrive(volume_path)
if ':' in volume_config:
(host, container) = volume_config.split(':', 1)

View file

@ -1,13 +1,16 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "service_schema_v1.json",
"id": "config_schema_v1.json",
"type": "object",
"allOf": [
{"$ref": "#/definitions/service"},
{"$ref": "#/definitions/constraints"}
],
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/service"
}
},
"additionalProperties": false,
"definitions": {
"service": {
@ -82,6 +85,7 @@
"mac_address": {"type": "string"},
"mem_limit": {"type": ["number", "string"]},
"memswap_limit": {"type": ["number", "string"]},
"mem_swappiness": {"type": "integer"},
"net": {"type": "string"},
"pid": {"type": ["string", "null"]},
@ -98,6 +102,7 @@
"read_only": {"type": "boolean"},
"restart": {"type": "string"},
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"shm_size": {"type": ["number", "string"]},
"stdin_open": {"type": "boolean"},
"stop_signal": {"type": "string"},
"tty": {"type": "boolean"},
@ -152,8 +157,7 @@
"type": "object",
"patternProperties": {
".+": {
"type": ["string", "number", "boolean", "null"],
"format": "bool-value-in-mapping"
"type": ["string", "number", "null"]
}
},
"additionalProperties": false
@ -161,21 +165,24 @@
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
]
},
"constraints": {
"id": "#/definitions/constraints",
"anyOf": [
{
"required": ["build"],
"not": {"required": ["image"]}
},
{
"required": ["image"],
"not": {"anyOf": [
{"required": ["build"]},
{"required": ["dockerfile"]}
]}
}
]
"service": {
"id": "#/definitions/constraints/service",
"anyOf": [
{
"required": ["build"],
"not": {"required": ["image"]}
},
{
"required": ["image"],
"not": {"anyOf": [
{"required": ["build"]},
{"required": ["dockerfile"]}
]}
}
]
}
}
}
}

View file

@ -1,15 +1,50 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "service_schema_v2.0.json",
"id": "config_schema_v2.0.json",
"type": "object",
"allOf": [
{"$ref": "#/definitions/service"},
{"$ref": "#/definitions/constraints"}
],
"properties": {
"version": {
"type": "string"
},
"services": {
"id": "#/properties/services",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/service"
}
},
"additionalProperties": false
},
"networks": {
"id": "#/properties/networks",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/network"
}
}
},
"volumes": {
"id": "#/properties/volumes",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/volume"
}
},
"additionalProperties": false
}
},
"additionalProperties": false,
"definitions": {
"service": {
"id": "#/definitions/service",
"type": "object",
@ -23,20 +58,7 @@
"properties": {
"context": {"type": "string"},
"dockerfile": {"type": "string"},
"args": {
"oneOf": [
{"$ref": "#/definitions/list_of_strings"},
{
"type": "object",
"patternProperties": {
"^.+$": {
"type": ["string", "number"]
}
},
"additionalProperties": false
}
]
}
"args": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
}
@ -117,6 +139,7 @@
"mac_address": {"type": "string"},
"mem_limit": {"type": ["number", "string"]},
"memswap_limit": {"type": ["number", "string"]},
"mem_swappiness": {"type": "integer"},
"network_mode": {"type": "string"},
"networks": {
@ -130,7 +153,9 @@
{
"type": "object",
"properties": {
"aliases": {"$ref": "#/definitions/list_of_strings"}
"aliases": {"$ref": "#/definitions/list_of_strings"},
"ipv4_address": {"type": "string"},
"ipv6_address": {"type": "string"}
},
"additionalProperties": false
},
@ -142,6 +167,14 @@
}
]
},
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
"group_add": {
"type": "array",
"items": {
"type": ["string", "number"]
},
"uniqueItems": true
},
"pid": {"type": ["string", "null"]},
"ports": {
@ -157,8 +190,11 @@
"read_only": {"type": "boolean"},
"restart": {"type": "string"},
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"shm_size": {"type": ["number", "string"]},
"stdin_open": {"type": "boolean"},
"stop_grace_period": {"type": "string", "format": "duration"},
"stop_signal": {"type": "string"},
"tmpfs": {"$ref": "#/definitions/string_or_list"},
"tty": {"type": "boolean"},
"ulimits": {
"type": "object",
@ -192,6 +228,61 @@
"additionalProperties": false
},
"network": {
"id": "#/definitions/network",
"type": "object",
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"ipam": {
"type": "object",
"properties": {
"driver": {"type": "string"},
"config": {
"type": "array"
}
},
"additionalProperties": false
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
},
"internal": {"type": "boolean"}
},
"additionalProperties": false
},
"volume": {
"id": "#/definitions/volume",
"type": ["object", "null"],
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"string_or_list": {
"oneOf": [
{"type": "string"},
@ -211,8 +302,7 @@
"type": "object",
"patternProperties": {
".+": {
"type": ["string", "number", "boolean", "null"],
"format": "bool-value-in-mapping"
"type": ["string", "number", "null"]
}
},
"additionalProperties": false
@ -220,15 +310,18 @@
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
]
},
"constraints": {
"id": "#/definitions/constraints",
"anyOf": [
"service": {
"id": "#/definitions/constraints/service",
"anyOf": [
{"required": ["build"]},
{"required": ["image"]}
],
"properties": {
"build": {
"required": ["context"]
],
"properties": {
"build": {
"required": ["context"]
}
}
}
}

View file

@ -0,0 +1,376 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "config_schema_v2.1.json",
"type": "object",
"properties": {
"version": {
"type": "string"
},
"services": {
"id": "#/properties/services",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/service"
}
},
"additionalProperties": false
},
"networks": {
"id": "#/properties/networks",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/network"
}
}
},
"volumes": {
"id": "#/properties/volumes",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/volume"
}
},
"additionalProperties": false
}
},
"additionalProperties": false,
"definitions": {
"service": {
"id": "#/definitions/service",
"type": "object",
"properties": {
"build": {
"oneOf": [
{"type": "string"},
{
"type": "object",
"properties": {
"context": {"type": "string"},
"dockerfile": {"type": "string"},
"args": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
}
]
},
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"cgroup_parent": {"type": "string"},
"command": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"container_name": {"type": "string"},
"cpu_shares": {"type": ["number", "string"]},
"cpu_quota": {"type": ["number", "string"]},
"cpuset": {"type": "string"},
"depends_on": {
"oneOf": [
{"$ref": "#/definitions/list_of_strings"},
{
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"type": "object",
"additionalProperties": false,
"properties": {
"condition": {
"type": "string",
"enum": ["service_started", "service_healthy"]
}
},
"required": ["condition"]
}
}
}
]
},
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"dns": {"$ref": "#/definitions/string_or_list"},
"dns_search": {"$ref": "#/definitions/string_or_list"},
"domainname": {"type": "string"},
"entrypoint": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"env_file": {"$ref": "#/definitions/string_or_list"},
"environment": {"$ref": "#/definitions/list_or_dict"},
"expose": {
"type": "array",
"items": {
"type": ["string", "number"],
"format": "expose"
},
"uniqueItems": true
},
"extends": {
"oneOf": [
{
"type": "string"
},
{
"type": "object",
"properties": {
"service": {"type": "string"},
"file": {"type": "string"}
},
"required": ["service"],
"additionalProperties": false
}
]
},
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
"healthcheck": {"$ref": "#/definitions/healthcheck"},
"hostname": {"type": "string"},
"image": {"type": "string"},
"ipc": {"type": "string"},
"isolation": {"type": "string"},
"labels": {"$ref": "#/definitions/list_or_dict"},
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"logging": {
"type": "object",
"properties": {
"driver": {"type": "string"},
"options": {"type": "object"}
},
"additionalProperties": false
},
"mac_address": {"type": "string"},
"mem_limit": {"type": ["number", "string"]},
"memswap_limit": {"type": ["number", "string"]},
"mem_swappiness": {"type": "integer"},
"network_mode": {"type": "string"},
"networks": {
"oneOf": [
{"$ref": "#/definitions/list_of_strings"},
{
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"oneOf": [
{
"type": "object",
"properties": {
"aliases": {"$ref": "#/definitions/list_of_strings"},
"ipv4_address": {"type": "string"},
"ipv6_address": {"type": "string"},
"link_local_ips": {"$ref": "#/definitions/list_of_strings"}
},
"additionalProperties": false
},
{"type": "null"}
]
}
},
"additionalProperties": false
}
]
},
"oom_score_adj": {"type": "integer", "minimum": -1000, "maximum": 1000},
"group_add": {
"type": "array",
"items": {
"type": ["string", "number"]
},
"uniqueItems": true
},
"pid": {"type": ["string", "null"]},
"ports": {
"type": "array",
"items": {
"type": ["string", "number"],
"format": "ports"
},
"uniqueItems": true
},
"privileged": {"type": "boolean"},
"read_only": {"type": "boolean"},
"restart": {"type": "string"},
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"shm_size": {"type": ["number", "string"]},
"sysctls": {"$ref": "#/definitions/list_or_dict"},
"stdin_open": {"type": "boolean"},
"stop_grace_period": {"type": "string", "format": "duration"},
"stop_signal": {"type": "string"},
"tmpfs": {"$ref": "#/definitions/string_or_list"},
"tty": {"type": "boolean"},
"ulimits": {
"type": "object",
"patternProperties": {
"^[a-z]+$": {
"oneOf": [
{"type": "integer"},
{
"type":"object",
"properties": {
"hard": {"type": "integer"},
"soft": {"type": "integer"}
},
"required": ["soft", "hard"],
"additionalProperties": false
}
]
}
}
},
"user": {"type": "string"},
"userns_mode": {"type": "string"},
"volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"volume_driver": {"type": "string"},
"volumes_from": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"working_dir": {"type": "string"}
},
"dependencies": {
"memswap_limit": ["mem_limit"]
},
"additionalProperties": false
},
"healthcheck": {
"id": "#/definitions/healthcheck",
"type": "object",
"additionalProperties": false,
"properties": {
"disable": {"type": "boolean"},
"interval": {"type": "string"},
"retries": {"type": "number"},
"test": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"timeout": {"type": "string"}
}
},
"network": {
"id": "#/definitions/network",
"type": "object",
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"ipam": {
"type": "object",
"properties": {
"driver": {"type": "string"},
"config": {
"type": "array"
}
},
"additionalProperties": false
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
},
"internal": {"type": "boolean"},
"enable_ipv6": {"type": "boolean"},
"labels": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
},
"volume": {
"id": "#/definitions/volume",
"type": ["object", "null"],
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
},
"labels": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
},
"string_or_list": {
"oneOf": [
{"type": "string"},
{"$ref": "#/definitions/list_of_strings"}
]
},
"list_of_strings": {
"type": "array",
"items": {"type": "string"},
"uniqueItems": true
},
"list_or_dict": {
"oneOf": [
{
"type": "object",
"patternProperties": {
".+": {
"type": ["string", "number", "null"]
}
},
"additionalProperties": false
},
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
]
},
"constraints": {
"service": {
"id": "#/definitions/constraints/service",
"anyOf": [
{"required": ["build"]},
{"required": ["image"]}
],
"properties": {
"build": {
"required": ["context"]
}
}
}
}
}
}

View file

@ -0,0 +1,383 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "config_schema_v3.0.json",
"type": "object",
"required": ["version"],
"properties": {
"version": {
"type": "string"
},
"services": {
"id": "#/properties/services",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/service"
}
},
"additionalProperties": false
},
"networks": {
"id": "#/properties/networks",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/network"
}
}
},
"volumes": {
"id": "#/properties/volumes",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/volume"
}
},
"additionalProperties": false
}
},
"additionalProperties": false,
"definitions": {
"service": {
"id": "#/definitions/service",
"type": "object",
"properties": {
"deploy": {"$ref": "#/definitions/deployment"},
"build": {
"oneOf": [
{"type": "string"},
{
"type": "object",
"properties": {
"context": {"type": "string"},
"dockerfile": {"type": "string"},
"args": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
}
]
},
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"cgroup_parent": {"type": "string"},
"command": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"container_name": {"type": "string"},
"depends_on": {"$ref": "#/definitions/list_of_strings"},
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"dns": {"$ref": "#/definitions/string_or_list"},
"dns_search": {"$ref": "#/definitions/string_or_list"},
"domainname": {"type": "string"},
"entrypoint": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"env_file": {"$ref": "#/definitions/string_or_list"},
"environment": {"$ref": "#/definitions/list_or_dict"},
"expose": {
"type": "array",
"items": {
"type": ["string", "number"],
"format": "expose"
},
"uniqueItems": true
},
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
"healthcheck": {"$ref": "#/definitions/healthcheck"},
"hostname": {"type": "string"},
"image": {"type": "string"},
"ipc": {"type": "string"},
"labels": {"$ref": "#/definitions/list_or_dict"},
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"logging": {
"type": "object",
"properties": {
"driver": {"type": "string"},
"options": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number", "null"]}
}
}
},
"additionalProperties": false
},
"mac_address": {"type": "string"},
"network_mode": {"type": "string"},
"networks": {
"oneOf": [
{"$ref": "#/definitions/list_of_strings"},
{
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"oneOf": [
{
"type": "object",
"properties": {
"aliases": {"$ref": "#/definitions/list_of_strings"},
"ipv4_address": {"type": "string"},
"ipv6_address": {"type": "string"}
},
"additionalProperties": false
},
{"type": "null"}
]
}
},
"additionalProperties": false
}
]
},
"pid": {"type": ["string", "null"]},
"ports": {
"type": "array",
"items": {
"type": ["string", "number"],
"format": "ports"
},
"uniqueItems": true
},
"privileged": {"type": "boolean"},
"read_only": {"type": "boolean"},
"restart": {"type": "string"},
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"shm_size": {"type": ["number", "string"]},
"sysctls": {"$ref": "#/definitions/list_or_dict"},
"stdin_open": {"type": "boolean"},
"stop_grace_period": {"type": "string", "format": "duration"},
"stop_signal": {"type": "string"},
"tmpfs": {"$ref": "#/definitions/string_or_list"},
"tty": {"type": "boolean"},
"ulimits": {
"type": "object",
"patternProperties": {
"^[a-z]+$": {
"oneOf": [
{"type": "integer"},
{
"type":"object",
"properties": {
"hard": {"type": "integer"},
"soft": {"type": "integer"}
},
"required": ["soft", "hard"],
"additionalProperties": false
}
]
}
}
},
"user": {"type": "string"},
"userns_mode": {"type": "string"},
"volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"working_dir": {"type": "string"}
},
"additionalProperties": false
},
"healthcheck": {
"id": "#/definitions/healthcheck",
"type": "object",
"additionalProperties": false,
"properties": {
"disable": {"type": "boolean"},
"interval": {"type": "string"},
"retries": {"type": "number"},
"test": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"timeout": {"type": "string"}
}
},
"deployment": {
"id": "#/definitions/deployment",
"type": ["object", "null"],
"properties": {
"mode": {"type": "string"},
"replicas": {"type": "integer"},
"labels": {"$ref": "#/definitions/list_or_dict"},
"update_config": {
"type": "object",
"properties": {
"parallelism": {"type": "integer"},
"delay": {"type": "string", "format": "duration"},
"failure_action": {"type": "string"},
"monitor": {"type": "string", "format": "duration"},
"max_failure_ratio": {"type": "number"}
},
"additionalProperties": false
},
"resources": {
"type": "object",
"properties": {
"limits": {"$ref": "#/definitions/resource"},
"reservations": {"$ref": "#/definitions/resource"}
}
},
"restart_policy": {
"type": "object",
"properties": {
"condition": {"type": "string"},
"delay": {"type": "string", "format": "duration"},
"max_attempts": {"type": "integer"},
"window": {"type": "string", "format": "duration"}
},
"additionalProperties": false
},
"placement": {
"type": "object",
"properties": {
"constraints": {"type": "array", "items": {"type": "string"}}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"resource": {
"id": "#/definitions/resource",
"type": "object",
"properties": {
"cpus": {"type": "string"},
"memory": {"type": "string"}
},
"additionalProperties": false
},
"network": {
"id": "#/definitions/network",
"type": ["object", "null"],
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"ipam": {
"type": "object",
"properties": {
"driver": {"type": "string"},
"config": {
"type": "array",
"items": {
"type": "object",
"properties": {
"subnet": {"type": "string"}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
},
"internal": {"type": "boolean"},
"labels": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
},
"volume": {
"id": "#/definitions/volume",
"type": ["object", "null"],
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
},
"labels": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
},
"string_or_list": {
"oneOf": [
{"type": "string"},
{"$ref": "#/definitions/list_of_strings"}
]
},
"list_of_strings": {
"type": "array",
"items": {"type": "string"},
"uniqueItems": true
},
"list_or_dict": {
"oneOf": [
{
"type": "object",
"patternProperties": {
".+": {
"type": ["string", "number", "null"]
}
},
"additionalProperties": false
},
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
]
},
"constraints": {
"service": {
"id": "#/definitions/constraints/service",
"anyOf": [
{"required": ["build"]},
{"required": ["image"]}
],
"properties": {
"build": {
"required": ["context"]
}
}
}
}
}
}

View file

@ -0,0 +1,428 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "config_schema_v3.1.json",
"type": "object",
"required": ["version"],
"properties": {
"version": {
"type": "string"
},
"services": {
"id": "#/properties/services",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/service"
}
},
"additionalProperties": false
},
"networks": {
"id": "#/properties/networks",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/network"
}
}
},
"volumes": {
"id": "#/properties/volumes",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/volume"
}
},
"additionalProperties": false
},
"secrets": {
"id": "#/properties/secrets",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/secret"
}
},
"additionalProperties": false
}
},
"additionalProperties": false,
"definitions": {
"service": {
"id": "#/definitions/service",
"type": "object",
"properties": {
"deploy": {"$ref": "#/definitions/deployment"},
"build": {
"oneOf": [
{"type": "string"},
{
"type": "object",
"properties": {
"context": {"type": "string"},
"dockerfile": {"type": "string"},
"args": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
}
]
},
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"cgroup_parent": {"type": "string"},
"command": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"container_name": {"type": "string"},
"depends_on": {"$ref": "#/definitions/list_of_strings"},
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"dns": {"$ref": "#/definitions/string_or_list"},
"dns_search": {"$ref": "#/definitions/string_or_list"},
"domainname": {"type": "string"},
"entrypoint": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"env_file": {"$ref": "#/definitions/string_or_list"},
"environment": {"$ref": "#/definitions/list_or_dict"},
"expose": {
"type": "array",
"items": {
"type": ["string", "number"],
"format": "expose"
},
"uniqueItems": true
},
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
"healthcheck": {"$ref": "#/definitions/healthcheck"},
"hostname": {"type": "string"},
"image": {"type": "string"},
"ipc": {"type": "string"},
"labels": {"$ref": "#/definitions/list_or_dict"},
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"logging": {
"type": "object",
"properties": {
"driver": {"type": "string"},
"options": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number", "null"]}
}
}
},
"additionalProperties": false
},
"mac_address": {"type": "string"},
"network_mode": {"type": "string"},
"networks": {
"oneOf": [
{"$ref": "#/definitions/list_of_strings"},
{
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"oneOf": [
{
"type": "object",
"properties": {
"aliases": {"$ref": "#/definitions/list_of_strings"},
"ipv4_address": {"type": "string"},
"ipv6_address": {"type": "string"}
},
"additionalProperties": false
},
{"type": "null"}
]
}
},
"additionalProperties": false
}
]
},
"pid": {"type": ["string", "null"]},
"ports": {
"type": "array",
"items": {
"type": ["string", "number"],
"format": "ports"
},
"uniqueItems": true
},
"privileged": {"type": "boolean"},
"read_only": {"type": "boolean"},
"restart": {"type": "string"},
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"shm_size": {"type": ["number", "string"]},
"secrets": {
"type": "array",
"items": {
"oneOf": [
{"type": "string"},
{
"type": "object",
"properties": {
"source": {"type": "string"},
"target": {"type": "string"},
"uid": {"type": "string"},
"gid": {"type": "string"},
"mode": {"type": "number"}
}
}
]
}
},
"sysctls": {"$ref": "#/definitions/list_or_dict"},
"stdin_open": {"type": "boolean"},
"stop_grace_period": {"type": "string", "format": "duration"},
"stop_signal": {"type": "string"},
"tmpfs": {"$ref": "#/definitions/string_or_list"},
"tty": {"type": "boolean"},
"ulimits": {
"type": "object",
"patternProperties": {
"^[a-z]+$": {
"oneOf": [
{"type": "integer"},
{
"type":"object",
"properties": {
"hard": {"type": "integer"},
"soft": {"type": "integer"}
},
"required": ["soft", "hard"],
"additionalProperties": false
}
]
}
}
},
"user": {"type": "string"},
"userns_mode": {"type": "string"},
"volumes": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"working_dir": {"type": "string"}
},
"additionalProperties": false
},
"healthcheck": {
"id": "#/definitions/healthcheck",
"type": "object",
"additionalProperties": false,
"properties": {
"disable": {"type": "boolean"},
"interval": {"type": "string"},
"retries": {"type": "number"},
"test": {
"oneOf": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}}
]
},
"timeout": {"type": "string"}
}
},
"deployment": {
"id": "#/definitions/deployment",
"type": ["object", "null"],
"properties": {
"mode": {"type": "string"},
"replicas": {"type": "integer"},
"labels": {"$ref": "#/definitions/list_or_dict"},
"update_config": {
"type": "object",
"properties": {
"parallelism": {"type": "integer"},
"delay": {"type": "string", "format": "duration"},
"failure_action": {"type": "string"},
"monitor": {"type": "string", "format": "duration"},
"max_failure_ratio": {"type": "number"}
},
"additionalProperties": false
},
"resources": {
"type": "object",
"properties": {
"limits": {"$ref": "#/definitions/resource"},
"reservations": {"$ref": "#/definitions/resource"}
}
},
"restart_policy": {
"type": "object",
"properties": {
"condition": {"type": "string"},
"delay": {"type": "string", "format": "duration"},
"max_attempts": {"type": "integer"},
"window": {"type": "string", "format": "duration"}
},
"additionalProperties": false
},
"placement": {
"type": "object",
"properties": {
"constraints": {"type": "array", "items": {"type": "string"}}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"resource": {
"id": "#/definitions/resource",
"type": "object",
"properties": {
"cpus": {"type": "string"},
"memory": {"type": "string"}
},
"additionalProperties": false
},
"network": {
"id": "#/definitions/network",
"type": ["object", "null"],
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"ipam": {
"type": "object",
"properties": {
"driver": {"type": "string"},
"config": {
"type": "array",
"items": {
"type": "object",
"properties": {
"subnet": {"type": "string"}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
},
"internal": {"type": "boolean"},
"labels": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
},
"volume": {
"id": "#/definitions/volume",
"type": ["object", "null"],
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
},
"labels": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
},
"secret": {
"id": "#/definitions/secret",
"type": "object",
"properties": {
"file": {"type": "string"},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
}
},
"labels": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false
},
"string_or_list": {
"oneOf": [
{"type": "string"},
{"$ref": "#/definitions/list_of_strings"}
]
},
"list_of_strings": {
"type": "array",
"items": {"type": "string"},
"uniqueItems": true
},
"list_or_dict": {
"oneOf": [
{
"type": "object",
"patternProperties": {
".+": {
"type": ["string", "number", "null"]
}
},
"additionalProperties": false
},
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
]
},
"constraints": {
"service": {
"id": "#/definitions/constraints/service",
"anyOf": [
{"required": ["build"]},
{"required": ["image"]}
],
"properties": {
"build": {
"required": ["context"]
}
}
}
}
}
}

View file

@ -0,0 +1,120 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import codecs
import contextlib
import logging
import os
import six
from ..const import IS_WINDOWS_PLATFORM
from .errors import ConfigurationError
log = logging.getLogger(__name__)
def split_env(env):
if isinstance(env, six.binary_type):
env = env.decode('utf-8', 'replace')
if '=' in env:
return env.split('=', 1)
else:
return env, None
def env_vars_from_file(filename):
"""
Read in a line delimited file of environment variables.
"""
if not os.path.exists(filename):
raise ConfigurationError("Couldn't find env file: %s" % filename)
elif not os.path.isfile(filename):
raise ConfigurationError("%s is not a file." % (filename))
env = {}
with contextlib.closing(codecs.open(filename, 'r', 'utf-8')) as fileobj:
for line in fileobj:
line = line.strip()
if line and not line.startswith('#'):
k, v = split_env(line)
env[k] = v
return env
class Environment(dict):
def __init__(self, *args, **kwargs):
super(Environment, self).__init__(*args, **kwargs)
self.missing_keys = []
@classmethod
def from_env_file(cls, base_dir):
def _initialize():
result = cls()
if base_dir is None:
return result
env_file_path = os.path.join(base_dir, '.env')
try:
return cls(env_vars_from_file(env_file_path))
except ConfigurationError:
pass
return result
instance = _initialize()
instance.update(os.environ)
return instance
@classmethod
def from_command_line(cls, parsed_env_opts):
result = cls()
for k, v in parsed_env_opts.items():
# Values from the command line take priority, unless they're unset
# in which case they take the value from the system's environment
if v is None and k in os.environ:
result[k] = os.environ[k]
else:
result[k] = v
return result
def __getitem__(self, key):
try:
return super(Environment, self).__getitem__(key)
except KeyError:
if IS_WINDOWS_PLATFORM:
try:
return super(Environment, self).__getitem__(key.upper())
except KeyError:
pass
if key not in self.missing_keys:
log.warn(
"The {} variable is not set. Defaulting to a blank string."
.format(key)
)
self.missing_keys.append(key)
return ""
def __contains__(self, key):
result = super(Environment, self).__contains__(key)
if IS_WINDOWS_PLATFORM:
return (
result or super(Environment, self).__contains__(key.upper())
)
return result
def get(self, key, *args, **kwargs):
if IS_WINDOWS_PLATFORM:
return super(Environment, self).get(
key,
super(Environment, self).get(key.upper(), *args, **kwargs)
)
return super(Environment, self).get(key, *args, **kwargs)
def get_boolean(self, key):
# Convert a value to a boolean using "common sense" rules.
# Unset, empty, "0" and "false" (i-case) yield False.
# All other values yield True.
value = self.get(key)
if not value:
return False
if value.lower() in ['0', 'false']:
return False
return True

View file

@ -3,10 +3,11 @@ from __future__ import unicode_literals
VERSION_EXPLANATION = (
'Either specify a version of "2" (or "2.0") and place your service '
'definitions under the `services` key, or omit the `version` key and place '
'your service definitions at the root of the file to use version 1.\n'
'For more on the Compose file format versions, see '
'You might be seeing this error because you\'re using the wrong Compose file version. '
'Either specify a supported version ("2.0", "2.1", "3.0") and place your '
'service definitions under the `services` key, or omit the `version` key '
'and place your service definitions at the root of the file to use '
'version 1.\nFor more on the Compose file format versions, see '
'https://docs.docker.com/compose/compose-file/')
@ -38,7 +39,8 @@ class CircularReference(ConfigurationError):
class ComposeFileNotFound(ConfigurationError):
def __init__(self, supported_filenames):
super(ComposeFileNotFound, self).__init__("""
Can't find a suitable configuration file in this directory or any parent. Are you in the right directory?
Can't find a suitable configuration file in this directory or any
parent. Are you in the right directory?
Supported filenames: %s
""" % ", ".join(supported_filenames))

View file

@ -1,13 +0,0 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"id": "fields_schema_v1.json",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "service_schema_v1.json#/definitions/service"
}
},
"additionalProperties": false
}

View file

@ -1,96 +0,0 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"id": "fields_schema_v2.0.json",
"properties": {
"version": {
"type": "string"
},
"services": {
"id": "#/properties/services",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "service_schema_v2.0.json#/definitions/service"
}
},
"additionalProperties": false
},
"networks": {
"id": "#/properties/networks",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/network"
}
}
},
"volumes": {
"id": "#/properties/volumes",
"type": "object",
"patternProperties": {
"^[a-zA-Z0-9._-]+$": {
"$ref": "#/definitions/volume"
}
},
"additionalProperties": false
}
},
"definitions": {
"network": {
"id": "#/definitions/network",
"type": "object",
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"ipam": {
"type": "object",
"properties": {
"driver": {"type": "string"},
"config": {
"type": "array"
}
},
"additionalProperties": false
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"volume": {
"id": "#/definitions/volume",
"type": ["object", "null"],
"properties": {
"driver": {"type": "string"},
"driver_opts": {
"type": "object",
"patternProperties": {
"^.+$": {"type": ["string", "number"]}
}
},
"external": {
"type": ["boolean", "object"],
"properties": {
"name": {"type": "string"}
}
},
"additionalProperties": false
},
"additionalProperties": false
}
},
"additionalProperties": false
}

View file

@ -2,21 +2,40 @@ from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import os
from string import Template
import six
from .errors import ConfigurationError
from compose.const import COMPOSEFILE_V1 as V1
from compose.const import COMPOSEFILE_V2_0 as V2_0
log = logging.getLogger(__name__)
def interpolate_environment_variables(config, section):
mapping = BlankDefaultDict(os.environ)
class Interpolator(object):
def __init__(self, templater, mapping):
self.templater = templater
self.mapping = mapping
def interpolate(self, string):
try:
return self.templater(string).substitute(self.mapping)
except ValueError:
raise InvalidInterpolation(string)
def interpolate_environment_variables(version, config, section, environment):
if version in (V2_0, V1):
interpolator = Interpolator(Template, environment)
else:
interpolator = Interpolator(TemplateWithDefaults, environment)
def process_item(name, config_dict):
return dict(
(key, interpolate_value(name, key, val, section, mapping))
(key, interpolate_value(name, key, val, section, interpolator))
for key, val in (config_dict or {}).items()
)
@ -26,9 +45,9 @@ def interpolate_environment_variables(config, section):
)
def interpolate_value(name, config_key, value, section, mapping):
def interpolate_value(name, config_key, value, section, interpolator):
try:
return recursive_interpolate(value, mapping)
return recursive_interpolate(value, interpolator)
except InvalidInterpolation as e:
raise ConfigurationError(
'Invalid interpolation format for "{config_key}" option '
@ -39,44 +58,44 @@ def interpolate_value(name, config_key, value, section, mapping):
string=e.string))
def recursive_interpolate(obj, mapping):
def recursive_interpolate(obj, interpolator):
if isinstance(obj, six.string_types):
return interpolate(obj, mapping)
elif isinstance(obj, dict):
return interpolator.interpolate(obj)
if isinstance(obj, dict):
return dict(
(key, recursive_interpolate(val, mapping))
(key, recursive_interpolate(val, interpolator))
for (key, val) in obj.items()
)
elif isinstance(obj, list):
return [recursive_interpolate(val, mapping) for val in obj]
else:
return obj
if isinstance(obj, list):
return [recursive_interpolate(val, interpolator) for val in obj]
return obj
def interpolate(string, mapping):
try:
return Template(string).substitute(mapping)
except ValueError:
raise InvalidInterpolation(string)
class TemplateWithDefaults(Template):
idpattern = r'[_a-z][_a-z0-9]*(?::?-[^}]+)?'
class BlankDefaultDict(dict):
def __init__(self, *args, **kwargs):
super(BlankDefaultDict, self).__init__(*args, **kwargs)
self.missing_keys = []
def __getitem__(self, key):
try:
return super(BlankDefaultDict, self).__getitem__(key)
except KeyError:
if key not in self.missing_keys:
log.warn(
"The {} variable is not set. Defaulting to a blank string."
.format(key)
)
self.missing_keys.append(key)
return ""
# Modified from python2.7/string.py
def substitute(self, mapping):
# Helper function for .sub()
def convert(mo):
# Check the most common path first.
named = mo.group('named') or mo.group('braced')
if named is not None:
if ':-' in named:
var, _, default = named.partition(':-')
return mapping.get(var) or default
if '-' in named:
var, _, default = named.partition('-')
return mapping.get(var, default)
val = mapping[named]
return '%s' % (val,)
if mo.group('escaped') is not None:
return self.delimiter
if mo.group('invalid') is not None:
self._invalid(mo)
raise ValueError('Unrecognized named group in pattern',
self.pattern)
return self.pattern.sub(convert, self.template)
class InvalidInterpolation(Exception):

View file

@ -5,6 +5,8 @@ import six
import yaml
from compose.config import types
from compose.config.config import V1
from compose.config.config import V2_1
def serialize_config_type(dumper, data):
@ -16,15 +18,91 @@ yaml.SafeDumper.add_representer(types.VolumeFromSpec, serialize_config_type)
yaml.SafeDumper.add_representer(types.VolumeSpec, serialize_config_type)
def serialize_config(config):
output = {
'version': config.version,
'services': {service.pop('name'): service for service in config.services},
'networks': config.networks,
'volumes': config.volumes,
def denormalize_config(config):
denormalized_services = [
denormalize_service_dict(service_dict, config.version)
for service_dict in config.services
]
services = {
service_dict.pop('name'): service_dict
for service_dict in denormalized_services
}
networks = config.networks.copy()
for net_name, net_conf in networks.items():
if 'external_name' in net_conf:
del net_conf['external_name']
volumes = config.volumes.copy()
for vol_name, vol_conf in volumes.items():
if 'external_name' in vol_conf:
del vol_conf['external_name']
version = config.version
if version == V1:
version = V2_1
return {
'version': version,
'services': services,
'networks': networks,
'volumes': volumes,
}
def serialize_config(config):
return yaml.safe_dump(
output,
denormalize_config(config),
default_flow_style=False,
indent=2,
width=80)
def serialize_ns_time_value(value):
result = (value, 'ns')
table = [
(1000., 'us'),
(1000., 'ms'),
(1000., 's'),
(60., 'm'),
(60., 'h')
]
for stage in table:
tmp = value / stage[0]
if tmp == int(value / stage[0]):
value = tmp
result = (int(value), stage[1])
else:
break
return '{0}{1}'.format(*result)
def denormalize_service_dict(service_dict, version):
service_dict = service_dict.copy()
if 'restart' in service_dict:
service_dict['restart'] = types.serialize_restart_spec(
service_dict['restart']
)
if version == V1 and 'network_mode' not in service_dict:
service_dict['network_mode'] = 'bridge'
if 'depends_on' in service_dict and version != V2_1:
service_dict['depends_on'] = sorted([
svc for svc in service_dict['depends_on'].keys()
])
if 'healthcheck' in service_dict:
if 'interval' in service_dict['healthcheck']:
service_dict['healthcheck']['interval'] = serialize_ns_time_value(
service_dict['healthcheck']['interval']
)
if 'timeout' in service_dict['healthcheck']:
service_dict['healthcheck']['timeout'] = serialize_ns_time_value(
service_dict['healthcheck']['timeout']
)
if 'secrets' in service_dict:
service_dict['secrets'] = map(lambda s: s.repr(), service_dict['secrets'])
return service_dict

View file

@ -23,28 +23,31 @@ def get_source_name_from_network_mode(network_mode, source_type):
return net_name
def get_service_names(links):
return [link.split(':')[0] for link in links]
def get_service_names_from_volumes_from(volumes_from):
return [volume_from.source for volume_from in volumes_from]
def get_service_dependents(service_dict, services):
name = service_dict['name']
return [
service for service in services
if (name in get_service_names(service.get('links', [])) or
name in get_service_names_from_volumes_from(service.get('volumes_from', [])) or
name == get_service_name_from_network_mode(service.get('network_mode')) or
name in service.get('depends_on', []))
]
def sort_service_dicts(services):
# Topological sort (Cormen/Tarjan algorithm).
unmarked = services[:]
temporary_marked = set()
sorted_services = []
def get_service_names(links):
return [link.split(':')[0] for link in links]
def get_service_names_from_volumes_from(volumes_from):
return [volume_from.source for volume_from in volumes_from]
def get_service_dependents(service_dict, services):
name = service_dict['name']
return [
service for service in services
if (name in get_service_names(service.get('links', [])) or
name in get_service_names_from_volumes_from(service.get('volumes_from', [])) or
name == get_service_name_from_network_mode(service.get('network_mode')) or
name in service.get('depends_on', []))
]
def visit(n):
if n['name'] in temporary_marked:
if n['name'] in get_service_names(n.get('links', [])):

View file

@ -5,11 +5,17 @@ from __future__ import absolute_import
from __future__ import unicode_literals
import os
import re
from collections import namedtuple
from compose.config.config import V1
from compose.config.errors import ConfigurationError
import six
from ..const import COMPOSEFILE_V1 as V1
from .errors import ConfigurationError
from compose.const import IS_WINDOWS_PLATFORM
from compose.utils import splitdrive
win32_root_path_pattern = re.compile(r'^[A-Za-z]\:\\.*')
class VolumeFromSpec(namedtuple('_VolumeFromSpec', 'source mode type')):
@ -89,6 +95,15 @@ def parse_restart_spec(restart_config):
return {'Name': name, 'MaximumRetryCount': int(max_retry_count)}
def serialize_restart_spec(restart_spec):
if not restart_spec:
return ''
parts = [restart_spec['Name']]
if restart_spec['MaximumRetryCount']:
parts.append(six.text_type(restart_spec['MaximumRetryCount']))
return ':'.join(parts)
def parse_extra_hosts(extra_hosts_config):
if not extra_hosts_config:
return {}
@ -105,41 +120,23 @@ def parse_extra_hosts(extra_hosts_config):
return extra_hosts_dict
def normalize_paths_for_engine(external_path, internal_path):
def normalize_path_for_engine(path):
"""Windows paths, c:\my\path\shiny, need to be changed to be compatible with
the Engine. Volume paths are expected to be linux style /c/my/path/shiny/
"""
if not IS_WINDOWS_PLATFORM:
return external_path, internal_path
drive, tail = splitdrive(path)
if external_path:
drive, tail = os.path.splitdrive(external_path)
if drive:
path = '/' + drive.lower().rstrip(':') + tail
if drive:
external_path = '/' + drive.lower().rstrip(':') + tail
external_path = external_path.replace('\\', '/')
return external_path, internal_path.replace('\\', '/')
return path.replace('\\', '/')
class VolumeSpec(namedtuple('_VolumeSpec', 'external internal mode')):
@classmethod
def parse(cls, volume_config):
"""Parse a volume_config path and split it into external:internal[:mode]
parts to be returned as a valid VolumeSpec.
"""
if IS_WINDOWS_PLATFORM:
# relative paths in windows expand to include the drive, eg C:\
# so we join the first 2 parts back together to count as one
drive, tail = os.path.splitdrive(volume_config)
parts = tail.split(":")
if drive:
parts[0] = drive + parts[0]
else:
parts = volume_config.split(':')
def _parse_unix(cls, volume_config):
parts = volume_config.split(':')
if len(parts) > 3:
raise ConfigurationError(
@ -147,13 +144,11 @@ class VolumeSpec(namedtuple('_VolumeSpec', 'external internal mode')):
"external:internal[:mode]" % volume_config)
if len(parts) == 1:
external, internal = normalize_paths_for_engine(
None,
os.path.normpath(parts[0]))
external = None
internal = os.path.normpath(parts[0])
else:
external, internal = normalize_paths_for_engine(
os.path.normpath(parts[0]),
os.path.normpath(parts[1]))
external = os.path.normpath(parts[0])
internal = os.path.normpath(parts[1])
mode = 'rw'
if len(parts) == 3:
@ -161,13 +156,65 @@ class VolumeSpec(namedtuple('_VolumeSpec', 'external internal mode')):
return cls(external, internal, mode)
@classmethod
def _parse_win32(cls, volume_config, normalize):
# relative paths in windows expand to include the drive, eg C:\
# so we join the first 2 parts back together to count as one
mode = 'rw'
def separate_next_section(volume_config):
drive, tail = splitdrive(volume_config)
parts = tail.split(':', 1)
if drive:
parts[0] = drive + parts[0]
return parts
parts = separate_next_section(volume_config)
if len(parts) == 1:
internal = parts[0]
external = None
else:
external = parts[0]
parts = separate_next_section(parts[1])
external = os.path.normpath(external)
internal = parts[0]
if len(parts) > 1:
if ':' in parts[1]:
raise ConfigurationError(
"Volume %s has incorrect format, should be "
"external:internal[:mode]" % volume_config
)
mode = parts[1]
if normalize:
external = normalize_path_for_engine(external) if external else None
return cls(external, internal, mode)
@classmethod
def parse(cls, volume_config, normalize=False):
"""Parse a volume_config path and split it into external:internal[:mode]
parts to be returned as a valid VolumeSpec.
"""
if IS_WINDOWS_PLATFORM:
return cls._parse_win32(volume_config, normalize)
else:
return cls._parse_unix(volume_config)
def repr(self):
external = self.external + ':' if self.external else ''
return '{ext}{v.internal}:{v.mode}'.format(ext=external, v=self)
@property
def is_named_volume(self):
return self.external and not self.external.startswith(('.', '/', '~'))
res = self.external and not self.external.startswith(('.', '/', '~'))
if not IS_WINDOWS_PLATFORM:
return res
return (
res and not self.external.startswith('\\') and
not win32_root_path_pattern.match(self.external)
)
class ServiceLink(namedtuple('_ServiceLink', 'target alias')):
@ -187,3 +234,27 @@ class ServiceLink(namedtuple('_ServiceLink', 'target alias')):
@property
def merge_field(self):
return self.alias
class ServiceSecret(namedtuple('_ServiceSecret', 'source target uid gid mode')):
@classmethod
def parse(cls, spec):
if isinstance(spec, six.string_types):
return cls(spec, None, None, None, None)
return cls(
spec.get('source'),
spec.get('target'),
spec.get('uid'),
spec.get('gid'),
spec.get('mode'),
)
@property
def merge_field(self):
return self.source
def repr(self):
return dict(
[(k, v) for k, v in self._asdict().items() if v is not None]
)

View file

@ -14,6 +14,7 @@ from jsonschema import FormatChecker
from jsonschema import RefResolver
from jsonschema import ValidationError
from ..const import COMPOSEFILE_V1 as V1
from .errors import ConfigurationError
from .errors import VERSION_EXPLANATION
from .sort_services import get_service_name_from_network_mode
@ -62,23 +63,6 @@ def format_expose(instance):
return True
@FormatChecker.cls_checks(format="bool-value-in-mapping")
def format_boolean_in_environment(instance):
"""Check if there is a boolean in the mapping sections and display a warning.
Always return True here so the validation won't raise an error.
"""
if isinstance(instance, bool):
log.warn(
"There is a boolean value in the 'environment', 'labels', or "
"'extra_hosts' field of a service.\n"
"These sections only support string values.\n"
"Please add quotes to any boolean values to make them strings "
"(eg, 'True', 'false', 'yes', 'N', 'on', 'Off').\n"
"This warning will become an error in a future release. \r\n"
)
return True
def match_named_volumes(service_dict, project_volumes):
service_volumes = service_dict.get('volumes', [])
for volume_spec in service_volumes:
@ -187,12 +171,22 @@ def validate_network_mode(service_config, service_names):
"is undefined.".format(s=service_config, dep=dependency))
def validate_links(service_config, service_names):
for link in service_config.config.get('links', []):
if link.split(':')[0] not in service_names:
raise ConfigurationError(
"Service '{s.name}' has a link to service '{link}' which is "
"undefined.".format(s=service_config, link=link))
def validate_depends_on(service_config, service_names):
for dependency in service_config.config.get('depends_on', []):
deps = service_config.config.get('depends_on', {})
for dependency in deps.keys():
if dependency not in service_names:
raise ConfigurationError(
"Service '{s.name}' depends on service '{dep}' which is "
"undefined.".format(s=service_config, dep=dependency))
"undefined.".format(s=service_config, dep=dependency)
)
def get_unsupported_config_msg(path, error_key):
@ -209,7 +203,7 @@ def anglicize_json_type(json_type):
def is_service_dict_schema(schema_id):
return schema_id == 'fields_schema_v1.json' or schema_id == '#/properties/services'
return schema_id in ('config_schema_v1.json', '#/properties/services')
def handle_error_for_schema_with_id(error, path):
@ -221,45 +215,16 @@ def handle_error_for_schema_with_id(error, path):
list(error.instance)[0],
VALID_NAME_CHARS)
if schema_id == '#/definitions/constraints':
# Build context could in 'build' or 'build.context' and dockerfile could be
# in 'dockerfile' or 'build.dockerfile'
context = False
dockerfile = 'dockerfile' in error.instance
if 'build' in error.instance:
if isinstance(error.instance['build'], six.string_types):
context = True
else:
context = 'context' in error.instance['build']
dockerfile = dockerfile or 'dockerfile' in error.instance['build']
# TODO: only applies to v1
if 'image' in error.instance and context:
return (
"{} has both an image and build path specified. "
"A service can either be built to image or use an existing "
"image, not both.".format(path_string(path)))
if 'image' not in error.instance and not context:
return (
"{} has neither an image nor a build path specified. "
"At least one must be provided.".format(path_string(path)))
# TODO: only applies to v1
if 'image' in error.instance and dockerfile:
return (
"{} has both an image and alternate Dockerfile. "
"A service can either be built to image or use an existing "
"image, not both.".format(path_string(path)))
if error.validator == 'additionalProperties':
if schema_id == '#/definitions/service':
invalid_config_key = parse_key_from_error_msg(error)
return get_unsupported_config_msg(path, invalid_config_key)
if not error.path:
return '{}\n{}'.format(error.message, VERSION_EXPLANATION)
return '{}\n\n{}'.format(error.message, VERSION_EXPLANATION)
def handle_generic_service_error(error, path):
def handle_generic_error(error, path):
msg_format = None
error_msg = error.message
@ -365,75 +330,94 @@ def _parse_oneof_validator(error):
return (None, "contains an invalid type, it should be {}".format(valid_types))
def process_errors(errors, path_prefix=None):
"""jsonschema gives us an error tree full of information to explain what has
def process_service_constraint_errors(error, service_name, version):
if version == V1:
if 'image' in error.instance and 'build' in error.instance:
return (
"Service {} has both an image and build path specified. "
"A service can either be built to image or use an existing "
"image, not both.".format(service_name))
if 'image' in error.instance and 'dockerfile' in error.instance:
return (
"Service {} has both an image and alternate Dockerfile. "
"A service can either be built to image or use an existing "
"image, not both.".format(service_name))
if 'image' not in error.instance and 'build' not in error.instance:
return (
"Service {} has neither an image nor a build context specified. "
"At least one must be provided.".format(service_name))
def process_config_schema_errors(error):
path = list(error.path)
if 'id' in error.schema:
error_msg = handle_error_for_schema_with_id(error, path)
if error_msg:
return error_msg
return handle_generic_error(error, path)
def validate_against_config_schema(config_file):
schema = load_jsonschema(config_file.version)
format_checker = FormatChecker(["ports", "expose"])
validator = Draft4Validator(
schema,
resolver=RefResolver(get_resolver_path(), schema),
format_checker=format_checker)
handle_errors(
validator.iter_errors(config_file.config),
process_config_schema_errors,
config_file.filename)
def validate_service_constraints(config, service_name, version):
def handler(errors):
return process_service_constraint_errors(errors, service_name, version)
schema = load_jsonschema(version)
validator = Draft4Validator(schema['definitions']['constraints']['service'])
handle_errors(validator.iter_errors(config), handler, None)
def get_schema_path():
return os.path.dirname(os.path.abspath(__file__))
def load_jsonschema(version):
filename = os.path.join(
get_schema_path(),
"config_schema_v{0}.json".format(version))
with open(filename, "r") as fh:
return json.load(fh)
def get_resolver_path():
schema_path = get_schema_path()
if sys.platform == "win32":
scheme = "///"
# TODO: why is this necessary?
schema_path = schema_path.replace('\\', '/')
else:
scheme = "//"
return "file:{}{}/".format(scheme, schema_path)
def handle_errors(errors, format_error_func, filename):
"""jsonschema returns an error tree full of information to explain what has
gone wrong. Process each error and pull out relevant information and re-write
helpful error messages that are relevant.
"""
path_prefix = path_prefix or []
def format_error_message(error):
path = path_prefix + list(error.path)
if 'id' in error.schema:
error_msg = handle_error_for_schema_with_id(error, path)
if error_msg:
return error_msg
return handle_generic_service_error(error, path)
return '\n'.join(format_error_message(error) for error in errors)
def validate_against_fields_schema(config_file):
schema_filename = "fields_schema_v{0}.json".format(config_file.version)
_validate_against_schema(
config_file.config,
schema_filename,
format_checker=["ports", "expose", "bool-value-in-mapping"],
filename=config_file.filename)
def validate_against_service_schema(config, service_name, version):
_validate_against_schema(
config,
"service_schema_v{0}.json".format(version),
format_checker=["ports"],
path_prefix=[service_name])
def _validate_against_schema(
config,
schema_filename,
format_checker=(),
path_prefix=None,
filename=None):
config_source_dir = os.path.dirname(os.path.abspath(__file__))
if sys.platform == "win32":
file_pre_fix = "///"
config_source_dir = config_source_dir.replace('\\', '/')
else:
file_pre_fix = "//"
resolver_full_path = "file:{}{}/".format(file_pre_fix, config_source_dir)
schema_file = os.path.join(config_source_dir, schema_filename)
with open(schema_file, "r") as schema_fh:
schema = json.load(schema_fh)
resolver = RefResolver(resolver_full_path, schema)
validation_output = Draft4Validator(
schema,
resolver=resolver,
format_checker=FormatChecker(format_checker))
errors = [error for error in sorted(validation_output.iter_errors(config), key=str)]
errors = list(sorted(errors, key=str))
if not errors:
return
error_msg = process_errors(errors, path_prefix=path_prefix)
file_msg = " in file '{}'".format(filename) if filename else ''
raise ConfigurationError("Validation failed{}, reason(s):\n{}".format(
file_msg,
error_msg))
error_msg = '\n'.join(format_error_func(error) for error in errors)
raise ConfigurationError(
"The Compose file{file_msg} is invalid because:\n{error_msg}".format(
file_msg=" '{}'".format(filename) if filename else "",
error_msg=error_msg))

View file

@ -1,29 +1,41 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import sys
DEFAULT_TIMEOUT = 10
HTTP_TIMEOUT = int(os.environ.get('COMPOSE_HTTP_TIMEOUT', os.environ.get('DOCKER_CLIENT_TIMEOUT', 60)))
IMAGE_EVENTS = ['delete', 'import', 'pull', 'push', 'tag', 'untag']
HTTP_TIMEOUT = 60
IMAGE_EVENTS = ['delete', 'import', 'load', 'pull', 'push', 'save', 'tag', 'untag']
IS_WINDOWS_PLATFORM = (sys.platform == "win32")
LABEL_CONTAINER_NUMBER = 'com.docker.compose.container-number'
LABEL_ONE_OFF = 'com.docker.compose.oneoff'
LABEL_PROJECT = 'com.docker.compose.project'
LABEL_SERVICE = 'com.docker.compose.service'
LABEL_NETWORK = 'com.docker.compose.network'
LABEL_VERSION = 'com.docker.compose.version'
LABEL_VOLUME = 'com.docker.compose.volume'
LABEL_CONFIG_HASH = 'com.docker.compose.config-hash'
SECRETS_PATH = '/run/secrets'
COMPOSEFILE_V1 = '1'
COMPOSEFILE_V2_0 = '2.0'
COMPOSEFILE_V2_1 = '2.1'
COMPOSEFILE_V3_0 = '3.0'
COMPOSEFILE_V3_1 = '3.1'
API_VERSIONS = {
COMPOSEFILE_V1: '1.21',
COMPOSEFILE_V2_0: '1.22',
COMPOSEFILE_V2_1: '1.24',
COMPOSEFILE_V3_0: '1.25',
COMPOSEFILE_V3_1: '1.25',
}
API_VERSION_TO_ENGINE_VERSION = {
API_VERSIONS[COMPOSEFILE_V1]: '1.9.0',
API_VERSIONS[COMPOSEFILE_V2_0]: '1.10.0'
API_VERSIONS[COMPOSEFILE_V2_0]: '1.10.0',
API_VERSIONS[COMPOSEFILE_V2_1]: '1.12.0',
API_VERSIONS[COMPOSEFILE_V3_0]: '1.13.0',
API_VERSIONS[COMPOSEFILE_V3_1]: '1.13.0',
}

View file

@ -39,7 +39,7 @@ class Container(object):
@classmethod
def from_id(cls, client, id):
return cls(client, client.inspect_container(id))
return cls(client, client.inspect_container(id), has_been_inspected=True)
@classmethod
def create(cls, client, **options):
@ -163,7 +163,7 @@ class Container(object):
@property
def has_api_logs(self):
log_type = self.log_driver
return not log_type or log_type != 'none'
return not log_type or log_type in ('json-file', 'journald')
def attach_log_stream(self):
"""A log stream can only be attached if the container uses a json-file
@ -216,6 +216,12 @@ class Container(object):
def remove(self, **options):
return self.client.remove_container(self.id, **options)
def create_exec(self, command, **options):
return self.client.exec_create(self.id, command, **options)
def start_exec(self, exec_id, **options):
return self.client.exec_start(exec_id, **options)
def rename_to_tmp_name(self):
"""Rename the container to a hopefully unique temporary container name
by prepending the short id.

33
compose/errors.py Normal file
View file

@ -0,0 +1,33 @@
from __future__ import absolute_import
from __future__ import unicode_literals
class OperationFailedError(Exception):
def __init__(self, reason):
self.msg = reason
class StreamParseError(RuntimeError):
def __init__(self, reason):
self.msg = reason
class HealthCheckException(Exception):
def __init__(self, reason):
self.msg = reason
class HealthCheckFailed(HealthCheckException):
def __init__(self, container_id):
super(HealthCheckFailed, self).__init__(
'Container "{}" is unhealthy.'.format(container_id)
)
class NoHealthCheckConfigured(HealthCheckException):
def __init__(self, service_name):
super(NoHealthCheckConfigured, self).__init__(
'Service "{}" is missing a healthcheck configuration'.format(
service_name
)
)

View file

@ -4,18 +4,27 @@ from __future__ import unicode_literals
import logging
from docker.errors import NotFound
from docker.utils import create_ipam_config
from docker.utils import create_ipam_pool
from docker.types import IPAMConfig
from docker.types import IPAMPool
from docker.utils import version_gte
from docker.utils import version_lt
from .config import ConfigurationError
from .const import LABEL_NETWORK
from .const import LABEL_PROJECT
log = logging.getLogger(__name__)
OPTS_EXCEPTIONS = [
'com.docker.network.driver.overlay.vxlanid_list',
]
class Network(object):
def __init__(self, client, project, name, driver=None, driver_opts=None,
ipam=None, external_name=None):
ipam=None, external_name=None, internal=False, enable_ipv6=False,
labels=None):
self.client = client
self.project = project
self.name = name
@ -23,6 +32,9 @@ class Network(object):
self.driver_opts = driver_opts
self.ipam = create_ipam_config_from_dict(ipam)
self.external_name = external_name
self.internal = internal
self.enable_ipv6 = enable_ipv6
self.labels = labels
def ensure(self):
if self.external_name:
@ -45,14 +57,7 @@ class Network(object):
try:
data = self.inspect()
if self.driver and data['Driver'] != self.driver:
raise ConfigurationError(
'Network "{}" needs to be recreated - driver has changed'
.format(self.full_name))
if data['Options'] != (self.driver_opts or {}):
raise ConfigurationError(
'Network "{}" needs to be recreated - options have changed'
.format(self.full_name))
check_remote_network_config(data, self)
except NotFound:
driver_name = 'the default driver'
if self.driver:
@ -68,6 +73,10 @@ class Network(object):
driver=self.driver,
options=self.driver_opts,
ipam=self.ipam,
internal=self.internal,
enable_ipv6=self.enable_ipv6,
labels=self._labels,
attachable=version_gte(self.client._version, '1.24') or None,
)
def remove(self):
@ -87,15 +96,26 @@ class Network(object):
return self.external_name
return '{0}_{1}'.format(self.project, self.name)
@property
def _labels(self):
if version_lt(self.client._version, '1.23'):
return None
labels = self.labels.copy() if self.labels else {}
labels.update({
LABEL_PROJECT: self.project,
LABEL_NETWORK: self.name,
})
return labels
def create_ipam_config_from_dict(ipam_dict):
if not ipam_dict:
return None
return create_ipam_config(
return IPAMConfig(
driver=ipam_dict.get('driver'),
pool_configs=[
create_ipam_pool(
IPAMPool(
subnet=config.get('subnet'),
iprange=config.get('ip_range'),
gateway=config.get('gateway'),
@ -106,6 +126,24 @@ def create_ipam_config_from_dict(ipam_dict):
)
def check_remote_network_config(remote, local):
if local.driver and remote.get('Driver') != local.driver:
raise ConfigurationError(
'Network "{}" needs to be recreated - driver has changed'
.format(local.full_name)
)
local_opts = local.driver_opts or {}
remote_opts = remote.get('Options') or {}
for k in set.union(set(remote_opts.keys()), set(local_opts.keys())):
if k in OPTS_EXCEPTIONS:
continue
if remote_opts.get(k) != local_opts.get(k):
raise ConfigurationError(
'Network "{}" needs to be recreated - options have changed'
.format(local.full_name)
)
def build_networks(name, config_data, client):
network_config = config_data.networks or {}
networks = {
@ -115,6 +153,9 @@ def build_networks(name, config_data, client):
driver_opts=data.get('driver_opts'),
ipam=data.get('ipam'),
external_name=data.get('external_name'),
internal=data.get('internal'),
enable_ipv6=data.get('enable_ipv6'),
labels=data.get('labels'),
)
for network_name, data in network_config.items()
}
@ -149,7 +190,10 @@ class ProjectNetworks(object):
if not self.use_networking:
return
for network in self.networks.values():
network.remove()
try:
network.remove()
except NotFound:
log.warn("Network %s not found.", network.full_name)
def initialize(self):
if not self.use_networking:
@ -159,26 +203,26 @@ class ProjectNetworks(object):
network.ensure()
def get_network_aliases_for_service(service_dict):
def get_network_defs_for_service(service_dict):
if 'network_mode' in service_dict:
return {}
networks = service_dict.get('networks', {'default': None})
return dict(
(net, (config or {}).get('aliases', []))
(net, (config or {}))
for net, config in networks.items()
)
def get_network_names_for_service(service_dict):
return get_network_aliases_for_service(service_dict).keys()
return get_network_defs_for_service(service_dict).keys()
def get_networks(service_dict, network_definitions):
networks = {}
for name, aliases in get_network_aliases_for_service(service_dict).items():
for name, netdef in get_network_defs_for_service(service_dict).items():
network = network_definitions.get(name)
if network:
networks[network.full_name] = aliases
networks[network.full_name] = netdef
else:
raise ConfigurationError(
'Service "{}" uses an undefined network "{}"'

View file

@ -1,71 +1,199 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import operator
import sys
from threading import Thread
from docker.errors import APIError
from six.moves import _thread as thread
from six.moves.queue import Empty
from six.moves.queue import Queue
from compose.cli.signals import ShutdownException
from compose.errors import HealthCheckFailed
from compose.errors import NoHealthCheckConfigured
from compose.errors import OperationFailedError
from compose.utils import get_output_stream
def perform_operation(func, arg, callback, index):
try:
callback((index, func(arg)))
except Exception as e:
callback((index, e))
log = logging.getLogger(__name__)
STOP = object()
def parallel_execute(objects, func, index_func, msg):
"""For a given list of objects, call the callable passing in the first
object we give it.
def parallel_execute(objects, func, get_name, msg, get_deps=None):
"""Runs func on objects in parallel while ensuring that func is
ran on object only after it is ran on all its dependencies.
get_deps called on object must return a collection with its dependencies.
get_name called on object must return its name.
"""
objects = list(objects)
stream = get_output_stream(sys.stderr)
writer = ParallelStreamWriter(stream, msg)
for obj in objects:
writer.initialize(index_func(obj))
writer.initialize(get_name(obj))
q = Queue()
events = parallel_execute_iter(objects, func, get_deps)
# TODO: limit the number of threads #1828
for obj in objects:
t = Thread(
target=perform_operation,
args=(func, obj, q.put, index_func(obj)))
t.daemon = True
t.start()
done = 0
errors = {}
results = []
error_to_reraise = None
for obj, result, exception in events:
if exception is None:
writer.write(get_name(obj), 'done')
results.append(result)
elif isinstance(exception, APIError):
errors[get_name(obj)] = exception.explanation
writer.write(get_name(obj), 'error')
elif isinstance(exception, (OperationFailedError, HealthCheckFailed, NoHealthCheckConfigured)):
errors[get_name(obj)] = exception.msg
writer.write(get_name(obj), 'error')
elif isinstance(exception, UpstreamError):
writer.write(get_name(obj), 'error')
else:
errors[get_name(obj)] = exception
error_to_reraise = exception
for obj_name, error in errors.items():
stream.write("\nERROR: for {} {}\n".format(obj_name, error))
if error_to_reraise:
raise error_to_reraise
return results, errors
def _no_deps(x):
return []
class State(object):
"""
Holds the state of a partially-complete parallel operation.
state.started: objects being processed
state.finished: objects which have been processed
state.failed: objects which either failed or whose dependencies failed
"""
def __init__(self, objects):
self.objects = objects
self.started = set()
self.finished = set()
self.failed = set()
def is_done(self):
return len(self.finished) + len(self.failed) >= len(self.objects)
def pending(self):
return set(self.objects) - self.started - self.finished - self.failed
def parallel_execute_iter(objects, func, get_deps):
"""
Runs func on objects in parallel while ensuring that func is
ran on object only after it is ran on all its dependencies.
Returns an iterator of tuples which look like:
# if func returned normally when run on object
(object, result, None)
# if func raised an exception when run on object
(object, None, exception)
# if func raised an exception when run on one of object's dependencies
(object, None, UpstreamError())
"""
if get_deps is None:
get_deps = _no_deps
results = Queue()
state = State(objects)
while True:
feed_queue(objects, func, get_deps, results, state)
while done < len(objects):
try:
msg_index, result = q.get(timeout=1)
event = results.get(timeout=0.1)
except Empty:
continue
# See https://github.com/docker/compose/issues/189
except thread.error:
raise ShutdownException()
if isinstance(result, APIError):
errors[msg_index] = "error", result.explanation
writer.write(msg_index, 'error')
elif isinstance(result, Exception):
errors[msg_index] = "unexpected_exception", result
if event is STOP:
break
obj, _, exception = event
if exception is None:
log.debug('Finished processing: {}'.format(obj))
state.finished.add(obj)
else:
writer.write(msg_index, 'done')
done += 1
log.debug('Failed: {}'.format(obj))
state.failed.add(obj)
if not errors:
return
yield event
stream.write("\n")
for msg_index, (result, error) in errors.items():
stream.write("ERROR: for {} {} \n".format(msg_index, error))
if result == 'unexpected_exception':
raise error
def producer(obj, func, results):
"""
The entry point for a producer thread which runs func on a single object.
Places a tuple on the results queue once func has either returned or raised.
"""
try:
result = func(obj)
results.put((obj, result, None))
except Exception as e:
results.put((obj, None, e))
def feed_queue(objects, func, get_deps, results, state):
"""
Starts producer threads for any objects which are ready to be processed
(i.e. they have no dependencies which haven't been successfully processed).
Shortcuts any objects whose dependencies have failed and places an
(object, None, UpstreamError()) tuple on the results queue.
"""
pending = state.pending()
log.debug('Pending: {}'.format(pending))
for obj in pending:
deps = get_deps(obj)
try:
if any(dep[0] in state.failed for dep in deps):
log.debug('{} has upstream errors - not processing'.format(obj))
results.put((obj, None, UpstreamError()))
state.failed.add(obj)
elif all(
dep not in objects or (
dep in state.finished and (not ready_check or ready_check(dep))
) for dep, ready_check in deps
):
log.debug('Starting producer thread for {}'.format(obj))
t = Thread(target=producer, args=(obj, func, results))
t.daemon = True
t.start()
state.started.add(obj)
except (HealthCheckFailed, NoHealthCheckConfigured) as e:
log.debug(
'Healthcheck for service(s) upstream of {} failed - '
'not processing'.format(obj)
)
results.put((obj, None, e))
if state.is_done():
results.put(STOP)
class UpstreamError(Exception):
pass
class ParallelStreamWriter(object):
@ -81,11 +209,15 @@ class ParallelStreamWriter(object):
self.lines = []
def initialize(self, obj_index):
if self.msg is None:
return
self.lines.append(obj_index)
self.stream.write("{} {} ... \r\n".format(self.msg, obj_index))
self.stream.flush()
def write(self, obj_index, status):
if self.msg is None:
return
position = self.lines.index(obj_index)
diff = len(self.lines) - position
# move up
@ -111,10 +243,6 @@ def parallel_remove(containers, options):
parallel_operation(stopped_containers, 'remove', options, 'Removing')
def parallel_stop(containers, options):
parallel_operation(containers, 'stop', options, 'Stopping')
def parallel_start(containers, options):
parallel_operation(containers, 'start', options, 'Starting')
@ -129,7 +257,3 @@ def parallel_unpause(containers, options):
def parallel_kill(containers, options):
parallel_operation(containers, 'kill', options, 'Killing')
def parallel_restart(containers, options):
parallel_operation(containers, 'restart', options, 'Restarting')

View file

@ -32,12 +32,11 @@ def stream_output(output, stream):
if not image_id:
continue
if image_id in lines:
diff = len(lines) - lines[image_id]
else:
if image_id not in lines:
lines[image_id] = len(lines)
stream.write("\n")
diff = 0
diff = len(lines) - lines[image_id]
# move cursor up `diff` rows
stream.write("%c[%dA" % (27, diff))
@ -91,3 +90,22 @@ def print_output_event(event, stream, is_terminal):
stream.write("%s%s" % (event['stream'], terminator))
else:
stream.write("%s%s\n" % (status, terminator))
def get_digest_from_pull(events):
for event in events:
status = event.get('status')
if not status or 'Digest' not in status:
continue
_, digest = status.split(':', 1)
return digest.strip()
return None
def get_digest_from_push(events):
for event in events:
digest = event.get('aux', {}).get('Digest')
if digest:
return digest
return None

View file

@ -3,8 +3,10 @@ from __future__ import unicode_literals
import datetime
import logging
import operator
from functools import reduce
import enum
from docker.errors import APIError
from . import parallel
@ -12,7 +14,6 @@ from .config import ConfigurationError
from .config.config import V1
from .config.sort_services import get_container_name_from_network_mode
from .config.sort_services import get_service_name_from_network_mode
from .const import DEFAULT_TIMEOUT
from .const import IMAGE_EVENTS
from .const import LABEL_ONE_OFF
from .const import LABEL_PROJECT
@ -21,6 +22,7 @@ from .container import Container
from .network import build_networks
from .network import get_networks
from .network import ProjectNetworks
from .service import BuildAction
from .service import ContainerNetworkMode
from .service import ConvergenceStrategy
from .service import NetworkMode
@ -33,6 +35,24 @@ from .volume import ProjectVolumes
log = logging.getLogger(__name__)
@enum.unique
class OneOffFilter(enum.Enum):
include = 0
exclude = 1
only = 2
@classmethod
def update_labels(cls, value, labels):
if value == cls.only:
labels.append('{0}={1}'.format(LABEL_ONE_OFF, "True"))
elif value == cls.exclude:
labels.append('{0}={1}'.format(LABEL_ONE_OFF, "False"))
elif value == cls.include:
pass
else:
raise ValueError("Invalid value for one_off: {}".format(repr(value)))
class Project(object):
"""
A collection of services.
@ -44,11 +64,11 @@ class Project(object):
self.volumes = volumes or ProjectVolumes({})
self.networks = networks or ProjectNetworks({}, False)
def labels(self, one_off=False):
return [
'{0}={1}'.format(LABEL_PROJECT, self.name),
'{0}={1}'.format(LABEL_ONE_OFF, "True" if one_off else "False"),
]
def labels(self, one_off=OneOffFilter.exclude):
labels = ['{0}={1}'.format(LABEL_PROJECT, self.name)]
OneOffFilter.update_labels(one_off, labels)
return labels
@classmethod
def from_config(cls, name, config_data, client):
@ -84,6 +104,11 @@ class Project(object):
for volume_spec in service_dict.get('volumes', [])
]
secrets = get_secrets(
service_dict['name'],
service_dict.pop('secrets', None) or [],
config_data.secrets)
project.services.append(
Service(
service_dict.pop('name'),
@ -94,6 +119,7 @@ class Project(object):
links=links,
network_mode=network_mode,
volumes_from=volumes_from,
secrets=secrets,
**service_dict)
)
@ -199,13 +225,43 @@ class Project(object):
def start(self, service_names=None, **options):
containers = []
for service in self.get_services(service_names):
service_containers = service.start(**options)
def start_service(service):
service_containers = service.start(quiet=True, **options)
containers.extend(service_containers)
services = self.get_services(service_names)
def get_deps(service):
return {
(self.get_service(dep), config)
for dep, config in service.get_dependency_configs().items()
}
parallel.parallel_execute(
services,
start_service,
operator.attrgetter('name'),
'Starting',
get_deps)
return containers
def stop(self, service_names=None, **options):
parallel.parallel_stop(self.containers(service_names), options)
def stop(self, service_names=None, one_off=OneOffFilter.exclude, **options):
containers = self.containers(service_names, one_off=one_off)
def get_deps(container):
# actually returning inversed dependencies
return {(other, None) for other in containers
if container.service in
self.get_service(other.service).get_dependency_names()}
parallel.parallel_execute(
containers,
self.build_container_operation_with_timeout_func('stop', options),
operator.attrgetter('name'),
'Stopping',
get_deps)
def pause(self, service_names=None, **options):
containers = self.containers(service_names)
@ -220,12 +276,16 @@ class Project(object):
def kill(self, service_names=None, **options):
parallel.parallel_kill(self.containers(service_names), options)
def remove_stopped(self, service_names=None, **options):
parallel.parallel_remove(self.containers(service_names, stopped=True), options)
def remove_stopped(self, service_names=None, one_off=OneOffFilter.exclude, **options):
parallel.parallel_remove(self.containers(
service_names, stopped=True, one_off=one_off
), options)
def down(self, remove_image_type, include_volumes, remove_orphans=False):
self.stop(one_off=OneOffFilter.include)
self.find_orphan_containers(remove_orphans)
self.remove_stopped(v=include_volumes, one_off=OneOffFilter.include)
def down(self, remove_image_type, include_volumes):
self.stop()
self.remove_stopped(v=include_volumes)
self.networks.remove()
if include_volumes:
@ -239,7 +299,12 @@ class Project(object):
def restart(self, service_names=None, **options):
containers = self.containers(service_names, stopped=True)
parallel.parallel_restart(containers, options)
parallel.parallel_execute(
containers,
self.build_container_operation_with_timeout_func('restart', options),
operator.attrgetter('name'),
'Restarting')
return containers
def build(self, service_names=None, no_cache=False, pull=False, force_rm=False):
@ -249,19 +314,25 @@ class Project(object):
else:
log.info('%s uses an image, skipping' % service.name)
def create(self, service_names=None, strategy=ConvergenceStrategy.changed, do_build=True):
def create(
self,
service_names=None,
strategy=ConvergenceStrategy.changed,
do_build=BuildAction.none,
):
services = self.get_services_without_duplicate(service_names, include_deps=True)
for svc in services:
svc.ensure_image_exists(do_build=do_build)
plans = self._get_convergence_plans(services, strategy)
for service in services:
service.execute_convergence_plan(
plans[service.name],
do_build,
detached=True,
start=False)
def events(self):
def events(self, service_names=None):
def build_container_event(event, container):
time = datetime.datetime.fromtimestamp(event['time'])
time = time.replace(
@ -275,21 +346,29 @@ class Project(object):
'attributes': {
'name': container.name,
'image': event['from'],
}
},
'container': container,
}
service_names = set(self.service_names)
service_names = set(service_names or self.service_names)
for event in self.client.events(
filters={'label': self.labels()},
decode=True
):
if event['status'] in IMAGE_EVENTS:
# The first part of this condition is a guard against some events
# broadcasted by swarm that don't have a status field.
# See https://github.com/docker/compose/issues/3316
if 'status' not in event or event['status'] in IMAGE_EVENTS:
# We don't receive any image events because labels aren't applied
# to images
continue
# TODO: get labels from the API v1.22 , see github issue 2618
container = Container.from_id(self.client, event['id'])
try:
# this can fail if the container has been removed
container = Container.from_id(self.client, event['id'])
except APIError:
continue
if container.service not in service_names:
continue
yield build_container_event(event, container)
@ -298,25 +377,54 @@ class Project(object):
service_names=None,
start_deps=True,
strategy=ConvergenceStrategy.changed,
do_build=True,
timeout=DEFAULT_TIMEOUT,
detached=False):
do_build=BuildAction.none,
timeout=None,
detached=False,
remove_orphans=False):
warn_for_swarm_mode(self.client)
self.initialize()
self.find_orphan_containers(remove_orphans)
services = self.get_services_without_duplicate(
service_names,
include_deps=start_deps)
for svc in services:
svc.ensure_image_exists(do_build=do_build)
plans = self._get_convergence_plans(services, strategy)
return [
container
for service in services
for container in service.execute_convergence_plan(
def do(service):
return service.execute_convergence_plan(
plans[service.name],
do_build=do_build,
timeout=timeout,
detached=detached
)
def get_deps(service):
return {
(self.get_service(dep), config)
for dep, config in service.get_dependency_configs().items()
}
results, errors = parallel.parallel_execute(
services,
do,
operator.attrgetter('name'),
None,
get_deps
)
if errors:
raise ProjectError(
'Encountered errors while bringing up the project.'
)
return [
container
for svc_containers in results
if svc_containers is not None
for container in svc_containers
]
def initialize(self):
@ -350,23 +458,56 @@ class Project(object):
for service in self.get_services(service_names, include_deps=False):
service.pull(ignore_pull_failures)
def containers(self, service_names=None, stopped=False, one_off=False):
def push(self, service_names=None, ignore_push_failures=False):
for service in self.get_services(service_names, include_deps=False):
service.push(ignore_push_failures)
def _labeled_containers(self, stopped=False, one_off=OneOffFilter.exclude):
return list(filter(None, [
Container.from_ps(self.client, container)
for container in self.client.containers(
all=stopped,
filters={'label': self.labels(one_off=one_off)})])
)
def containers(self, service_names=None, stopped=False, one_off=OneOffFilter.exclude):
if service_names:
self.validate_service_names(service_names)
else:
service_names = self.service_names
containers = list(filter(None, [
Container.from_ps(self.client, container)
for container in self.client.containers(
all=stopped,
filters={'label': self.labels(one_off=one_off)})]))
containers = self._labeled_containers(stopped, one_off)
def matches_service_names(container):
return container.labels.get(LABEL_SERVICE) in service_names
return [c for c in containers if matches_service_names(c)]
def find_orphan_containers(self, remove_orphans):
def _find():
containers = self._labeled_containers()
for ctnr in containers:
service_name = ctnr.labels.get(LABEL_SERVICE)
if service_name not in self.service_names:
yield ctnr
orphans = list(_find())
if not orphans:
return
if remove_orphans:
for ctnr in orphans:
log.info('Removing orphan container "{0}"'.format(ctnr.name))
ctnr.kill()
ctnr.remove(force=True)
else:
log.warning(
'Found orphan containers ({0}) for this project. If '
'you removed or renamed this service in your compose '
'file, you can run this command with the '
'--remove-orphans flag to clean it up.'.format(
', '.join(["{}".format(ctnr.name) for ctnr in orphans])
)
)
def _inject_deps(self, acc, service):
dep_names = service.get_dependency_names()
@ -381,6 +522,14 @@ class Project(object):
dep_services.append(service)
return acc + dep_services
def build_container_operation_with_timeout_func(self, operation, options):
def container_operation_with_timeout(container):
if options.get('timeout') is None:
service = self.get_service(container.service)
options['timeout'] = service.stop_timeout(None)
return getattr(container, operation)(**options)
return container_operation_with_timeout
def get_volumes_from(project, service_dict):
volumes_from = service_dict.pop('volumes_from', None)
@ -410,6 +559,49 @@ def get_volumes_from(project, service_dict):
return [build_volume_from(vf) for vf in volumes_from]
def get_secrets(service, service_secrets, secret_defs):
secrets = []
for secret in service_secrets:
secret_def = secret_defs.get(secret.source)
if not secret_def:
raise ConfigurationError(
"Service \"{service}\" uses an undefined secret \"{secret}\" "
.format(service=service, secret=secret.source))
if secret_def.get('external_name'):
log.warn("Service \"{service}\" uses secret \"{secret}\" which is external. "
"External secrets are not available to containers created by "
"docker-compose.".format(service=service, secret=secret.source))
continue
if secret.uid or secret.gid or secret.mode:
log.warn("Service \"{service}\" uses secret \"{secret}\" with uid, "
"gid, or mode. These fields are not supported by this "
"implementation of the Compose file".format(
service=service, secret=secret.source))
secrets.append({'secret': secret, 'file': secret_def.get('file')})
return secrets
def warn_for_swarm_mode(client):
info = client.info()
if info.get('Swarm', {}).get('LocalNodeState') == 'active':
if info.get('ServerVersion', '').startswith('ucp'):
# UCP does multi-node scheduling with traditional Compose files.
return
log.warn(
"The Docker Engine you're using is running in swarm mode.\n\n"
"Compose does not use swarm mode to deploy services to multiple nodes in a swarm. "
"All containers will be scheduled on the current node.\n\n"
"To deploy your application across the swarm, "
"use `docker stack deploy`.\n"
)
class NoSuchService(Exception):
def __init__(self, name):
self.name = name
@ -417,3 +609,8 @@ class NoSuchService(Exception):
def __str__(self):
return self.msg
class ProjectError(Exception):
def __init__(self, msg):
self.msg = msg

View file

@ -10,15 +10,20 @@ from operator import attrgetter
import enum
import six
from docker.errors import APIError
from docker.utils import LogConfig
from docker.errors import ImageNotFound
from docker.errors import NotFound
from docker.types import LogConfig
from docker.utils.ports import build_port_bindings
from docker.utils.ports import split_port
from . import __version__
from . import const
from . import progress_stream
from .config import DOCKER_CONFIG_KEYS
from .config import merge_environment
from .config.types import VolumeSpec
from .const import DEFAULT_TIMEOUT
from .const import IS_WINDOWS_PLATFORM
from .const import LABEL_CONFIG_HASH
from .const import LABEL_CONTAINER_NUMBER
from .const import LABEL_ONE_OFF
@ -26,11 +31,15 @@ from .const import LABEL_PROJECT
from .const import LABEL_SERVICE
from .const import LABEL_VERSION
from .container import Container
from .errors import HealthCheckFailed
from .errors import NoHealthCheckConfigured
from .errors import OperationFailedError
from .parallel import parallel_execute
from .parallel import parallel_start
from .progress_stream import stream_output
from .progress_stream import StreamOutputError
from .utils import json_hash
from .utils import parse_seconds_float
log = logging.getLogger(__name__)
@ -40,25 +49,34 @@ DOCKER_START_KEYS = [
'cap_add',
'cap_drop',
'cgroup_parent',
'cpu_quota',
'devices',
'dns',
'dns_search',
'env_file',
'extra_hosts',
'group_add',
'ipc',
'read_only',
'log_driver',
'log_opt',
'mem_limit',
'memswap_limit',
'oom_score_adj',
'mem_swappiness',
'pid',
'privileged',
'restart',
'volumes_from',
'security_opt',
'cpu_quota',
'shm_size',
'sysctls',
'userns_mode',
'volumes_from',
]
CONDITION_STARTED = 'service_started'
CONDITION_HEALTHY = 'service_healthy'
class BuildError(Exception):
def __init__(self, service, reason):
@ -103,6 +121,14 @@ class ImageType(enum.Enum):
all = 2
@enum.unique
class BuildAction(enum.Enum):
"""Enumeration for the possible build actions."""
none = 0
force = 1
skip = 2
class Service(object):
def __init__(
self,
@ -114,6 +140,7 @@ class Service(object):
volumes_from=None,
network_mode=None,
networks=None,
secrets=None,
**options
):
self.name = name
@ -124,8 +151,12 @@ class Service(object):
self.volumes_from = volumes_from or []
self.network_mode = network_mode or NetworkMode(None)
self.networks = networks or {}
self.secrets = secrets or []
self.options = options
def __repr__(self):
return '<Service: {}>'.format(self.name)
def containers(self, stopped=False, one_off=False, filters={}):
filters.update({'label': self.labels(one_off=one_off)})
@ -151,7 +182,7 @@ class Service(object):
self.start_container_if_stopped(c, **options)
return containers
def scale(self, desired_num, timeout=DEFAULT_TIMEOUT):
def scale(self, desired_num, timeout=None):
"""
Adjusts the number of containers to the specified number and ensures
they are running.
@ -161,13 +192,13 @@ class Service(object):
- starts containers until there are at least `desired_num` running
- removes all stopped containers
"""
if self.custom_container_name() and desired_num > 1:
if self.custom_container_name and desired_num > 1:
log.warn('The "%s" service is using the custom container name "%s". '
'Docker requires each container to have a unique name. '
'Remove the custom name to scale the service.'
% (self.name, self.custom_container_name()))
% (self.name, self.custom_container_name))
if self.specifies_host_port():
if self.specifies_host_port() and desired_num > 1:
log.warn('The "%s" service specifies a port on the host. If multiple containers '
'for this service are created on a single host, the port will clash.'
% self.name)
@ -178,7 +209,7 @@ class Service(object):
return container
def stop_and_remove(container):
container.stop(timeout=timeout)
container.stop(timeout=self.stop_timeout(timeout))
container.remove()
running_containers = self.containers(stopped=False)
@ -195,7 +226,9 @@ class Service(object):
if num_running != len(all_containers):
# we have some stopped containers, let's start them up again
stopped_containers = sorted([c for c in all_containers if not c.is_running], key=attrgetter('number'))
stopped_containers = sorted(
(c for c in all_containers if not c.is_running),
key=attrgetter('number'))
num_stopped = len(stopped_containers)
@ -220,7 +253,7 @@ class Service(object):
parallel_execute(
container_numbers,
lambda n: create_and_start(service=self, number=n),
lambda n: n,
lambda n: self.get_container_name(n),
"Creating and starting"
)
@ -240,7 +273,6 @@ class Service(object):
def create_container(self,
one_off=False,
do_build=True,
previous_container=None,
number=None,
quiet=False,
@ -249,7 +281,9 @@ class Service(object):
Create a container for this service. If the image doesn't exist, attempt to pull
it.
"""
self.ensure_image_exists(do_build=do_build)
# This is only necessary for `scale` and `volumes_from`
# auto-creating containers to satisfy the dependency.
self.ensure_image_exists()
container_options = self._get_container_create_options(
override_options,
@ -261,31 +295,41 @@ class Service(object):
if 'name' in container_options and not quiet:
log.info("Creating %s" % container_options['name'])
return Container.create(self.client, **container_options)
try:
return Container.create(self.client, **container_options)
except APIError as ex:
raise OperationFailedError("Cannot create container for service %s: %s" %
(self.name, ex.explanation))
def ensure_image_exists(self, do_build=BuildAction.none):
if self.can_be_built() and do_build == BuildAction.force:
self.build()
return
def ensure_image_exists(self, do_build=True):
try:
self.image()
return
except NoSuchImageError:
pass
if self.can_be_built():
if do_build:
self.build()
else:
raise NeedsBuildError(self)
else:
if not self.can_be_built():
self.pull()
return
if do_build == BuildAction.skip:
raise NeedsBuildError(self)
self.build()
log.warn(
"Image for service {} was built because it did not already exist. To "
"rebuild this image you must use `docker-compose build` or "
"`docker-compose up --build`.".format(self.name))
def image(self):
try:
return self.client.inspect_image(self.image_name)
except APIError as e:
if e.response.status_code == 404 and e.explanation and 'No such image' in str(e.explanation):
raise NoSuchImageError("Image '{}' not found".format(self.image_name))
else:
raise
except ImageNotFound:
raise NoSuchImageError("Image '{}' not found".format(self.image_name))
@property
def image_name(self):
@ -340,15 +384,14 @@ class Service(object):
def execute_convergence_plan(self,
plan,
do_build=True,
timeout=DEFAULT_TIMEOUT,
timeout=None,
detached=False,
start=True):
(action, containers) = plan
should_attach_logs = not detached
if action == 'create':
container = self.create_container(do_build=do_build)
container = self.create_container()
if should_attach_logs:
container.attach_log_stream()
@ -362,7 +405,6 @@ class Service(object):
return [
self.recreate_container(
container,
do_build=do_build,
timeout=timeout,
attach_logs=should_attach_logs,
start_new_container=start
@ -389,8 +431,7 @@ class Service(object):
def recreate_container(
self,
container,
do_build=False,
timeout=DEFAULT_TIMEOUT,
timeout=None,
attach_logs=False,
start_new_container=True):
"""Recreate a container.
@ -401,10 +442,9 @@ class Service(object):
"""
log.info("Recreating %s" % container.name)
container.stop(timeout=timeout)
container.stop(timeout=self.stop_timeout(timeout))
container.rename_to_tmp_name()
new_container = self.create_container(
do_build=do_build,
previous_container=container,
number=container.labels.get(LABEL_CONTAINER_NUMBER),
quiet=True,
@ -416,36 +456,55 @@ class Service(object):
container.remove()
return new_container
def start_container_if_stopped(self, container, attach_logs=False):
def stop_timeout(self, timeout):
if timeout is not None:
return timeout
timeout = parse_seconds_float(self.options.get('stop_grace_period'))
if timeout is not None:
return timeout
return DEFAULT_TIMEOUT
def start_container_if_stopped(self, container, attach_logs=False, quiet=False):
if not container.is_running:
log.info("Starting %s" % container.name)
if not quiet:
log.info("Starting %s" % container.name)
if attach_logs:
container.attach_log_stream()
return self.start_container(container)
def start_container(self, container):
self.connect_container_to_networks(container)
container.start()
try:
container.start()
except APIError as ex:
raise OperationFailedError("Cannot start service %s: %s" % (self.name, ex.explanation))
return container
def connect_container_to_networks(self, container):
connected_networks = container.get('NetworkSettings.Networks')
for network, aliases in self.networks.items():
for network, netdefs in self.networks.items():
if network in connected_networks:
if short_id_alias_exists(container, network):
continue
self.client.disconnect_container_from_network(
container.id, network)
container.id,
network)
self.client.connect_container_to_network(
container.id, network,
aliases=list(self._get_aliases(container).union(aliases)),
aliases=self._get_aliases(netdefs, container),
ipv4_address=netdefs.get('ipv4_address', None),
ipv6_address=netdefs.get('ipv6_address', None),
links=self._get_links(False),
link_local_ips=netdefs.get('link_local_ips', None),
)
def remove_duplicate_containers(self, timeout=DEFAULT_TIMEOUT):
def remove_duplicate_containers(self, timeout=None):
for c in self.duplicate_containers():
log.info('Removing %s' % c.name)
c.stop(timeout=timeout)
c.stop(timeout=self.stop_timeout(timeout))
c.remove()
def duplicate_containers(self):
@ -472,7 +531,7 @@ class Service(object):
'image_id': self.image()['Id'],
'links': self.get_link_names(),
'net': self.network_mode.id,
'networks': list(self.networks.keys()),
'networks': self.networks,
'volumes_from': [
(v.source.name, v.mode)
for v in self.volumes_from if isinstance(v.source, Service)
@ -481,10 +540,38 @@ class Service(object):
def get_dependency_names(self):
net_name = self.network_mode.service_name
return (self.get_linked_service_names() +
self.get_volumes_from_names() +
([net_name] if net_name else []) +
self.options.get('depends_on', []))
return (
self.get_linked_service_names() +
self.get_volumes_from_names() +
([net_name] if net_name else []) +
list(self.options.get('depends_on', {}).keys())
)
def get_dependency_configs(self):
net_name = self.network_mode.service_name
configs = dict(
[(name, None) for name in self.get_linked_service_names()]
)
configs.update(dict(
[(name, None) for name in self.get_volumes_from_names()]
))
configs.update({net_name: None} if net_name else {})
configs.update(self.options.get('depends_on', {}))
for svc, config in self.options.get('depends_on', {}).items():
if config['condition'] == CONDITION_STARTED:
configs[svc] = lambda s: True
elif config['condition'] == CONDITION_HEALTHY:
configs[svc] = lambda s: s.is_healthy()
else:
# The config schema already prevents this, but it might be
# bypassed if Compose is called programmatically.
raise ValueError(
'depends_on condition "{}" is invalid.'.format(
config['condition']
)
)
return configs
def get_linked_service_names(self):
return [service.name for (service, _) in self.links]
@ -495,10 +582,6 @@ class Service(object):
def get_volumes_from_names(self):
return [s.source.name for s in self.volumes_from if isinstance(s.source, Service)]
def get_container_name(self, number, one_off=False):
# TODO: Implement issue #652 here
return build_container_name(self.project, self.name, number, one_off)
# TODO: this would benefit from github.com/docker/docker/pull/14699
# to remove the need to inspect every container
def _next_container_number(self, one_off=False):
@ -511,11 +594,32 @@ class Service(object):
numbers = [c.number for c in containers]
return 1 if not numbers else max(numbers) + 1
def _get_aliases(self, container):
if container.labels.get(LABEL_ONE_OFF) == "True":
return set()
def _get_aliases(self, network, container=None):
if container and container.labels.get(LABEL_ONE_OFF) == "True":
return []
return {self.name, container.short_id}
return list(
{self.name} |
({container.short_id} if container else set()) |
set(network.get('aliases', ()))
)
def build_default_networking_config(self):
if not self.networks:
return {}
network = self.networks[self.network_mode.id]
endpoint = {
'Aliases': self._get_aliases(network),
'IPAMConfig': {},
}
if network.get('ipv4_address'):
endpoint['IPAMConfig']['IPv4Address'] = network.get('ipv4_address')
if network.get('ipv6_address'):
endpoint['IPAMConfig']['IPv6Address'] = network.get('ipv6_address')
return {"EndpointsConfig": {self.network_mode.id: endpoint}}
def _get_links(self, link_to_self):
links = {}
@ -560,13 +664,10 @@ class Service(object):
for k in DOCKER_CONFIG_KEYS if k in self.options)
container_options.update(override_options)
if self.custom_container_name() and not one_off:
container_options['name'] = self.custom_container_name()
elif not container_options.get('name'):
if not container_options.get('name'):
container_options['name'] = self.get_container_name(number, one_off)
if 'detach' not in container_options:
container_options['detach'] = True
container_options.setdefault('detach', True)
# If a qualified hostname was given, split it into an
# unqualified hostname and a domainname unless domainname
@ -580,16 +681,9 @@ class Service(object):
container_options['domainname'] = parts[2]
if 'ports' in container_options or 'expose' in self.options:
ports = []
all_ports = container_options.get('ports', []) + self.options.get('expose', [])
for port_range in all_ports:
internal_range, _ = split_port(port_range)
for port in internal_range:
port = str(port)
if '/' in port:
port = tuple(port.split('/'))
ports.append(port)
container_options['ports'] = ports
container_options['ports'] = build_container_ports(
container_options,
self.options)
container_options['environment'] = merge_environment(
self.options.get('environment'),
@ -601,9 +695,14 @@ class Service(object):
override_options['binds'] = binds
container_options['environment'].update(affinity)
if 'volumes' in container_options:
container_options['volumes'] = dict(
(v.internal, {}) for v in container_options['volumes'])
container_options['volumes'] = dict(
(v.internal, {}) for v in container_options.get('volumes') or {})
secret_volumes = self.get_secret_volumes()
if secret_volumes:
override_options['binds'].extend(v.repr() for v in secret_volumes)
container_options['volumes'].update(
(v.internal, {}) for v in secret_volumes)
container_options['image'] = self.image_name
@ -621,6 +720,10 @@ class Service(object):
override_options,
one_off=one_off)
networking_config = self.build_default_networking_config()
if networking_config:
container_options['networking_config'] = networking_config
container_options['environment'] = format_environment(
container_options['environment'])
return container_options
@ -631,7 +734,7 @@ class Service(object):
logging_dict = options.get('logging', None)
log_config = get_log_config(logging_dict)
return self.client.create_host_config(
host_config = self.client.create_host_config(
links=self._get_links(link_to_self=one_off),
port_bindings=build_port_bindings(options.get('ports') or []),
binds=options.get('binds'),
@ -655,16 +758,38 @@ class Service(object):
ipc_mode=options.get('ipc'),
cgroup_parent=options.get('cgroup_parent'),
cpu_quota=options.get('cpu_quota'),
shm_size=options.get('shm_size'),
sysctls=options.get('sysctls'),
tmpfs=options.get('tmpfs'),
oom_score_adj=options.get('oom_score_adj'),
mem_swappiness=options.get('mem_swappiness'),
group_add=options.get('group_add'),
userns_mode=options.get('userns_mode')
)
# TODO: Add as an argument to create_host_config once it's supported
# in docker-py
host_config['Isolation'] = options.get('isolation')
return host_config
def get_secret_volumes(self):
def build_spec(secret):
target = '{}/{}'.format(
const.SECRETS_PATH,
secret['secret'].target or secret['secret'].source)
return VolumeSpec(secret['file'], target, 'ro')
return [build_spec(secret) for secret in self.secrets]
def build(self, no_cache=False, pull=False, force_rm=False):
log.info('Building %s' % self.name)
build_opts = self.options.get('build', {})
path = build_opts.get('context')
# python2 os.path() doesn't support unicode, so we need to encode it to
# a byte string
if not six.PY3:
# python2 os.stat() doesn't support unicode on some UNIX, so we
# encode it to a bytestring to be safe
if not six.PY3 and not IS_WINDOWS_PLATFORM:
path = path.encode('utf8')
build_output = self.client.build(
@ -712,9 +837,16 @@ class Service(object):
'{0}={1}'.format(LABEL_ONE_OFF, "True" if one_off else "False")
]
@property
def custom_container_name(self):
return self.options.get('container_name')
def get_container_name(self, number, one_off=False):
if self.custom_container_name and not one_off:
return self.custom_container_name
return build_container_name(self.project, self.name, number, one_off)
def remove_image(self, image_type):
if not image_type or image_type == ImageType.none:
return False
@ -760,20 +892,58 @@ class Service(object):
repo, tag, separator = parse_repository_tag(self.options['image'])
tag = tag or 'latest'
log.info('Pulling %s (%s%s%s)...' % (self.name, repo, separator, tag))
output = self.client.pull(
repo,
tag=tag,
stream=True,
)
try:
stream_output(output, sys.stdout)
except StreamOutputError as e:
output = self.client.pull(repo, tag=tag, stream=True)
return progress_stream.get_digest_from_pull(
stream_output(output, sys.stdout))
except (StreamOutputError, NotFound) as e:
if not ignore_pull_failures:
raise
else:
log.error(six.text_type(e))
def push(self, ignore_push_failures=False):
if 'image' not in self.options or 'build' not in self.options:
return
repo, tag, separator = parse_repository_tag(self.options['image'])
tag = tag or 'latest'
log.info('Pushing %s (%s%s%s)...' % (self.name, repo, separator, tag))
output = self.client.push(repo, tag=tag, stream=True)
try:
return progress_stream.get_digest_from_push(
stream_output(output, sys.stdout))
except StreamOutputError as e:
if not ignore_push_failures:
raise
else:
log.error(six.text_type(e))
def is_healthy(self):
""" Check that all containers for this service report healthy.
Returns false if at least one healthcheck is pending.
If an unhealthy container is detected, raise a HealthCheckFailed
exception.
"""
result = True
for ctnr in self.containers():
ctnr.inspect()
status = ctnr.get('State.Health.Status')
if status is None:
raise NoHealthCheckConfigured(self.name)
elif status == 'starting':
result = False
elif status == 'unhealthy':
raise HealthCheckFailed(ctnr.short_id)
return result
def short_id_alias_exists(container, network):
aliases = container.get(
'NetworkSettings.Networks.{net}.Aliases'.format(net=network)) or ()
return container.short_id in aliases
class NetworkMode(object):
"""A `standard` network mode (ex: host, bridge)"""
@ -1027,5 +1197,22 @@ def format_environment(environment):
def format_env(key, value):
if value is None:
return key
if isinstance(value, six.binary_type):
value = value.decode('utf-8')
return '{key}={value}'.format(key=key, value=value)
return [format_env(*item) for item in environment.items()]
# Ports
def build_container_ports(container_options, options):
ports = []
all_ports = container_options.get('ports', []) + options.get('expose', [])
for port_range in all_ports:
internal_range, _ = split_port(port_range)
for port in internal_range:
port = str(port)
if '/' in port:
port = tuple(port.split('/'))
ports.append(port)
return ports

96
compose/timeparse.py Normal file
View file

@ -0,0 +1,96 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
timeparse.py
(c) Will Roberts <wildwilhelm@gmail.com> 1 February, 2014
This is a vendored and modified copy of:
github.com/wroberts/pytimeparse @ cc0550d
It has been modified to mimic the behaviour of
https://golang.org/pkg/time/#ParseDuration
'''
# MIT LICENSE
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from __future__ import absolute_import
from __future__ import unicode_literals
import re
HOURS = r'(?P<hours>[\d.]+)h'
MINS = r'(?P<mins>[\d.]+)m'
SECS = r'(?P<secs>[\d.]+)s'
MILLI = r'(?P<milli>[\d.]+)ms'
MICRO = r'(?P<micro>[\d.]+)(?:us|µs)'
NANO = r'(?P<nano>[\d.]+)ns'
def opt(x):
return r'(?:{x})?'.format(x=x)
TIMEFORMAT = r'{HOURS}{MINS}{SECS}{MILLI}{MICRO}{NANO}'.format(
HOURS=opt(HOURS),
MINS=opt(MINS),
SECS=opt(SECS),
MILLI=opt(MILLI),
MICRO=opt(MICRO),
NANO=opt(NANO),
)
MULTIPLIERS = dict([
('hours', 60 * 60),
('mins', 60),
('secs', 1),
('milli', 1.0 / 1000),
('micro', 1.0 / 1000.0 / 1000),
('nano', 1.0 / 1000.0 / 1000.0 / 1000.0),
])
def timeparse(sval):
"""Parse a time expression, returning it as a number of seconds. If
possible, the return value will be an `int`; if this is not
possible, the return will be a `float`. Returns `None` if a time
expression cannot be parsed from the given string.
Arguments:
- `sval`: the string value to parse
>>> timeparse('1m24s')
84
>>> timeparse('1.2 minutes')
72
>>> timeparse('1.2 seconds')
1.2
"""
match = re.match(r'\s*' + TIMEFORMAT + r'\s*$', sval, re.I)
if not match or not match.group(0).strip():
return
mdict = match.groupdict()
return sum(
MULTIPLIERS[k] * cast(v) for (k, v) in mdict.items() if v is not None)
def cast(value):
return int(value, 10) if value.isdigit() else float(value)

View file

@ -5,11 +5,17 @@ import codecs
import hashlib
import json
import json.decoder
import logging
import ntpath
import six
from .errors import StreamParseError
from .timeparse import timeparse
json_decoder = json.JSONDecoder()
log = logging.getLogger(__name__)
def get_output_stream(stream):
@ -60,13 +66,21 @@ def split_buffer(stream, splitter=None, decoder=lambda a: a):
yield item
if buffered:
yield decoder(buffered)
try:
yield decoder(buffered)
except Exception as e:
log.error(
'Compose tried decoding the following data chunk, but failed:'
'\n%s' % repr(buffered)
)
raise StreamParseError(e)
def json_splitter(buffer):
"""Attempt to parse a json object from a buffer. If there is at least one
object, return it and the rest of the buffer, otherwise return None.
"""
buffer = buffer.strip()
try:
obj, index = json_decoder.raw_decode(buffer)
rest = buffer[json.decoder.WHITESPACE.match(buffer, index).end():]
@ -94,5 +108,28 @@ def microseconds_from_time_nano(time_nano):
return int(time_nano % 1000000000 / 1000)
def nanoseconds_from_time_seconds(time_seconds):
return time_seconds * 1000000000
def parse_seconds_float(value):
return timeparse(value or '')
def parse_nanoseconds_int(value):
parsed = timeparse(value or '')
if parsed is None:
return None
return int(parsed * 1000000000)
def build_string_dict(source_dict):
return dict((k, str(v)) for k, v in source_dict.items())
return dict((k, str(v if v is not None else '')) for k, v in source_dict.items())
def splitdrive(path):
if len(path) == 0:
return ('', '')
if path[0] in ['.', '\\', '/', '~']:
return ('', path)
return ntpath.splitdrive(path)

View file

@ -3,27 +3,30 @@ from __future__ import unicode_literals
import logging
from docker.errors import APIError
from docker.errors import NotFound
from docker.utils import version_lt
from .config import ConfigurationError
from .const import LABEL_PROJECT
from .const import LABEL_VOLUME
log = logging.getLogger(__name__)
class Volume(object):
def __init__(self, client, project, name, driver=None, driver_opts=None,
external_name=None):
external_name=None, labels=None):
self.client = client
self.project = project
self.name = name
self.driver = driver
self.driver_opts = driver_opts
self.external_name = external_name
self.labels = labels
def create(self):
return self.client.create_volume(
self.full_name, self.driver, self.driver_opts
self.full_name, self.driver, self.driver_opts, labels=self._labels
)
def remove(self):
@ -53,6 +56,17 @@ class Volume(object):
return self.external_name
return '{0}_{1}'.format(self.project, self.name)
@property
def _labels(self):
if version_lt(self.client._version, '1.23'):
return None
labels = self.labels.copy() if self.labels else {}
labels.update({
LABEL_PROJECT: self.project,
LABEL_VOLUME: self.name,
})
return labels
class ProjectVolumes(object):
@ -69,7 +83,8 @@ class ProjectVolumes(object):
name=vol_name,
driver=data.get('driver'),
driver_opts=data.get('driver_opts'),
external_name=data.get('external_name')
external_name=data.get('external_name'),
labels=data.get('labels')
)
for vol_name, data in config_volumes.items()
}
@ -77,17 +92,21 @@ class ProjectVolumes(object):
def remove(self):
for volume in self.volumes.values():
volume.remove()
try:
volume.remove()
except NotFound:
log.warn("Volume %s not found.", volume.full_name)
def initialize(self):
try:
for volume in self.volumes.values():
volume_exists = volume.exists()
if volume.external:
log.debug(
'Volume {0} declared as external. No new '
'volume will be created.'.format(volume.name)
)
if not volume.exists():
if not volume_exists:
raise ConfigurationError(
'Volume {name} declared as external, but could'
' not be found. Please create the volume manually'
@ -97,28 +116,32 @@ class ProjectVolumes(object):
)
)
continue
log.info(
'Creating volume "{0}" with {1} driver'.format(
volume.full_name, volume.driver or 'default'
if not volume_exists:
log.info(
'Creating volume "{0}" with {1} driver'.format(
volume.full_name, volume.driver or 'default'
)
)
)
volume.create()
volume.create()
else:
driver = volume.inspect()['Driver']
if volume.driver is not None and driver != volume.driver:
raise ConfigurationError(
'Configuration for volume {0} specifies driver '
'{1}, but a volume with the same name uses a '
'different driver ({3}). If you wish to use the '
'new configuration, please remove the existing '
'volume "{2}" first:\n'
'$ docker volume rm {2}'.format(
volume.name, volume.driver, volume.full_name,
volume.inspect()['Driver']
)
)
except NotFound:
raise ConfigurationError(
'Volume %s specifies nonexistent driver %s' % (volume.name, volume.driver)
)
except APIError as e:
if 'Choose a different volume name' in str(e):
raise ConfigurationError(
'Configuration for volume {0} specifies driver {1}, but '
'a volume with the same name uses a different driver '
'({3}). If you wish to use the new configuration, please '
'remove the existing volume "{2}" first:\n'
'$ docker volume rm {2}'.format(
volume.name, volume.driver, volume.full_name,
volume.inspect()['Driver']
)
)
def namespace_spec(self, volume_spec):
if not volume_spec.is_named_volume:

View file

@ -18,7 +18,22 @@
__docker_compose_q() {
docker-compose 2>/dev/null ${compose_file:+-f $compose_file} ${compose_project:+-p $compose_project} "$@"
docker-compose 2>/dev/null $daemon_options "$@"
}
# Transforms a multiline list of strings into a single line string
# with the words separated by "|".
__docker_compose_to_alternatives() {
local parts=( $1 )
local IFS='|'
echo "${parts[*]}"
}
# Transforms a multiline list of options into an extglob pattern
# suitable for use in case statements.
__docker_compose_to_extglob() {
local extglob=$( __docker_compose_to_alternatives "$1" )
echo "@($extglob)"
}
# suppress trailing whitespace
@ -27,20 +42,6 @@ __docker_compose_nospace() {
type compopt &>/dev/null && compopt -o nospace
}
# For compatibility reasons, Compose and therefore its completion supports several
# stack compositon files as listed here, in descending priority.
# Support for these filenames might be dropped in some future version.
__docker_compose_compose_file() {
local file
for file in docker-compose.y{,a}ml ; do
[ -e $file ] && {
echo $file
return
}
done
echo docker-compose.yml
}
# Extracts all service names from the compose file.
___docker_compose_all_services_in_compose_file() {
__docker_compose_q config --services
@ -108,6 +109,18 @@ _docker_compose_build() {
}
_docker_compose_bundle() {
case "$prev" in
--output|-o)
_filedir
return
;;
esac
COMPREPLY=( $( compgen -W "--push-images --help --output -o" -- "$cur" ) )
}
_docker_compose_config() {
COMPREPLY=( $( compgen -W "--help --quiet -q --services" -- "$cur" ) )
}
@ -127,18 +140,22 @@ _docker_compose_create() {
_docker_compose_docker_compose() {
case "$prev" in
--tlscacert|--tlscert|--tlskey)
_filedir
return
;;
--file|-f)
_filedir "y?(a)ml"
return
;;
--project-name|-p)
$(__docker_compose_to_extglob "$daemon_options_with_args") )
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--file -f --help -h --project-name -p --verbose --version -v" -- "$cur" ) )
COMPREPLY=( $( compgen -W "$daemon_boolean_options $daemon_options_with_args --help -h --verbose --version -v" -- "$cur" ) )
;;
*)
COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
@ -157,7 +174,7 @@ _docker_compose_down() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help --rmi --volumes -v" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--help --rmi --volumes -v --remove-orphans" -- "$cur" ) )
;;
esac
}
@ -181,6 +198,24 @@ _docker_compose_events() {
}
_docker_compose_exec() {
case "$prev" in
--index|--user)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "-d --help --index --privileged -T --user" -- "$cur" ) )
;;
*)
__docker_compose_services_running
;;
esac
}
_docker_compose_help() {
COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
}
@ -206,9 +241,15 @@ _docker_compose_kill() {
_docker_compose_logs() {
case "$prev" in
--tail)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help --no-color" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--follow -f --help --no-color --tail --timestamps -t" -- "$cur" ) )
;;
*)
__docker_compose_services_all
@ -275,6 +316,18 @@ _docker_compose_pull() {
}
_docker_compose_push() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help --ignore-push-failures" -- "$cur" ) )
;;
*)
__docker_compose_services_all
;;
esac
}
_docker_compose_restart() {
case "$prev" in
--timeout|-t)
@ -312,14 +365,14 @@ _docker_compose_run() {
__docker_compose_nospace
return
;;
--entrypoint|--name|--user|-u)
--entrypoint|--name|--user|-u|--workdir|-w)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "-d --entrypoint -e --help --name --no-deps --publish -p --rm --service-ports -T --user -u" -- "$cur" ) )
COMPREPLY=( $( compgen -W "-d --entrypoint -e --help --name --no-deps --publish -p --rm --service-ports -T --user -u --workdir -w" -- "$cur" ) )
;;
*)
__docker_compose_services_all
@ -381,6 +434,18 @@ _docker_compose_stop() {
}
_docker_compose_top() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
;;
*)
__docker_compose_services_running
;;
esac
}
_docker_compose_unpause() {
case "$cur" in
-*)
@ -402,7 +467,7 @@ _docker_compose_up() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--abort-on-container-exit -d --force-recreate --help --no-build --no-color --no-deps --no-recreate --timeout -t" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--abort-on-container-exit --build -d --force-recreate --help --no-build --no-color --no-deps --no-recreate --timeout -t --remove-orphans" -- "$cur" ) )
;;
*)
__docker_compose_services_all
@ -426,10 +491,12 @@ _docker_compose() {
local commands=(
build
bundle
config
create
down
events
exec
help
kill
logs
@ -437,17 +504,35 @@ _docker_compose() {
port
ps
pull
push
restart
rm
run
scale
start
stop
top
unpause
up
version
)
# options for the docker daemon that have to be passed to secondary calls to
# docker-compose executed by this script
local daemon_boolean_options="
--skip-hostname-check
--tls
--tlsverify
"
local daemon_options_with_args="
--file -f
--host -H
--project-name -p
--tlscacert
--tlscert
--tlskey
"
COMPREPLY=()
local cur prev words cword
_get_comp_words_by_ref -n : cur prev words cword
@ -455,17 +540,19 @@ _docker_compose() {
# search subcommand and invoke its handler.
# special treatment of some top-level options
local command='docker_compose'
local daemon_options=()
local counter=1
local compose_file compose_project
while [ $counter -lt $cword ]; do
case "${words[$counter]}" in
--file|-f)
(( counter++ ))
compose_file="${words[$counter]}"
$(__docker_compose_to_extglob "$daemon_boolean_options") )
local opt=${words[counter]}
daemon_options+=($opt)
;;
--project-name|p)
(( counter++ ))
compose_project="${words[$counter]}"
$(__docker_compose_to_extglob "$daemon_options_with_args") )
local opt=${words[counter]}
local arg=${words[++counter]}
daemon_options+=($opt $arg)
;;
-*)
;;

View file

@ -19,52 +19,49 @@
# * @felixr docker zsh completion script : https://github.com/felixr/docker-zsh-completion
# -------------------------------------------------------------------------
# For compatibility reasons, Compose and therefore its completion supports several
# stack compositon files as listed here, in descending priority.
# Support for these filenames might be dropped in some future version.
__docker-compose_compose_file() {
local file
for file in docker-compose.y{,a}ml ; do
[ -e $file ] && {
echo $file
return
}
done
echo docker-compose.yml
__docker-compose_q() {
docker-compose 2>/dev/null $compose_options "$@"
}
# Extracts all service names from docker-compose.yml.
___docker-compose_all_services_in_compose_file() {
# All services defined in docker-compose.yml
__docker-compose_all_services_in_compose_file() {
local already_selected
local -a services
already_selected=$(echo $words | tr " " "|")
awk -F: '/^[a-zA-Z0-9]/{print $1}' "${compose_file:-$(__docker-compose_compose_file)}" 2>/dev/null | grep -Ev "$already_selected"
__docker-compose_q config --services \
| grep -Ev "^(${already_selected})$"
}
# All services, even those without an existing container
__docker-compose_services_all() {
[[ $PREFIX = -* ]] && return 1
integer ret=1
services=$(___docker-compose_all_services_in_compose_file)
services=$(__docker-compose_all_services_in_compose_file)
_alternative "args:services:($services)" && ret=0
return ret
}
# All services that have an entry with the given key in their docker-compose.yml section
___docker-compose_services_with_key() {
__docker-compose_services_with_key() {
local already_selected
local -a buildable
already_selected=$(echo $words | tr " " "|")
# flatten sections to one line, then filter lines containing the key and return section name.
awk '/^[a-zA-Z0-9]/{printf "\n"};{printf $0;next;}' "${compose_file:-$(__docker-compose_compose_file)}" 2>/dev/null | awk -F: -v key=": +$1:" '$0 ~ key {print $1}' 2>/dev/null | grep -Ev "$already_selected"
__docker-compose_q config \
| sed -n -e '/^services:/,/^[^ ]/p' \
| sed -n 's/^ //p' \
| awk '/^[a-zA-Z0-9]/{printf "\n"};{printf $0;next;}' \
| grep " \+$1:" \
| cut -d: -f1 \
| grep -Ev "^(${already_selected})$"
}
# All services that are defined by a Dockerfile reference
__docker-compose_services_from_build() {
[[ $PREFIX = -* ]] && return 1
integer ret=1
buildable=$(___docker-compose_services_with_key build)
buildable=$(__docker-compose_services_with_key build)
_alternative "args:buildable services:($buildable)" && ret=0
return ret
@ -74,7 +71,7 @@ __docker-compose_services_from_build() {
__docker-compose_services_from_image() {
[[ $PREFIX = -* ]] && return 1
integer ret=1
pullable=$(___docker-compose_services_with_key image)
pullable=$(__docker-compose_services_with_key image)
_alternative "args:pullable services:($pullable)" && ret=0
return ret
@ -96,7 +93,7 @@ __docker-compose_get_services() {
shift
[[ $kind =~ (stopped|all) ]] && args=($args -a)
lines=(${(f)"$(_call_program commands docker ps $args)"})
lines=(${(f)"$(_call_program commands docker $docker_options ps $args)"})
services=(${(f)"$(_call_program commands docker-compose 2>/dev/null $compose_options ps -q)"})
# Parse header line to find columns
@ -185,7 +182,17 @@ __docker-compose_commands() {
}
__docker-compose_subcommand() {
local opts_help='(: -)--help[Print usage]'
local opts_help opts_force_recreate opts_no_recreate opts_no_build opts_remove_orphans opts_timeout opts_no_color opts_no_deps
opts_help='(: -)--help[Print usage]'
opts_force_recreate="(--no-recreate)--force-recreate[Recreate containers even if their configuration and image haven't changed. Incompatible with --no-recreate.]"
opts_no_recreate="(--force-recreate)--no-recreate[If containers already exist, don't recreate them. Incompatible with --force-recreate.]"
opts_no_build="(--build)--no-build[Don't build an image, even if it's missing.]"
opts_remove_orphans="--remove-orphans[Remove containers for services not defined in the Compose file]"
opts_timeout=('(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: ")
opts_no_color='--no-color[Produce monochrome output.]'
opts_no_deps="--no-deps[Don't start linked services.]"
integer ret=1
case "$words[1]" in
@ -193,10 +200,16 @@ __docker-compose_subcommand() {
_arguments \
$opts_help \
'--force-rm[Always remove intermediate containers.]' \
'--no-cache[Do not use cache when building the image]' \
'--no-cache[Do not use cache when building the image.]' \
'--pull[Always attempt to pull a newer version of the image.]' \
'*:services:__docker-compose_services_from_build' && ret=0
;;
(bundle)
_arguments \
$opts_help \
'--push-images[Automatically push images for any services which have a `build` option specified.]' \
'(--output -o)'{--output,-o}'[Path to write the bundle file to. Defaults to "<project name>.dab".]:file:_files' && ret=0
;;
(config)
_arguments \
$opts_help \
@ -206,23 +219,37 @@ __docker-compose_subcommand() {
(create)
_arguments \
$opts_help \
"(--no-recreate --no-build)--force-recreate[Recreate containers even if their configuration and image haven't changed. Incompatible with --no-recreate.]" \
"(--force-recreate)--no-build[If containers already exist, don't recreate them. Incompatible with --force-recreate.]" \
"(--force-recreate)--no-recreate[Don't build an image, even if it's missing]" \
$opts_force_recreate \
$opts_no_recreate \
$opts_no_build \
"(--no-build)--build[Build images before creating containers.]" \
'*:services:__docker-compose_services_all' && ret=0
;;
(down)
_arguments \
$opts_help \
"--rmi[Remove images, type may be one of: 'all' to remove all images, or 'local' to remove only images that don't have an custom name set by the 'image' field]:type:(all local)" \
'(-v --volumes)'{-v,--volumes}"[Remove data volumes]" && ret=0
"--rmi[Remove images. Type must be one of: 'all': Remove all images used by any service. 'local': Remove only images that don't have a custom tag set by the \`image\` field.]:type:(all local)" \
'(-v --volumes)'{-v,--volumes}"[Remove named volumes declared in the \`volumes\` section of the Compose file and anonymous volumes attached to containers.]" \
$opts_remove_orphans && ret=0
;;
(events)
_arguments \
$opts_help \
'--json[Output events as a stream of json objects.]' \
'--json[Output events as a stream of json objects]' \
'*:services:__docker-compose_services_all' && ret=0
;;
(exec)
_arguments \
$opts_help \
'-d[Detached mode: Run command in the background.]' \
'--privileged[Give extended privileges to the process.]' \
'--user=[Run the command as this user.]:username:_users' \
'-T[Disable pseudo-tty allocation. By default `docker-compose exec` allocates a TTY.]' \
'--index=[Index of the container if there are multiple instances of a service \[default: 1\]]:index: ' \
'(-):running services:__docker-compose_runningservices' \
'(-):command: _command_names -e' \
'*::arguments: _normal' && ret=0
;;
(help)
_arguments ':subcommand:__docker-compose_commands' && ret=0
;;
@ -235,7 +262,10 @@ __docker-compose_subcommand() {
(logs)
_arguments \
$opts_help \
'--no-color[Produce monochrome output.]' \
'(-f --follow)'{-f,--follow}'[Follow log output]' \
$opts_no_color \
'--tail=[Number of lines to show from the end of the logs for each container.]:number of lines: ' \
'(-t --timestamps)'{-t,--timestamps}'[Show timestamps]' \
'*:services:__docker-compose_services_all' && ret=0
;;
(pause)
@ -246,8 +276,8 @@ __docker-compose_subcommand() {
(port)
_arguments \
$opts_help \
'--protocol=-[tcp or udap (defaults to tcp)]:protocol:(tcp udp)' \
'--index=-[index of the container if there are mutiple instances of a service (defaults to 1)]:index: ' \
'--protocol=[tcp or udp \[default: tcp\]]:protocol:(tcp udp)' \
'--index=[index of the container if there are multiple instances of a service \[default: 1\]]:index: ' \
'1:running services:__docker-compose_runningservices' \
'2:port:_ports' && ret=0
;;
@ -263,26 +293,33 @@ __docker-compose_subcommand() {
'--ignore-pull-failures[Pull what it can and ignores images with pull failures.]' \
'*:services:__docker-compose_services_from_image' && ret=0
;;
(push)
_arguments \
$opts_help \
'--ignore-push-failures[Push what it can and ignores images with push failures.]' \
'*:services:__docker-compose_services' && ret=0
;;
(rm)
_arguments \
$opts_help \
'(-f --force)'{-f,--force}"[Don't ask to confirm removal]" \
'-v[Remove volumes associated with containers]' \
'-v[Remove any anonymous volumes attached to containers]' \
'*:stopped services:__docker-compose_stoppedservices' && ret=0
;;
(run)
_arguments \
$opts_help \
'-d[Detached mode: Run container in the background, print new container name.]' \
'--name[Assign a name to the container]:name: ' \
'--entrypoint[Overwrite the entrypoint of the image.]:entry point: ' \
'*-e[KEY=VAL Set an environment variable (can be used multiple times)]:environment variable KEY=VAL: ' \
'(-u --user)'{-u,--user=-}'[Run as specified username or uid]:username or uid:_users' \
"--no-deps[Don't start linked services.]" \
'--entrypoint[Overwrite the entrypoint of the image.]:entry point: ' \
'--name=[Assign a name to the container]:name: ' \
$opts_no_deps \
'(-p --publish)'{-p,--publish=}"[Publish a container's port(s) to the host]" \
'--rm[Remove container after run. Ignored in detached mode.]' \
"--service-ports[Run command with the service's ports enabled and mapped to the host.]" \
'(-p --publish)'{-p,--publish=-}"[Run command with manually mapped container's port(s) to the host.]" \
'-T[Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY.]' \
'(-u --user)'{-u,--user=}'[Run as specified username or uid]:username or uid:_users' \
'(-w --workdir)'{-w,--workdir=}'[Working directory inside the container]:workdir: ' \
'(-):services:__docker-compose_services' \
'(-):command: _command_names -e' \
'*::arguments: _normal' && ret=0
@ -290,7 +327,7 @@ __docker-compose_subcommand() {
(scale)
_arguments \
$opts_help \
'(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: " \
$opts_timeout \
'*:running services:__docker-compose_runningservices' && ret=0
;;
(start)
@ -301,7 +338,12 @@ __docker-compose_subcommand() {
(stop|restart)
_arguments \
$opts_help \
'(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: " \
$opts_timeout \
'*:running services:__docker-compose_runningservices' && ret=0
;;
(top)
_arguments \
$opts_help \
'*:running services:__docker-compose_runningservices' && ret=0
;;
(unpause)
@ -312,14 +354,16 @@ __docker-compose_subcommand() {
(up)
_arguments \
$opts_help \
'(--abort-on-container-exit)-d[Detached mode: Run containers in the background, print new container names.]' \
'--no-color[Produce monochrome output.]' \
"--no-deps[Don't start linked services.]" \
"--force-recreate[Recreate containers even if their configuration and image haven't changed. Incompatible with --no-recreate.]" \
"--no-recreate[If containers already exist, don't recreate them.]" \
"--no-build[Don't build an image, even if it's missing]" \
'(--abort-on-container-exit)-d[Detached mode: Run containers in the background, print new container names. Incompatible with --abort-on-container-exit.]' \
$opts_no_color \
$opts_no_deps \
$opts_force_recreate \
$opts_no_recreate \
$opts_no_build \
"(--no-build)--build[Build images before starting containers.]" \
"(-d)--abort-on-container-exit[Stops all containers if any container was stopped. Incompatible with -d.]" \
'(-t --timeout)'{-t,--timeout}"[Specify a shutdown timeout in seconds. (default: 10)]:seconds: " \
'(-t --timeout)'{-t,--timeout}"[Use this timeout in seconds for container shutdown when attached or when containers are already running. (default: 10)]:seconds: " \
$opts_remove_orphans \
'*:services:__docker-compose_services_all' && ret=0
;;
(version)
@ -347,18 +391,67 @@ _docker-compose() {
integer ret=1
typeset -A opt_args
local file_description
if [[ -n ${words[(r)-f]} || -n ${words[(r)--file]} ]] ; then
file_description="Specify an override docker-compose file (default: docker-compose.override.yml)"
else
file_description="Specify an alternate docker-compose file (default: docker-compose.yml)"
fi
_arguments -C \
'(- :)'{-h,--help}'[Get help]' \
'*'{-f,--file}"[${file_description}]:file:_files -g '*.yml'" \
'(-p --project-name)'{-p,--project-name}'[Specify an alternate project name (default: directory name)]:project name:' \
'--verbose[Show more output]' \
'(- :)'{-v,--version}'[Print version and exit]' \
'(-f --file)'{-f,--file}'[Specify an alternate docker-compose file (default: docker-compose.yml)]:file:_files -g "*.yml"' \
'(-p --project-name)'{-p,--project-name}'[Specify an alternate project name (default: directory name)]:project name:' \
'(-H --host)'{-H,--host}'[Daemon socket to connect to]:host:' \
'--tls[Use TLS; implied by --tlsverify]' \
'--tlscacert=[Trust certs signed only by this CA]:ca path:' \
'--tlscert=[Path to TLS certificate file]:client cert path:' \
'--tlskey=[Path to TLS key file]:tls key path:' \
'--tlsverify[Use TLS and verify the remote]' \
"--skip-hostname-check[Don't check the daemon's hostname against the name specified in the client certificate (for example if your docker host is an IP address)]" \
'(-): :->command' \
'(-)*:: :->option-or-argument' && ret=0
local compose_file=${opt_args[-f]}${opt_args[--file]}
local compose_project=${opt_args[-p]}${opt_args[--project-name]}
local compose_options="${compose_file:+--file $compose_file} ${compose_project:+--project-name $compose_project}"
local -a relevant_compose_flags relevant_docker_flags compose_options docker_options
relevant_compose_flags=(
"--file" "-f"
"--host" "-H"
"--project-name" "-p"
"--tls"
"--tlscacert"
"--tlscert"
"--tlskey"
"--tlsverify"
"--skip-hostname-check"
)
relevant_docker_flags=(
"--host" "-H"
"--tls"
"--tlscacert"
"--tlscert"
"--tlskey"
"--tlsverify"
)
for k in "${(@k)opt_args}"; do
if [[ -n "${relevant_docker_flags[(r)$k]}" ]]; then
docker_options+=$k
if [[ -n "$opt_args[$k]" ]]; then
docker_options+=$opt_args[$k]
fi
fi
if [[ -n "${relevant_compose_flags[(r)$k]}" ]]; then
compose_options+=$k
if [[ -n "$opt_args[$k]" ]]; then
compose_options+=$opt_args[$k]
fi
fi
done
case $state in
(command)

View file

@ -18,23 +18,28 @@ exe = EXE(pyz,
a.datas,
[
(
'compose/config/fields_schema_v1.json',
'compose/config/fields_schema_v1.json',
'compose/config/config_schema_v1.json',
'compose/config/config_schema_v1.json',
'DATA'
),
(
'compose/config/fields_schema_v2.0.json',
'compose/config/fields_schema_v2.0.json',
'compose/config/config_schema_v2.0.json',
'compose/config/config_schema_v2.0.json',
'DATA'
),
(
'compose/config/service_schema_v1.json',
'compose/config/service_schema_v1.json',
'compose/config/config_schema_v2.1.json',
'compose/config/config_schema_v2.1.json',
'DATA'
),
(
'compose/config/service_schema_v2.0.json',
'compose/config/service_schema_v2.0.json',
'compose/config/config_schema_v3.0.json',
'compose/config/config_schema_v3.0.json',
'DATA'
),
(
'compose/config/config_schema_v3.1.json',
'compose/config/config_schema_v3.1.json',
'DATA'
),
(

View file

@ -1,17 +0,0 @@
FROM docs/base:latest
MAINTAINER Mary Anthony <mary@docker.com> (@moxiegirl)
RUN svn checkout https://github.com/docker/docker/trunk/docs /docs/content/engine
RUN svn checkout https://github.com/docker/swarm/trunk/docs /docs/content/swarm
RUN svn checkout https://github.com/docker/machine/trunk/docs /docs/content/machine
RUN svn checkout https://github.com/docker/distribution/trunk/docs /docs/content/registry
RUN svn checkout https://github.com/docker/notary/trunk/docs /docs/content/notary
RUN svn checkout https://github.com/docker/kitematic/trunk/docs /docs/content/kitematic
RUN svn checkout https://github.com/docker/toolbox/trunk/docs /docs/content/toolbox
RUN svn checkout https://github.com/docker/opensource/trunk/docs /docs/content/project
ENV PROJECT=compose
# To get the git info for this repo
COPY . /src
COPY . /docs/content/$PROJECT/

View file

@ -1,55 +0,0 @@
.PHONY: all binary build cross default docs docs-build docs-shell shell test test-unit test-integration test-integration-cli test-docker-py validate
# env vars passed through directly to Docker's build scripts
# to allow things like `make DOCKER_CLIENTONLY=1 binary` easily
# `docs/sources/contributing/devenvironment.md ` and `project/PACKAGERS.md` have some limited documentation of some of these
DOCKER_ENVS := \
-e BUILDFLAGS \
-e DOCKER_CLIENTONLY \
-e DOCKER_EXECDRIVER \
-e DOCKER_GRAPHDRIVER \
-e TESTDIRS \
-e TESTFLAGS \
-e TIMEOUT
# note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds
# to allow `make DOCSDIR=1 docs-shell` (to create a bind mount in docs)
DOCS_MOUNT := $(if $(DOCSDIR),-v $(CURDIR):/docs/content/compose)
# to allow `make DOCSPORT=9000 docs`
DOCSPORT := 8000
# Get the IP ADDRESS
DOCKER_IP=$(shell python -c "import urlparse ; print urlparse.urlparse('$(DOCKER_HOST)').hostname or ''")
HUGO_BASE_URL=$(shell test -z "$(DOCKER_IP)" && echo localhost || echo "$(DOCKER_IP)")
HUGO_BIND_IP=0.0.0.0
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
DOCKER_IMAGE := docker$(if $(GIT_BRANCH),:$(GIT_BRANCH))
DOCKER_DOCS_IMAGE := docs-base$(if $(GIT_BRANCH),:$(GIT_BRANCH))
DOCKER_RUN_DOCS := docker run --rm -it $(DOCS_MOUNT) -e AWS_S3_BUCKET -e NOCACHE
# for some docs workarounds (see below in "docs-build" target)
GITCOMMIT := $(shell git rev-parse --short HEAD 2>/dev/null)
default: docs
docs: docs-build
$(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 -e DOCKERHOST "$(DOCKER_DOCS_IMAGE)" hugo server --port=$(DOCSPORT) --baseUrl=$(HUGO_BASE_URL) --bind=$(HUGO_BIND_IP) --watch
docs-draft: docs-build
$(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 -e DOCKERHOST "$(DOCKER_DOCS_IMAGE)" hugo server --buildDrafts="true" --port=$(DOCSPORT) --baseUrl=$(HUGO_BASE_URL) --bind=$(HUGO_BIND_IP)
docs-shell: docs-build
$(DOCKER_RUN_DOCS) -p $(if $(DOCSPORT),$(DOCSPORT):)8000 "$(DOCKER_DOCS_IMAGE)" bash
docs-build:
# ( git remote | grep -v upstream ) || git diff --name-status upstream/release..upstream/docs ./ > ./changed-files
# echo "$(GIT_BRANCH)" > GIT_BRANCH
# echo "$(AWS_S3_BUCKET)" > AWS_S3_BUCKET
# echo "$(GITCOMMIT)" > GITCOMMIT
docker build -t "$(DOCKER_DOCS_IMAGE)" .

View file

@ -1,86 +1,16 @@
<!--[metadata]>
+++
draft = true
title = "Compose README"
description = "Compose README"
keywords = ["Docker, documentation, manual, guide, reference, api"]
+++
<![end-metadata]-->
# The docs have been moved!
# Contributing to the Docker Compose documentation
The documentation for Compose has been merged into
[the general documentation repo](https://github.com/docker/docker.github.io).
The documentation in this directory is part of the [https://docs.docker.com](https://docs.docker.com) website. Docker uses [the Hugo static generator](http://gohugo.io/overview/introduction/) to convert project Markdown files to a static HTML site.
The docs for Compose are now here:
https://github.com/docker/docker.github.io/tree/master/compose
You don't need to be a Hugo expert to contribute to the compose documentation. If you are familiar with Markdown, you can modify the content in the `docs` files.
Please submit pull requests for unpublished features on the `vnext-compose` branch (https://github.com/docker/docker.github.io/tree/vnext-compose).
If you want to add a new file or change the location of the document in the menu, you do need to know a little more.
If you submit a PR to this codebase that has a docs impact, create a second docs PR on `docker.github.io`. Use the docs PR template provided (coming soon - watch this space).
## Documentation contributing workflow
PRs for typos, additional information, etc. for already-published features should be labeled as `okay-to-publish` (we are still settling on a naming convention, will provide a label soon). You can submit these PRs either to `vnext-compose` or directly to `master` on `docker.github.io`
1. Edit a Markdown file in the tree.
2. Save your changes.
3. Make sure you are in the `docs` subdirectory.
4. Build the documentation.
$ make docs
---> ffcf3f6c4e97
Removing intermediate container a676414185e8
Successfully built ffcf3f6c4e97
docker run --rm -it -e AWS_S3_BUCKET -e NOCACHE -p 8000:8000 -e DOCKERHOST "docs-base:test-tooling" hugo server --port=8000 --baseUrl=192.168.59.103 --bind=0.0.0.0
ERROR: 2015/06/13 MenuEntry's .Url is deprecated and will be removed in Hugo 0.15. Use .URL instead.
0 of 4 drafts rendered
0 future content
12 pages created
0 paginator pages created
0 tags created
0 categories created
in 55 ms
Serving pages from /docs/public
Web Server is available at http://0.0.0.0:8000/
Press Ctrl+C to stop
5. Open the available server in your browser.
The documentation server has the complete menu but only the Docker Compose
documentation resolves. You can't access the other project docs from this
localized build.
## Tips on Hugo metadata and menu positioning
The top of each Docker Compose documentation file contains TOML metadata. The metadata is commented out to prevent it from appearing in GitHub.
<!--[metadata]>
+++
title = "Extending services in Compose"
description = "How to use Docker Compose's extends keyword to share configuration between files and projects"
keywords = ["fig, composition, compose, docker, orchestration, documentation, docs"]
[menu.main]
parent="workw_compose"
weight=2
+++
<![end-metadata]-->
The metadata alone has this structure:
+++
title = "Extending services in Compose"
description = "How to use Docker Compose's extends keyword to share configuration between files and projects"
keywords = ["fig, composition, compose, docker, orchestration, documentation, docs"]
[menu.main]
parent="workw_compose"
weight=2
+++
The `[menu.main]` section refers to navigation defined [in the main Docker menu](https://github.com/docker/docs-base/blob/hugo/config.toml). This metadata says *add a menu item called* Extending services in Compose *to the menu with the* `smn_workdw_compose` *identifier*. If you locate the menu in the configuration, you'll find *Create multi-container applications* is the menu title.
You can move an article in the tree by specifying a new parent. You can shift the location of the item by changing its weight. Higher numbers are heavier and shift the item to the bottom of menu. Low or no numbers shift it up.
## Other key documentation repositories
The `docker/docs-base` repository contains [the Hugo theme and menu configuration](https://github.com/docker/docs-base). If you open the `Dockerfile` you'll see the `make docs` relies on this as a base image for building the Compose documentation.
The `docker/docs.docker.com` repository contains [build system for building the Docker documentation site](https://github.com/docker/docs.docker.com). Fork this repository to build the entire documentation site.
As always, the docs remain open-source and we appreciate your feedback and
pull requests!

View file

@ -1,68 +0,0 @@
<!--[metadata]>
+++
title = "Command-line Completion"
description = "Compose CLI reference"
keywords = ["fig, composition, compose, docker, orchestration, cli, reference"]
[menu.main]
parent="workw_compose"
weight=88
+++
<![end-metadata]-->
# Command-line Completion
Compose comes with [command completion](http://en.wikipedia.org/wiki/Command-line_completion)
for the bash and zsh shell.
## Installing Command Completion
### Bash
Make sure bash completion is installed. If you use a current Linux in a non-minimal installation, bash completion should be available.
On a Mac, install with `brew install bash-completion`
Place the completion script in `/etc/bash_completion.d/` (`/usr/local/etc/bash_completion.d/` on a Mac), using e.g.
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
Completion will be available upon next login.
### Zsh
Place the completion script in your `/path/to/zsh/completion`, using e.g. `~/.zsh/completion/`
mkdir -p ~/.zsh/completion
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/zsh/_docker-compose > ~/.zsh/completion/_docker-compose
Include the directory in your `$fpath`, e.g. by adding in `~/.zshrc`
fpath=(~/.zsh/completion $fpath)
Make sure `compinit` is loaded or do it by adding in `~/.zshrc`
autoload -Uz compinit && compinit -i
Then reload your shell
exec $SHELL -l
## Available completions
Depending on what you typed on the command line so far, it will complete
- available docker-compose commands
- options that are available for a particular command
- service names that make sense in a given context (e.g. services with running or stopped instances or services based on images vs. services based on Dockerfiles). For `docker-compose scale`, completed service names will automatically have "=" appended.
- arguments for selected options, e.g. `docker-compose kill -s` will complete some signals like SIGHUP and SIGUSR1.
Enjoy working with Compose faster and with less typos!
## Compose documentation
- [User guide](index.md)
- [Installing Compose](install.md)
- [Get started with Django](django.md)
- [Get started with Rails](rails.md)
- [Get started with WordPress](wordpress.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

File diff suppressed because it is too large Load diff

View file

@ -1,182 +0,0 @@
<!--[metadata]>
+++
title = "Quickstart: Compose and Django"
description = "Getting started with Docker Compose and Django"
keywords = ["documentation, docs, docker, compose, orchestration, containers"]
[menu.main]
parent="workw_compose"
weight=4
+++
<![end-metadata]-->
# Quickstart: Compose and Django
This quick-start guide demonstrates how to use Compose to set up and run a
simple Django/PostgreSQL app. Before starting, you'll need to have
[Compose installed](install.md).
## Define the project components
For this project, you need to create a Dockerfile, a Python dependencies file,
and a `docker-compose.yml` file.
1. Create an empty project directory.
You can name the directory something easy for you to remember. This directory is the context for your application image. The directory should only contain resources to build that image.
2. Create a new file called `Dockerfile` in your project directory.
The Dockerfile defines an application's image content via one or more build
commands that configure that image. Once built, you can run the image in a
container. For more information on `Dockerfiles`, see the [Docker user
guide](https://docs.docker.com/engine/userguide/dockerimages/#building-an-image-from-a-dockerfile)
and the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/).
3. Add the following content to the `Dockerfile`.
FROM python:2.7
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
This `Dockerfile` starts with a Python 2.7 base image. The base image is
modified by adding a new `code` directory. The base image is further modified
by installing the Python requirements defined in the `requirements.txt` file.
4. Save and close the `Dockerfile`.
5. Create a `requirements.txt` in your project directory.
This file is used by the `RUN pip install -r requirements.txt` command in your `Dockerfile`.
6. Add the required software in the file.
Django
psycopg2
7. Save and close the `requirements.txt` file.
8. Create a file called `docker-compose.yml` in your project directory.
The `docker-compose.yml` file describes the services that make your app. In
this example those services are a web server and database. The compose file
also describes which Docker images these services use, how they link
together, any volumes they might need mounted inside the containers.
Finally, the `docker-compose.yml` file describes which ports these services
expose. See the [`docker-compose.yml` reference](compose-file.md) for more
information on how this file works.
9. Add the following configuration to the file.
version: '2'
services:
db:
image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
This file defines two services: The `db` service and the `web` service.
10. Save and close the `docker-compose.yml` file.
## Create a Django project
In this step, you create a Django started project by building the image from the build context defined in the previous procedure.
1. Change to the root of your project directory.
2. Create the Django project using the `docker-compose` command.
$ docker-compose run web django-admin.py startproject composeexample .
This instructs Compose to run `django-admin.py startproject composeeexample`
in a container, using the `web` service's image and configuration. Because
the `web` image doesn't exist yet, Compose builds it from the current
directory, as specified by the `build: .` line in `docker-compose.yml`.
Once the `web` service image is built, Compose runs it and executes the
`django-admin.py startproject` command in the container. This command
instructs Django to create a set of files and directories representing a
Django project.
3. After the `docker-compose` command completes, list the contents of your project.
$ ls -l
drwxr-xr-x 2 root root composeexample
-rw-rw-r-- 1 user user docker-compose.yml
-rw-rw-r-- 1 user user Dockerfile
-rwxr-xr-x 1 root root manage.py
-rw-rw-r-- 1 user user requirements.txt
The files `django-admin` created are owned by root. This happens because
the container runs as the `root` user.
4. Change the ownership of the new files.
sudo chown -R $USER:$USER .
## Connect the database
In this section, you set up the database connection for Django.
1. In your project directory, edit the `composeexample/settings.py` file.
2. Replace the `DATABASES = ...` with the following:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
These settings are determined by the
[postgres](https://hub.docker.com/_/postgres/) Docker image
specified in `docker-compose.yml`.
3. Save and close the file.
4. Run the `docker-compose up` command.
$ docker-compose up
Starting composepractice_db_1...
Starting composepractice_web_1...
Attaching to composepractice_db_1, composepractice_web_1
...
db_1 | PostgreSQL init process complete; ready for start up.
...
db_1 | LOG: database system is ready to accept connections
db_1 | LOG: autovacuum launcher started
..
web_1 | Django version 1.8.4, using settings 'composeexample.settings'
web_1 | Starting development server at http://0.0.0.0:8000/
web_1 | Quit the server with CONTROL-C.
At this point, your Django app should be running at port `8000` on your
Docker host. If you are using a Docker Machine VM, you can use the
`docker-machine ip MACHINE_NAME` to get the IP address.
## More Compose documentation
- [User guide](index.md)
- [Installing Compose](install.md)
- [Getting Started](gettingstarted.md)
- [Get started with Rails](rails.md)
- [Get started with WordPress](wordpress.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -1,368 +0,0 @@
<!--[metadata]>
+++
title = "Extending Services in Compose"
description = "How to use Docker Compose's extends keyword to share configuration between files and projects"
keywords = ["fig, composition, compose, docker, orchestration, documentation, docs"]
[menu.main]
parent="workw_compose"
weight=20
+++
<![end-metadata]-->
# Extending services and Compose files
Compose supports two methods of sharing common configuration:
1. Extending an entire Compose file by
[using multiple Compose files](#multiple-compose-files)
2. Extending individual services with [the `extends` field](#extending-services)
## Multiple Compose files
Using multiple Compose files enables you to customize a Compose application
for different environments or different workflows.
### Understanding multiple Compose files
By default, Compose reads two files, a `docker-compose.yml` and an optional
`docker-compose.override.yml` file. By convention, the `docker-compose.yml`
contains your base configuration. The override file, as its name implies, can
contain configuration overrides for existing services or entirely new
services.
If a service is defined in both files Compose merges the configurations using
the rules described in [Adding and overriding
configuration](#adding-and-overriding-configuration).
To use multiple override files, or an override file with a different name, you
can use the `-f` option to specify the list of files. Compose merges files in
the order they're specified on the command line. See the [`docker-compose`
command reference](./reference/overview.md) for more information about
using `-f`.
When you use multiple configuration files, you must make sure all paths in the
files are relative to the base Compose file (the first Compose file specified
with `-f`). This is required because override files need not be valid
Compose files. Override files can contain small fragments of configuration.
Tracking which fragment of a service is relative to which path is difficult and
confusing, so to keep paths easier to understand, all paths must be defined
relative to the base file.
### Example use case
In this section are two common use cases for multiple compose files: changing a
Compose app for different environments, and running administrative tasks
against a Compose app.
#### Different environments
A common use case for multiple files is changing a development Compose app
for a production-like environment (which may be production, staging or CI).
To support these differences, you can split your Compose configuration into
a few different files:
Start with a base file that defines the canonical configuration for the
services.
**docker-compose.yml**
web:
image: example/my_web_app:latest
links:
- db
- cache
db:
image: postgres:latest
cache:
image: redis:latest
In this example the development configuration exposes some ports to the
host, mounts our code as a volume, and builds the web image.
**docker-compose.override.yml**
web:
build: .
volumes:
- '.:/code'
ports:
- 8883:80
environment:
DEBUG: 'true'
db:
command: '-d'
ports:
- 5432:5432
cache:
ports:
- 6379:6379
When you run `docker-compose up` it reads the overrides automatically.
Now, it would be nice to use this Compose app in a production environment. So,
create another override file (which might be stored in a different git
repo or managed by a different team).
**docker-compose.prod.yml**
web:
ports:
- 80:80
environment:
PRODUCTION: 'true'
cache:
environment:
TTL: '500'
To deploy with this production Compose file you can run
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
This deploys all three services using the configuration in
`docker-compose.yml` and `docker-compose.prod.yml` (but not the
dev configuration in `docker-compose.override.yml`).
See [production](production.md) for more information about Compose in
production.
#### Administrative tasks
Another common use case is running adhoc or administrative tasks against one
or more services in a Compose app. This example demonstrates running a
database backup.
Start with a **docker-compose.yml**.
web:
image: example/my_web_app:latest
links:
- db
db:
image: postgres:latest
In a **docker-compose.admin.yml** add a new service to run the database
export or backup.
dbadmin:
build: database_admin/
links:
- db
To start a normal environment run `docker-compose up -d`. To run a database
backup, include the `docker-compose.admin.yml` as well.
docker-compose -f docker-compose.yml -f docker-compose.admin.yml \
run dbadmin db-backup
## Extending services
Docker Compose's `extends` keyword enables sharing of common configurations
among different files, or even different projects entirely. Extending services
is useful if you have several services that reuse a common set of configuration
options. Using `extends` you can define a common set of service options in one
place and refer to it from anywhere.
> **Note:** `links`, `volumes_from`, and `depends_on` are never shared between
> services using >`extends`. These exceptions exist to avoid
> implicit dependencies&mdash;you always define `links` and `volumes_from`
> locally. This ensures dependencies between services are clearly visible when
> reading the current file. Defining these locally also ensures changes to the
> referenced file don't result in breakage.
### Understand the extends configuration
When defining any service in `docker-compose.yml`, you can declare that you are
extending another service like this:
web:
extends:
file: common-services.yml
service: webapp
This instructs Compose to re-use the configuration for the `webapp` service
defined in the `common-services.yml` file. Suppose that `common-services.yml`
looks like this:
webapp:
build: .
ports:
- "8000:8000"
volumes:
- "/data"
In this case, you'll get exactly the same result as if you wrote
`docker-compose.yml` with the same `build`, `ports` and `volumes` configuration
values defined directly under `web`.
You can go further and define (or re-define) configuration locally in
`docker-compose.yml`:
web:
extends:
file: common-services.yml
service: webapp
environment:
- DEBUG=1
cpu_shares: 5
important_web:
extends: web
cpu_shares: 10
You can also write other services and link your `web` service to them:
web:
extends:
file: common-services.yml
service: webapp
environment:
- DEBUG=1
cpu_shares: 5
links:
- db
db:
image: postgres
### Example use case
Extending an individual service is useful when you have multiple services that
have a common configuration. The example below is a Compose app with
two services: a web application and a queue worker. Both services use the same
codebase and share many configuration options.
In a **common.yml** we define the common configuration:
app:
build: .
environment:
CONFIG_FILE_PATH: /code/config
API_KEY: xxxyyy
cpu_shares: 5
In a **docker-compose.yml** we define the concrete services which use the
common configuration:
webapp:
extends:
file: common.yml
service: app
command: /code/run_web_app
ports:
- 8080:8080
links:
- queue
- db
queue_worker:
extends:
file: common.yml
service: app
command: /code/run_worker
links:
- queue
## Adding and overriding configuration
Compose copies configurations from the original service over to the local one.
If a configuration option is defined in both the original service the local
service, the local value *replaces* or *extends* the original value.
For single-value options like `image`, `command` or `mem_limit`, the new value
replaces the old value.
# original service
command: python app.py
# local service
command: python otherapp.py
# result
command: python otherapp.py
In the case of `build` and `image`, using one in the local service causes
Compose to discard the other, if it was defined in the original service.
Example of image replacing build:
# original service
build: .
# local service
image: redis
# result
image: redis
Example of build replacing image:
# original service
image: redis
# local service
build: .
# result
build: .
For the **multi-value options** `ports`, `expose`, `external_links`, `dns` and
`dns_search`, Compose concatenates both sets of values:
# original service
expose:
- "3000"
# local service
expose:
- "4000"
- "5000"
# result
expose:
- "3000"
- "4000"
- "5000"
In the case of `environment`, `labels`, `volumes` and `devices`, Compose
"merges" entries together with locally-defined values taking precedence:
# original service
environment:
- FOO=original
- BAR=original
# local service
environment:
- BAR=local
- BAZ=local
# result
environment:
- FOO=original
- BAR=local
- BAZ=local
## Compose documentation
- [User guide](index.md)
- [Installing Compose](install.md)
- [Getting Started](gettingstarted.md)
- [Get started with Django](django.md)
- [Get started with Rails](rails.md)
- [Get started with WordPress](wordpress.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -1,140 +0,0 @@
<!--[metadata]>
+++
title = "Frequently Asked Questions"
description = "Docker Compose FAQ"
keywords = "documentation, docs, docker, compose, faq"
[menu.main]
identifier="faq.compose"
parent="workw_compose"
weight=90
+++
<![end-metadata]-->
# Frequently asked questions
If you dont see your question here, feel free to drop by `#docker-compose` on
freenode IRC and ask the community.
## Why do my services take 10 seconds to stop?
Compose stop attempts to stop a container by sending a `SIGTERM`. It then waits
for a [default timeout of 10 seconds](./reference/stop.md). After the timeout,
a `SIGKILL` is sent to the container to forcefully kill it. If you
are waiting for this timeout, it means that your containers aren't shutting down
when they receive the `SIGTERM` signal.
There has already been a lot written about this problem of
[processes handling signals](https://medium.com/@gchudnov/trapping-signals-in-docker-containers-7a57fdda7d86)
in containers.
To fix this problem, try the following:
* Make sure you're using the JSON form of `CMD` and `ENTRYPOINT`
in your Dockerfile.
For example use `["program", "arg1", "arg2"]` not `"program arg1 arg2"`.
Using the string form causes Docker to run your process using `bash` which
doesn't handle signals properly. Compose always uses the JSON form, so don't
worry if you override the command or entrypoint in your Compose file.
* If you are able, modify the application that you're running to
add an explicit signal handler for `SIGTERM`.
* If you can't modify the application, wrap the application in a lightweight init
system (like [s6](http://skarnet.org/software/s6/)) or a signal proxy (like
[dumb-init](https://github.com/Yelp/dumb-init) or
[tini](https://github.com/krallin/tini)). Either of these wrappers take care of
handling `SIGTERM` properly.
## How do I run multiple copies of a Compose file on the same host?
Compose uses the project name to create unique identifiers for all of a
project's containers and other resources. To run multiple copies of a project,
set a custom project name using the [`-p` command line
option](./reference/overview.md) or the [`COMPOSE_PROJECT_NAME`
environment variable](./reference/envvars.md#compose-project-name).
## What's the difference between `up`, `run`, and `start`?
Typically, you want `docker-compose up`. Use `up` to start or restart all the
services defined in a `docker-compose.yml`. In the default "attached"
mode, you'll see all the logs from all the containers. In "detached" mode (`-d`),
Compose exits after starting the containers, but the containers continue to run
in the background.
The `docker-compose run` command is for running "one-off" or "adhoc" tasks. It
requires the service name you want to run and only starts containers for services
that the running service depends on. Use `run` to run tests or perform
an administrative task such as removing or adding data to a data volume
container. The `run` command acts like `docker run -ti` in that it opens an
interactive terminal to the container and returns an exit status matching the
exit status of the process in the container.
The `docker-compose start` command is useful only to restart containers
that were previously created, but were stopped. It never creates new
containers.
## Can I use json instead of yaml for my Compose file?
Yes. [Yaml is a superset of json](http://stackoverflow.com/a/1729545/444646) so
any JSON file should be valid Yaml. To use a JSON file with Compose,
specify the filename to use, for example:
```bash
docker-compose -f docker-compose.json up
```
## How do I get Compose to wait for my database to be ready before starting my application?
Unfortunately, Compose won't do that for you but for a good reason.
The problem of waiting for a database to be ready is really just a subset of a
much larger problem of distributed systems. In production, your database could
become unavailable or move hosts at any time. The application needs to be
resilient to these types of failures.
To handle this, the application would attempt to re-establish a connection to
the database after a failure. If the application retries the connection,
it should eventually be able to connect to the database.
To wait for the application to be in a good state, you can implement a
healthcheck. A healthcheck makes a request to the application and checks
the response for a success status code. If it is not successful it waits
for a short period of time, and tries again. After some timeout value, the check
stops trying and report a failure.
If you need to run tests against your application, you can start by running a
healthcheck. Once the healthcheck gets a successful response, you can start
running your tests.
## Should I include my code with `COPY`/`ADD` or a volume?
You can add your code to the image using `COPY` or `ADD` directive in a
`Dockerfile`. This is useful if you need to relocate your code along with the
Docker image, for example when you're sending code to another environment
(production, CI, etc).
You should use a `volume` if you want to make changes to your code and see them
reflected immediately, for example when you're developing code and your server
supports hot code reloading or live-reload.
There may be cases where you'll want to use both. You can have the image
include the code using a `COPY`, and use a `volume` in your Compose file to
include the code from the host during development. The volume overrides
the directory contents of the image.
## Where can I find example compose files?
There are [many examples of Compose files on
github](https://github.com/search?q=in%3Apath+docker-compose.yml+extension%3Ayml&type=Code).
## Compose documentation
- [Installing Compose](install.md)
- [Get started with Django](django.md)
- [Get started with Rails](rails.md)
- [Get started with WordPress](wordpress.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -1,191 +0,0 @@
<!--[metadata]>
+++
title = "Getting Started"
description = "Getting started with Docker Compose"
keywords = ["documentation, docs, docker, compose, orchestration, containers"]
[menu.main]
parent="workw_compose"
weight=-85
+++
<![end-metadata]-->
# Getting Started
On this page you build a simple Python web application running on Compose. The
application uses the Flask framework and increments a value in Redis. While the
sample uses Python, the concepts demonstrated here should be understandable even
if you're not familiar with it.
## Prerequisites
Make sure you have already
[installed both Docker Engine and Docker Compose](install.md). You
don't need to install Python, it is provided by a Docker image.
## Step 1: Setup
1. Create a directory for the project:
$ mkdir composetest
$ cd composetest
2. With your favorite text editor create a file called `app.py` in your project
directory.
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello World! I have been seen %s times.' % redis.get('hits')
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
3. Create another file called `requirements.txt` in your project directory and
add the following:
flask
redis
These define the applications dependencies.
## Step 2: Create a Docker image
In this step, you build a new Docker image. The image contains all the
dependencies the Python application requires, including Python itself.
1. In your project directory create a file named `Dockerfile` and add the
following:
FROM python:2.7
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD python app.py
This tells Docker to:
* Build an image starting with the Python 2.7 image.
* Add the current directory `.` into the path `/code` in the image.
* Set the working directory to `/code`.
* Install the Python dependencies.
* Set the default command for the container to `python app.py`
For more information on how to write Dockerfiles, see the [Docker user guide](https://docs.docker.com/engine/userguide/dockerimages/#building-an-image-from-a-dockerfile) and the [Dockerfile reference](http://docs.docker.com/reference/builder/).
2. Build the image.
$ docker build -t web .
This command builds an image named `web` from the contents of the current
directory. The command automatically locates the `Dockerfile`, `app.py`, and
`requirements.txt` files.
## Step 3: Define services
Define a set of services using `docker-compose.yml`:
1. Create a file called docker-compose.yml in your project directory and add
the following:
version: '2'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
depends_on:
- redis
redis:
image: redis
This Compose file defines two services, `web` and `redis`. The web service:
* Builds from the `Dockerfile` in the current directory.
* Forwards the exposed port 5000 on the container to port 5000 on the host machine.
* Mounts the project directory on the host to `/code` inside the container allowing you to modify the code without having to rebuild the image.
* Links the web service to the Redis service.
The `redis` service uses the latest public [Redis](https://registry.hub.docker.com/_/redis/) image pulled from the Docker Hub registry.
## Step 4: Build and run your app with Compose
1. From your project directory, start up your application.
$ docker-compose up
Pulling image redis...
Building web...
Starting composetest_redis_1...
Starting composetest_web_1...
redis_1 | [8] 02 Jan 18:43:35.576 # Server started, Redis version 2.8.3
web_1 | * Running on http://0.0.0.0:5000/
web_1 | * Restarting with stat
Compose pulls a Redis image, builds an image for your code, and start the
services you defined.
2. Enter `http://0.0.0.0:5000/` in a browser to see the application running.
If you're using Docker on Linux natively, then the web app should now be
listening on port 5000 on your Docker daemon host. If http://0.0.0.0:5000
doesn't resolve, you can also try http://localhost:5000.
If you're using Docker Machine on a Mac, use `docker-machine ip MACHINE_VM` to get
the IP address of your Docker host. Then, `open http://MACHINE_VM_IP:5000` in a
browser.
You should see a message in your browser saying:
`Hello World! I have been seen 1 times.`
3. Refresh the page.
The number should increment.
## Step 5: Experiment with some other commands
If you want to run your services in the background, you can pass the `-d` flag
(for "detached" mode) to `docker-compose up` and use `docker-compose ps` to
see what is currently running:
$ docker-compose up -d
Starting composetest_redis_1...
Starting composetest_web_1...
$ docker-compose ps
Name Command State Ports
-------------------------------------------------------------------
composetest_redis_1 /usr/local/bin/run Up
composetest_web_1 /bin/sh -c python app.py Up 5000->5000/tcp
The `docker-compose run` command allows you to run one-off commands for your
services. For example, to see what environment variables are available to the
`web` service:
$ docker-compose run web env
See `docker-compose --help` to see other available commands. You can also install [command completion](completion.md) for the bash and zsh shell, which will also show you available commands.
If you started Compose with `docker-compose up -d`, you'll probably want to stop
your services once you've finished with them:
$ docker-compose stop
At this point, you have seen the basics of how Compose works.
## Where to go next
- Next, try the quick start guide for [Django](django.md),
[Rails](rails.md), or [WordPress](wordpress.md).
- [Explore the full list of Compose commands](./reference/index.md)
- [Compose configuration file reference](compose-file.md)

View file

@ -1,29 +0,0 @@
<!--[metadata]>
+++
title = "Docker Compose"
description = "Introduction and Overview of Compose"
keywords = ["documentation, docs, docker, compose, orchestration, containers"]
[menu.main]
identifier="workw_compose"
weight=-70
+++
<![end-metadata]-->
# Docker Compose
Compose is a tool for defining and running multi-container Docker applications. To learn more about Compose refer to the following documentation:
- [Compose Overview](overview.md)
- [Install Compose](install.md)
- [Getting Started](gettingstarted.md)
- [Get started with Django](django.md)
- [Get started with Rails](rails.md)
- [Get started with WordPress](wordpress.md)
- [Frequently asked questions](faq.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)
To see a detailed list of changes for past and current releases of Docker
Compose, please refer to the
[CHANGELOG](https://github.com/docker/compose/blob/master/CHANGELOG.md).

View file

@ -1,136 +0,0 @@
<!--[metadata]>
+++
title = "Install Compose"
description = "How to install Docker Compose"
keywords = ["compose, orchestration, install, installation, docker, documentation"]
[menu.main]
parent="workw_compose"
weight=-90
+++
<![end-metadata]-->
# Install Docker Compose
You can run Compose on OS X and 64-bit Linux. It is currently not supported on
the Windows operating system. To install Compose, you'll need to install Docker
first.
To install Compose, do the following:
1. Install Docker Engine version 1.7.1 or greater:
* <a href="https://docs.docker.com/engine/installation/mac/" target="_blank">Mac OS X installation</a> (Toolbox installation includes both Engine and Compose)
* <a href="https://docs.docker.com/engine/installation/ubuntulinux/" target="_blank">Ubuntu installation</a>
* <a href="https://docs.docker.com/engine/installation/" target="_blank">other system installations</a>
2. Mac OS X users are done installing. Others should continue to the next step.
3. Go to the <a href="https://github.com/docker/compose/releases" target="_blank">Compose repository release page on GitHub</a>.
4. Follow the instructions from the release page and run the `curl` command,
which the release page specifies, in your terminal.
> Note: If you get a "Permission denied" error, your `/usr/local/bin` directory
probably isn't writable and you'll need to install Compose as the superuser. Run
`sudo -i`, then the two commands below, then `exit`.
The following is an example command illustrating the format:
curl -L https://github.com/docker/compose/releases/download/1.6.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
If you have problems installing with `curl`, see
[Alternative Install Options](#alternative-install-options).
5. Apply executable permissions to the binary:
$ chmod +x /usr/local/bin/docker-compose
6. Optionally, install [command completion](completion.md) for the
`bash` and `zsh` shell.
7. Test the installation.
$ docker-compose --version
docker-compose version: 1.6.1
## Alternative install options
### Install using pip
Compose can be installed from [pypi](https://pypi.python.org/pypi/docker-compose)
using `pip`. If you install using `pip` it is highly recommended that you use a
[virtualenv](https://virtualenv.pypa.io/en/latest/) because many operating systems
have python system packages that conflict with docker-compose dependencies. See
the [virtualenv tutorial](http://docs.python-guide.org/en/latest/dev/virtualenvs/)
to get started.
$ pip install docker-compose
> **Note:** pip version 6.0 or greater is required
### Install as a container
Compose can also be run inside a container, from a small bash script wrapper.
To install compose as a container run:
$ curl -L https://github.com/docker/compose/releases/download/1.6.1/run.sh > /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
## Master builds
If you're interested in trying out a pre-release build you can download a
binary from https://dl.bintray.com/docker-compose/master/. Pre-release
builds allow you to try out new features before they are released, but may
be less stable.
## Upgrading
If you're upgrading from Compose 1.2 or earlier, you'll need to remove or migrate
your existing containers after upgrading Compose. This is because, as of version
1.3, Compose uses Docker labels to keep track of containers, and so they need to
be recreated with labels added.
If Compose detects containers that were created without labels, it will refuse
to run so that you don't end up with two sets of them. If you want to keep using
your existing containers (for example, because they have data volumes you want
to preserve) you can use compose 1.5.x to migrate them with the following command:
$ docker-compose migrate-to-labels
Alternatively, if you're not worried about keeping them, you can remove them.
Compose will just create new ones.
$ docker rm -f -v myapp_web_1 myapp_db_1 ...
## Uninstallation
To uninstall Docker Compose if you installed using `curl`:
$ rm /usr/local/bin/docker-compose
To uninstall Docker Compose if you installed using `pip`:
$ pip uninstall docker-compose
>**Note**: If you get a "Permission denied" error using either of the above
>methods, you probably do not have the proper permissions to remove
>`docker-compose`. To force the removal, prepend `sudo` to either of the above
>commands and run again.
## Where to go next
- [User guide](index.md)
- [Getting Started](gettingstarted.md)
- [Get started with Django](django.md)
- [Get started with Rails](rails.md)
- [Get started with WordPress](wordpress.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -1,48 +0,0 @@
<!--[metadata]>
+++
title = "Link Environment Variables"
description = "Compose CLI reference"
keywords = ["fig, composition, compose, docker, orchestration, cli, reference"]
aliases = ["/compose/env"]
[menu.main]
parent="workw_compose"
weight=89
+++
<![end-metadata]-->
# Link environment variables reference
> **Note:** Environment variables are no longer the recommended method for connecting to linked services. Instead, you should use the link name (by default, the name of the linked service) as the hostname to connect to. See the [docker-compose.yml documentation](compose-file.md#links) for details.
>
> Environment variables will only be populated if you're using the [legacy version 1 Compose file format](compose-file.md#versioning).
Compose uses [Docker links] to expose services' containers to one another. Each linked container injects a set of environment variables, each of which begins with the uppercase name of the container.
To see what environment variables are available to a service, run `docker-compose run SERVICE env`.
<b><i>name</i>\_PORT</b><br>
Full URL, e.g. `DB_PORT=tcp://172.17.0.5:5432`
<b><i>name</i>\_PORT\_<i>num</i>\_<i>protocol</i></b><br>
Full URL, e.g. `DB_PORT_5432_TCP=tcp://172.17.0.5:5432`
<b><i>name</i>\_PORT\_<i>num</i>\_<i>protocol</i>\_ADDR</b><br>
Container's IP address, e.g. `DB_PORT_5432_TCP_ADDR=172.17.0.5`
<b><i>name</i>\_PORT\_<i>num</i>\_<i>protocol</i>\_PORT</b><br>
Exposed port number, e.g. `DB_PORT_5432_TCP_PORT=5432`
<b><i>name</i>\_PORT\_<i>num</i>\_<i>protocol</i>\_PROTO</b><br>
Protocol (tcp or udp), e.g. `DB_PORT_5432_TCP_PROTO=tcp`
<b><i>name</i>\_NAME</b><br>
Fully qualified container name, e.g. `DB_1_NAME=/myapp_web_1/myapp_db_1`
[Docker links]: https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/
## Related Information
- [User guide](index.md)
- [Installing Compose](install.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -1,152 +0,0 @@
<!--[metadata]>
+++
title = "Networking in Compose"
description = "How Compose sets up networking between containers"
keywords = ["documentation, docs, docker, compose, orchestration, containers, networking"]
[menu.main]
parent="workw_compose"
weight=21
+++
<![end-metadata]-->
# Networking in Compose
> **Note:** This document only applies if you're using [version 2 of the Compose file format](compose-file.md#versioning). Networking features are not supported for version 1 (legacy) Compose files.
By default Compose sets up a single
[network](/engine/reference/commandline/network_create.md) for your app. Each
container for a service joins the default network and is both *reachable* by
other containers on that network, and *discoverable* by them at a hostname
identical to the container name.
> **Note:** Your app's network is given a name based on the "project name",
> which is based on the name of the directory it lives in. You can override the
> project name with either the [`--project-name`
> flag](reference/overview.md) or the [`COMPOSE_PROJECT_NAME` environment
> variable](reference/envvars.md#compose-project-name).
For example, suppose your app is in a directory called `myapp`, and your `docker-compose.yml` looks like this:
version: '2'
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
When you run `docker-compose up`, the following happens:
1. A network called `myapp_default` is created.
2. A container is created using `web`'s configuration. It joins the network
`myapp_default` under the name `web`.
3. A container is created using `db`'s configuration. It joins the network
`myapp_default` under the name `db`.
Each container can now look up the hostname `web` or `db` and
get back the appropriate container's IP address. For example, `web`'s
application code could connect to the URL `postgres://db:5432` and start
using the Postgres database.
Because `web` explicitly maps a port, it's also accessible from the outside world via port 8000 on your Docker host's network interface.
## Updating containers
If you make a configuration change to a service and run `docker-compose up` to update it, the old container will be removed and the new one will join the network under a different IP address but the same name. Running containers will be able to look up that name and connect to the new address, but the old address will stop working.
If any containers have connections open to the old container, they will be closed. It is a container's responsibility to detect this condition, look up the name again and reconnect.
## Links
Links allow you to define extra aliases by which a service is reachable from another service. They are not required to enable services to communicate - by default, any service can reach any other service at that service's name. In the following example, `db` is reachable from `web` at the hostnames `db` and `database`:
version: '2'
services:
web:
build: .
links:
- "db:database"
db:
image: postgres
See the [links reference](compose-file.md#links) for more information.
## Multi-host networking
When [deploying a Compose application to a Swarm cluster](swarm.md), you can make use of the built-in `overlay` driver to enable multi-host communication between containers with no changes to your Compose file or application code.
Consult the [Getting started with multi-host networking](/engine/userguide/networking/get-started-overlay.md) to see how to set up a Swarm cluster. The cluster will use the `overlay` driver by default, but you can specify it explicitly if you prefer - see below for how to do this.
## Specifying custom networks
Instead of just using the default app network, you can specify your own networks with the top-level `networks` key. This lets you create more complex topologies and specify [custom network drivers](/engine/extend/plugins_network.md) and options. You can also use it to connect services to externally-created networks which aren't managed by Compose.
Each service can specify what networks to connect to with the *service-level* `networks` key, which is a list of names referencing entries under the *top-level* `networks` key.
Here's an example Compose file defining two custom networks. The `proxy` service is isolated from the `db` service, because they do not share a network in common - only `app` can talk to both.
version: '2'
services:
proxy:
build: ./proxy
networks:
- front
app:
build: ./app
networks:
- front
- back
db:
image: postgres
networks:
- back
networks:
front:
# Use a custom driver
driver: custom-driver-1
back:
# Use a custom driver which takes special options
driver: custom-driver-2
driver_opts:
foo: "1"
bar: "2"
For full details of the network configuration options available, see the following references:
- [Top-level `networks` key](compose-file.md#network-configuration-reference)
- [Service-level `networks` key](compose-file.md#networks)
## Configuring the default network
Instead of (or as well as) specifying your own networks, you can also change the settings of the app-wide default network by defining an entry under `networks` named `default`:
version: '2'
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
networks:
default:
# Use a custom driver
driver: custom-driver-1
## Using a pre-existing network
If you want your containers to join a pre-existing network, use the [`external` option](compose-file.md#network-configuration-reference):
networks:
default:
external:
name: my-pre-existing-network
Instead of attemping to create a network called `[projectname]_default`, Compose will look for a network called `my-pre-existing-network` and connect your app's containers to it.

View file

@ -1,191 +0,0 @@
<!--[metadata]>
+++
title = "Overview of Docker Compose"
description = "Introduction and Overview of Compose"
keywords = ["documentation, docs, docker, compose, orchestration, containers"]
[menu.main]
parent="workw_compose"
weight=-99
+++
<![end-metadata]-->
# Overview of Docker Compose
Compose is a tool for defining and running multi-container Docker applications.
With Compose, you use a Compose file to configure your application's services.
Then, using a single command, you create and start all the services
from your configuration. To learn more about all the features of Compose
see [the list of features](#features).
Compose is great for development, testing, and staging environments, as well as
CI workflows. You can learn more about each case in
[Common Use Cases](#common-use-cases).
Using Compose is basically a three-step process.
1. Define your app's environment with a `Dockerfile` so it can be
reproduced anywhere.
2. Define the services that make up your app in `docker-compose.yml` so
they can be run together in an isolated environment.
3. Lastly, run `docker-compose up` and Compose will start and run your entire app.
A `docker-compose.yml` looks like this:
version: '2'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
For more information about the Compose file, see the
[Compose file reference](compose-file.md)
Compose has commands for managing the whole lifecycle of your application:
* Start, stop and rebuild services
* View the status of running services
* Stream the log output of running services
* Run a one-off command on a service
## Compose documentation
- [Installing Compose](install.md)
- [Getting Started](gettingstarted.md)
- [Get started with Django](django.md)
- [Get started with Rails](rails.md)
- [Get started with WordPress](wordpress.md)
- [Frequently asked questions](faq.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)
## Features
The features of Compose that make it effective are:
* [Multiple isolated environments on a single host](#Multiple-isolated-environments-on-a-single-host)
* [Preserve volume data when containers are created](#preserve-volume-data-when-containers-are-created)
* [Only recreate containers that have changed](#only-recreate-containers-that-have-changed)
* [Variables and moving a composition between environments](#variables-and-moving-a-composition-between-environments)
### Multiple isolated environments on a single host
Compose uses a project name to isolate environments from each other. You can use
this project name to:
* on a dev host, to create multiple copies of a single environment (ex: you want
to run a stable copy for each feature branch of a project)
* on a CI server, to keep builds from interfering with each other, you can set
the project name to a unique build number
* on a shared host or dev host, to prevent different projects which may use the
same service names, from interfering with each other
The default project name is the basename of the project directory. You can set
a custom project name by using the
[`-p` command line option](./reference/overview.md) or the
[`COMPOSE_PROJECT_NAME` environment variable](./reference/envvars.md#compose-project-name).
### Preserve volume data when containers are created
Compose preserves all volumes used by your services. When `docker-compose up`
runs, if it finds any containers from previous runs, it copies the volumes from
the old container to the new container. This process ensures that any data
you've created in volumes isn't lost.
### Only recreate containers that have changed
Compose caches the configuration used to create a container. When you
restart a service that has not changed, Compose re-uses the existing
containers. Re-using containers means that you can make changes to your
environment very quickly.
### Variables and moving a composition between environments
Compose supports variables in the Compose file. You can use these variables
to customize your composition for different environments, or different users.
See [Variable substitution](compose-file.md#variable-substitution) for more
details.
You can extend a Compose file using the `extends` field or by creating multiple
Compose files. See [extends](extends.md) for more details.
## Common Use Cases
Compose can be used in many different ways. Some common use cases are outlined
below.
### Development environments
When you're developing software, the ability to run an application in an
isolated environment and interact with it is crucial. The Compose command
line tool can be used to create the environment and interact with it.
The [Compose file](compose-file.md) provides a way to document and configure
all of the application's service dependencies (databases, queues, caches,
web service APIs, etc). Using the Compose command line tool you can create
and start one or more containers for each dependency with a single command
(`docker-compose up`).
Together, these features provide a convenient way for developers to get
started on a project. Compose can reduce a multi-page "developer getting
started guide" to a single machine readable Compose file and a few commands.
### Automated testing environments
An important part of any Continuous Deployment or Continuous Integration process
is the automated test suite. Automated end-to-end testing requires an
environment in which to run tests. Compose provides a convenient way to create
and destroy isolated testing environments for your test suite. By defining the full
environment in a [Compose file](compose-file.md) you can create and destroy these
environments in just a few commands:
$ docker-compose up -d
$ ./run_tests
$ docker-compose down
### Single host deployments
Compose has traditionally been focused on development and testing workflows,
but with each release we're making progress on more production-oriented features.
You can use Compose to deploy to a remote Docker Engine. The Docker Engine may
be a single instance provisioned with
[Docker Machine](https://docs.docker.com/machine/) or an entire
[Docker Swarm](https://docs.docker.com/swarm/) cluster.
For details on using production-oriented features, see
[compose in production](production.md) in this documentation.
## Release Notes
To see a detailed list of changes for past and current releases of Docker
Compose, please refer to the
[CHANGELOG](https://github.com/docker/compose/blob/master/CHANGELOG.md).
## Getting help
Docker Compose is under active development. If you need help, would like to
contribute, or simply want to talk about the project with like-minded
individuals, we have a number of open channels for communication.
* To report bugs or file feature requests: please use the [issue tracker on Github](https://github.com/docker/compose/issues).
* To talk about the project with people in real time: please join the
`#docker-compose` channel on freenode IRC.
* To contribute code or documentation changes: please submit a [pull request on Github](https://github.com/docker/compose/pulls).
For more information and resources, please visit the [Getting Help project page](https://docs.docker.com/opensource/get-help/).

View file

@ -1,83 +0,0 @@
<!--[metadata]>
+++
title = "Using Compose in Production"
description = "Guide to using Docker Compose in production"
keywords = ["documentation, docs, docker, compose, orchestration, containers, production"]
[menu.main]
parent="workw_compose"
weight=22
+++
<![end-metadata]-->
## Using Compose in production
> Compose is still primarily aimed at development and testing environments.
> Compose may be used for smaller production deployments, but is probably
> not yet suitable for larger deployments.
When deploying to production, you'll almost certainly want to make changes to
your app configuration that are more appropriate to a live environment. These
changes may include:
- Removing any volume bindings for application code, so that code stays inside
the container and can't be changed from outside
- Binding to different ports on the host
- Setting environment variables differently (e.g., to decrease the verbosity of
logging, or to enable email sending)
- Specifying a restart policy (e.g., `restart: always`) to avoid downtime
- Adding extra services (e.g., a log aggregator)
For this reason, you'll probably want to define an additional Compose file, say
`production.yml`, which specifies production-appropriate
configuration. This configuration file only needs to include the changes you'd
like to make from the original Compose file. The additional Compose file
can be applied over the original `docker-compose.yml` to create a new configuration.
Once you've got a second configuration file, tell Compose to use it with the
`-f` option:
$ docker-compose -f docker-compose.yml -f production.yml up -d
See [Using multiple compose files](extends.md#different-environments) for a more
complete example.
### Deploying changes
When you make changes to your app code, you'll need to rebuild your image and
recreate your app's containers. To redeploy a service called
`web`, you would use:
$ docker-compose build web
$ docker-compose up --no-deps -d web
This will first rebuild the image for `web` and then stop, destroy, and recreate
*just* the `web` service. The `--no-deps` flag prevents Compose from also
recreating any services which `web` depends on.
### Running Compose on a single server
You can use Compose to deploy an app to a remote Docker host by setting the
`DOCKER_HOST`, `DOCKER_TLS_VERIFY`, and `DOCKER_CERT_PATH` environment variables
appropriately. For tasks like this,
[Docker Machine](/machine/overview) makes managing local and
remote Docker hosts very easy, and is recommended even if you're not deploying
remotely.
Once you've set up your environment variables, all the normal `docker-compose`
commands will work with no further configuration.
### Running Compose on a Swarm cluster
[Docker Swarm](/swarm/overview), a Docker-native clustering
system, exposes the same API as a single Docker host, which means you can use
Compose against a Swarm instance and run your apps across multiple hosts.
Compose/Swarm integration is still in the experimental stage, but if you'd like
to explore and experiment, check out the [integration guide](swarm.md).
## Compose documentation
- [Installing Compose](install.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -1,144 +0,0 @@
<!--[metadata]>
+++
title = "Quickstart: Compose and Rails"
description = "Getting started with Docker Compose and Rails"
keywords = ["documentation, docs, docker, compose, orchestration, containers"]
[menu.main]
parent="workw_compose"
weight=5
+++
<![end-metadata]-->
## Quickstart: Compose and Rails
This Quickstart guide will show you how to use Compose to set up and run a Rails/PostgreSQL app. Before starting, you'll need to have [Compose installed](install.md).
### Define the project
Start by setting up the three files you'll need to build the app. First, since
your app is going to run inside a Docker container containing all of its
dependencies, you'll need to define exactly what needs to be included in the
container. This is done using a file called `Dockerfile`. To begin with, the
Dockerfile consists of:
FROM ruby:2.2.0
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
That'll put your application code inside an image that will build a container with Ruby, Bundler and all your dependencies inside it. For more information on how to write Dockerfiles, see the [Docker user guide](https://docs.docker.com/engine/userguide/dockerimages/#building-an-image-from-a-dockerfile) and the [Dockerfile reference](https://docs.docker.com/engine/reference/builder/).
Next, create a bootstrap `Gemfile` which just loads Rails. It'll be overwritten in a moment by `rails new`.
source 'https://rubygems.org'
gem 'rails', '4.2.0'
You'll need an empty `Gemfile.lock` in order to build our `Dockerfile`.
$ touch Gemfile.lock
Finally, `docker-compose.yml` is where the magic happens. This file describes the services that comprise your app (a database and a web app), how to get each one's Docker image (the database just runs on a pre-made PostgreSQL image, and the web app is built from the current directory), and the configuration needed to link them together and expose the web app's port.
version: '2'
services:
db:
image: postgres
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
### Build the project
With those three files in place, you can now generate the Rails skeleton app
using `docker-compose run`:
$ docker-compose run web rails new . --force --database=postgresql --skip-bundle
First, Compose will build the image for the `web` service using the
`Dockerfile`. Then it'll run `rails new` inside a new container, using that
image. Once it's done, you should have generated a fresh app:
$ ls
Dockerfile app docker-compose.yml tmp
Gemfile bin lib vendor
Gemfile.lock config log
README.rdoc config.ru public
Rakefile db test
The files `rails new` created are owned by root. This happens because the
container runs as the `root` user. Change the ownership of the new files.
sudo chown -R $USER:$USER .
Uncomment the line in your new `Gemfile` which loads `therubyracer`, so you've
got a Javascript runtime:
gem 'therubyracer', platforms: :ruby
Now that you've got a new `Gemfile`, you need to build the image again. (This,
and changes to the Dockerfile itself, should be the only times you'll need to
rebuild.)
$ docker-compose build
### Connect the database
The app is now bootable, but you're not quite there yet. By default, Rails
expects a database to be running on `localhost` - so you need to point it at the
`db` container instead. You also need to change the database and username to
align with the defaults set by the `postgres` image.
Replace the contents of `config/database.yml` with the following:
development: &default
adapter: postgresql
encoding: unicode
database: postgres
pool: 5
username: postgres
password:
host: db
test:
<<: *default
database: myapp_test
You can now boot the app with:
$ docker-compose up
If all's well, you should see some PostgreSQL output, and then—after a few
seconds—the familiar refrain:
myapp_web_1 | [2014-01-17 17:16:29] INFO WEBrick 1.3.1
myapp_web_1 | [2014-01-17 17:16:29] INFO ruby 2.2.0 (2014-12-25) [x86_64-linux-gnu]
myapp_web_1 | [2014-01-17 17:16:29] INFO WEBrick::HTTPServer#start: pid=1 port=3000
Finally, you need to create the database. In another terminal, run:
$ docker-compose run web rake db:create
That's it. Your app should now be running on port 3000 on your Docker daemon. If you're using [Docker Machine](https://docs.docker.com/machine/), then `docker-machine ip MACHINE_VM` returns the Docker host IP address.
## More Compose documentation
- [User guide](index.md)
- [Installing Compose](install.md)
- [Getting Started](gettingstarted.md)
- [Get started with Django](django.md)
- [Get started with WordPress](wordpress.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -1,25 +0,0 @@
<!--[metadata]>
+++
title = "build"
description = "build"
keywords = ["fig, composition, compose, docker, orchestration, cli, build"]
[menu.main]
identifier="build.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# build
```
Usage: build [options] [SERVICE...]
Options:
--force-rm Always remove intermediate containers.
--no-cache Do not use cache when building the image.
--pull Always attempt to pull a newer version of the image.
```
Services are built once and then tagged as `project_service`, e.g.,
`composetest_db`. If you change a service's Dockerfile or the contents of its
build directory, run `docker-compose build` to rebuild it.

View file

@ -1,23 +0,0 @@
<!--[metadata]>
+++
title = "config"
description = "Config validates and view the compose file."
keywords = ["fig, composition, compose, docker, orchestration, cli, config"]
[menu.main]
identifier="config.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# config
```:
Usage: config [options]
Options:
-q, --quiet Only validate the configuration, don't print
anything.
--services Print the service names, one per line.
```
Validate and view the compose file.

View file

@ -1,25 +0,0 @@
<!--[metadata]>
+++
title = "create"
description = "Create creates containers for a service."
keywords = ["fig, composition, compose, docker, orchestration, cli, create"]
[menu.main]
identifier="create.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# create
```
Usage: create [options] [SERVICE...]
Options:
--force-recreate Recreate containers even if their configuration and
image haven't changed. Incompatible with --no-recreate.
--no-recreate If containers already exist, don't recreate them.
Incompatible with --force-recreate.
--no-build Don't build an image, even if it's missing
```
Creates containers for a service.

View file

@ -1,26 +0,0 @@
<!--[metadata]>
+++
title = "down"
description = "down"
keywords = ["fig, composition, compose, docker, orchestration, cli, down"]
[menu.main]
identifier="down.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# down
```
Stop containers and remove containers, networks, volumes, and images
created by `up`. Only containers and networks are removed by default.
Usage: down [options]
Options:
--rmi type Remove images, type may be one of: 'all' to remove
all images, or 'local' to remove only images that
don't have an custom name set by the `image` field
-v, --volumes Remove data volumes
```

View file

@ -1,78 +0,0 @@
<!--[metadata]>
+++
title = "CLI Environment Variables"
description = "CLI Environment Variables"
keywords = ["fig, composition, compose, docker, orchestration, cli, reference"]
[menu.main]
parent = "smn_compose_cli"
weight=-1
+++
<![end-metadata]-->
# CLI Environment Variables
Several environment variables are available for you to configure the Docker Compose command-line behaviour.
Variables starting with `DOCKER_` are the same as those used to configure the
Docker command-line client. If you're using `docker-machine`, then the `eval "$(docker-machine env my-docker-vm)"` command should set them to their correct values. (In this example, `my-docker-vm` is the name of a machine you created.)
## COMPOSE\_PROJECT\_NAME
Sets the project name. This value is prepended along with the service name to the container container on start up. For example, if you project name is `myapp` and it includes two services `db` and `web` then compose starts containers named `myapp_db_1` and `myapp_web_1` respectively.
Setting this is optional. If you do not set this, the `COMPOSE_PROJECT_NAME`
defaults to the `basename` of the project directory. See also the `-p`
[command-line option](overview.md).
## COMPOSE\_FILE
Specify the file containing the compose configuration. If not provided,
Compose looks for a file named `docker-compose.yml` in the current directory
and then each parent directory in succession until a file by that name is
found. See also the `-f` [command-line option](overview.md).
## COMPOSE\_API\_VERSION
The Docker API only supports requests from clients which report a specific
version. If you receive a `client and server don't have same version error` using
`docker-compose`, you can workaround this error by setting this environment
variable. Set the version value to match the server version.
Setting this variable is intended as a workaround for situations where you need
to run temporarily with a mismatch between the client and server version. For
example, if you can upgrade the client but need to wait to upgrade the server.
Running with this variable set and a known mismatch does prevent some Docker
features from working properly. The exact features that fail would depend on the
Docker client and server versions. For this reason, running with this variable
set is only intended as a workaround and it is not officially supported.
If you run into problems running with this set, resolve the mismatch through
upgrade and remove this setting to see if your problems resolve before notifying
support.
## DOCKER\_HOST
Sets the URL of the `docker` daemon. As with the Docker client, defaults to `unix:///var/run/docker.sock`.
## DOCKER\_TLS\_VERIFY
When set to anything other than an empty string, enables TLS communication with
the `docker` daemon.
## DOCKER\_CERT\_PATH
Configures the path to the `ca.pem`, `cert.pem`, and `key.pem` files used for TLS verification. Defaults to `~/.docker`.
## COMPOSE\_HTTP\_TIMEOUT
Configures the time (in seconds) a request to the Docker daemon is allowed to hang before Compose considers
it failed. Defaults to 60 seconds.
## Related Information
- [User guide](../index.md)
- [Installing Compose](../install.md)
- [Compose file reference](../compose-file.md)

View file

@ -1,34 +0,0 @@
<!--[metadata]>
+++
title = "events"
description = "Receive real time events from containers."
keywords = ["fig, composition, compose, docker, orchestration, cli, events"]
[menu.main]
identifier="events.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# events
```
Usage: events [options] [SERVICE...]
Options:
--json Output events as a stream of json objects
```
Stream container events for every container in the project.
With the `--json` flag, a json object will be printed one per line with the
format:
```
{
"service": "web",
"event": "create",
"container": "213cf75fc39a",
"image": "alpine:edge",
"time": "2015-11-20T18:01:03.615550",
}
```

View file

@ -1,18 +0,0 @@
<!--[metadata]>
+++
title = "help"
description = "help"
keywords = ["fig, composition, compose, docker, orchestration, cli, help"]
[menu.main]
identifier="help.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# help
```
Usage: help COMMAND
```
Displays help and usage instructions for a command.

View file

@ -1,42 +0,0 @@
<!--[metadata]>
+++
title = "Command-line Reference"
description = "Compose CLI reference"
keywords = ["fig, composition, compose, docker, orchestration, cli, reference"]
[menu.main]
identifier = "smn_compose_cli"
parent = "workw_compose"
weight=80
+++
<![end-metadata]-->
## Compose command-line reference
The following pages describe the usage information for the [docker-compose](overview.md) subcommands. You can also see this information by running `docker-compose [SUBCOMMAND] --help` from the command line.
* [docker-compose](overview.md)
* [build](build.md)
* [config](config.md)
* [create](create.md)
* [down](down.md)
* [events](events.md)
* [help](help.md)
* [kill](kill.md)
* [logs](logs.md)
* [pause](pause.md)
* [port](port.md)
* [ps](ps.md)
* [pull](pull.md)
* [restart](restart.md)
* [rm](rm.md)
* [run](run.md)
* [scale](scale.md)
* [start](start.md)
* [stop](stop.md)
* [unpause](unpause.md)
* [up](up.md)
## Where to go next
* [CLI environment variables](envvars.md)
* [docker-compose Command](overview.md)

View file

@ -1,24 +0,0 @@
<!--[metadata]>
+++
title = "kill"
description = "Forces running containers to stop."
keywords = ["fig, composition, compose, docker, orchestration, cli, kill"]
[menu.main]
identifier="kill.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# kill
```
Usage: kill [options] [SERVICE...]
Options:
-s SIGNAL SIGNAL to send to the container. Default signal is SIGKILL.
```
Forces running containers to stop by sending a `SIGKILL` signal. Optionally the
signal can be passed, for example:
$ docker-compose kill -s SIGINT

View file

@ -1,21 +0,0 @@
<!--[metadata]>
+++
title = "logs"
description = "Displays log output from services."
keywords = ["fig, composition, compose, docker, orchestration, cli, logs"]
[menu.main]
identifier="logs.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# logs
```
Usage: logs [options] [SERVICE...]
Options:
--no-color Produce monochrome output.
```
Displays log output from services.

View file

@ -1,117 +0,0 @@
<!--[metadata]>
+++
title = "Overview of docker-compose CLI"
description = "Overview of docker-compose CLI"
keywords = ["fig, composition, compose, docker, orchestration, cli, docker-compose"]
aliases = ["/compose/reference/docker-compose/"]
[menu.main]
parent = "smn_compose_cli"
weight=-2
+++
<![end-metadata]-->
# Overview of docker-compose CLI
This page provides the usage information for the `docker-compose` Command.
You can also see this information by running `docker-compose --help` from the
command line.
```
Define and run multi-container applications with Docker.
Usage:
docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
Options:
-f, --file FILE Specify an alternate compose file (default: docker-compose.yml)
-p, --project-name NAME Specify an alternate project name (default: directory name)
--verbose Show more output
-v, --version Print version and exit
Commands:
build Build or rebuild services
config Validate and view the compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
help Get help on a command
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pulls service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information
```
The Docker Compose binary. You use this command to build and manage multiple
services in Docker containers.
Use the `-f` flag to specify the location of a Compose configuration file. You
can supply multiple `-f` configuration files. When you supply multiple files,
Compose combines them into a single configuration. Compose builds the
configuration in the order you supply the files. Subsequent files override and
add to their successors.
For example, consider this command line:
```
$ docker-compose -f docker-compose.yml -f docker-compose.admin.yml run backup_db`
```
The `docker-compose.yml` file might specify a `webapp` service.
```
webapp:
image: examples/web
ports:
- "8000:8000"
volumes:
- "/data"
```
If the `docker-compose.admin.yml` also specifies this same service, any matching
fields will override the previous file. New values, add to the `webapp` service
configuration.
```
webapp:
build: .
environment:
- DEBUG=1
```
Use a `-f` with `-` (dash) as the filename to read the configuration from
stdin. When stdin is used all paths in the configuration are
relative to the current working directory.
The `-f` flag is optional. If you don't provide this flag on the command line,
Compose traverses the working directory and its parent directories looking for a
`docker-compose.yml` and a `docker-compose.override.yml` file. You must
supply at least the `docker-compose.yml` file. If both files are present on the
same directory level, Compose combines the two files into a single configuration.
The configuration in the `docker-compose.override.yml` file is applied over and
in addition to the values in the `docker-compose.yml` file.
See also the `COMPOSE_FILE` [environment variable](envvars.md#compose-file).
Each configuration has a project name. If you supply a `-p` flag, you can
specify a project name. If you don't specify the flag, Compose uses the current
directory name. See also the `COMPOSE_PROJECT_NAME` [environment variable](
envvars.md#compose-project-name)
## Where to go next
* [CLI environment variables](envvars.md)

View file

@ -1,18 +0,0 @@
<!--[metadata]>
+++
title = "pause"
description = "Pauses running containers for a service."
keywords = ["fig, composition, compose, docker, orchestration, cli, pause"]
[menu.main]
identifier="pause.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# pause
```
Usage: pause [SERVICE...]
```
Pauses running containers of a service. They can be unpaused with `docker-compose unpause`.

View file

@ -1,23 +0,0 @@
<!--[metadata]>
+++
title = "port"
description = "Prints the public port for a port binding.s"
keywords = ["fig, composition, compose, docker, orchestration, cli, port"]
[menu.main]
identifier="port.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# port
```
Usage: port [options] SERVICE PRIVATE_PORT
Options:
--protocol=proto tcp or udp [default: tcp]
--index=index index of the container if there are multiple
instances of a service [default: 1]
```
Prints the public port for a port binding.

View file

@ -1,21 +0,0 @@
<!--[metadata]>
+++
title = "ps"
description = "Lists containers."
keywords = ["fig, composition, compose, docker, orchestration, cli, ps"]
[menu.main]
identifier="ps.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# ps
```
Usage: ps [options] [SERVICE...]
Options:
-q Only display IDs
```
Lists containers.

View file

@ -1,21 +0,0 @@
<!--[metadata]>
+++
title = "pull"
description = "Pulls service images."
keywords = ["fig, composition, compose, docker, orchestration, cli, pull"]
[menu.main]
identifier="pull.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# pull
```
Usage: pull [options] [SERVICE...]
Options:
--ignore-pull-failures Pull what it can and ignores images with pull failures.
```
Pulls service images.

View file

@ -1,21 +0,0 @@
<!--[metadata]>
+++
title = "restart"
description = "Restarts Docker Compose services."
keywords = ["fig, composition, compose, docker, orchestration, cli, restart"]
[menu.main]
identifier="restart.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# restart
```
Usage: restart [options] [SERVICE...]
Options:
-t, --timeout TIMEOUT Specify a shutdown timeout in seconds. (default: 10)
```
Restarts services.

View file

@ -1,27 +0,0 @@
<!--[metadata]>
+++
title = "rm"
description = "Removes stopped service containers."
keywords = ["fig, composition, compose, docker, orchestration, cli, rm"]
[menu.main]
identifier="rm.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# rm
```
Usage: rm [options] [SERVICE...]
Options:
-f, --force Don't ask to confirm removal
-v Remove volumes associated with containers
```
Removes stopped service containers.
By default, volumes attached to containers will not be removed. You can see all
volumes with `docker volume ls`.
Any data which is not in a volume will be lost.

View file

@ -1,55 +0,0 @@
<!--[metadata]>
+++
title = "run"
description = "Runs a one-off command on a service."
keywords = ["fig, composition, compose, docker, orchestration, cli, run"]
[menu.main]
identifier="run.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# run
```
Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
Options:
-d Detached mode: Run container in the background, print
new container name.
--name NAME Assign a name to the container
--entrypoint CMD Override the entrypoint of the image.
-e KEY=VAL Set an environment variable (can be used multiple times)
-u, --user="" Run as specified username or uid
--no-deps Don't start linked services.
--rm Remove container after run. Ignored in detached mode.
-p, --publish=[] Publish a container's port(s) to the host
--service-ports Run command with the service's ports enabled and mapped to the host.
-T Disable pseudo-tty allocation. By default `docker-compose run` allocates a TTY.
```
Runs a one-time command against a service. For example, the following command starts the `web` service and runs `bash` as its command.
$ docker-compose run web bash
Commands you use with `run` start in new containers with the same configuration as defined by the service' configuration. This means the container has the same volumes, links, as defined in the configuration file. There two differences though.
First, the command passed by `run` overrides the command defined in the service configuration. For example, if the `web` service configuration is started with `bash`, then `docker-compose run web python app.py` overrides it with `python app.py`.
The second difference is the `docker-compose run` command does not create any of the ports specified in the service configuration. This prevents the port collisions with already open ports. If you *do want* the service's ports created and mapped to the host, specify the `--service-ports` flag:
$ docker-compose run --service-ports web python manage.py shell
Alternatively manual port mapping can be specified. Same as when running Docker's `run` command - using `--publish` or `-p` options:
$ docker-compose run --publish 8080:80 -p 2022:22 -p 127.0.0.1:2021:21 web python manage.py shell
If you start a service configured with links, the `run` command first checks to see if the linked service is running and starts the service if it is stopped. Once all the linked services are running, the `run` executes the command you passed it. So, for example, you could run:
$ docker-compose run db psql -h db -U docker
This would open up an interactive PostgreSQL shell for the linked `db` container.
If you do not want the `run` command to start linked containers, specify the `--no-deps` flag:
$ docker-compose run --no-deps web python manage.py shell

View file

@ -1,21 +0,0 @@
<!--[metadata]>
+++
title = "scale"
description = "Sets the number of containers to run for a service."
keywords = ["fig, composition, compose, docker, orchestration, cli, scale"]
[menu.main]
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# scale
```
Usage: scale [SERVICE=NUM...]
```
Sets the number of containers to run for a service.
Numbers are specified as arguments in the form `service=num`. For example:
$ docker-compose scale web=2 worker=3

View file

@ -1,18 +0,0 @@
<!--[metadata]>
+++
title = "start"
description = "Starts existing containers for a service."
keywords = ["fig, composition, compose, docker, orchestration, cli, start"]
[menu.main]
identifier="start.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# start
```
Usage: start [SERVICE...]
```
Starts existing containers for a service.

View file

@ -1,22 +0,0 @@
<!--[metadata]>
+++
title = "stop"
description = "Stops running containers without removing them. "
keywords = ["fig, composition, compose, docker, orchestration, cli, stop"]
[menu.main]
identifier="stop.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# stop
```
Usage: stop [options] [SERVICE...]
Options:
-t, --timeout TIMEOUT Specify a shutdown timeout in seconds (default: 10).
```
Stops running containers without removing them. They can be started again with
`docker-compose start`.

View file

@ -1,18 +0,0 @@
<!--[metadata]>
+++
title = "unpause"
description = "Unpauses paused containers for a service."
keywords = ["fig, composition, compose, docker, orchestration, cli, unpause"]
[menu.main]
identifier="unpause.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# unpause
```
Usage: unpause [SERVICE...]
```
Unpauses paused containers of a service.

View file

@ -1,51 +0,0 @@
<!--[metadata]>
+++
title = "up"
description = "Builds, (re)creates, starts, and attaches to containers for a service."
keywords = ["fig, composition, compose, docker, orchestration, cli, up"]
[menu.main]
identifier="up.compose"
parent = "smn_compose_cli"
+++
<![end-metadata]-->
# up
```
Usage: up [options] [SERVICE...]
Options:
-d Detached mode: Run containers in the background,
print new container names.
Incompatible with --abort-on-container-exit.
--no-color Produce monochrome output.
--no-deps Don't start linked services.
--force-recreate Recreate containers even if their configuration
and image haven't changed.
Incompatible with --no-recreate.
--no-recreate If containers already exist, don't recreate them.
Incompatible with --force-recreate.
--no-build Don't build an image, even if it's missing
--abort-on-container-exit Stops all containers if any container was stopped.
Incompatible with -d.
-t, --timeout TIMEOUT Use this timeout in seconds for container shutdown
when attached or when containers are already
running. (default: 10)
```
Builds, (re)creates, starts, and attaches to containers for a service.
Unless they are already running, this command also starts any linked services.
The `docker-compose up` command aggregates the output of each container. When
the command exits, all containers are stopped. Running `docker-compose up -d`
starts the containers in the background and leaves them running.
If there are existing containers for a service, and the service's configuration
or image was changed after the container's creation, `docker-compose up` picks
up the changes by stopping and recreating the containers (preserving mounted
volumes). To prevent Compose from picking up changes, use the `--no-recreate`
flag.
If you want to force Compose to stop and recreate all containers, use the
`--force-recreate` flag.

View file

@ -1,184 +0,0 @@
<!--[metadata]>
+++
title = "Using Compose with Swarm"
description = "How to use Compose and Swarm together to deploy apps to multi-host clusters"
keywords = ["documentation, docs, docker, compose, orchestration, containers, swarm"]
[menu.main]
parent="workw_compose"
+++
<![end-metadata]-->
# Using Compose with Swarm
Docker Compose and [Docker Swarm](/swarm/overview) aim to have full integration, meaning
you can point a Compose app at a Swarm cluster and have it all just work as if
you were using a single Docker host.
The actual extent of integration depends on which version of the [Compose file
format](compose-file.md#versioning) you are using:
1. If you're using version 1 along with `links`, your app will work, but Swarm
will schedule all containers on one host, because links between containers
do not work across hosts with the old networking system.
2. If you're using version 2, your app should work with no changes:
- subject to the [limitations](#limitations) described below,
- as long as the Swarm cluster is configured to use the [overlay
driver](/engine/userguide/networking/dockernetworks.md#an-overlay-network),
or a custom driver which supports multi-host networking.
Read the [Getting started with multi-host
networking](/engine/userguide/networking/get-started-overlay.md) to see how to
set up a Swarm cluster with [Docker Machine](/machine/overview) and the overlay driver.
Once you've got it running, deploying your app to it should be as simple as:
$ eval "$(docker-machine env --swarm <name of swarm master machine>)"
$ docker-compose up
## Limitations
### Building images
Swarm can build an image from a Dockerfile just like a single-host Docker
instance can, but the resulting image will only live on a single node and won't
be distributed to other nodes.
If you want to use Compose to scale the service in question to multiple nodes,
you'll have to build it yourself, push it to a registry (e.g. the Docker Hub)
and reference it from `docker-compose.yml`:
$ docker build -t myusername/web .
$ docker push myusername/web
$ cat docker-compose.yml
web:
image: myusername/web
$ docker-compose up -d
$ docker-compose scale web=3
### Multiple dependencies
If a service has multiple dependencies of the type which force co-scheduling
(see [Automatic scheduling](#automatic-scheduling) below), it's possible that
Swarm will schedule the dependencies on different nodes, making the dependent
service impossible to schedule. For example, here `foo` needs to be co-scheduled
with `bar` and `baz`:
version: "2"
services:
foo:
image: foo
volumes_from: ["bar"]
network_mode: "service:baz"
bar:
image: bar
baz:
image: baz
The problem is that Swarm might first schedule `bar` and `baz` on different
nodes (since they're not dependent on one another), making it impossible to
pick an appropriate node for `foo`.
To work around this, use [manual scheduling](#manual-scheduling) to ensure that
all three services end up on the same node:
version: "2"
services:
foo:
image: foo
volumes_from: ["bar"]
network_mode: "service:baz"
environment:
- "constraint:node==node-1"
bar:
image: bar
environment:
- "constraint:node==node-1"
baz:
image: baz
environment:
- "constraint:node==node-1"
### Host ports and recreating containers
If a service maps a port from the host, e.g. `80:8000`, then you may get an
error like this when running `docker-compose up` on it after the first time:
docker: Error response from daemon: unable to find a node that satisfies
container==6ab2dfe36615ae786ef3fc35d641a260e3ea9663d6e69c5b70ce0ca6cb373c02.
The usual cause of this error is that the container has a volume (defined either
in its image or in the Compose file) without an explicit mapping, and so in
order to preserve its data, Compose has directed Swarm to schedule the new
container on the same node as the old container. This results in a port clash.
There are two viable workarounds for this problem:
- Specify a named volume, and use a volume driver which is capable of mounting
the volume into the container regardless of what node it's scheduled on.
Compose does not give Swarm any specific scheduling instructions if a
service uses only named volumes.
version: "2"
services:
web:
build: .
ports:
- "80:8000"
volumes:
- web-logs:/var/log/web
volumes:
web-logs:
driver: custom-volume-driver
- Remove the old container before creating the new one. You will lose any data
in the volume.
$ docker-compose stop web
$ docker-compose rm -f web
$ docker-compose up web
## Scheduling containers
### Automatic scheduling
Some configuration options will result in containers being automatically
scheduled on the same Swarm node to ensure that they work correctly. These are:
- `network_mode: "service:..."` and `network_mode: "container:..."` (and
`net: "container:..."` in the version 1 file format).
- `volumes_from`
- `links`
### Manual scheduling
Swarm offers a rich set of scheduling and affinity hints, enabling you to
control where containers are located. They are specified via container
environment variables, so you can use Compose's `environment` option to set
them.
# Schedule containers on a specific node
environment:
- "constraint:node==node-1"
# Schedule containers on a node that has the 'storage' label set to 'ssd'
environment:
- "constraint:storage==ssd"
# Schedule containers where the 'redis' image is already pulled
environment:
- "affinity:image==redis"
For the full set of available filters and expressions, see the [Swarm
documentation](/swarm/scheduler/filter.md).

View file

@ -1,104 +0,0 @@
<!--[metadata]>
+++
title = "Quickstart: Compose and WordPress"
description = "Getting started with Compose and WordPress"
keywords = ["documentation, docs, docker, compose, orchestration, containers"]
[menu.main]
parent="workw_compose"
weight=6
+++
<![end-metadata]-->
# Quickstart: Compose and WordPress
You can use Compose to easily run WordPress in an isolated environment built
with Docker containers.
## Define the project
First, [Install Compose](install.md) and then download WordPress into the
current directory:
$ curl https://wordpress.org/latest.tar.gz | tar -xvzf -
This will create a directory called `wordpress`. If you wish, you can rename it
to the name of your project.
Next, inside that directory, create a `Dockerfile`, a file that defines what
environment your app is going to run in. For more information on how to write
Dockerfiles, see the
[Docker user guide](https://docs.docker.com/engine/userguide/dockerimages/#building-an-image-from-a-dockerfile) and the
[Dockerfile reference](https://docs.docker.com/engine/reference/builder/). In
this case, your Dockerfile should be:
FROM orchardup/php5
ADD . /code
This tells Docker how to build an image defining a container that contains PHP
and WordPress.
Next you'll create a `docker-compose.yml` file that will start your web service
and a separate MySQL instance:
version: '2'
services:
web:
build: .
command: php -S 0.0.0.0:8000 -t /code
ports:
- "8000:8000"
depends_on:
- db
volumes:
- .:/code
db:
image: orchardup/mysql
environment:
MYSQL_DATABASE: wordpress
A supporting file is needed to get this working. `wp-config.php` is
the standard WordPress config file with a single change to point the database
configuration at the `db` container:
<?php
define('DB_NAME', 'wordpress');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', "db:3306");
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
define('AUTH_KEY', 'put your unique phrase here');
define('SECURE_AUTH_KEY', 'put your unique phrase here');
define('LOGGED_IN_KEY', 'put your unique phrase here');
define('NONCE_KEY', 'put your unique phrase here');
define('AUTH_SALT', 'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT', 'put your unique phrase here');
define('NONCE_SALT', 'put your unique phrase here');
$table_prefix = 'wp_';
define('WPLANG', '');
define('WP_DEBUG', false);
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');
require_once(ABSPATH . 'wp-settings.php');
### Build the project
With those four files in place, run `docker-compose up` inside your WordPress
directory and it'll pull and build the needed images, and then start the web and
database containers. If you're using [Docker Machine](https://docs.docker.com/machine/), then `docker-machine ip MACHINE_VM` gives you the machine address and you can open `http://MACHINE_VM_IP:8000` in a browser.
## More Compose documentation
- [User guide](index.md)
- [Installing Compose](install.md)
- [Getting Started](gettingstarted.md)
- [Get started with Django](django.md)
- [Get started with Rails](rails.md)
- [Command line reference](./reference/index.md)
- [Compose file reference](compose-file.md)

View file

@ -1,183 +1,5 @@
# Experimental: Compose, Swarm and Multi-Host Networking
The [experimental build of Docker](https://github.com/docker/docker/tree/master/experimental) has an entirely new networking system, which enables secure communication between containers on multiple hosts. In combination with Docker Swarm and Docker Compose, you can now run multi-container apps on multi-host clusters with the same tooling and configuration format you use to develop them locally.
Compose now supports multi-host networking as standard. Read more here:
> Note: This functionality is in the experimental stage, and contains some hacks and workarounds which will be removed as it matures.
## Prerequisites
Before you start, youll need to install the experimental build of Docker, and the latest versions of Machine and Compose.
- To install the experimental Docker build on a Linux machine, follow the instructions [here](https://github.com/docker/docker/tree/master/experimental#install-docker-experimental).
- To install the experimental Docker build on a Mac, run these commands:
$ curl -L https://experimental.docker.com/builds/Darwin/x86_64/docker-latest > /usr/local/bin/docker
$ chmod +x /usr/local/bin/docker
- To install Machine, follow the instructions [here](https://docs.docker.com/machine/install-machine/).
- To install Compose, follow the instructions [here](https://docs.docker.com/compose/install/).
Youll also need a [Docker Hub](https://hub.docker.com/account/signup/) account and a [Digital Ocean](https://www.digitalocean.com/) account.
## Set up a swarm with multi-host networking
Set the `DIGITALOCEAN_ACCESS_TOKEN` environment variable to a valid Digital Ocean API token, which you can generate in the [API panel](https://cloud.digitalocean.com/settings/applications).
DIGITALOCEAN_ACCESS_TOKEN=abc12345
Start a consul server:
docker-machine create -d digitalocean --engine-install-url https://experimental.docker.com consul
docker $(docker-machine config consul) run -d -p 8500:8500 -h consul progrium/consul -server -bootstrap
(In a real world setting youd set up a distributed consul, but thats beyond the scope of this guide!)
Create a Swarm token:
SWARM_TOKEN=$(docker run swarm create)
Create a Swarm master:
docker-machine create -d digitalocean --swarm --swarm-master --swarm-discovery=token://$SWARM_TOKEN --engine-install-url="https://experimental.docker.com" --digitalocean-image "ubuntu-14-10-x64" --engine-opt=default-network=overlay:multihost --engine-label=com.docker.network.driver.overlay.bind_interface=eth0 --engine-opt=kv-store=consul:$(docker-machine ip consul):8500 swarm-0
Create a Swarm node:
docker-machine create -d digitalocean --swarm --swarm-discovery=token://$SWARM_TOKEN --engine-install-url="https://experimental.docker.com" --digitalocean-image "ubuntu-14-10-x64" --engine-opt=default-network=overlay:multihost --engine-label=com.docker.network.driver.overlay.bind_interface=eth0 --engine-opt=kv-store=consul:$(docker-machine ip consul):8500 --engine-label com.docker.network.driver.overlay.neighbor_ip=$(docker-machine ip swarm-0) swarm-1
You can create more Swarm nodes if you want - its best to give them sensible names (swarm-2, swarm-3, etc).
Finally, point Docker at your swarm:
eval "$(docker-machine env --swarm swarm-0)"
## Run containers and get them communicating
Now that youve got a swarm up and running, you can create containers on it just like a single Docker instance:
$ docker run busybox echo hello world
hello world
If you run `docker ps -a`, you can see what node that container was started on by looking at its name (here its swarm-3):
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
41f59749737b busybox "echo hello world" 15 seconds ago Exited (0) 13 seconds ago swarm-3/trusting_leakey
As you start more containers, theyll be placed on different nodes across the cluster, thanks to Swarms default “spread” scheduling strategy.
Every container started on this swarm will use the “overlay:multihost” network by default, meaning they can all intercommunicate. Each container gets an IP address on that network, and an `/etc/hosts` file which will be updated on-the-fly with every other containers IP address and name. That means that if you have a running container named foo, other containers can access it at the hostname foo.
Lets verify that multi-host networking is functioning. Start a long-running container:
$ docker run -d --name long-running busybox top
<container id>
If you start a new container and inspect its /etc/hosts file, youll see the long-running container in there:
$ docker run busybox cat /etc/hosts
...
172.21.0.6 long-running
Verify that connectivity works between containers:
$ docker run busybox ping long-running
PING long-running (172.21.0.6): 56 data bytes
64 bytes from 172.21.0.6: seq=0 ttl=64 time=7.975 ms
64 bytes from 172.21.0.6: seq=1 ttl=64 time=1.378 ms
64 bytes from 172.21.0.6: seq=2 ttl=64 time=1.348 ms
^C
--- long-running ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.140/2.099/7.975 ms
## Run a Compose application
Heres an example of a simple Python + Redis app using multi-host networking on a swarm.
Create a directory for the app:
$ mkdir composetest
$ cd composetest
Inside this directory, create 2 files.
First, create `app.py` - a simple web app that uses the Flask framework and increments a value in Redis:
from flask import Flask
from redis import Redis
import os
app = Flask(__name__)
redis = Redis(host='composetest_redis_1', port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello World! I have been seen %s times.' % redis.get('hits')
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
Note that were connecting to a host called `composetest_redis_1` - this is the name of the Redis container that Compose will start.
Second, create a Dockerfile for the app container:
FROM python:2.7
RUN pip install flask redis
ADD . /code
WORKDIR /code
CMD ["python", "app.py"]
Build the Docker image and push it to the Hub (youll need a Hub account). Replace `<username>` with your Docker Hub username:
$ docker build -t <username>/counter .
$ docker push <username>/counter
Next, create a `docker-compose.yml`, which defines the configuration for the web and redis containers. Once again, replace `<username>` with your Hub username:
web:
image: <username>/counter
ports:
- "80:5000"
redis:
image: redis
Now start the app:
$ docker-compose up -d
Pulling web (username/counter:latest)...
swarm-0: Pulling username/counter:latest... : downloaded
swarm-2: Pulling username/counter:latest... : downloaded
swarm-1: Pulling username/counter:latest... : downloaded
swarm-3: Pulling username/counter:latest... : downloaded
swarm-4: Pulling username/counter:latest... : downloaded
Creating composetest_web_1...
Pulling redis (redis:latest)...
swarm-2: Pulling redis:latest... : downloaded
swarm-1: Pulling redis:latest... : downloaded
swarm-3: Pulling redis:latest... : downloaded
swarm-4: Pulling redis:latest... : downloaded
swarm-0: Pulling redis:latest... : downloaded
Creating composetest_redis_1...
Swarm has created containers for both web and redis, and placed them on different nodes, which you can check with `docker ps`:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
92faad2135c9 redis "/entrypoint.sh redi 43 seconds ago Up 42 seconds swarm-2/composetest_redis_1
adb809e5cdac username/counter "/bin/sh -c 'python 55 seconds ago Up 54 seconds 45.67.8.9:80->5000/tcp swarm-1/composetest_web_1
You can also see that the web container has exposed port 80 on its swarm node. If you curl that IP, youll get a response from the container:
$ curl http://45.67.8.9
Hello World! I have been seen 1 times.
If you hit it repeatedly, the counter will increment, demonstrating that the web and redis container are communicating:
$ curl http://45.67.8.9
Hello World! I have been seen 2 times.
$ curl http://45.67.8.9
Hello World! I have been seen 3 times.
$ curl http://45.67.8.9
Hello World! I have been seen 4 times.
https://docs.docker.com/compose/networking

View file

@ -20,18 +20,30 @@ release.
As part of this script you'll be asked to:
1. Update the version in `docs/install.md` and `compose/__init__.py`.
1. Update the version in `compose/__init__.py` and `script/run/run.sh`.
If the next release will be an RC, append `rcN`, e.g. `1.4.0rc1`.
If the next release will be an RC, append `-rcN`, e.g. `1.4.0-rc1`.
2. Write release notes in `CHANGES.md`.
Almost every feature enhancement should be mentioned, with the most visible/exciting ones first. Use descriptive sentences and give context where appropriate.
Almost every feature enhancement should be mentioned, with the most
visible/exciting ones first. Use descriptive sentences and give context
where appropriate.
Bug fixes are worth mentioning if it's likely that they've affected lots of people, or if they were regressions in the previous version.
Bug fixes are worth mentioning if it's likely that they've affected lots
of people, or if they were regressions in the previous version.
Improvements to the code are not worth mentioning.
3. Create a new repository on [bintray](https://bintray.com/docker-compose).
The name has to match the name of the branch (e.g. `bump-1.9.0`) and the
type should be "Generic". Other fields can be left blank.
4. Check that the `vnext-compose` branch on
[the docs repo](https://github.com/docker/docker.github.io/) has
documentation for all the new additions in the upcoming release, and create
a PR there for what needs to be amended.
## When a PR is merged into master that we want in the release
@ -55,10 +67,10 @@ Check out the bump branch and run the `build-binaries` script
When prompted build the non-linux binaries and test them.
1. Build the Mac binary in a Mountain Lion VM:
1. Download the osx binary from Bintray. Make sure that the latest Travis
build has finished, otherwise you'll be downloading an old binary.
script/prepare-osx
script/build-osx
https://dl.bintray.com/docker-compose/$BRANCH_NAME/
2. Download the windows binary from AppVeyor
@ -67,28 +79,30 @@ When prompted build the non-linux binaries and test them.
3. Draft a release from the tag on GitHub (the script will open the window for
you)
In the "Tag version" dropdown, select the tag you just pushed.
The tag will only be present on Github when you run the `push-release`
script in step 7, but you can pre-fill it at that point.
4. Paste in installation instructions and release notes. Here's an example - change the Compose version and Docker version as appropriate:
4. Paste in installation instructions and release notes. Here's an example -
change the Compose version and Docker version as appropriate:
Firstly, note that Compose 1.5.0 requires Docker 1.8.0 or later.
If you're a Mac or Windows user, the best way to install Compose and keep it up-to-date is **[Docker for Mac and Windows](https://www.docker.com/products/docker)**.
Secondly, if you're a Mac user, the **[Docker Toolbox](https://www.docker.com/toolbox)** will install Compose 1.5.0 for you, alongside the latest versions of the Docker Engine, Machine and Kitematic.
Note that Compose 1.9.0 requires Docker Engine 1.10.0 or later for version 2 of the Compose File format, and Docker Engine 1.9.1 or later for version 1. Docker for Mac and Windows will automatically install the latest version of Docker Engine for you.
Otherwise, you can use the usual commands to install/upgrade. Either download the binary:
Alternatively, you can use the usual commands to install or upgrade Compose:
curl -L https://github.com/docker/compose/releases/download/1.5.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
```
curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
```
Or install the PyPi package:
pip install -U docker-compose==1.5.0
See the [install docs](https://docs.docker.com/compose/install/) for more install options and instructions.
Here's what's new:
...release notes go here...
5. Attach the binaries and `script/run.sh`
5. Attach the binaries and `script/run/run.sh`
6. Add "Thanks" with a list of contributors. The contributor list can be generated
by running `./script/release/contributors`.
@ -99,6 +113,8 @@ When prompted build the non-linux binaries and test them.
./script/release/push-release
8. Merge the bump PR.
8. Publish the release on GitHub.
9. Check that all the binaries download (following the install instructions) and run.
@ -107,19 +123,7 @@ When prompted build the non-linux binaries and test them.
## If its a stable release (not an RC)
1. Merge the bump PR.
2. Make sure `origin/release` is updated locally:
git fetch origin
3. Update the `docs` branch on the upstream repo:
git push git@github.com:docker/compose.git origin/release:docs
4. Let the docs team know that its been updated so they can publish it.
5. Close the releases milestone.
1. Close the releases milestone.
## If its a minor release (1.x.0), rather than a patch release (1.x.y)

View file

@ -1 +1 @@
pyinstaller==3.1.1
pyinstaller==3.2.1

View file

@ -1,11 +1,16 @@
PyYAML==3.11
backports.ssl-match-hostname==3.5.0.1; python_version < '3'
cached-property==1.2.0
docker-py==1.7.1
colorama==0.3.7
docker==2.0.2
dockerpty==0.4.1
docopt==0.6.1
enum34==1.0.4
enum34==1.0.4; python_version < '3.4'
functools32==3.2.3.post2; python_version < '3.2'
ipaddress==1.0.16
jsonschema==2.5.1
requests==2.7.0
six==1.7.3
pypiwin32==219; sys_platform == 'win32'
requests==2.11.1
six==1.10.0
texttable==0.8.4
websocket-client==0.32.0

View file

@ -1,16 +0,0 @@
#!/bin/bash
set -e
if [ -z "$1" ]; then
>&2 echo "First argument must be image tag."
exit 1
fi
TAG=$1
VERSION="$(python setup.py --version)"
./script/write-git-sha
python setup.py sdist
cp dist/docker-compose-$VERSION.tar.gz dist/docker-compose-release.tar.gz
docker build -t docker/compose:$TAG -f Dockerfile.run .

15
script/build/image Executable file
View file

@ -0,0 +1,15 @@
#!/bin/bash
set -e
if [ -z "$1" ]; then
>&2 echo "First argument must be image tag."
exit 1
fi
TAG=$1
VERSION="$(python setup.py --version)"
./script/build/write-git-sha
python setup.py sdist bdist_wheel
docker build --build-arg version=$VERSION -t docker/compose:$TAG -f Dockerfile.run .

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