diff --git a/repo2docker/app.py b/repo2docker/app.py index 7f658852..73ac12c5 100644 --- a/repo2docker/app.py +++ b/repo2docker/app.py @@ -18,6 +18,7 @@ import tempfile import time import docker +from urllib.parse import urlparse from docker.utils import kwargs_from_env from docker.errors import DockerException import escapism @@ -520,11 +521,26 @@ class Repo2Docker(Application): Returns running container """ client = docker.from_env(version='auto') + + docker_host = os.environ.get('DOCKER_HOST') + if docker_host: + host_name = urlparse(docker_host).hostname + else: + host_name = '127.0.0.1' + self.hostname = host_name + if not self.run_cmd: port = str(self._get_free_port()) self.port = port - run_cmd = ['jupyter', 'notebook', '--ip', '0.0.0.0', - '--port', port] + # To use the option --NotebookApp.custom_display_url + # make sure the base-notebook image is updated: + # docker pull jupyter/base-notebook + run_cmd = [ + 'jupyter', 'notebook', + '--ip', '0.0.0.0', + '--port', port, + "--NotebookApp.custom_display_url=http://{}:{}".format(host_name, port), + ] ports = {'%s/tcp' % port: port} else: # run_cmd given by user, if port is also given then pass it on @@ -535,6 +551,7 @@ class Repo2Docker(Application): ports = {} # store ports on self so they can be retrieved in tests self.ports = ports + container_volumes = {} if self.volumes: api_client = docker.APIClient( diff --git a/tests/test_connect_url.py b/tests/test_connect_url.py new file mode 100644 index 00000000..5c5e1acf --- /dev/null +++ b/tests/test_connect_url.py @@ -0,0 +1,52 @@ +""" +Test if the explict hostname is supplied correctly to the container +""" +import requests +import time +from repo2docker.app import Repo2Docker + +def test_connect_url(tmpdir): + tmpdir.chdir() + #q = tmpdir.join("environment.yml") + #q.write("dependencies:\n" + # " - notebook==5.6.0") + p = tmpdir.join("requirements.txt") + p.write("notebook==5.6.0") + + app = Repo2Docker() + argv = [str(tmpdir), ] + app.initialize(argv) + app.debug = True + app.run = False + app.start() # This just build the image and does not run it. + container = app.start_container() + container_url = 'http://{}:{}/api'.format(app.hostname, app.port) + expected_url = 'http://{}:{}'.format(app.hostname, app.port) + + # wait a bit for the container to be ready + # give the container a chance to start + time.sleep(1) + + try: + # try a few times to connect + success = False + for i in range(1, 4): + container.reload() + assert container.status == 'running' + if expected_url not in container.logs().decode("utf8"): + time.sleep(i * 3) + continue + try: + info = requests.get(container_url).json() + except Exception as e: + print("Error: %s" % e) + time.sleep(i * 3) + else: + print(info) + success = True + break + assert success, "Notebook never started in %s" % container + finally: + # stop the container + container.stop() + app.wait_for_container(container)