mirror of
https://github.com/docker/compose.git
synced 2026-02-16 21:42:33 +08:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9164125177 | ||
|
|
2595f89519 | ||
|
|
a058c40dfb | ||
|
|
fc4b3d2771 | ||
|
|
59cc9c9b68 | ||
|
|
d1a52d2b1a | ||
|
|
5f5fbb3ea4 | ||
|
|
2d98071e55 | ||
|
|
6a3d1d06b5 | ||
|
|
6813cb86a2 | ||
|
|
f5cf9b60b2 | ||
|
|
7cec029f03 | ||
|
|
4fbad941cb | ||
|
|
d4bff56a61 | ||
|
|
f430b82b43 | ||
|
|
71533791dd | ||
|
|
65f3411320 | ||
|
|
b92651070f | ||
|
|
5be8a37b7e | ||
|
|
044c348faf | ||
|
|
465c7d569c | ||
|
|
2ca0e7954a | ||
|
|
96a92a73f1 | ||
|
|
48e7b4b0a6 |
@@ -2,8 +2,6 @@ language: python
|
||||
python:
|
||||
- '2.6'
|
||||
- '2.7'
|
||||
- '3.2'
|
||||
- '3.3'
|
||||
env:
|
||||
- DOCKER_VERSION=0.8.0
|
||||
- DOCKER_VERSION=0.8.1
|
||||
|
||||
13
CHANGES.md
13
CHANGES.md
@@ -1,6 +1,19 @@
|
||||
Change log
|
||||
==========
|
||||
|
||||
0.3.2 (2014-03-05)
|
||||
------------------
|
||||
|
||||
- Added an `--rm` option to `fig run`. (Thanks @marksteve!)
|
||||
- Added an `expose` option to `fig.yml`.
|
||||
|
||||
0.3.1 (2014-03-04)
|
||||
------------------
|
||||
|
||||
- Added contribution instructions. (Thanks @kvz!)
|
||||
- Fixed `fig rm` throwing an error.
|
||||
- Fixed a bug in `fig ps` on Docker 0.8.1 when there is a container with no command.
|
||||
|
||||
0.3.0 (2014-03-03)
|
||||
------------------
|
||||
|
||||
|
||||
13
README.md
13
README.md
@@ -60,3 +60,16 @@ Building OS X binaries
|
||||
|
||||
Note that this only works on Mountain Lion, not Mavericks, due to a [bug in PyInstaller](http://www.pyinstaller.org/ticket/807).
|
||||
|
||||
Contributing to Fig
|
||||
-------------------
|
||||
|
||||
If you're looking contribute to [Fig](http://orchardup.github.io/fig/)
|
||||
but you're new to the project or maybe even to Python, here are the steps
|
||||
that should get you started.
|
||||
|
||||
1. Fork [https://github.com/orchardup/fig](https://github.com/orchardup/fig) to your username. kvz in this example.
|
||||
1. Clone your forked repository locally `git clone git@github.com:kvz/fig.git`.
|
||||
1. Enter the local directory `cd fig`.
|
||||
1. Set up a development environment `python setup.py develop`. That will install the dependencies and set up a symlink from your `fig` executable to the checkout of the repo. So from any of your fig projects, `fig` now refers to your development project. Time to start hacking : )
|
||||
1. Works for you? Run the test suite via `./scripts/test` to verify it won't break other usecases.
|
||||
1. All good? Commit and push to GitHub, and submit a pull request.
|
||||
|
||||
@@ -28,8 +28,6 @@ Simple enough. Finally, this is all tied together with a file called `fig.yml`.
|
||||
|
||||
db:
|
||||
image: orchardup/postgresql
|
||||
ports:
|
||||
- "5432"
|
||||
web:
|
||||
build: .
|
||||
command: python manage.py runserver 0.0.0.0:8000
|
||||
|
||||
@@ -16,12 +16,12 @@ Docker has guides for [Ubuntu](http://docs.docker.io/en/latest/installation/ubun
|
||||
|
||||
Next, install Fig. On OS X:
|
||||
|
||||
$ curl -L https://github.com/orchardup/fig/releases/download/0.3.0/darwin > /usr/local/bin/fig
|
||||
$ curl -L https://github.com/orchardup/fig/releases/download/0.3.1/darwin > /usr/local/bin/fig
|
||||
$ chmod +x /usr/local/bin/fig
|
||||
|
||||
On 64-bit Linux:
|
||||
|
||||
$ curl -L https://github.com/orchardup/fig/releases/download/0.3.0/linux > /usr/local/bin/fig
|
||||
$ curl -L https://github.com/orchardup/fig/releases/download/0.3.1/linux > /usr/local/bin/fig
|
||||
$ chmod +x /usr/local/bin/fig
|
||||
|
||||
Fig is also available as a Python package if you're on another platform (or if you prefer that sort of thing):
|
||||
|
||||
@@ -33,8 +33,6 @@ web:
|
||||
- .:/code
|
||||
db:
|
||||
image: orchardup/mysql
|
||||
ports:
|
||||
- "3306:3306"
|
||||
environment:
|
||||
MYSQL_DATABASE: wordpress
|
||||
```
|
||||
|
||||
@@ -44,6 +44,12 @@ ports:
|
||||
- "8000:8000"
|
||||
- "49100:22"
|
||||
|
||||
-- Expose ports without publishing them to the host machine - they'll only be
|
||||
-- accessible to linked services. Only the internal port can be specified.
|
||||
expose:
|
||||
- "3000"
|
||||
- "8000"
|
||||
|
||||
-- Map volumes from the host machine (HOST:CONTAINER).
|
||||
volumes:
|
||||
- cache/:/tmp/cache
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from __future__ import unicode_literals
|
||||
from .service import Service
|
||||
|
||||
__version__ = '0.3.0'
|
||||
__version__ = '0.3.2'
|
||||
|
||||
@@ -170,19 +170,23 @@ class TopLevelCommand(Command):
|
||||
"""
|
||||
Remove stopped service containers.
|
||||
|
||||
Usage: rm [SERVICE...]
|
||||
Usage: rm [options] [SERVICE...]
|
||||
|
||||
Options:
|
||||
-v Remove volumes associated with containers
|
||||
--force Don't ask to confirm removal
|
||||
-v Remove volumes associated with containers
|
||||
"""
|
||||
all_containers = self.project.containers(service_names=options['SERVICE'], stopped=True)
|
||||
stopped_containers = [c for c in all_containers if not c.is_running]
|
||||
|
||||
if len(stopped_containers) > 0:
|
||||
print("Going to remove", list_containers(stopped_containers))
|
||||
if yesno("Are you sure? [yN] ", default=False):
|
||||
self.project.remove_stopped(service_names=options['SERVICE'],
|
||||
remove_volumes=options['-v'])
|
||||
if options.get('--force') \
|
||||
or yesno("Are you sure? [yN] ", default=False):
|
||||
self.project.remove_stopped(
|
||||
service_names=options['SERVICE'],
|
||||
v=options.get('-v', False)
|
||||
)
|
||||
else:
|
||||
print("No stopped containers")
|
||||
|
||||
@@ -205,6 +209,7 @@ class TopLevelCommand(Command):
|
||||
container name
|
||||
-T Disable pseudo-tty allocation. By default `fig run`
|
||||
allocates a TTY.
|
||||
--rm Remove container after run. Ignored in detached mode.
|
||||
"""
|
||||
service = self.project.get_service(options['SERVICE'])
|
||||
|
||||
@@ -225,6 +230,10 @@ class TopLevelCommand(Command):
|
||||
with self._attach_to_container(container.id, raw=tty) as c:
|
||||
service.start_container(container, ports=None)
|
||||
c.run()
|
||||
if options['--rm']:
|
||||
container.wait()
|
||||
log.info("Removing %s..." % container.name)
|
||||
self.client.remove_container(container.id)
|
||||
|
||||
def scale(self, options):
|
||||
"""
|
||||
|
||||
@@ -70,6 +70,8 @@ class Container(object):
|
||||
for private, public in list(self.dictionary['NetworkSettings']['Ports'].items()):
|
||||
if public:
|
||||
ports.append('%s->%s' % (public[0]['HostPort'], private))
|
||||
else:
|
||||
ports.append(private)
|
||||
return ', '.join(ports)
|
||||
|
||||
@property
|
||||
@@ -86,7 +88,10 @@ class Container(object):
|
||||
@property
|
||||
def human_readable_command(self):
|
||||
self.inspect_if_not_inspected()
|
||||
return ' '.join(self.dictionary['Config']['Cmd'])
|
||||
if self.dictionary['Config']['Cmd']:
|
||||
return ' '.join(self.dictionary['Config']['Cmd'])
|
||||
else:
|
||||
return ''
|
||||
|
||||
@property
|
||||
def environment(self):
|
||||
@@ -112,8 +117,7 @@ class Container(object):
|
||||
return self.client.kill(self.id)
|
||||
|
||||
def remove(self, **options):
|
||||
v = options.get('remove_volumes', False)
|
||||
return self.client.remove_container(self.id, v=v)
|
||||
return self.client.remove_container(self.id, **options)
|
||||
|
||||
def inspect_if_not_inspected(self):
|
||||
if not self.has_been_inspected:
|
||||
|
||||
@@ -39,7 +39,7 @@ class Service(object):
|
||||
if 'image' in options and 'build' in options:
|
||||
raise ConfigError('Service %s has both an image and build path specified. A service can either be built to image or use an existing image, not both.' % name)
|
||||
|
||||
supported_options = DOCKER_CONFIG_KEYS + ['build']
|
||||
supported_options = DOCKER_CONFIG_KEYS + ['build', 'expose']
|
||||
|
||||
for k in options:
|
||||
if k not in supported_options:
|
||||
@@ -246,9 +246,10 @@ class Service(object):
|
||||
|
||||
container_options['name'] = self.next_container_name(one_off)
|
||||
|
||||
if 'ports' in container_options:
|
||||
if 'ports' in container_options or 'expose' in self.options:
|
||||
ports = []
|
||||
for port in container_options['ports']:
|
||||
all_ports = container_options.get('ports', []) + self.options.get('expose', [])
|
||||
for port in all_ports:
|
||||
port = str(port)
|
||||
if ':' in port:
|
||||
port = port.split(':')[-1]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -ex
|
||||
rm -r venv
|
||||
virtualenv venv
|
||||
venv/bin/pip install pyinstaller==2.1
|
||||
venv/bin/pip install .
|
||||
|
||||
@@ -32,7 +32,7 @@ class CLITestCase(DockerClientTestCase):
|
||||
self.assertIn('fig_simple_1', mock_stdout.getvalue())
|
||||
|
||||
@patch('sys.stdout', new_callable=StringIO)
|
||||
def test_default_figfile(self, mock_stdout):
|
||||
def test_ps_default_figfile(self, mock_stdout):
|
||||
self.command.base_dir = 'tests/fixtures/multiple-figfiles'
|
||||
self.command.dispatch(['up', '-d'], None)
|
||||
self.command.dispatch(['ps'], None)
|
||||
@@ -43,7 +43,7 @@ class CLITestCase(DockerClientTestCase):
|
||||
self.assertNotIn('fig_yetanother_1', output)
|
||||
|
||||
@patch('sys.stdout', new_callable=StringIO)
|
||||
def test_alternate_figfile(self, mock_stdout):
|
||||
def test_ps_alternate_figfile(self, mock_stdout):
|
||||
self.command.base_dir = 'tests/fixtures/multiple-figfiles'
|
||||
self.command.dispatch(['-f', 'fig2.yml', 'up', '-d'], None)
|
||||
self.command.dispatch(['-f', 'fig2.yml', 'ps'], None)
|
||||
@@ -53,6 +53,14 @@ class CLITestCase(DockerClientTestCase):
|
||||
self.assertNotIn('fig_another_1', output)
|
||||
self.assertIn('fig_yetanother_1', output)
|
||||
|
||||
def test_rm(self):
|
||||
service = self.command.project.get_service('simple')
|
||||
service.create_container()
|
||||
service.kill()
|
||||
self.assertEqual(len(service.containers(stopped=True)), 1)
|
||||
self.command.dispatch(['rm', '--force'], None)
|
||||
self.assertEqual(len(service.containers(stopped=True)), 0)
|
||||
|
||||
def test_scale(self):
|
||||
project = self.command.project
|
||||
|
||||
@@ -74,4 +82,3 @@ class CLITestCase(DockerClientTestCase):
|
||||
self.command.scale({'SERVICE=NUM': ['simple=0', 'another=0']})
|
||||
self.assertEqual(len(project.get_service('simple').containers()), 0)
|
||||
self.assertEqual(len(project.get_service('another').containers()), 0)
|
||||
|
||||
|
||||
@@ -209,25 +209,30 @@ class ServiceTest(DockerClientTestCase):
|
||||
def test_start_container_creates_ports(self):
|
||||
service = self.create_service('web', ports=[8000])
|
||||
container = service.start_container().inspect()
|
||||
self.assertEqual(list(container['HostConfig']['PortBindings'].keys()), ['8000/tcp'])
|
||||
self.assertNotEqual(container['HostConfig']['PortBindings']['8000/tcp'][0]['HostPort'], '8000')
|
||||
self.assertEqual(list(container['NetworkSettings']['Ports'].keys()), ['8000/tcp'])
|
||||
self.assertNotEqual(container['NetworkSettings']['Ports']['8000/tcp'][0]['HostPort'], '8000')
|
||||
|
||||
def test_expose_does_not_publish_ports(self):
|
||||
service = self.create_service('web', expose=[8000])
|
||||
container = service.start_container().inspect()
|
||||
self.assertEqual(container['NetworkSettings']['Ports'], {'8000/tcp': None})
|
||||
|
||||
def test_start_container_creates_port_with_explicit_protocol(self):
|
||||
service = self.create_service('web', ports=['8000/udp'])
|
||||
container = service.start_container().inspect()
|
||||
self.assertEqual(list(container['HostConfig']['PortBindings'].keys()), ['8000/udp'])
|
||||
self.assertEqual(list(container['NetworkSettings']['Ports'].keys()), ['8000/udp'])
|
||||
|
||||
def test_start_container_creates_fixed_external_ports(self):
|
||||
service = self.create_service('web', ports=['8000:8000'])
|
||||
container = service.start_container().inspect()
|
||||
self.assertIn('8000/tcp', container['HostConfig']['PortBindings'])
|
||||
self.assertEqual(container['HostConfig']['PortBindings']['8000/tcp'][0]['HostPort'], '8000')
|
||||
self.assertIn('8000/tcp', container['NetworkSettings']['Ports'])
|
||||
self.assertEqual(container['NetworkSettings']['Ports']['8000/tcp'][0]['HostPort'], '8000')
|
||||
|
||||
def test_start_container_creates_fixed_external_ports_when_it_is_different_to_internal_port(self):
|
||||
service = self.create_service('web', ports=['8001:8000'])
|
||||
container = service.start_container().inspect()
|
||||
self.assertIn('8000/tcp', container['HostConfig']['PortBindings'])
|
||||
self.assertEqual(container['HostConfig']['PortBindings']['8000/tcp'][0]['HostPort'], '8001')
|
||||
self.assertIn('8000/tcp', container['NetworkSettings']['Ports'])
|
||||
self.assertEqual(container['NetworkSettings']['Ports']['8000/tcp'][0]['HostPort'], '8001')
|
||||
|
||||
def test_scale(self):
|
||||
service = self.create_service('web')
|
||||
|
||||
Reference in New Issue
Block a user