Compare commits

...

142 commits

Author SHA1 Message Date
Daniel Nephin
be6b811c4e Bump 1.5.0rc3
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:53:17 -04:00
Daniel Nephin
bdb9a280bc Make storage driver configurable in CI
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:53:16 -04:00
Daniel Nephin
73ca4eb599 On error print daemon logs
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:46:57 -04:00
Daniel Nephin
569ccbadec Convert the README to rst and fix the logo url before packaging it up for pypi.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:46:57 -04:00
Daniel Nephin
ed1b584c42 Fix release script notes about software and typos.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:46:57 -04:00
Daniel Nephin
2f2e946907 Don't set a default network driver, let the server decide.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:36:15 -04:00
Daniel Nephin
d392f70cc6 Fixes #1843, #1936 - chown files back to host user in django example.
Also add a missing 'touch Gemfile.lock' to fix the rails tutorial.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:36:15 -04:00
Daniel Nephin
db164cefd3 Remove the duplicate 'Warning' prefix now that the logger adds the prefix.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:36:15 -04:00
Daniel Nephin
4d613d3ba7 Use colors when logging warnings or errors, so they are more obvious.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-30 15:36:15 -04:00
Joffrey F
1f26841e23 Integration test for run command with networking enabled
Signed-off-by: Joffrey F <joffrey@docker.com>
2015-10-30 15:36:15 -04:00
Joffrey F
9370cb033c Ensure network exists when calling run before up
Otherwise the daemon will error out because the network doesn't exist
yet.

Signed-off-by: Joffrey F <joffrey@docker.com>
2015-10-30 15:36:15 -04:00
Mazz Mosley
ab0ddb593f Clarify the command is an example
Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-10-29 15:01:33 -04:00
Daniel Nephin
f67503d9fd Logs are available for all log drivers except for none.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-29 15:01:33 -04:00
Daniel Nephin
ce729b0721 Update docs about networking for current release.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-29 15:01:33 -04:00
Daniel Nephin
8156cdc56e Disable a test against docker 1.8.3 because it fails due to a bug in docker engine.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-29 15:01:33 -04:00
Daniel Nephin
8cc8e61474 Bump 1.5.0rc2
Signed-off-by: Daniel Nephin <dnephin@docker.com>

Fill out 1.5.0 release notes

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-10-27 19:48:54 -04:00
Sven Dowideit
29b0ffe5e9 Possible link fixes
Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
2015-10-27 19:33:28 -04:00
Mazz Mosley
a772a0d7d7 Remove redundant try/except
Code cleanup. We no longer need this as the api returns a 304 for any
stopped containers, which doesn't raise an error.

Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-10-27 19:33:28 -04:00
Mazz Mosley
6f0096c87b Move rename functionality into Container
Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-10-27 19:33:28 -04:00
Mazz Mosley
da41ed22f9 Fix tests
Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-10-27 19:33:28 -04:00
Mazz Mosley
d6fa8596d2 Attach to a container's log_stream before they're started
So we're not displaying output of all previous logs for a container, we attach,
if possible, to a container before the container is started.

LogPrinter checks if a container has a log_stream already attached and
print from that rather than always attempting to attach one itself.

Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-10-27 19:33:28 -04:00
Daniel Nephin
a9b4fe768d Fix running one-off containers with --x-networking by disabling linking to self.
docker create fails if networking and links are used together.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-27 19:33:28 -04:00
Daniel Nephin
88e53e177d Upgrade pyinstaller to 3.0
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-26 13:05:41 -04:00
Daniel Nephin
e168fd03ca Fix unicode in environment variables for python2.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-26 13:05:41 -04:00
Daniel Nephin
95a23eb682 Change version check from engine version to api version.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-26 13:05:40 -04:00
Daniel Nephin
f5ad363143 Use inspect network to query for an existing network.
And more tests for get_network()

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-26 13:05:40 -04:00
Daniel Nephin
f290faf4ba Minor refactor to use guard and replace instead of split+join
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-21 11:29:49 -04:00
Daniel Nephin
725088a18b Force windows drives to be lowercase.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-21 11:29:49 -04:00
Daniel Nephin
bf672ec340 Fixes #2205 - extends must be copied from override file.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-20 11:27:11 -04:00
Mazz Mosley
0e4f9c9a66 Environment keys can contain empty values
Environment keys that contain no value, get populated with values taken
from the environment not from the build phase but from running the command `up`.

Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-10-19 15:16:19 -04:00
Mazz Mosley
5fdb75b541 Improve error message for type constraints
It was missing a space between the different types, when there
were 3 possible type values.

Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-10-19 15:16:19 -04:00
Daniel Nephin
24d4a1045a Fixes #2203 - properly validate files when multiple files are used.
Remove the single-use decorators so the functionality can be used directly as a function.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-19 15:16:19 -04:00
Daniel Nephin
514f0650b2 Give the user a better error message (without a stack trace) when there is a yaml error.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-19 12:02:40 -04:00
Steve Durrheimer
20d34c8b14 Add zsh completion for 'docker-compose --x-networking --x-network-driver'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2015-10-19 10:38:22 -04:00
Harald Albers
6f45eb7959 bash completion for networking options
Signed-off-by: Harald Albers <github@albersweb.de>
2015-10-19 10:11:35 -04:00
Mazz Mosley
49b98fa111 Attempt to document escaping env vars
People are likely to run into their env vars being set to empty strings,
if they're not aware that they need to escape them for Compose to not
interpolate them.

Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-10-16 15:52:32 -04:00
Cameron Eagans
6048630a11 docker-compose pull SERVICE should not pull SERVICE's dependencies
Signed-off-by: Cameron Eagans <me@cweagans.net>
2015-10-16 12:59:57 -04:00
Aanand Prasad
46de4411a7 Revert networking-related changes to getting started guides
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-10-16 12:59:57 -04:00
Karol Duleba
883f251e7d Docs for shorthand notation of extends. Issue #1989
Signed-off-by: Karol Duleba <mr.fuxi@gmail.com>
2015-10-16 12:59:57 -04:00
Daniel Nephin
284cda087e Add missing merge for release branch.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-16 12:59:57 -04:00
Daniel Nephin
b2f9c182f3 Fix some release docs.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-16 12:59:57 -04:00
Daniel Nephin
558098d322 Add a script to generate contributor list.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-16 12:59:57 -04:00
Per Persson
6571e079b9 Remove incorrectly placed comment
I'm not sure if it should be there at all, but at least it should hardly be where it currently is located.

Signed-off-by: Per Persson <per.persson@exertisztorm.com>
2015-10-16 12:59:57 -04:00
Tim Butler
49ca23c034 Fix link to Release Process doc in README.md
Signed-off-by: Tim Butler <tim.butler.au@gmail.com>
2015-10-16 12:59:57 -04:00
Daniel Nephin
709bd9c363 Bump 1.5.0rc1
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-14 12:59:31 -04:00
Daniel Nephin
8cecf2e02d Merge remote-tracking branch 'docker/release' into bump-1.5.0rc1 2015-10-14 12:59:25 -04:00
Daniel Nephin
d59c759cdd Merge pull request #2082 from dnephin/bump-1.4.2
[WIP] Release 1.4.2
2015-09-22 14:17:04 -04:00
Daniel Nephin
7b5d5fcd58 Bump 1.4.2
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-09-22 12:26:51 -04:00
Daniel Nephin
d01f712376 Fix a test case that assumes busybox image id.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-09-22 12:26:51 -04:00
Daniel Nephin
ac75d35927 Fix #1961 - docker-compose up should attach to all containers with no service names are specified, and add tests.
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
2015-09-22 11:09:59 -04:00
Daniel Nephin
605d7f26e7 Merge pull request #2027 from dnephin/bump-1.4.1
Bump 1.4.1
2015-09-15 17:47:09 -04:00
Daniel Nephin
b24ca75914 Bump 1.4.1
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-09-14 18:18:01 -04:00
Daniel Nephin
2b75741e5a Fix cherry-pick errors.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-09-11 14:22:35 -04:00
Daniel Nephin
7ff8c2b224 Resolves #1804
Fix mutation of service.options when a label or environment variable is specified in the config.

Signed-off-by: Daniel Nephin <dnephin@gmail.com>
2015-09-10 19:32:30 -04:00
Daniel Nephin
db31adc208 Extract link names into a function.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-09-10 19:32:30 -04:00
Daniel Nephin
805f6a7683 Refactor network_mode logic out of Service.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-09-10 19:32:30 -04:00
Daniel Nephin
d92f323e6d Fixes #1757 - include all service properties in the config_dict()
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
2015-09-10 19:32:30 -04:00
Daniel Nephin
cf2dbf55b8 Cleanup some project logic.
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
2015-09-10 19:32:30 -04:00
Daniel Nephin
8d4c724c2d Sort config keys
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
2015-09-10 19:32:30 -04:00
Daniel Nephin
9cb2770da4 Make external_links a regular service.option so that it's part of the config hash
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
2015-09-10 19:32:30 -04:00
Daniel Nephin
6a23491fa9 Resolves #1856, fix regression in #1645. Includes some refactoring to make testing easier.
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
2015-09-10 19:32:30 -04:00
Mazz Mosley
294b9742be Handle all exceptions
If we get back an error that wasn't an APIError, it was causing the
thread to hang. This catch all, while I appreciate feels risky to
have a catch all, is better than not catching and silently failing,
with a never ending thread.

If something worse than an APIError has gone wrong, we want to stop
the incredible journey of what we're doing.

Signed-off-by: Mazz Mosley <mazz@houseofmnowster.com>
2015-09-10 19:32:30 -04:00
Aanand Prasad
a9b1f15f92 Fix volume path warning
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-09-10 19:32:29 -04:00
Aanand Prasad
aa7c7cdf93 Merge pull request #1763 from aanand/bump-1.4.0
Bump 1.4.0
2015-08-11 18:38:49 +01:00
Aanand Prasad
28139ab90d Bump 1.4.0
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-08-11 16:00:20 +01:00
Aanand Prasad
d0792b49fa Merge pull request #1846 from aanand/fix-mem-limit-options
Fix mem_limit and memswap_limit regression
(cherry picked from commit 93cc7e3751)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-08-11 16:00:20 +01:00
Mazz Mosley
5548aa5c79 Merge pull request #1833 from aanand/deprecate-relative-volumes-without-dot
Show a warning when a relative path is specified without "./"
(cherry picked from commit 52733f6996)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>

Conflicts:
	compose/config.py
	tests/unit/config_test.py
2015-08-11 12:57:42 +01:00
Ben Firshman
16440ff055 Merge pull request #1829 from vlajos/typofixes-vlajos-20150807
typofix - https://github.com/vlajos/misspell_fixer
(cherry picked from commit b7baa899e2)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-08-11 09:44:28 +01:00
Ben Firshman
7850d6de45 Merge pull request #1832 from aanand/use-docker-1.8.0-rc3
Test against Docker 1.8.0 RC3
(cherry picked from commit afc9629c59)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-08-11 09:44:28 +01:00
Ben Firshman
74b4fb89bb Merge pull request #1835 from aanand/fix-crash-when-container-has-no-name
Ignore containers that don't have a name
(cherry picked from commit 4e12ce39b3)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-08-11 09:44:27 +01:00
Ben Firshman
22ccf35fa1 Merge pull request #1836 from aanand/use-overlay-driver-in-tests
Use overlay driver in tests
(cherry picked from commit 197d332620)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-08-11 09:44:27 +01:00
Aanand Prasad
7ad1fe24bd Merge pull request #1815 from aanand/abort-if-daemon-cant-start
Abort tests if daemon fails to start
(cherry picked from commit f7b9daf927)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-08-11 09:44:27 +01:00
Aanand Prasad
450ba978c1 Merge pull request #1812 from moxiegirl/install-update-for-1811
Closes #1811 for Toolbox
(cherry picked from commit 6cb8e512f2)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>

Conflicts:
	docs/install.md
2015-08-10 12:51:10 +01:00
Aanand Prasad
3d6946417d Merge pull request #1800 from aanand/volume-driver-support
Support volume_driver
(cherry picked from commit 41b9df7639)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-31 16:29:24 +01:00
Daniel Nephin
31cf63b374 Merge pull request #1799 from d2bit/clean-rails-quickstart-guide-db-config
Remove useless postgres 'port' configuration
(cherry picked from commit b25f05bed4)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-31 15:46:07 +01:00
Daniel Nephin
5c853c4a2c Merge pull request #1794 from aanand/add-test-for-trailing-slash-volume-copy
Add test for trailing slash volume copying bug
(cherry picked from commit ea7276031c)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-31 15:29:44 +01:00
Aanand Prasad
ad922cd7a1 Merge pull request #1787 from aanand/fix-duplicate-volume-bind
Fix "Duplicate volume mount" error when config has trailing slashes
(cherry picked from commit dc7bdd10d4)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-31 15:29:44 +01:00
Aanand Prasad
49bafdc4cd Merge pull request #1777 from aanand/update-api-version
Update API version to 1.19
(cherry picked from commit 276e369c31)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-31 15:29:44 +01:00
Aanand Prasad
989b2491b9 Merge pull request #1780 from gheart/specify_api_version_via_env
Allow API version specification via env var
(cherry picked from commit 2759ab5ab6)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-31 15:29:44 +01:00
Aanand Prasad
ca2ce3a034 Merge pull request #1779 from aanand/mac-binary-error-hint
Add hint about OS X binary compatibility
(cherry picked from commit 1496734cbb)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-31 15:29:43 +01:00
Aanand Prasad
dfe9dccab8 Merge pull request #1774 from moxiegirl/test-entire-build
Contributors can build public docs with compose docs in context
(cherry picked from commit 487eae3b7b)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-31 15:29:43 +01:00
Aanand Prasad
d456c3909d Merge remote-tracking branch 'origin/release' into bump-1.4.0 2015-07-23 16:46:57 +01:00
Aanand Prasad
29ceef6d93 Merge pull request #1706 from aanand/bump-1.3.3
Bump 1.3.3
2015-07-16 11:40:20 +01:00
Aanand Prasad
8cff440800 Bump 1.3.3
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-16 11:21:01 +01:00
Mazz Mosley
e5f6ae767d Merge pull request #1704 from aanand/fix-timeout-type
Make sure up/restart/stop timeout is an int
(cherry picked from commit c7dccccd1f)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-16 11:19:21 +01:00
Aanand Prasad
cd44179305 Merge pull request #1705 from aanand/fix-labels-null
Handle case where /containers/json returns "Labels": null
(cherry picked from commit 7b9664be8e)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-15 17:33:08 +01:00
Aanand Prasad
c3c5b354b8 Merge pull request #1690 from aanand/bump-1.3.2
Bump 1.3.2
2015-07-14 18:04:22 +01:00
Aanand Prasad
95cf195dbd Bump 1.3.2
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-14 17:40:43 +01:00
Aanand Prasad
a80afd67ab Merge pull request #1688 from aanand/use-docker-py-1.3.0
Use docker-py 1.3.0
(cherry picked from commit 1e71eebc74)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-14 17:29:25 +01:00
Aanand Prasad
4bc4d273ac Merge pull request #1643 from aanand/warn-about-legacy-one-off-containers
Show an error on 'run' when there are legacy one-off containers
(cherry picked from commit 81707ef1ad)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-14 17:29:12 +01:00
Aanand Prasad
4911c77134 Merge pull request #1489 from dnephin/faster_integration_tests
Faster integration tests
(cherry picked from commit 5231288b4e)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>

Conflicts:
	compose/cli/main.py
2015-07-14 17:28:54 +01:00
Aanand Prasad
c1b9a76a54 Merge pull request #1658 from aanand/fix-smart-recreate-nonexistent-image
Fix smart recreate when 'image' is changed to something nonexistent
(cherry picked from commit 2bc10db545)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-14 17:25:33 +01:00
Aanand Prasad
c31e25af72 Merge pull request #1642 from aanand/fix-1573
Fix bug where duplicate container is leftover after 'up' fails
(cherry picked from commit f42fd6a3ad)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-14 17:25:03 +01:00
Aanand Prasad
c8295d36cc Merge pull request #1644 from aanand/fix-rm-bug
Stop 'rm' and 'ps' listing services not defined in the current file
(cherry picked from commit d85688892c)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-14 17:24:15 +01:00
Aanand Prasad
b12c29479e Merge pull request #1521 from dano/validate-service-names
Validate that service names passed to Project.containers aren't bogus.
(cherry picked from commit bc14c473c9)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-07-14 17:24:15 +01:00
Aanand Prasad
cd47829f3d Merge pull request #1588 from aanand/bump-1.3.1
Bump 1.3.1
2015-06-22 08:01:13 -07:00
Aanand Prasad
4d4ef4e0b3 Bump 1.3.1
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-21 17:32:36 -07:00
Aanand Prasad
882ef2ccd8 Merge pull request #1578 from aanand/fix-migrate-help
Fix 'docker-compose help migrate-to-labels'
(cherry picked from commit c8751980f9)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-21 17:28:18 -07:00
Aanand Prasad
d6cd76c3c1 Merge pull request #1570 from aanand/fix-build-pull
Explicitly set pull=False when building
(cherry picked from commit 4f83a18912)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-21 17:28:09 -07:00
Ben Firshman
bd0be2cdc7 Merge pull request #1580 from aanand/dont-set-network-mode-when-none-is-specified
Don't set network mode when none is specified
(cherry picked from commit 911cd60360)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-21 17:27:59 -07:00
Aanand Prasad
a8d7ebd987 Merge pull request #1461 from aanand/bump-1.3.0
Bump 1.3.0
2015-06-18 11:41:40 -07:00
Aanand Prasad
00f61196a4 Bump 1.3.0
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-18 11:25:10 -07:00
Aanand Prasad
c21d6706b6 Merge pull request #1565 from aanand/use-docker-1.7.0
Use docker 1.7.0 and docker-py 1.2.3
(cherry picked from commit 8ffeaf2a54)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>

Conflicts:
	Dockerfile
2015-06-18 11:25:10 -07:00
Aanand Prasad
c3c5d91c47 Merge pull request #1563 from moxiegirl/hugo-test-fixes
Hugo final 1.7 Documentation PR -- please read carefully
(cherry picked from commit 4e73e86d94)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-18 11:25:10 -07:00
Aanand Prasad
7fa4cd1214 Merge pull request #1552 from aanand/add-upgrade-instructions
Add upgrading instructions to install docs
(cherry picked from commit bc7161b475)
2015-06-16 16:29:18 -07:00
Aanand Prasad
f353d9fbc0 Merge pull request #1406 from vdemeester/667-compose-port-scale
Fixing docker-compose port with scale (#667)
(cherry picked from commit 5b2a0cc73d)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:08 -07:00
Daniel Nephin
09018855ce Merge pull request #1550 from aanand/update-docker-py
Update setup.py with new docker-py minimum
(cherry picked from commit b3b44b8e4c)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:08 -07:00
Aanand Prasad
719954b02f Merge pull request #1545 from moxiegirl/test-tooling
Updated for new documentation tooling
(cherry picked from commit aaccd12d3d)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:08 -07:00
Daniel Nephin
67bc3fabe4 Merge pull request #1544 from aanand/fix-volume-deduping
Fix volume binds de-duplication
(cherry picked from commit 77e594dc94)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:08 -07:00
Daniel Nephin
e724a346c7 Merge pull request #1526 from aanand/remove-start-or-create-containers
Remove Service.start_or_create_containers()
(cherry picked from commit 38a11c4c28)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:08 -07:00
Daniel Nephin
87b4545b44 Merge pull request #1508 from thaJeztah/update-dockerproject-links
Update dockerproject.com links
(cherry picked from commit 417e6ce0c9)
2015-06-15 11:22:07 -07:00
Aanand Prasad
58a7844129 Merge pull request #1482 from bfirsh/add-build-and-dist-to-dockerignore
Make it possible to run tests remotely
(cherry picked from commit c8e096e089)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:07 -07:00
Daniel Nephin
4353f7b9f9 Merge pull request #1475 from fordhurley/patch-1
Fix markdown formatting for `--service-ports` example
(cherry picked from commit d64bf88e26)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:07 -07:00
Aanand Prasad
8f8693e13e Merge pull request #1480 from bfirsh/change-sigint-test-to-use-sigstop
Change kill SIGINT test to use SIGSTOP
(cherry picked from commit a15f996744)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:07 -07:00
Ben Firshman
363a6563c7 Merge pull request #1537 from aanand/reorder-service-utils
Reorder service.py utility methods
(cherry picked from commit e3525d64b5)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:07 -07:00
Aanand Prasad
59d6af73fa Merge pull request #1539 from bfirsh/add-image-affinity-to-test
Add image affinity to test script
(cherry picked from commit 4c2112dbfd)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:07 -07:00
Aanand Prasad
cd7f67018e Merge pull request #1466 from noironetworks/changing-scale-to-warning
Modified scale awareness from exception to warning
(cherry picked from commit 7d2a89427c)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:07 -07:00
Ben Firshman
b7e8770c4f Merge pull request #1538 from thieman/tnt-serivce-misspelled
Correct misspelling of "Service" in an error message
(cherry picked from commit bd246fb011)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:07 -07:00
Aanand Prasad
ad4cc5d6df Merge pull request #1497 from aanand/use-1.7-rc1
Run tests against Docker 1.7 RC2
(cherry picked from commit 0e9ccd36f3)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:06 -07:00
Aanand Prasad
ca14ed68f7 Merge pull request #1533 from edmorley/update-b2d-shellinit-example
Docs: Update boot2docker shellinit example to use 'eval'
(cherry picked from commit 17e03b29f9)
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:06 -07:00
Daniel Nephin
71514cb380 Merge pull request #1531 from aanand/test-crash-resilience
Test that data volumes now survive a crash when recreating
(cherry picked from commit 87c30ae6e4)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-15 11:22:06 -07:00
Daniel Nephin
8212f1bd45 Merge pull request #1529 from aanand/update-dockerpty
Update dockerpty to 0.3.4
(cherry picked from commit 95b2eaac04)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-09 18:24:14 -04:00
Daniel Nephin
dca3bbdea3 Merge pull request #1527 from aanand/remove-logging-on-run-rm
Remove logging on run --rm
(cherry picked from commit 5578ccbb01)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-09 14:39:53 -04:00
Daniel Nephin
8ed7dfef6f Merge pull request #1525 from aanand/fix-duplicate-logging
Fix duplicate logging on up/run
(cherry picked from commit e2b790f732)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-09 14:39:52 -04:00
Daniel Nephin
631f5be02f Merge pull request #1481 from albers/completion-smart-recreate
Support --x-smart-recreate in bash completion
(cherry picked from commit 9a0bb325f2)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-09 14:39:52 -04:00
Ben Firshman
4f4ea2a402 Merge pull request #1325 from sdurrheimer/master
Zsh completion for docker-compose
(cherry picked from commit b638728d6c)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>

Conflicts:
	docs/completion.md
2015-06-09 14:39:50 -04:00
Aanand Prasad
5a5bffebd1 Merge pull request #1464 from twhiteman/bug1461
Possible division by zero error when pulling an image - fixes #1463
(cherry picked from commit d0e87929a1)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-09 14:39:05 -04:00
Aanand Prasad
8749bc0844 Build Python 2.7.9 in Docker image
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-02 11:39:17 +01:00
Aanand Prasad
f3d0c63db2 Make sure we use Python 2.7.9 and OpenSSL 1.0.1 when building OSX binary
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-06-02 11:39:17 +01:00
Aanand Prasad
93a846db31 Report Python and OpenSSL versions in --version output
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>

Conflicts:
	compose/cli/utils.py
2015-06-02 11:39:17 +01:00
Aanand Prasad
686c25d50f Script to prepare OSX build environment
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-05-27 17:52:23 +01:00
Aanand Prasad
ef6555f084 Merge branch 'release' into bump-1.3.0 2015-05-26 17:45:28 +01:00
Ben Firshman
3c6652c101 Merge pull request #1308 from aanand/update-docs-1.2.0
Update docs for 1.2.0
2015-04-17 10:35:06 -07:00
Aanand Prasad
43af1684c1 Update docs for 1.2.0
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-04-17 16:02:57 +01:00
Aanand Prasad
ed549155b3 Merge pull request #1159 from aanand/bump-1.2.0
Bump 1.2.0
2015-04-16 17:46:47 +01:00
Aanand Prasad
39ae91c81c Bump 1.2.0
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-04-16 13:53:27 +01:00
Daniel Nephin
b6acb3cd8c Merge pull request #1278 from albers/completion-run-user
Add bash completion for docker-compose run --user
(cherry picked from commit 3cd116b99d)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-04-16 13:50:33 +01:00
Ben Firshman
a467a8a094 Merge pull request #1261 from aanand/fix-vars-in-volume-paths
Fix vars in volume paths
(cherry picked from commit 4926f8aef6)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>

Conflicts:
	tests/unit/service_test.py
2015-04-09 15:26:10 +01:00
Aanand Prasad
78227c3c06 Merge pull request #1202 from aanand/jenkins-script
WIP: Jenkins script
(cherry picked from commit 853ce255ea)
Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-04-01 11:00:51 -04:00
Daniel Nephin
e4e802d1f8 Merge pull request #1213 from moysesb/relative_build
Make value of 'build:' relative to the yml file.
(cherry picked from commit 0f70b8638f)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-04-01 11:00:48 -04:00
Aanand Prasad
b24a60ba9f Merge pull request #1226 from aanand/merge-multi-value-options
Merge multi-value options when extending
(cherry picked from commit e708f4f59d)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-04-01 11:00:45 -04:00
Aanand Prasad
461b600068 Merge pull request #1225 from aanand/fix-1222
When extending, `build` replaces `image` and vice versa
(cherry picked from commit 6dbe321a45)

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
2015-04-01 11:00:40 -04:00
49 changed files with 698 additions and 222 deletions

1
.gitignore vendored
View file

@ -7,3 +7,4 @@
/dist
/docs/_site
/venv
README.rst

View file

@ -1,6 +1,108 @@
Change log
==========
1.5.0 (2015-11-02)
------------------
**Breaking changes:**
With the introduction of variable substitution support in the Compose file, any
Compose file that uses an environment variable (`$VAR` or `${VAR}`) in the `command:`
or `entrypoint:` field will break.
Previously these values were interpolated inside the container, with a value
from the container environment. In Compose 1.5.0, the values will be
interpolated on the host, with a value from the host environment.
To migrate a Compose file to 1.5.0, escape the variables with an extra `$`
(ex: `$$VAR` or `$${VAR}`). See
https://github.com/docker/compose/blob/8cc8e61/docs/compose-file.md#variable-substitution
Major features:
- Compose is now available for Windows.
- Environment variables can be used in the Compose file. See
https://github.com/docker/compose/blob/8cc8e61/docs/compose-file.md#variable-substitution
- Multiple compose files can be specified, allowing you to override
settings in the default Compose file. See
https://github.com/docker/compose/blob/8cc8e61/docs/reference/docker-compose.md
for more details.
- Compose now produces better error messages when a file contains
invalid configuration.
- `up` now waits for all services to exit before shutting down,
rather than shutting down as soon as one container exits.
- Experimental support for the new docker networking system can be
enabled with the `--x-networking` flag. Read more here:
https://github.com/docker/docker/blob/8fee1c20/docs/userguide/dockernetworks.md
New features:
- You can now optionally pass a mode to `volumes_from`, e.g.
`volumes_from: ["servicename:ro"]`.
- Since Docker now lets you create volumes with names, you can refer to those
volumes by name in `docker-compose.yml`. For example,
`volumes: ["mydatavolume:/data"]` will mount the volume named
`mydatavolume` at the path `/data` inside the container.
If the first component of an entry in `volumes` starts with a `.`, `/` or
`~`, it is treated as a path and expansion of relative paths is performed as
necessary. Otherwise, it is treated as a volume name and passed straight
through to Docker.
Read more on named volumes and volume drivers here:
https://github.com/docker/docker/blob/244d9c33/docs/userguide/dockervolumes.md
- `docker-compose build --pull` instructs Compose to pull the base image for
each Dockerfile before building.
- `docker-compose pull --ignore-pull-failures` instructs Compose to continue
if it fails to pull a single service's image, rather than aborting.
- You can now specify an IPC namespace in `docker-compose.yml` with the `ipc`
option.
- Containers created by `docker-compose run` can now be named with the
`--name` flag.
- If you install Compose with pip or use it as a library, it now works with
Python 3.
- `image` now supports image digests (in addition to ids and tags), e.g.
`image: "busybox@sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b52004ee8502d"`
- `ports` now supports ranges of ports, e.g.
ports:
- "3000-3005"
- "9000-9001:8000-8001"
- `docker-compose run` now supports a `-p|--publish` parameter, much like
`docker run -p`, for publishing specific ports to the host.
- `docker-compose pause` and `docker-compose unpause` have been implemented,
analogous to `docker pause` and `docker unpause`.
- When using `extends` to copy configuration from another service in the same
Compose file, you can omit the `file` option.
- Compose can be installed and run as a Docker image. This is an experimental
feature.
Bug fixes:
- All values for the `log_driver` option which are supported by the Docker
daemon are now supported by Compose.
- `docker-compose build` can now be run successfully against a Swarm cluster.
1.4.2 (2015-09-22)
------------------

View file

@ -4,6 +4,8 @@ include requirements.txt
include requirements-dev.txt
include tox.ini
include *.md
exclude README.md
include README.rst
include compose/config/*.json
recursive-include contrib/completion *
recursive-include tests *

View file

@ -56,4 +56,4 @@ Want to help build Compose? Check out our [contributing documentation](https://g
Releasing
---------
Releases are built by maintainers, following an outline of the [release process](https://github.com/docker/compose/blob/master/RELEASE_PROCESS.md).
Releases are built by maintainers, following an outline of the [release process](https://github.com/docker/compose/blob/master/project/RELEASE-PROCESS.md).

View file

@ -1,3 +1,3 @@
from __future__ import unicode_literals
__version__ = '1.5.0dev'
__version__ = '1.5.0rc3'

View file

@ -1,10 +1,13 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
import os
import texttable
from compose.cli import colors
def get_tty_width():
tty_size = os.popen('stty size', 'r').read().split()
@ -15,6 +18,7 @@ def get_tty_width():
class Formatter(object):
"""Format tabular data for printing."""
def table(self, headers, rows):
table = texttable.Texttable(max_width=get_tty_width())
table.set_cols_dtype(['t' for h in headers])
@ -23,3 +27,22 @@ class Formatter(object):
table.set_chars(['-', '|', '+', '-'])
return table.draw()
class ConsoleWarningFormatter(logging.Formatter):
"""A logging.Formatter which prints WARNING and ERROR messages with
a prefix of the log level colored appropriate for the log level.
"""
def get_level_message(self, record):
separator = ': '
if record.levelno == logging.WARNING:
return colors.yellow(record.levelname) + separator
if record.levelno == logging.ERROR:
return colors.red(record.levelname) + separator
return ''
def format(self, record):
message = super(ConsoleWarningFormatter, self).format(record)
return self.get_level_message(record) + message

View file

@ -73,9 +73,13 @@ def build_no_log_generator(container, prefix, color_func):
def build_log_generator(container, prefix, color_func):
# Attach to container before log printer starts running
stream = container.attach(stdout=True, stderr=True, stream=True, logs=True)
line_generator = split_buffer(stream)
# 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)
else:
line_generator = split_buffer(container.log_stream)
for line in line_generator:
yield prefix + line

View file

@ -28,6 +28,7 @@ from .command import project_from_options
from .docopt_command import DocoptCommand
from .docopt_command import NoSuchCommand
from .errors import UserError
from .formatter import ConsoleWarningFormatter
from .formatter import Formatter
from .log_printer import LogPrinter
from .utils import get_version_info
@ -41,7 +42,7 @@ log = logging.getLogger(__name__)
console_handler = logging.StreamHandler(sys.stderr)
INSECURE_SSL_WARNING = """
Warning: --allow-insecure-ssl is deprecated and has no effect.
--allow-insecure-ssl is deprecated and has no effect.
It will be removed in a future version of Compose.
"""
@ -58,9 +59,8 @@ def main():
log.error(e.msg)
sys.exit(1)
except NoSuchCommand as e:
log.error("No such command: %s", e.command)
log.error("")
log.error("\n".join(parse_doc_section("commands:", getdoc(e.supercommand))))
commands = "\n".join(parse_doc_section("commands:", getdoc(e.supercommand)))
log.error("No such command: %s\n\n%s", e.command, commands)
sys.exit(1)
except APIError as e:
log.error(e.explanation)
@ -91,13 +91,18 @@ def setup_logging():
logging.getLogger("requests").propagate = False
def setup_console_handler(verbose):
if verbose:
console_handler.setFormatter(logging.Formatter('%(name)s.%(funcName)s: %(message)s'))
console_handler.setLevel(logging.DEBUG)
def setup_console_handler(handler, verbose):
if handler.stream.isatty():
format_class = ConsoleWarningFormatter
else:
console_handler.setFormatter(logging.Formatter())
console_handler.setLevel(logging.INFO)
format_class = logging.Formatter
if verbose:
handler.setFormatter(format_class('%(name)s.%(funcName)s: %(message)s'))
handler.setLevel(logging.DEBUG)
else:
handler.setFormatter(format_class())
handler.setLevel(logging.INFO)
# stolen from docopt master
@ -153,7 +158,7 @@ class TopLevelCommand(DocoptCommand):
return options
def perform_command(self, options, handler, command_options):
setup_console_handler(options.get('--verbose'))
setup_console_handler(console_handler, options.get('--verbose'))
if options['COMMAND'] in ('help', 'version'):
# Skip looking up the compose file.
@ -380,6 +385,8 @@ class TopLevelCommand(DocoptCommand):
start_deps=True,
strategy=ConvergenceStrategy.never,
)
elif project.use_networking:
project.ensure_network_exists()
tty = True
if detach or options['-T'] or not sys.stdin.isatty():
@ -565,16 +572,18 @@ class TopLevelCommand(DocoptCommand):
start_deps = not options['--no-deps']
service_names = options['SERVICE']
timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)
detached = options.get('-d')
to_attach = project.up(
service_names=service_names,
start_deps=start_deps,
strategy=convergence_strategy_from_opts(options),
do_build=not options['--no-build'],
timeout=timeout
timeout=timeout,
detached=detached
)
if not options['-d']:
if not detached:
log_printer = build_log_printer(to_attach, service_names, monochrome)
attach_to_logs(project, log_printer, service_names, timeout)
@ -636,7 +645,10 @@ def convergence_strategy_from_opts(options):
def build_log_printer(containers, service_names, monochrome):
if service_names:
containers = [c for c in containers if c.service in service_names]
containers = [
container
for container in containers if container.service in service_names
]
return LogPrinter(containers, monochrome=monochrome)

View file

@ -1,3 +1,4 @@
import codecs
import logging
import os
import sys
@ -14,7 +15,6 @@ from .validation import validate_against_fields_schema
from .validation import validate_against_service_schema
from .validation import validate_extended_service_exists
from .validation import validate_extends_file_path
from .validation import validate_service_names
from .validation import validate_top_level_object
@ -165,16 +165,6 @@ def find_candidates_in_parent_dirs(filenames, path):
return (candidates, path)
@validate_top_level_object
@validate_service_names
def pre_process_config(config):
"""
Pre validation checks and processing of the config file to interpolate env
vars returning a config dict ready to be tested against the schema.
"""
return interpolate_environment_variables(config)
def load(config_details):
"""Load the configuration from a working directory and a list of
configuration files. Files are loaded in order, and merged on top
@ -194,7 +184,7 @@ def load(config_details):
return service_dict
def load_file(filename, config):
processed_config = pre_process_config(config)
processed_config = interpolate_environment_variables(config)
validate_against_fields_schema(processed_config)
return [
build_service(filename, name, service_config)
@ -204,12 +194,17 @@ def load(config_details):
def merge_services(base, override):
all_service_names = set(base) | set(override)
return {
name: merge_service_dicts(base.get(name, {}), override.get(name, {}))
name: merge_service_dicts_from_files(
base.get(name, {}),
override.get(name, {}))
for name in all_service_names
}
config_file = config_details.config_files[0]
validate_top_level_object(config_file.config)
for next_file in config_details.config_files[1:]:
validate_top_level_object(next_file.config)
config_file = ConfigFile(
config_file.filename,
merge_services(config_file.config, next_file.config))
@ -278,14 +273,12 @@ class ServiceLoader(object):
extends,
self.filename
)
self.extended_config_path = self.get_extended_config_path(
extends
)
self.extended_config_path = self.get_extended_config_path(extends)
self.extended_service_name = extends['service']
full_extended_config = pre_process_config(
load_yaml(self.extended_config_path)
)
config = load_yaml(self.extended_config_path)
validate_top_level_object(config)
full_extended_config = interpolate_environment_variables(config)
validate_extended_service_exists(
self.extended_service_name,
@ -363,6 +356,17 @@ def process_container_options(service_dict, working_dir=None):
return service_dict
def merge_service_dicts_from_files(base, override):
"""When merging services from multiple files we need to merge the `extends`
field. This is not handled by `merge_service_dicts()` which is used to
perform the `extends`.
"""
new_service = merge_service_dicts(base, override)
if 'extends' in override:
new_service['extends'] = override['extends']
return new_service
def merge_service_dicts(base, override):
d = base.copy()
@ -448,6 +452,8 @@ def parse_environment(environment):
def split_env(env):
if isinstance(env, six.binary_type):
env = env.decode('utf-8')
if '=' in env:
return env.split('=', 1)
else:
@ -470,7 +476,7 @@ def env_vars_from_file(filename):
if not os.path.exists(filename):
raise ConfigurationError("Couldn't find env file: %s" % filename)
env = {}
for line in open(filename, 'r'):
for line in codecs.open(filename, 'r', 'utf-8'):
line = line.strip()
if line and not line.startswith('#'):
k, v = split_env(line)
@ -610,5 +616,6 @@ def load_yaml(filename):
try:
with open(filename, 'r') as fh:
return yaml.safe_load(fh)
except IOError as e:
raise ConfigurationError(six.text_type(e))
except (IOError, yaml.YAMLError) as e:
error_name = getattr(e, '__module__', '') + '.' + e.__class__.__name__
raise ConfigurationError(u"{}: {}".format(error_name, e))

View file

@ -41,7 +41,7 @@
"type": "object",
"patternProperties": {
"^[^-]+$": {
"type": ["string", "number", "boolean"],
"type": ["string", "number", "boolean", "null"],
"format": "environment"
}
},

View file

@ -78,7 +78,7 @@ class BlankDefaultDict(dict):
except KeyError:
if key not in self.missing_keys:
log.warn(
"The {} variable is not set. Substituting a blank string."
"The {} variable is not set. Defaulting to a blank string."
.format(key)
)
self.missing_keys.append(key)

View file

@ -2,7 +2,6 @@ import json
import logging
import os
import sys
from functools import wraps
import six
from docker.utils.ports import split_port
@ -58,34 +57,30 @@ def format_boolean_in_environment(instance):
"""
if isinstance(instance, bool):
log.warn(
"Warning: There is a boolean value in the 'environment' key.\n"
"Environment variables can only be strings.\nPlease add quotes to any boolean values to make them string "
"(eg, 'True', 'yes', 'N').\nThis warning will become an error in a future release. \r\n"
"There is a boolean value in the 'environment' key.\n"
"Environment variables can only be strings.\n"
"Please add quotes to any boolean values to make them string "
"(eg, 'True', 'yes', 'N').\n"
"This warning will become an error in a future release. \r\n"
)
return True
def validate_service_names(func):
@wraps(func)
def func_wrapper(config):
for service_name in config.keys():
if type(service_name) is int:
raise ConfigurationError(
"Service name: {} needs to be a string, eg '{}'".format(service_name, service_name)
)
return func(config)
return func_wrapper
def validate_top_level_object(func):
@wraps(func)
def func_wrapper(config):
if not isinstance(config, dict):
def validate_service_names(config):
for service_name in config.keys():
if not isinstance(service_name, six.string_types):
raise ConfigurationError(
"Top level object needs to be a dictionary. Check your .yml file that you have defined a service at the top level."
)
return func(config)
return func_wrapper
"Service name: {} needs to be a string, eg '{}'".format(
service_name,
service_name))
def validate_top_level_object(config):
if not isinstance(config, dict):
raise ConfigurationError(
"Top level object needs to be a dictionary. Check your .yml file "
"that you have defined a service at the top level.")
validate_service_names(config)
def validate_extends_file_path(service_name, extends_options, filename):
@ -143,7 +138,7 @@ def process_errors(errors, service_name=None):
if len(validator) >= 2:
first_type = anglicize_validator(validator[0])
last_type = anglicize_validator(validator[-1])
types_from_validator = "{}{}".format(first_type, ", ".join(validator[1:-1]))
types_from_validator = ", ".join([first_type] + validator[1:-1])
msg = "{} or {}".format(
types_from_validator,
@ -163,7 +158,6 @@ def process_errors(errors, service_name=None):
Inspecting the context value of a ValidationError gives us information about
which sub schema failed and which kind of error it is.
"""
required = [context for context in error.context if context.validator == 'required']
if required:
return required[0].message

View file

@ -19,6 +19,7 @@ class Container(object):
self.client = client
self.dictionary = dictionary
self.has_been_inspected = has_been_inspected
self.log_stream = None
@classmethod
def from_ps(cls, client, dictionary, **kwargs):
@ -144,7 +145,14 @@ class Container(object):
@property
def has_api_logs(self):
log_type = self.log_driver
return not log_type or log_type == 'json-file'
return not log_type or log_type != 'none'
def attach_log_stream(self):
"""A log stream can only be attached if the container uses a json-file
log driver.
"""
if self.has_api_logs:
self.log_stream = self.attach(stdout=True, stderr=True, stream=True)
def get(self, key):
"""Return a value from the container or None if the value is not set.
@ -184,6 +192,15 @@ class Container(object):
def remove(self, **options):
return self.client.remove_container(self.id, **options)
def rename_to_tmp_name(self):
"""Rename the container to a hopefully unique temporary container name
by prepending the short id.
"""
self.client.rename(
self.id,
'%s_%s' % (self.short_id, self.name)
)
def inspect_if_not_inspected(self):
if not self.has_been_inspected:
self.inspect()

View file

@ -5,6 +5,7 @@ import logging
from functools import reduce
from docker.errors import APIError
from docker.errors import NotFound
from .config import ConfigurationError
from .config import get_service_name_from_net
@ -82,7 +83,7 @@ class Project(object):
self.services = services
self.client = client
self.use_networking = use_networking
self.network_driver = network_driver or 'bridge'
self.network_driver = network_driver
def labels(self, one_off=False):
return [
@ -289,7 +290,8 @@ class Project(object):
start_deps=True,
strategy=ConvergenceStrategy.changed,
do_build=True,
timeout=DEFAULT_TIMEOUT):
timeout=DEFAULT_TIMEOUT,
detached=False):
services = self.get_services(service_names, include_deps=start_deps)
@ -307,7 +309,8 @@ class Project(object):
for container in service.execute_convergence_plan(
plans[service.name],
do_build=do_build,
timeout=timeout
timeout=timeout,
detached=detached
)
]
@ -335,7 +338,7 @@ class Project(object):
return plans
def pull(self, service_names=None, ignore_pull_failures=False):
for service in self.get_services(service_names, include_deps=True):
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):
@ -363,10 +366,10 @@ class Project(object):
return [c for c in containers if matches_service_names(c)]
def get_network(self):
networks = self.client.networks(names=[self.name])
if networks:
return networks[0]
return None
try:
return self.client.inspect_network(self.name)
except NotFound:
return None
def ensure_network_exists(self):
# TODO: recreate network if driver has changed?

View file

@ -399,13 +399,17 @@ class Service(object):
def execute_convergence_plan(self,
plan,
do_build=True,
timeout=DEFAULT_TIMEOUT):
timeout=DEFAULT_TIMEOUT,
detached=False):
(action, containers) = plan
should_attach_logs = not detached
if action == 'create':
container = self.create_container(
do_build=do_build,
)
container = self.create_container(do_build=do_build)
if should_attach_logs:
container.attach_log_stream()
self.start_container(container)
return [container]
@ -413,15 +417,16 @@ class Service(object):
elif action == 'recreate':
return [
self.recreate_container(
c,
timeout=timeout
container,
timeout=timeout,
attach_logs=should_attach_logs
)
for c in containers
for container in containers
]
elif action == 'start':
for c in containers:
self.start_container_if_stopped(c)
for container in containers:
self.start_container_if_stopped(container, attach_logs=should_attach_logs)
return containers
@ -436,7 +441,8 @@ class Service(object):
def recreate_container(self,
container,
timeout=DEFAULT_TIMEOUT):
timeout=DEFAULT_TIMEOUT,
attach_logs=False):
"""Recreate a container.
The original container is renamed to a temporary name so that data
@ -444,36 +450,28 @@ class Service(object):
container is removed.
"""
log.info("Recreating %s" % container.name)
try:
container.stop(timeout=timeout)
except APIError as e:
if (e.response.status_code == 500
and e.explanation
and 'no such process' in str(e.explanation)):
pass
else:
raise
# Use a hopefully unique container name by prepending the short id
self.client.rename(
container.id,
'%s_%s' % (container.short_id, container.name))
container.stop(timeout=timeout)
container.rename_to_tmp_name()
new_container = self.create_container(
do_build=False,
previous_container=container,
number=container.labels.get(LABEL_CONTAINER_NUMBER),
quiet=True,
)
if attach_logs:
new_container.attach_log_stream()
self.start_container(new_container)
container.remove()
return new_container
def start_container_if_stopped(self, container):
def start_container_if_stopped(self, container, attach_logs=False):
if container.is_running:
return container
else:
log.info("Starting %s" % container.name)
if attach_logs:
container.attach_log_stream()
return self.start_container(container)
def start_container(self, container):
@ -545,6 +543,9 @@ class Service(object):
return 1 if not numbers else max(numbers) + 1
def _get_links(self, link_to_self):
if self.use_networking:
return []
links = []
for service, link_name in self.links:
for container in service.containers():
@ -847,7 +848,7 @@ class ServiceNet(object):
if containers:
return 'container:' + containers[0].id
log.warn("Warning: Service %s is trying to use reuse the network stack "
log.warn("Service %s is trying to use reuse the network stack "
"of another service that is not running." % (self.id))
return None
@ -943,24 +944,22 @@ def build_volume_binding(volume_spec):
def normalize_paths_for_engine(external_path, internal_path):
"""
Windows paths, c:\my\path\shiny, need to be changed to be compatible with
"""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 IS_WINDOWS_PLATFORM:
if external_path:
drive, tail = os.path.splitdrive(external_path)
if drive:
reformatted_drive = "/{}".format(drive.replace(":", ""))
external_path = reformatted_drive + tail
external_path = "/".join(external_path.split("\\"))
return external_path, "/".join(internal_path.split("\\"))
else:
if not IS_WINDOWS_PLATFORM:
return external_path, internal_path
if external_path:
drive, tail = os.path.splitdrive(external_path)
if drive:
external_path = '/' + drive.lower().rstrip(':') + tail
external_path = external_path.replace('\\', '/')
return external_path, internal_path.replace('\\', '/')
def parse_volume_spec(volume_config):
"""

View file

@ -105,11 +105,15 @@ _docker_compose_docker_compose() {
--project-name|-p)
return
;;
--x-network-driver)
COMPREPLY=( $( compgen -W "bridge host none overlay" -- "$cur" ) )
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help -h --verbose --version -v --file -f --project-name -p" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--file -f --help -h --project-name -p --verbose --version -v --x-networking --x-network-driver" -- "$cur" ) )
;;
*)
COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) )
@ -410,6 +414,9 @@ _docker_compose() {
(( counter++ ))
compose_project="${words[$counter]}"
;;
--x-network-driver)
(( counter++ ))
;;
-*)
;;
*)

View file

@ -330,6 +330,8 @@ _docker-compose() {
'(- :)'{-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:' \
'--x-networking[(EXPERIMENTAL) Use new Docker networking functionality. Requires Docker 1.9 or later.]' \
'--x-network-driver[(EXPERIMENTAL) Specify a network driver (default: "bridge"). Requires Docker 1.9 or later.]:Network Driver:(bridge host none overlay)' \
'(-): :->command' \
'(-)*:: :->option-or-argument' && ret=0

View file

@ -48,8 +48,6 @@ See `man 7 capabilities` for a full list.
- NET_ADMIN
- SYS_ADMIN
Using `dockerfile` together with `image` is not allowed. Attempting to do so results in an error.
### command
Override the default command.
@ -106,6 +104,8 @@ Compose will use an alternate file to build with.
dockerfile: Dockerfile-alternate
Using `dockerfile` together with `image` is not allowed. Attempting to do so results in an error.
### env_file
Add environment variables from a file. Can be a single value or a list.
@ -428,9 +428,18 @@ Both `$VARIABLE` and `${VARIABLE}` syntax are supported. Extended shell-style
features, such as `${VARIABLE-default}` and `${VARIABLE/foo/bar}`, are not
supported.
If you need to put a literal dollar sign in a configuration value, use a double
dollar sign (`$$`).
You can use a `$$` (double-dollar sign) when your configuration needs a literal
dollar sign. This also prevents Compose from interpolating a value, so a `$$`
allows you to refer to environment variables that you don't want processed by
Compose.
web:
build: .
command: "$$VAR_NOT_INTERPOLATED_BY_COMPOSE"
If you forget and use a single dollar sign (`$`), Compose interprets the value as an environment variable and will warn you:
The VAR_NOT_INTERPOLATED_BY_COMPOSE is not set. Substituting an empty string.
## Compose documentation

View file

@ -64,9 +64,10 @@ and a `docker-compose.yml` file.
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, any volumes they might
need mounted inside the containers, and any ports they might
expose. See the [`docker-compose.yml` reference](yml.md) for more
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.
@ -80,6 +81,8 @@ and a `docker-compose.yml` file.
- .:/code
ports:
- "8000:8000"
links:
- db
This file defines two services: The `db` service and the `web` service.
@ -107,8 +110,20 @@ In this step, you create a Django started project by building the image from the
3. After the `docker-compose` command completes, list the contents of your project.
$ ls
Dockerfile docker-compose.yml composeexample manage.py requirements.txt
$ 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

View file

@ -11,7 +11,7 @@ weight=3
# Compose 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](yml.md#links) for details.
**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.
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.

View file

@ -59,6 +59,10 @@ You can go further and define (or re-define) configuration locally in
- 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:
@ -233,7 +237,8 @@ manually keep both environments in sync.
### Reference
You can use `extends` on any service together with other configuration keys. It
always expects a dictionary that should always contain the key: `service` and optionally the `file` key.
expects a dictionary that contains a `service` key and optionally a `file` key.
The `extends` key can also take a string, whose value is the name of a `service` defined in the same file.
The `file` key specifies the location of a Compose configuration file defining
the extension. The `file` value can be an absolute or relative path. If you

View file

@ -154,7 +154,7 @@ Now, when you run `docker-compose up`, Compose will pull a Redis image, build an
If you're using [Docker Machine](https://docs.docker.com/machine), then `docker-machine ip MACHINE_VM` will tell you its address and you can open `http://MACHINE_VM_IP:5000` in a browser.
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 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`.
You should get a message in your browser saying:

View file

@ -30,13 +30,14 @@ To install Compose, do the following:
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 in your terminal.
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 command has the following format:
The following is an example command illustrating the format:
curl -L https://github.com/docker/compose/releases/download/VERSION_NUM/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
@ -53,7 +54,7 @@ To install Compose, do the following:
7. Test the installation.
$ docker-compose --version
docker-compose version: 1.4.2
docker-compose version: 1.5.0rc3
## Alternative install options
@ -75,7 +76,7 @@ to get started.
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.5.0/run.sh > /usr/local/bin/docker-compose
$ curl -L https://github.com/docker/compose/releases/download/1.5.0rc3/run.sh > /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
## Master builds

View file

@ -12,11 +12,15 @@ weight=6
# Networking in Compose
> **Note:** Compose’s networking support is experimental, and must be explicitly enabled with the `docker-compose --x-networking` flag.
> **Note:** Compose's networking support is experimental, and must be explicitly enabled with the `docker-compose --x-networking` flag.
Compose sets up a single default [network](http://TODO/docker-networking-docs) 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 service's name.
Compose sets up a single default
[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 the same name as the "project name", which is based on the name of the directory it lives in. See the [CLI docs](cli.md#p-project-name-name) for how to override it.
> **Note:** Your app's network is given the same name as the "project name", which is based on the name of the directory it lives in. See the [Command line overview](reference/docker-compose.md) for how to override it.
For example, suppose your app is in a directory called `myapp`, and your `docker-compose.yml` looks like this:
@ -30,13 +34,23 @@ For example, suppose your app is in a directory called `myapp`, and your `docker
When you run `docker-compose --x-networking up`, the following happens:
1. A network called `myapp` is created.
2. A container is created using `web`'s configuration. It joins the network `myapp` under the name `web`.
3. A container is created using `db`'s configuration. It joins the network `myapp` under the name `db`.
2. A container is created using `web`'s configuration. It joins the network
`myapp` under the name `myapp_web_1`.
3. A container is created using `db`'s configuration. It joins the network
`myapp` under the name `myapp_db_1`.
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.
Each container can now look up the hostname `myapp_web_1` or `myapp_db_1` and
get back the appropriate container's IP address. For example, `web`'s
application code could connect to the URL `postgres://myapp_db_1: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.
> **Note:** in the next release there will be additional aliases for the
> container, including a short name without the project name and container
> index. The full container name will remain as one of the alias for backwards
> compatibility.
## 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.
@ -45,19 +59,13 @@ If any containers have connections open to the old container, they will be close
## Configure how services are published
By default, containers for each service are published on the network with the same name as the service. If you want to change the name, or stop containers from being discoverable at all, you can use the `hostname` option:
By default, containers for each service are published on the network with the
container name. If you want to change the name, or stop containers from being
discoverable at all, you can use the `container_name` option:
web:
build: .
hostname: "my-web-application"
This will also change the hostname inside the container, so that the `hostname` command will return `my-web-application`.
## Scaling services
If you create multiple containers for a service with `docker-compose scale`, each container will join the network with the same name. For example, if you run `docker-compose scale web=3`, then 3 containers will join the network under the name `web`. Inside any container on the network, looking up the name `web` will return the IP address of one of them, but Docker and Compose do not provide any guarantees about which one.
This limitation will be addressed in a future version of Compose, where a load balancer will join under the service name and balance traffic between the service's containers in a configurable manner.
container_name: "my-web-application"
## Links
@ -65,7 +73,7 @@ Docker links are a one-way, single-host communication system. They should now be
## Specifying the network driver
By default, Compose uses the `bridge` driver when creating the app’s network. The Docker Engine provides one other driver out-of-the-box: `overlay`, which implements secure communication between containers on different hosts (see the next section for how to set up and use the `overlay` driver). Docker also allows you to install [custom network drivers](http://TODO/custom-driver-docs).
By default, Compose uses the `bridge` driver when creating the app’s network. The Docker Engine provides one other driver out-of-the-box: `overlay`, which implements secure communication between containers on different hosts (see the next section for how to set up and use the `overlay` driver). Docker also allows you to install [custom network drivers](/engine/extend/plugins_network.md).
You can specify which one to use with the `--x-network-driver` flag:

View file

@ -37,7 +37,11 @@ Next, create a bootstrap `Gemfile` which just loads Rails. It'll be overwritten
source 'https://rubygems.org'
gem 'rails', '4.2.0'
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 expose the web app's port.
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.
db:
image: postgres
@ -48,6 +52,8 @@ Finally, `docker-compose.yml` is where the magic happens. This file describes th
- .:/myapp
ports:
- "3000:3000"
links:
- db
### Build the project
@ -67,6 +73,12 @@ image. Once it's done, you should have generated a fresh app:
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:
@ -78,6 +90,7 @@ rebuild.)
$ docker-compose build
### Connect the database
The app is now bootable, but you're not quite there yet. By default, Rails
@ -85,8 +98,7 @@ 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.
Open up your newly-generated `database.yml` file. Replace its contents with the
following:
Replace the contents of `config/database.yml` with the following:
development: &default
adapter: postgresql

View file

@ -46,6 +46,8 @@ and a separate MySQL instance:
command: php -S 0.0.0.0:8000 -t /code
ports:
- "8000:8000"
links:
- db
volumes:
- .:/code
db:

View file

@ -20,15 +20,16 @@ The following labels are provided in additional to the standard labels:
Most issues should fit into one of the following functional areas:
| Area |
|----------------|
| area/build |
| area/cli |
| area/config |
| area/logs |
| area/packaging |
| area/run |
| area/scale |
| area/tests |
| area/up |
| area/volumes |
| Area |
|-----------------|
| area/build |
| area/cli |
| area/config |
| area/logs |
| area/networking |
| area/packaging |
| area/run |
| area/scale |
| area/tests |
| area/up |
| area/volumes |

View file

@ -1,6 +1,14 @@
Building a Compose release
==========================
## Prerequisites
The release scripts require the following tools installed on the host:
* https://hub.github.com/
* https://stedolan.github.io/jq/
* http://pandoc.org/
## To get started with a new release
Create a branch, update version, and add release notes by running `make-branch`
@ -40,10 +48,10 @@ As part of this script you'll be asked to:
## To release a version (whether RC or stable)
Check out the bump branch and run the `build-binary` script
Check out the bump branch and run the `build-binaries` script
git checkout bump-$VERSION
./script/release/build-binary
./script/release/build-binaries
When prompted build the non-linux binaries and test them.
@ -54,7 +62,7 @@ When prompted build the non-linux binaries and test them.
2. Download the windows binary from AppVeyor
https://ci.appveyor.com/project/docker/compose/build/<build id>/artifacts
https://ci.appveyor.com/project/docker/compose
3. Draft a release from the tag on GitHub (the script will open the window for
you)
@ -82,17 +90,20 @@ When prompted build the non-linux binaries and test them.
5. Attach the binaries and `script/run.sh`
6. If everything looks good, it's time to push the release.
6. Add "Thanks" with a list of contributors. The contributor list can be generated
by running `./script/release/contributors`.
7. If everything looks good, it's time to push the release.
./script/release/push-release
7. Publish the release on GitHub.
8. Publish the release on GitHub.
8. Check that both binaries download (following the install instructions) and run.
9. Check that all the binaries download (following the install instructions) and run.
9. Email maintainers@dockerproject.org and engineering@docker.com about the new release.
10. Email maintainers@dockerproject.org and engineering@docker.com about the new release.
## If it’s a stable release (not an RC)

View file

@ -1 +1 @@
git+https://github.com/pyinstaller/pyinstaller.git@12e40471c77f588ea5be352f7219c873ddaae056#egg=pyinstaller
pyinstaller==3.0

View file

@ -42,11 +42,6 @@ Get-ChildItem -Recurse -Include *.pyc | foreach ($_) { Remove-Item $_.FullName }
virtualenv .\venv
# Install dependencies
# TODO: pip warns when installing from a git sha, so we need to set ErrorAction to
# 'Continue'. See
# https://github.com/pypa/pip/blob/fbc4b7ae5fee00f95bce9ba4b887b22681327bb1/pip/vcs/git.py#L77
# This can be removed once pyinstaller 3.x is released and we upgrade
$ErrorActionPreference = "Continue"
.\venv\Scripts\pip install pypiwin32==219
.\venv\Scripts\pip install -r requirements.txt
.\venv\Scripts\pip install --no-deps .
@ -54,8 +49,9 @@ $ErrorActionPreference = "Continue"
# Build binary
# pyinstaller has lots of warnings, so we need to run with ErrorAction = Continue
$ErrorActionPreference = "Continue"
.\venv\Scripts\pyinstaller .\docker-compose.spec
$ErrorActionPreference = "Stop"
Move-Item -Force .\dist\docker-compose .\dist\docker-compose-Windows-x86_64.exe
Move-Item -Force .\dist\docker-compose.exe .\dist\docker-compose-Windows-x86_64.exe
.\dist\docker-compose-Windows-x86_64.exe --version

View file

@ -11,7 +11,9 @@ set -ex
docker version
export DOCKER_VERSIONS=all
export DOCKER_DAEMON_ARGS="--storage-driver=overlay"
STORAGE_DRIVER=${STORAGE_DRIVER:-overlay}
export DOCKER_DAEMON_ARGS="--storage-driver=$STORAGE_DRIVER"
GIT_VOLUME="--volumes-from=$(hostname)"
. script/test-versions

View file

@ -22,7 +22,7 @@ EOM
if [ -z "$(command -v hub 2> /dev/null)" ]; then
>&2 echo "$0 requires https://hub.github.com/."
>&2 echo "Please install it and ake sure it is available on your \$PATH."
>&2 echo "Please install it and make sure it is available on your \$PATH."
exit 2
fi

27
script/release/contributors Executable file
View file

@ -0,0 +1,27 @@
#!/bin/bash
set -e
function usage() {
>&2 cat << EOM
Print the list of github contributors for the release
Usage:
$0 <previous release tag>
EOM
exit 1
}
[[ -n "$1" ]] || usage
PREV_RELEASE=$1
VERSION=HEAD
URL="https://api.github.com/repos/docker/compose/compare"
curl -sf "$URL/$PREV_RELEASE...$VERSION" | \
jq -r '.commits[].author.login' | \
sort | \
uniq -c | \
sort -nr | \
awk '{print "@"$2","}' | \
xargs echo

View file

@ -39,7 +39,7 @@ fi
DEFAULT_REMOTE=release
REMOTE="$(find_remote "$GITHUB_REPO")"
# If we don't have a docker origin add one
# If we don't have a docker remote add one
if [ -z "$REMOTE" ]; then
echo "Creating $DEFAULT_REMOTE remote"
git remote add ${DEFAULT_REMOTE} ${GITHUB_REPO}
@ -55,6 +55,8 @@ read -n1 -r -p "Continue? (ctrl+c to cancel)"
git fetch $REMOTE -p
git checkout -b $BRANCH $BASE_VERSION
echo "Merging remote release branch into new release branch"
git merge --strategy=ours --no-edit $REMOTE/release
# Store the release version for this branch in git, so that other release
# scripts can use it

View file

@ -21,11 +21,17 @@ VERSION="$(git config "branch.${BRANCH}.release")" || usage
if [ -z "$(command -v jq 2> /dev/null)" ]; then
>&2 echo "$0 requires https://stedolan.github.io/jq/"
>&2 echo "Please install it and ake sure it is available on your \$PATH."
>&2 echo "Please install it and make sure it is available on your \$PATH."
exit 2
fi
if [ -z "$(command -v pandoc 2> /dev/null)" ]; then
>&2 echo "$0 requires http://pandoc.org/"
>&2 echo "Please install it and make sure it is available on your \$PATH."
exit 2
fi
API=https://api.github.com/repos
REPO=docker/compose
GITHUB_REPO=git@github.com:$REPO
@ -34,7 +40,9 @@ GITHUB_REPO=git@github.com:$REPO
sha=$(git rev-parse HEAD)
url=$API/$REPO/statuses/$sha
build_status=$(curl -s $url | jq -r '.[0].state')
if [[ "$build_status" != "success" ]]; then
if [ -n "$SKIP_BUILD_CHECK" ]; then
echo "Skipping build status check..."
elif [[ "$build_status" != "success" ]]; then
>&2 echo "Build status is $build_status, but it should be success."
exit -1
fi
@ -43,12 +51,13 @@ echo "Tagging the release as $VERSION"
git tag $VERSION
git push $GITHUB_REPO $VERSION
echo "Uploading sdist to pypi"
python setup.py sdist
echo "Uploading the docker image"
docker push docker/compose:$VERSION
echo "Uploading sdist to pypi"
pandoc -f markdown -t rst README.md -o README.rst
sed -i -e 's/logo.png?raw=true/https:\/\/github.com\/docker\/compose\/raw\/master\/logo.png?raw=true/' README.rst
python setup.py sdist
if [ "$(command -v twine 2> /dev/null)" ]; then
twine upload ./dist/docker-compose-${VERSION}.tar.gz
else
@ -61,6 +70,7 @@ source venv-test/bin/activate
pip install docker-compose==$VERSION
docker-compose version
deactivate
rm -rf venv-test
echo "Now publish the github release, and test the downloads."
echo "Email maintainers@dockerproject.org and engineering@docker.com about the new release."

View file

@ -15,7 +15,7 @@
set -e
VERSION="1.5.0"
VERSION="1.5.0rc3"
IMAGE="docker/compose:$VERSION"

View file

@ -28,10 +28,15 @@ for version in $DOCKER_VERSIONS; do
>&2 echo "Running tests against Docker $version"
daemon_container="compose-dind-$version-$BUILD_NUMBER"
trap "docker rm -vf $daemon_container" EXIT
# TODO: remove when we stop testing against 1.7.x
daemon=$([[ "$version" == "1.7"* ]] && echo "-d" || echo "daemon")
function on_exit() {
if [[ "$?" != "0" ]]; then
docker logs "$daemon_container"
fi
docker rm -vf "$daemon_container"
}
trap "on_exit" EXIT
docker run \
-d \
@ -39,7 +44,7 @@ for version in $DOCKER_VERSIONS; do
--privileged \
--volume="/var/lib/docker" \
dockerswarm/dind:$version \
docker $daemon -H tcp://0.0.0.0:2375 $DOCKER_DAEMON_ARGS \
docker daemon -H tcp://0.0.0.0:2375 $DOCKER_DAEMON_ARGS \
docker run \
--rm \

View file

@ -1,4 +1,4 @@
FILE_DEF=F1
FILE_DEF=bär
FILE_DEF_EMPTY=
ENV_DEF
NO_DEF

View file

@ -187,7 +187,7 @@ class CLITestCase(DockerClientTestCase):
)
def test_up_without_networking(self):
self.require_engine_version("1.9")
self.require_api_version('1.21')
self.command.base_dir = 'tests/fixtures/links-composefile'
self.command.dispatch(['up', '-d'], None)
@ -205,7 +205,7 @@ class CLITestCase(DockerClientTestCase):
self.assertTrue(web_container.get('HostConfig.Links'))
def test_up_with_networking(self):
self.require_engine_version("1.9")
self.require_api_version('1.21')
self.command.base_dir = 'tests/fixtures/links-composefile'
self.command.dispatch(['--x-networking', 'up', '-d'], None)
@ -508,6 +508,20 @@ class CLITestCase(DockerClientTestCase):
container, = service.containers(stopped=True, one_off=True)
self.assertEqual(container.name, name)
@mock.patch('dockerpty.start')
def test_run_with_networking(self, _):
self.require_api_version('1.21')
client = docker_client(version='1.21')
self.command.base_dir = 'tests/fixtures/simple-dockerfile'
self.command.dispatch(['--x-networking', 'run', 'simple', 'true'], None)
service = self.project.get_service('simple')
container, = service.containers(stopped=True, one_off=True)
networks = client.networks(names=[self.project.name])
for n in networks:
self.addCleanup(client.remove_network, n['id'])
self.assertEqual(len(networks), 1)
self.assertEqual(container.human_readable_command, u'true')
def test_rm(self):
service = self.project.get_service('simple')
service.create_container()

View file

@ -1,6 +1,7 @@
from __future__ import unicode_literals
from .testcases import DockerClientTestCase
from compose.cli.docker_client import docker_client
from compose.config import config
from compose.const import LABEL_PROJECT
from compose.container import Container
@ -96,6 +97,22 @@ class ProjectTest(DockerClientTestCase):
db = project.get_service('db')
self.assertEqual(db._get_volumes_from(), [data_container.id + ':rw'])
def test_get_network_does_not_exist(self):
self.require_api_version('1.21')
client = docker_client(version='1.21')
project = Project('composetest', [], client)
assert project.get_network() is None
def test_get_network(self):
self.require_api_version('1.21')
client = docker_client(version='1.21')
network_name = 'network_does_exist'
project = Project(network_name, [], client)
client.create_network(network_name)
assert project.get_network()['name'] == network_name
def test_net_from_service(self):
project = Project.from_dicts(
name='composetest',

View file

@ -362,6 +362,7 @@ class ServiceTest(DockerClientTestCase):
new_container, = service.execute_convergence_plan(
ConvergencePlan('recreate', [old_container]))
self.assertEqual(list(new_container.get('Volumes')), ['/data'])
self.assertEqual(new_container.get('Volumes')['/data'], volume_path)
@ -692,10 +693,11 @@ class ServiceTest(DockerClientTestCase):
@mock.patch('compose.service.log')
def test_scale_with_custom_container_name_outputs_warning(self, mock_log):
"""
Test that calling scale on a service that has a custom container name
"""Test that calling scale on a service that has a custom container name
results in warning output.
"""
# Disable this test against earlier versions because it is flaky
self.require_api_version('1.21')
service = self.create_service('app', container_name='custom-container')
self.assertEqual(service.custom_container_name(), 'custom-container')

View file

@ -18,6 +18,7 @@ from compose.service import ConvergenceStrategy
class ProjectTestCase(DockerClientTestCase):
def run_up(self, cfg, **kwargs):
kwargs.setdefault('timeout', 1)
kwargs.setdefault('detached', True)
project = self.make_project(cfg)
project.up(**kwargs)

View file

@ -76,11 +76,7 @@ class DockerClientTestCase(unittest.TestCase):
build_output = self.client.build(*args, **kwargs)
stream_output(build_output, open('/dev/null', 'w'))
def require_engine_version(self, minimum):
# Drop '-dev' or '-rcN' suffix
engine = self.client.version()['Version'].split('-', 1)[0]
if version_lt(engine, minimum):
skip(
"Engine version is too low ({} < {})"
.format(engine, minimum)
)
def require_api_version(self, minimum):
api_version = self.client.version()['ApiVersion']
if version_lt(api_version, minimum):
skip("API version is too low ({} < {})".format(api_version, minimum))

View file

@ -0,0 +1,35 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import logging
from compose.cli import colors
from compose.cli.formatter import ConsoleWarningFormatter
from tests import unittest
MESSAGE = 'this is the message'
def makeLogRecord(level):
return logging.LogRecord('name', level, 'pathame', 0, MESSAGE, (), None)
class ConsoleWarningFormatterTestCase(unittest.TestCase):
def setUp(self):
self.formatter = ConsoleWarningFormatter()
def test_format_warn(self):
output = self.formatter.format(makeLogRecord(logging.WARN))
expected = colors.yellow('WARNING') + ': '
assert output == expected + MESSAGE
def test_format_error(self):
output = self.formatter.format(makeLogRecord(logging.ERROR))
expected = colors.red('ERROR') + ': '
assert output == expected + MESSAGE
def test_format_info(self):
output = self.formatter.format(makeLogRecord(logging.INFO))
assert output == MESSAGE

View file

@ -16,6 +16,7 @@ def build_mock_container(reader):
name='myapp_web_1',
name_without_project='web_1',
has_api_logs=True,
log_stream=None,
attach=reader,
wait=mock.Mock(return_value=0),
)

View file

@ -1,11 +1,15 @@
from __future__ import absolute_import
import logging
from compose import container
from compose.cli.errors import UserError
from compose.cli.formatter import ConsoleWarningFormatter
from compose.cli.log_printer import LogPrinter
from compose.cli.main import attach_to_logs
from compose.cli.main import build_log_printer
from compose.cli.main import convergence_strategy_from_opts
from compose.cli.main import setup_console_handler
from compose.project import Project
from compose.service import ConvergenceStrategy
from tests import mock
@ -60,6 +64,31 @@ class CLIMainTestCase(unittest.TestCase):
timeout=timeout)
class SetupConsoleHandlerTestCase(unittest.TestCase):
def setUp(self):
self.stream = mock.Mock()
self.stream.isatty.return_value = True
self.handler = logging.StreamHandler(stream=self.stream)
def test_with_tty_verbose(self):
setup_console_handler(self.handler, True)
assert type(self.handler.formatter) == ConsoleWarningFormatter
assert '%(name)s' in self.handler.formatter._fmt
assert '%(funcName)s' in self.handler.formatter._fmt
def test_with_tty_not_verbose(self):
setup_console_handler(self.handler, False)
assert type(self.handler.formatter) == ConsoleWarningFormatter
assert '%(name)s' not in self.handler.formatter._fmt
assert '%(funcName)s' not in self.handler.formatter._fmt
def test_with_not_a_tty(self):
self.stream.isatty.return_value = False
setup_console_handler(self.handler, False)
assert type(self.handler.formatter) == logging.Formatter
class ConvergeStrategyFromOptsTestCase(unittest.TestCase):
def test_invalid_opts(self):

View file

@ -1,3 +1,4 @@
# encoding: utf-8
from __future__ import absolute_import
from __future__ import unicode_literals
@ -98,7 +99,7 @@ class CLITestCase(unittest.TestCase):
command.run(mock_project, {
'SERVICE': 'service',
'COMMAND': None,
'-e': ['BAR=NEW', 'OTHER=THREE'],
'-e': ['BAR=NEW', 'OTHER=bär'.encode('utf-8')],
'--user': None,
'--no-deps': None,
'--allow-insecure-ssl': None,
@ -114,7 +115,7 @@ class CLITestCase(unittest.TestCase):
_, _, call_kwargs = mock_client.create_container.mock_calls[0]
self.assertEqual(
call_kwargs['environment'],
{'FOO': 'ONE', 'BAR': 'NEW', 'OTHER': 'THREE'})
{'FOO': 'ONE', 'BAR': 'NEW', 'OTHER': u'bär'})
def test_run_service_with_restart_always(self):
command = TopLevelCommand()

View file

@ -1,3 +1,4 @@
# encoding: utf-8
from __future__ import print_function
import os
@ -5,6 +6,7 @@ import shutil
import tempfile
from operator import itemgetter
import py
import pytest
from compose.config import config
@ -133,6 +135,65 @@ class ConfigTest(unittest.TestCase):
]
self.assertEqual(service_sort(service_dicts), service_sort(expected))
def test_load_with_multiple_files_and_empty_override(self):
base_file = config.ConfigFile(
'base.yaml',
{'web': {'image': 'example/web'}})
override_file = config.ConfigFile('override.yaml', None)
details = config.ConfigDetails('.', [base_file, override_file])
with pytest.raises(ConfigurationError) as exc:
config.load(details)
assert 'Top level object needs to be a dictionary' in exc.exconly()
def test_load_with_multiple_files_and_empty_base(self):
base_file = config.ConfigFile('base.yaml', None)
override_file = config.ConfigFile(
'override.yaml',
{'web': {'image': 'example/web'}})
details = config.ConfigDetails('.', [base_file, override_file])
with pytest.raises(ConfigurationError) as exc:
config.load(details)
assert 'Top level object needs to be a dictionary' in exc.exconly()
def test_load_with_multiple_files_and_extends_in_override_file(self):
base_file = config.ConfigFile(
'base.yaml',
{
'web': {'image': 'example/web'},
})
override_file = config.ConfigFile(
'override.yaml',
{
'web': {
'extends': {
'file': 'common.yml',
'service': 'base',
},
'volumes': ['/home/user/project:/code'],
},
})
details = config.ConfigDetails('.', [base_file, override_file])
tmpdir = py.test.ensuretemp('config_test')
tmpdir.join('common.yml').write("""
base:
labels: ['label=one']
""")
with tmpdir.as_cwd():
service_dicts = config.load(details)
expected = [
{
'name': 'web',
'image': 'example/web',
'volumes': ['/home/user/project:/code'],
'labels': {'label': 'one'},
},
]
self.assertEqual(service_sort(service_dicts), service_sort(expected))
def test_config_valid_service_names(self):
for valid_name in ['_', '-', '.__.', '_what-up.', 'what_.up----', 'whatup']:
config.load(
@ -319,7 +380,7 @@ class ConfigTest(unittest.TestCase):
@mock.patch('compose.config.validation.log')
def test_logs_warning_for_boolean_in_environment(self, mock_logging):
expected_warning_msg = "Warning: There is a boolean value in the 'environment' key."
expected_warning_msg = "There is a boolean value in the 'environment' key."
config.load(
build_config_details(
{'web': {
@ -349,6 +410,18 @@ class ConfigTest(unittest.TestCase):
)
)
def test_load_yaml_with_yaml_error(self):
tmpdir = py.test.ensuretemp('invalid_yaml_test')
invalid_yaml_file = tmpdir.join('docker-compose.yml')
invalid_yaml_file.write("""
web:
this is bogus: ok: what
""")
with pytest.raises(ConfigurationError) as exc:
config.load_yaml(str(invalid_yaml_file))
assert 'line 3, column 32' in exc.exconly()
class InterpolationTest(unittest.TestCase):
@mock.patch.dict(os.environ)
@ -414,6 +487,23 @@ class InterpolationTest(unittest.TestCase):
self.assertIn('in service "web"', cm.exception.msg)
self.assertIn('"${"', cm.exception.msg)
def test_empty_environment_key_allowed(self):
service_dict = config.load(
build_config_details(
{
'web': {
'build': '.',
'environment': {
'POSTGRES_PASSWORD': ''
},
},
},
'.',
None,
)
)[0]
self.assertEquals(service_dict['environment']['POSTGRES_PASSWORD'], '')
class VolumeConfigTest(unittest.TestCase):
def test_no_binding(self):
@ -448,8 +538,8 @@ class VolumeConfigTest(unittest.TestCase):
self.assertEqual(d['volumes'], ['/var/lib/data:/data'])
def test_absolute_windows_path_does_not_expand(self):
d = make_service_dict('foo', {'build': '.', 'volumes': ['C:\\data:/data']}, working_dir='.')
self.assertEqual(d['volumes'], ['C:\\data:/data'])
d = make_service_dict('foo', {'build': '.', 'volumes': ['c:\\data:/data']}, working_dir='.')
self.assertEqual(d['volumes'], ['c:\\data:/data'])
@pytest.mark.skipif(IS_WINDOWS_PLATFORM, reason='posix paths')
def test_relative_path_does_expand_posix(self):
@ -464,14 +554,14 @@ class VolumeConfigTest(unittest.TestCase):
@pytest.mark.skipif(not IS_WINDOWS_PLATFORM, reason='windows paths')
def test_relative_path_does_expand_windows(self):
d = make_service_dict('foo', {'build': '.', 'volumes': ['./data:/data']}, working_dir='C:\\Users\\me\\myproject')
self.assertEqual(d['volumes'], ['C:\\Users\\me\\myproject\\data:/data'])
d = make_service_dict('foo', {'build': '.', 'volumes': ['./data:/data']}, working_dir='c:\\Users\\me\\myproject')
self.assertEqual(d['volumes'], ['c:\\Users\\me\\myproject\\data:/data'])
d = make_service_dict('foo', {'build': '.', 'volumes': ['.:/data']}, working_dir='C:\\Users\\me\\myproject')
self.assertEqual(d['volumes'], ['C:\\Users\\me\\myproject:/data'])
d = make_service_dict('foo', {'build': '.', 'volumes': ['.:/data']}, working_dir='c:\\Users\\me\\myproject')
self.assertEqual(d['volumes'], ['c:\\Users\\me\\myproject:/data'])
d = make_service_dict('foo', {'build': '.', 'volumes': ['../otherproject:/data']}, working_dir='C:\\Users\\me\\myproject')
self.assertEqual(d['volumes'], ['C:\\Users\\me\\otherproject:/data'])
d = make_service_dict('foo', {'build': '.', 'volumes': ['../otherproject:/data']}, working_dir='c:\\Users\\me\\myproject')
self.assertEqual(d['volumes'], ['c:\\Users\\me\\otherproject:/data'])
@mock.patch.dict(os.environ)
def test_home_directory_with_driver_does_not_expand(self):
@ -805,7 +895,12 @@ class EnvTest(unittest.TestCase):
)
self.assertEqual(
service_dict['environment'],
{'FILE_DEF': 'F1', 'FILE_DEF_EMPTY': '', 'ENV_DEF': 'E3', 'NO_DEF': ''},
{
'FILE_DEF': u'bär',
'FILE_DEF_EMPTY': '',
'ENV_DEF': 'E3',
'NO_DEF': ''
},
)
@pytest.mark.xfail(IS_WINDOWS_PLATFORM, reason='paths use slash')

View file

@ -323,9 +323,7 @@ class ServiceTest(unittest.TestCase):
new_container = service.recreate_container(mock_container)
mock_container.stop.assert_called_once_with(timeout=10)
self.mock_client.rename.assert_called_once_with(
mock_container.id,
'%s_%s' % (mock_container.short_id, mock_container.name))
mock_container.rename_to_tmp_name.assert_called_once_with()
new_container.start.assert_called_once_with()
mock_container.remove.assert_called_once_with()
@ -444,6 +442,14 @@ class ServiceTest(unittest.TestCase):
}
self.assertEqual(config_dict, expected)
def test_get_links_with_networking(self):
service = Service(
'foo',
image='foo',
links=[(Service('one'), 'one')],
use_networking=True)
self.assertEqual(service._get_links(link_to_self=True), [])
class NetTestCase(unittest.TestCase):