import socket
s = socket.socket()
s.bind(('127.0.0.1', 0))
s.getsockname()
('127.0.0.1', 58938)
port = s.getsockname()[1]
s.close()
port
58938
import docker
client = docker.from_env(version='auto')
client.containers.run?
Signature: client.containers.run(image, command=None, stdout=True, stderr=False, remove=False, **kwargs) Docstring: Run a container. By default, it will wait for the container to finish and return its logs, similar to ``docker run``. If the ``detach`` argument is ``True``, it will start the container and immediately return a :py:class:`Container` object, similar to ``docker run -d``. Example: Run a container and get its output: >>> import docker >>> client = docker.from_env() >>> client.containers.run('alpine', 'echo hello world') b'hello world\n' Run a container and detach: >>> container = client.containers.run('bfirsh/reticulate-splines', detach=True) >>> container.logs() 'Reticulating spline 1...\nReticulating spline 2...\n' Args: image (str): The image to run. command (str or list): The command to run in the container. auto_remove (bool): enable auto-removal of the container on daemon side when the container's process exits. blkio_weight_device: Block IO weight (relative device weight) in the form of: ``[{"Path": "device_path", "Weight": weight}]``. blkio_weight: Block IO weight (relative weight), accepts a weight value between 10 and 1000. cap_add (list of str): Add kernel capabilities. For example, ``["SYS_ADMIN", "MKNOD"]``. cap_drop (list of str): Drop kernel capabilities. cpu_count (int): Number of usable CPUs (Windows only). cpu_percent (int): Usable percentage of the available CPUs (Windows only). cpu_period (int): The length of a CPU period in microseconds. cpu_quota (int): Microseconds of CPU time that the container can get in a CPU period. cpu_shares (int): CPU shares (relative weight). cpuset_cpus (str): CPUs in which to allow execution (``0-3``, ``0,1``). cpuset_mems (str): Memory nodes (MEMs) in which to allow execution (``0-3``, ``0,1``). Only effective on NUMA systems. detach (bool): Run container in the background and return a :py:class:`Container` object. device_cgroup_rules (:py:class:`list`): A list of cgroup rules to apply to the container. device_read_bps: Limit read rate (bytes per second) from a device in the form of: `[{"Path": "device_path", "Rate": rate}]` device_read_iops: Limit read rate (IO per second) from a device. device_write_bps: Limit write rate (bytes per second) from a device. device_write_iops: Limit write rate (IO per second) from a device. devices (:py:class:`list`): Expose host devices to the container, as a list of strings in the form ``<path_on_host>:<path_in_container>:<cgroup_permissions>``. For example, ``/dev/sda:/dev/xvda:rwm`` allows the container to have read-write access to the host's ``/dev/sda`` via a node named ``/dev/xvda`` inside the container. dns (:py:class:`list`): Set custom DNS servers. dns_opt (:py:class:`list`): Additional options to be added to the container's ``resolv.conf`` file. dns_search (:py:class:`list`): DNS search domains. domainname (str or list): Set custom DNS search domains. entrypoint (str or list): The entrypoint for the container. environment (dict or list): Environment variables to set inside the container, as a dictionary or a list of strings in the format ``["SOMEVARIABLE=xxx"]``. extra_hosts (dict): Addtional hostnames to resolve inside the container, as a mapping of hostname to IP address. group_add (:py:class:`list`): List of additional group names and/or IDs that the container process will run as. healthcheck (dict): Specify a test to perform to check that the container is healthy. hostname (str): Optional hostname for the container. init (bool): Run an init inside the container that forwards signals and reaps processes init_path (str): Path to the docker-init binary ipc_mode (str): Set the IPC mode for the container. isolation (str): Isolation technology to use. Default: `None`. labels (dict or list): A dictionary of name-value labels (e.g. ``{"label1": "value1", "label2": "value2"}``) or a list of names of labels to set with empty values (e.g. ``["label1", "label2"]``) links (dict or list of tuples): Either a dictionary mapping name to alias or as a list of ``(name, alias)`` tuples. log_config (dict): Logging configuration, as a dictionary with keys: - ``type`` The logging driver name. - ``config`` A dictionary of configuration for the logging driver. mac_address (str): MAC address to assign to the container. mem_limit (int or str): Memory limit. Accepts float values (which represent the memory limit of the created container in bytes) or a string with a units identification char (``100000b``, ``1000k``, ``128m``, ``1g``). If a string is specified without a units character, bytes are assumed as an intended unit. mem_swappiness (int): Tune a container's memory swappiness behavior. Accepts number between 0 and 100. memswap_limit (str or int): Maximum amount of memory + swap a container is allowed to consume. mounts (:py:class:`list`): Specification for mounts to be added to the container. More powerful alternative to ``volumes``. Each item in the list is expected to be a :py:class:`docker.types.Mount` object. name (str): The name for this container. nano_cpus (int): CPU quota in units of 1e-9 CPUs. network (str): Name of the network this container will be connected to at creation time. You can connect to additional networks using :py:meth:`Network.connect`. Incompatible with ``network_mode``. network_disabled (bool): Disable networking. network_mode (str): One of: - ``bridge`` Create a new network stack for the container on on the bridge network. - ``none`` No networking for this container. - ``container:<name|id>`` Reuse another container's network stack. - ``host`` Use the host network stack. Incompatible with ``network``. oom_kill_disable (bool): Whether to disable OOM killer. oom_score_adj (int): An integer value containing the score given to the container in order to tune OOM killer preferences. pid_mode (str): If set to ``host``, use the host PID namespace inside the container. pids_limit (int): Tune a container's pids limit. Set ``-1`` for unlimited. platform (str): Platform in the format ``os[/arch[/variant]]``. Only used if the method needs to pull the requested image. ports (dict): Ports to bind inside the container. The keys of the dictionary are the ports to bind inside the container, either as an integer or a string in the form ``port/protocol``, where the protocol is either ``tcp`` or ``udp``. The values of the dictionary are the corresponding ports to open on the host, which can be either: - The port number, as an integer. For example, ``{'2222/tcp': 3333}`` will expose port 2222 inside the container as port 3333 on the host. - ``None``, to assign a random host port. For example, ``{'2222/tcp': None}``. - A tuple of ``(address, port)`` if you want to specify the host interface. For example, ``{'1111/tcp': ('127.0.0.1', 1111)}``. - A list of integers, if you want to bind multiple host ports to a single container port. For example, ``{'1111/tcp': [1234, 4567]}``. privileged (bool): Give extended privileges to this container. publish_all_ports (bool): Publish all ports to the host. read_only (bool): Mount the container's root filesystem as read only. remove (bool): Remove the container when it has finished running. Default: ``False``. restart_policy (dict): Restart the container when it exits. Configured as a dictionary with keys: - ``Name`` One of ``on-failure``, or ``always``. - ``MaximumRetryCount`` Number of times to restart the container on failure. For example: ``{"Name": "on-failure", "MaximumRetryCount": 5}`` security_opt (:py:class:`list`): A list of string values to customize labels for MLS systems, such as SELinux. shm_size (str or int): Size of /dev/shm (e.g. ``1G``). stdin_open (bool): Keep ``STDIN`` open even if not attached. stdout (bool): Return logs from ``STDOUT`` when ``detach=False``. Default: ``True``. stderr (bool): Return logs from ``STDERR`` when ``detach=False``. Default: ``False``. stop_signal (str): The stop signal to use to stop the container (e.g. ``SIGINT``). storage_opt (dict): Storage driver options per container as a key-value mapping. stream (bool): If true and ``detach`` is false, return a log generator instead of a string. Ignored if ``detach`` is true. Default: ``False``. sysctls (dict): Kernel parameters to set in the container. tmpfs (dict): Temporary filesystems to mount, as a dictionary mapping a path inside the container to options for that path. For example: .. code-block:: python { '/mnt/vol2': '', '/mnt/vol1': 'size=3G,uid=1000' } tty (bool): Allocate a pseudo-TTY. ulimits (:py:class:`list`): Ulimits to set inside the container, as a list of dicts. user (str or int): Username or UID to run commands as inside the container. userns_mode (str): Sets the user namespace mode for the container when user namespace remapping option is enabled. Supported values are: ``host`` volume_driver (str): The name of a volume driver/plugin. volumes (dict or list): A dictionary to configure volumes mounted inside the container. The key is either the host path or a volume name, and the value is a dictionary with the keys: - ``bind`` The path to mount the volume inside the container - ``mode`` Either ``rw`` to mount the volume read/write, or ``ro`` to mount it read-only. For example: .. code-block:: python {'/home/user1/': {'bind': '/mnt/vol2', 'mode': 'rw'}, '/var/www': {'bind': '/mnt/vol1', 'mode': 'ro'}} volumes_from (:py:class:`list`): List of container names or IDs to get volumes from. working_dir (str): Path to the working directory. runtime (str): Runtime to use with this container. Returns: The container logs, either ``STDOUT``, ``STDERR``, or both, depending on the value of the ``stdout`` and ``stderr`` arguments. ``STDOUT`` and ``STDERR`` may be read only if either ``json-file`` or ``journald`` logging driver used. Thus, if you are using none of these drivers, a ``None`` object is returned instead. See the `Engine API documentation <https://docs.docker.com/engine/api/v1.30/#operation/ContainerLogs/>`_ for full details. If ``detach`` is ``True``, a :py:class:`Container` object is returned instead. Raises: :py:class:`docker.errors.ContainerError` If the container exits with a non-zero exit code and ``detach`` is ``False``. :py:class:`docker.errors.ImageNotFound` If the specified image does not exist. :py:class:`docker.errors.APIError` If the server returns an error. File: ~/conda/lib/python3.6/site-packages/docker/models/containers.py Type: method
port
58938
Create the dictionary for docker that forwards our port on the host to the same port in the container
port_dict = {'%i/tcp' % port : port}
port_dict
{'58938/tcp': 58938}
Start the container. detach=True
allows this to return immediately while the container is still running.
container = client.containers.run(
"jupyter/base-notebook",
command=["jupyter", "notebook", "--ip=0.0.0.0", "--port=%i" % port],
ports=port_dict,
detach=True,
remove=True,
)
container.attrs
{'Id': '53b926531746b593163047adb2d551299f21012d8247776a4ddc5d528f5a87e5', 'Created': '2018-06-15T10:50:58.356344753Z', 'Path': 'tini', 'Args': ['-g', '--', 'jupyter', 'notebook', '--ip=0.0.0.0', '--port=58938'], 'State': {'Status': 'created', 'Running': False, 'Paused': False, 'Restarting': False, 'OOMKilled': False, 'Dead': False, 'Pid': 0, 'ExitCode': 0, 'Error': '', 'StartedAt': '0001-01-01T00:00:00Z', 'FinishedAt': '0001-01-01T00:00:00Z'}, 'Image': 'sha256:4d1850bf13b84d11db172e66449cabd718df7d9e609e7ef40354946993581efb', 'ResolvConfPath': '', 'HostnamePath': '', 'HostsPath': '', 'LogPath': '', 'Name': '/laughing_mccarthy', 'RestartCount': 0, 'Driver': 'overlay2', 'Platform': 'linux', 'MountLabel': '', 'ProcessLabel': '', 'AppArmorProfile': '', 'ExecIDs': None, 'HostConfig': {'Binds': None, 'ContainerIDFile': '', 'LogConfig': {'Type': 'json-file', 'Config': {}}, 'NetworkMode': 'default', 'PortBindings': {'58938/tcp': [{'HostIp': '', 'HostPort': '58938'}]}, 'RestartPolicy': {'Name': '', 'MaximumRetryCount': 0}, 'AutoRemove': True, 'VolumeDriver': '', 'VolumesFrom': None, 'CapAdd': None, 'CapDrop': None, 'Dns': None, 'DnsOptions': None, 'DnsSearch': None, 'ExtraHosts': None, 'GroupAdd': None, 'IpcMode': 'shareable', 'Cgroup': '', 'Links': None, 'OomScoreAdj': 0, 'PidMode': '', 'Privileged': False, 'PublishAllPorts': False, 'ReadonlyRootfs': False, 'SecurityOpt': None, 'UTSMode': '', 'UsernsMode': '', 'ShmSize': 67108864, 'Runtime': 'runc', 'ConsoleSize': [0, 0], 'Isolation': '', 'CpuShares': 0, 'Memory': 0, 'NanoCpus': 0, 'CgroupParent': '', 'BlkioWeight': 0, 'BlkioWeightDevice': None, 'BlkioDeviceReadBps': None, 'BlkioDeviceWriteBps': None, 'BlkioDeviceReadIOps': None, 'BlkioDeviceWriteIOps': None, 'CpuPeriod': 0, 'CpuQuota': 0, 'CpuRealtimePeriod': 0, 'CpuRealtimeRuntime': 0, 'CpusetCpus': '', 'CpusetMems': '', 'Devices': None, 'DeviceCgroupRules': None, 'DiskQuota': 0, 'KernelMemory': 0, 'MemoryReservation': 0, 'MemorySwap': 0, 'MemorySwappiness': None, 'OomKillDisable': False, 'PidsLimit': 0, 'Ulimits': None, 'CpuCount': 0, 'CpuPercent': 0, 'IOMaximumIOps': 0, 'IOMaximumBandwidth': 0}, 'GraphDriver': {'Data': {'LowerDir': '/var/lib/docker/overlay2/b824e3c97b4fafe4aa48f6d62730e19e6daa6abddbd324d59a0630eeeac22bb7-init/diff:/var/lib/docker/overlay2/05667eb1399d6d66f6372f897d9edebf3e073902a71e73f752844ba3438d19ac/diff:/var/lib/docker/overlay2/d5823f39e52af886171ade2255a566e7d872cdb6804d272f4551074982e92a4a/diff:/var/lib/docker/overlay2/d107b0575345e3f56c3712b862e94f943db9cfa626def1c83d8f7bdda909b26b/diff:/var/lib/docker/overlay2/c2c292d60e8cedf16e493de214b788eec7ef726f49528330954e256664059062/diff:/var/lib/docker/overlay2/7d5fb5b7ffc13480969a584f1d664e170d16f781db8368a7dc50cddc51cc287e/diff:/var/lib/docker/overlay2/59d975cfcc0618b114c574313082d1c8a08e3ad5afae9d87663f70ce971c8b6e/diff:/var/lib/docker/overlay2/f9f695ebf4b377d9f3e40b262cef08506cdca66beef9e4adcc8538290a1584c1/diff:/var/lib/docker/overlay2/9cdbb195af449cdaa984acb7607b0009b376d78fd143da291f700bd7ac358af5/diff:/var/lib/docker/overlay2/d8318b6efa7e9d55a2b4728e4e0904c9042b2b2dd69a02ad3669d10b6e5783cd/diff:/var/lib/docker/overlay2/449acd0c01f17967911b38249c4f8b9c96ffe7e0221eb0229a06f0af580529f9/diff:/var/lib/docker/overlay2/a9bc950634edfce5ae774d42834f6085a4f6adfcfd278a97f7e461388b79856e/diff:/var/lib/docker/overlay2/9068e6bd8ca13f5475ad1c126fd4952f2b369d3daf6795865431ccfb4739bcd1/diff:/var/lib/docker/overlay2/27bb5b5d3de166e8120ad20825eb8480c087edd09801b62f4d6ac6c51638969a/diff:/var/lib/docker/overlay2/2330f726c314f19d61722800572f3696e1a2e2df70994970db2b2921c05545b5/diff:/var/lib/docker/overlay2/54ee572efb2497b12025e5bae3a677a5002c08ba4204a319bf2d4530b5073eec/diff:/var/lib/docker/overlay2/582d30b95539508d5f7adbad5ac79bf4554ef641437bebe8317397bf2ad722c2/diff:/var/lib/docker/overlay2/03c130639ed4f6b742b8c7c22657391f371fff36a04215ffa68003e38edfde3c/diff:/var/lib/docker/overlay2/56ef359671bff45cab933d031c2f0d17a8d3eab31f60854356433ee53e4c903c/diff', 'MergedDir': '/var/lib/docker/overlay2/b824e3c97b4fafe4aa48f6d62730e19e6daa6abddbd324d59a0630eeeac22bb7/merged', 'UpperDir': '/var/lib/docker/overlay2/b824e3c97b4fafe4aa48f6d62730e19e6daa6abddbd324d59a0630eeeac22bb7/diff', 'WorkDir': '/var/lib/docker/overlay2/b824e3c97b4fafe4aa48f6d62730e19e6daa6abddbd324d59a0630eeeac22bb7/work'}, 'Name': 'overlay2'}, 'Mounts': [], 'Config': {'Hostname': '53b926531746', 'Domainname': '', 'User': '1000', 'AttachStdin': False, 'AttachStdout': False, 'AttachStderr': False, 'ExposedPorts': {'58938/tcp': {}, '8888/tcp': {}}, 'Tty': False, 'OpenStdin': False, 'StdinOnce': False, 'Env': ['PATH=/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', 'DEBIAN_FRONTEND=noninteractive', 'CONDA_DIR=/opt/conda', 'SHELL=/bin/bash', 'NB_USER=jovyan', 'NB_UID=1000', 'NB_GID=100', 'LC_ALL=en_US.UTF-8', 'LANG=en_US.UTF-8', 'LANGUAGE=en_US.UTF-8', 'HOME=/home/jovyan', 'MINICONDA_VERSION=4.5.1'], 'Cmd': ['jupyter', 'notebook', '--ip=0.0.0.0', '--port=58938'], 'Image': 'jupyter/base-notebook', 'Volumes': None, 'WorkingDir': '/home/jovyan', 'Entrypoint': ['tini', '-g', '--'], 'OnBuild': None, 'Labels': {'maintainer': 'Jupyter Project <jupyter@googlegroups.com>'}}, 'NetworkSettings': {'Bridge': '', 'SandboxID': '', 'HairpinMode': False, 'LinkLocalIPv6Address': '', 'LinkLocalIPv6PrefixLen': 0, 'Ports': {}, 'SandboxKey': '', 'SecondaryIPAddresses': None, 'SecondaryIPv6Addresses': None, 'EndpointID': '', 'Gateway': '', 'GlobalIPv6Address': '', 'GlobalIPv6PrefixLen': 0, 'IPAddress': '', 'IPPrefixLen': 0, 'IPv6Gateway': '', 'MacAddress': '', 'Networks': {'bridge': {'IPAMConfig': None, 'Links': None, 'Aliases': None, 'NetworkID': '', 'EndpointID': '', 'Gateway': '', 'IPAddress': '', 'IPPrefixLen': 0, 'IPv6Gateway': '', 'GlobalIPv6Address': '', 'GlobalIPv6PrefixLen': 0, 'MacAddress': '', 'DriverOpts': None}}}}
print(container.logs().decode('utf8'))
[I 10:50:59.099 NotebookApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret [I 10:50:59.262 NotebookApp] JupyterLab beta preview extension loaded from /opt/conda/lib/python3.6/site-packages/jupyterlab [I 10:50:59.262 NotebookApp] JupyterLab application directory is /opt/conda/share/jupyter/lab [I 10:50:59.265 NotebookApp] Serving notebooks from local directory: /home/jovyan [I 10:50:59.265 NotebookApp] 0 active kernels [I 10:50:59.265 NotebookApp] The Jupyter Notebook is running at: [I 10:50:59.265 NotebookApp] http://53b926531746:58938/?token=72f0ac9a4bf481fce1932b2f71b884fd85f5147845be0001 [I 10:50:59.265 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [C 10:50:59.266 NotebookApp] Copy/paste this URL into your browser when you connect for the first time, to login with a token: http://53b926531746:58938/?token=72f0ac9a4bf481fce1932b2f71b884fd85f5147845be0001&token=72f0ac9a4bf481fce1932b2f71b884fd85f5147845be0001 [I 10:51:22.954 NotebookApp] 302 GET / (172.17.0.1) 0.55ms [I 10:51:22.958 NotebookApp] 302 GET /tree? (172.17.0.1) 0.61ms [I 10:52:36.154 NotebookApp] 302 GET / (172.17.0.1) 0.65ms [I 10:52:36.162 NotebookApp] 302 GET /tree (172.17.0.1) 0.77ms [W 10:52:41.519 NotebookApp] Forbidden [W 10:52:41.520 NotebookApp] 403 GET /api/status (172.17.0.1) 0.96ms referer=None
import requests
r = requests.get("http://localhost:%i/api" % port)
r.json()
{'version': '5.5.0'}
import requests
r = requests.get("http://localhost:%i/api/contents/work?token=72f0ac9a4bf481fce1932b2f71b884fd85f5147845be0001" % port)
r.json()
{'name': 'work', 'path': 'work', 'last_modified': '2018-06-15T10:56:36.905869Z', 'created': '2018-06-15T10:56:36.905869Z', 'content': [{'name': 'Untitled.ipynb', 'path': 'work/Untitled.ipynb', 'last_modified': '2018-06-15T10:56:36.905869Z', 'created': '2018-06-15T10:56:36.905869Z', 'content': None, 'format': None, 'mimetype': None, 'size': 72, 'writable': True, 'type': 'notebook'}], 'format': 'json', 'mimetype': None, 'size': None, 'writable': True, 'type': 'directory'}
After we are done, remove the container
container.remove(force=True)