From f0490d3a57d1626d0d88ef4cee9ea784fbef216a Mon Sep 17 00:00:00 2001 From: Min RK Date: Thu, 13 Oct 2016 13:57:39 +0200 Subject: [PATCH] allow using docker networks and use them in `make dev` which is needed for OS X / etc. where host networking only sort-of exists --- Makefile | 27 ++++++++++++++++++--------- dockworker.py | 19 +++++++++++++++---- orchestrate.py | 5 +++++ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 038e311..71450c4 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,9 @@ CULL_PERIOD ?= 30 CULL_TIMEOUT ?= 60 CULL_MAX ?= 120 LOGGING ?= debug -POOL_SIZE ?= 5 +POOL_SIZE ?= 1 DOCKER_HOST ?= 127.0.0.1 +DOCKER_NETWORK_NAME ?= tmpnb tmpnb-image: Dockerfile docker build -t jupyter/tmpnb . @@ -20,24 +21,32 @@ demo-image: proxy-image: docker pull jupyter/configurable-http-proxy -proxy: proxy-image - docker run --net=host -d -e CONFIGPROXY_AUTH_TOKEN=devtoken \ +network: + @docker network inspect $(DOCKER_NETWORK_NAME) >/dev/null 2>&1 || docker network create $(DOCKER_NETWORK_NAME) + +proxy: proxy-image network + docker run -d -e CONFIGPROXY_AUTH_TOKEN=devtoken \ + --network $(DOCKER_NETWORK_NAME) \ + -p 8000:8000 \ + -p 8001:8001 \ --name proxy \ jupyter/configurable-http-proxy \ - --default-target http://127.0.0.1:9999 + --default-target http://tmpnb:9999 --api-ip 0.0.0.0 -tmpnb: minimal-image tmpnb-image - docker run --net=host -d -e CONFIGPROXY_AUTH_TOKEN=devtoken \ +tmpnb: minimal-image tmpnb-image network + docker run -d -e CONFIGPROXY_AUTH_TOKEN=devtoken \ + -e CONFIGPROXY_ENDPOINT=http://proxy:8001 \ + --network $(DOCKER_NETWORK_NAME) \ --name tmpnb \ -v /var/run/docker.sock:/docker.sock jupyter/tmpnb python orchestrate.py \ --image=jupyter/minimal-notebook --cull_timeout=$(CULL_TIMEOUT) --cull_period=$(CULL_PERIOD) \ - --logging=$(LOGGING) --pool_size=$(POOL_SIZE) --cull_max=$(CULL_MAX) + --logging=$(LOGGING) --pool_size=$(POOL_SIZE) --cull_max=$(CULL_MAX) \ + --docker_network=$(DOCKER_NETWORK_NAME) -dev: cleanup proxy tmpnb open +dev: cleanup network proxy tmpnb open open: docker ps | grep tmpnb - docker ps | grep minimal-notebook -open http:`echo $(DOCKER_HOST) | cut -d":" -f2`:8000 cleanup: diff --git a/dockworker.py b/dockworker.py index f145d5d..c2fb040 100644 --- a/dockworker.py +++ b/dockworker.py @@ -13,7 +13,7 @@ ContainerConfig = namedtuple('ContainerConfig', [ 'image', 'command', 'mem_limit', 'cpu_quota', 'cpu_shares', 'container_ip', 'container_port', 'container_user', 'host_network', 'host_directories', - 'extra_hosts' + 'extra_hosts', 'docker_network', ]) # Number of times to retry API calls before giving up. @@ -79,13 +79,13 @@ def create_notebook_server(self, base_path, container_name, container_config): Returns the (container_id, ip, port) tuple in a Future.''' - if container_config.host_network: + if container_config.host_network or container_config.docker_network: # Start with specified container port if self.port == 0: self.port = int(container_config.container_port) port = self.port self.port += 1 - # No bindings when using the host network + # No bindings when using the host network or internal docker network port_bindings = None else: # Bind the specified within-container port to a random port @@ -165,10 +165,16 @@ def create_notebook_server(self, base_path, container_name, container_config): docker_warnings = resp.get('Warnings') if docker_warnings is not None: - app_log.warn(docker_warnings) + app_log.warning(docker_warnings) container_id = resp['Id'] app_log.info("Created container {}".format(container_id)) + + if container_config.docker_network: + yield self._with_retries(self.docker_client.connect_container_to_network, + container_id, + container_config.docker_network, + ) yield self._with_retries(self.docker_client.start, container_id) @@ -176,6 +182,11 @@ def create_notebook_server(self, base_path, container_name, container_config): if container_config.host_network: host_port = port host_ip = container_config.container_ip + elif container_config.docker_network: + container_info = yield self._with_retries(self.docker_client.inspect_container, container_id) + host_port = port + # get ip of container on the specified docker network + host_ip = container_info['NetworkSettings']['Networks'][container_config.docker_network]['IPAddress'] else: container_network = yield self._with_retries(self.docker_client.port, container_id, diff --git a/orchestrate.py b/orchestrate.py index 61ff7ec..d89fb31 100644 --- a/orchestrate.py +++ b/orchestrate.py @@ -333,6 +333,10 @@ def main(): help="""Attaches the containers to the host networking instead of the default docker bridge. Affects the semantics of container_port and container_ip.""" ) + tornado.options.define('docker_network', default=None, + help="""Attaches the containers to the specified docker network. + For use when the proxy, tmpnb, and containers are all in docker.""" + ) tornado.options.define('host_directories', default=None, help=dedent(""" Mount the specified directory as a data volume, multiple @@ -394,6 +398,7 @@ def main(): container_port=opts.container_port, container_user=opts.container_user, host_network=opts.host_network, + docker_network=opts.docker_network, host_directories=opts.host_directories, extra_hosts=opts.extra_hosts )