From d209ded13c9a7478fc47c41b2319fcf3c1935131 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Thu, 19 Mar 2015 11:21:58 -0700 Subject: [PATCH 1/2] Use dev version of Docker Signed-off-by: Aanand Prasad --- Dockerfile | 17 +++++++++++------ script/test-versions | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index d7a6019aa..1b016e9ee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,13 +15,18 @@ RUN set -ex; \ ; \ rm -rf /var/lib/apt/lists/* -ENV ALL_DOCKER_VERSIONS 1.3.3 1.4.1 1.5.0 +# ENV ALL_DOCKER_VERSIONS 1.6.0 -RUN set -ex; \ - for v in ${ALL_DOCKER_VERSIONS}; do \ - curl https://get.docker.com/builds/Linux/x86_64/docker-$v -o /usr/local/bin/docker-$v; \ - chmod +x /usr/local/bin/docker-$v; \ - done +# RUN set -ex; \ +# for v in ${ALL_DOCKER_VERSIONS}; do \ +# curl https://get.docker.com/builds/Linux/x86_64/docker-$v -o /usr/local/bin/docker-$v; \ +# chmod +x /usr/local/bin/docker-$v; \ +# done + +# Temporarily use dev version of Docker +ENV ALL_DOCKER_VERSIONS dev +RUN curl https://master.dockerproject.com/linux/amd64/docker-1.5.0-dev > /usr/local/bin/docker-dev +RUN chmod +x /usr/local/bin/docker-dev RUN useradd -d /home/user -m -s /bin/bash user WORKDIR /code/ diff --git a/script/test-versions b/script/test-versions index a9e3bc4c7..d44cc9a7b 100755 --- a/script/test-versions +++ b/script/test-versions @@ -11,14 +11,14 @@ script/validate-dco flake8 compose if [ "$DOCKER_VERSIONS" == "" ]; then - DOCKER_VERSIONS="1.5.0" + DOCKER_VERSIONS="dev" elif [ "$DOCKER_VERSIONS" == "all" ]; then DOCKER_VERSIONS="$ALL_DOCKER_VERSIONS" fi for version in $DOCKER_VERSIONS; do >&2 echo "Running tests against Docker $version" - docker-1.5.0 run \ + docker-$version run \ --rm \ --privileged \ --volume="/var/lib/docker" \ From 721327110d922f807a225a572d772168c8c22641 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Thu, 19 Mar 2015 16:10:27 -0700 Subject: [PATCH 2/2] Add 'labels:' config option Signed-off-by: Aanand Prasad --- compose/cli/docker_client.py | 2 +- compose/config.py | 27 +++++++++++++++++++++++++++ docs/install.md | 2 +- docs/yml.md | 18 ++++++++++++++++++ requirements.txt | 2 +- tests/integration/service_test.py | 27 +++++++++++++++++++++++++++ 6 files changed, 75 insertions(+), 3 deletions(-) diff --git a/compose/cli/docker_client.py b/compose/cli/docker_client.py index 20acbdebc..e513182fb 100644 --- a/compose/cli/docker_client.py +++ b/compose/cli/docker_client.py @@ -32,4 +32,4 @@ def docker_client(): ) timeout = int(os.environ.get('DOCKER_CLIENT_TIMEOUT', 60)) - return Client(base_url=base_url, tls=tls_config, version='1.15', timeout=timeout) + return Client(base_url=base_url, tls=tls_config, version='1.18', timeout=timeout) diff --git a/compose/config.py b/compose/config.py index 668d2b726..0f7eec8b8 100644 --- a/compose/config.py +++ b/compose/config.py @@ -17,6 +17,7 @@ DOCKER_CONFIG_KEYS = [ 'environment', 'hostname', 'image', + 'labels', 'links', 'mem_limit', 'net', @@ -171,6 +172,9 @@ def process_container_options(service_dict, working_dir=None): if 'volumes' in service_dict: service_dict['volumes'] = resolve_host_paths(service_dict['volumes'], working_dir=working_dir) + if 'labels' in service_dict: + service_dict['labels'] = parse_labels(service_dict['labels']) + return service_dict @@ -332,6 +336,29 @@ def volumes_from_dict(d): return ["%s:%s" % (host_path, container_path) for (container_path, host_path) in d.items()] +def parse_labels(labels): + if not labels: + return {} + + if isinstance(labels, list): + return dict(split_label(e) for e in labels) + + if isinstance(labels, dict): + return labels + + raise ConfigurationError( + "labels \"%s\" must be a list or mapping" % + labels + ) + + +def split_label(label): + if '=' in label: + return label.split('=', 1) + else: + return label, '' + + def expand_path(working_dir, path): return os.path.abspath(os.path.join(working_dir, path)) diff --git a/docs/install.md b/docs/install.md index 0e60e1f18..00e4a3e3a 100644 --- a/docs/install.md +++ b/docs/install.md @@ -10,7 +10,7 @@ Compose with a `curl` command. ### Install Docker -First, install Docker version 1.3 or greater: +First, install Docker version 1.6 or greater: - [Instructions for Mac OS X](http://docs.docker.com/installation/mac/) - [Instructions for Ubuntu](http://docs.docker.com/installation/ubuntulinux/) diff --git a/docs/yml.md b/docs/yml.md index 157ba4e67..a85f0923f 100644 --- a/docs/yml.md +++ b/docs/yml.md @@ -253,6 +253,24 @@ db: > configuration options are **not** inherited - you will have to define > those manually each time you extend it. +### labels + +Add metadata to containers using [Docker labels](http://docs.docker.com/userguide/labels-custom-metadata/). You can use either an array or a dictionary. + +It's recommended that you use reverse-DNS notation to prevent your labels from conflicting with those used by other software. + +``` +labels: + com.example.description: "Accounting webapp" + com.example.department: "Finance" + com.example.label-with-empty-value: "" + +labels: + - "com.example.description=Accounting webapp" + - "com.example.department=Finance" + - "com.example.label-with-empty-value" +``` + ### net Networking mode. Use the same values as the docker client `--net` parameter. diff --git a/requirements.txt b/requirements.txt index 582aac1c2..32c2b082b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ PyYAML==3.10 -docker-py==1.1.0 +-e git+https://github.com/docker/docker-py.git@70ce156e26d283d181e6ec10bd1309ddc1da1bbd#egg=docker-py dockerpty==0.3.2 docopt==0.6.1 requests==2.5.3 diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py index 7c1695624..4e5ef8adb 100644 --- a/tests/integration/service_test.py +++ b/tests/integration/service_test.py @@ -491,3 +491,30 @@ class ServiceTest(DockerClientTestCase): env = create_and_start_container(service).environment for k,v in {'FILE_DEF': 'F1', 'FILE_DEF_EMPTY': '', 'ENV_DEF': 'E3', 'NO_DEF': ''}.items(): self.assertEqual(env[k], v) + + def test_labels(self): + labels_dict = { + 'com.example.description': "Accounting webapp", + 'com.example.department': "Finance", + 'com.example.label-with-empty-value': "", + } + + service = self.create_service('web', labels=labels_dict) + labels = create_and_start_container(service).get('Config.Labels').items() + for pair in labels_dict.items(): + self.assertIn(pair, labels) + + labels_list = ["%s=%s" % pair for pair in labels_dict.items()] + + service = self.create_service('web', labels=labels_list) + labels = create_and_start_container(service).get('Config.Labels').items() + for pair in labels_dict.items(): + self.assertIn(pair, labels) + + def test_empty_labels(self): + labels_list = ['foo', 'bar'] + + service = self.create_service('web', labels=labels_list) + labels = create_and_start_container(service).get('Config.Labels').items() + for name in labels_list: + self.assertIn((name, ''), labels)