mirror of https://github.com/docker/docker-py.git
1101 lines
42 KiB
Python
1101 lines
42 KiB
Python
import copy
|
|
import ntpath
|
|
from collections import namedtuple
|
|
|
|
from ..api import APIClient
|
|
from ..constants import DEFAULT_DATA_CHUNK_SIZE
|
|
from ..errors import (
|
|
ContainerError, DockerException, ImageNotFound,
|
|
NotFound, create_unexpected_kwargs_error
|
|
)
|
|
from ..types import HostConfig
|
|
from ..utils import version_gte
|
|
from .images import Image
|
|
from .resource import Collection, Model
|
|
|
|
|
|
class Container(Model):
|
|
""" Local representation of a container object. Detailed configuration may
|
|
be accessed through the :py:attr:`attrs` attribute. Note that local
|
|
attributes are cached; users may call :py:meth:`reload` to
|
|
query the Docker daemon for the current properties, causing
|
|
:py:attr:`attrs` to be refreshed.
|
|
"""
|
|
@property
|
|
def name(self):
|
|
"""
|
|
The name of the container.
|
|
"""
|
|
if self.attrs.get('Name') is not None:
|
|
return self.attrs['Name'].lstrip('/')
|
|
|
|
@property
|
|
def image(self):
|
|
"""
|
|
The image of the container.
|
|
"""
|
|
image_id = self.attrs.get('ImageID', self.attrs['Image'])
|
|
if image_id is None:
|
|
return None
|
|
return self.client.images.get(image_id.split(':')[1])
|
|
|
|
@property
|
|
def labels(self):
|
|
"""
|
|
The labels of a container as dictionary.
|
|
"""
|
|
try:
|
|
result = self.attrs['Config'].get('Labels')
|
|
return result or {}
|
|
except KeyError:
|
|
raise DockerException(
|
|
'Label data is not available for sparse objects. Call reload()'
|
|
' to retrieve all information'
|
|
)
|
|
|
|
@property
|
|
def status(self):
|
|
"""
|
|
The status of the container. For example, ``running``, or ``exited``.
|
|
"""
|
|
if isinstance(self.attrs['State'], dict):
|
|
return self.attrs['State']['Status']
|
|
return self.attrs['State']
|
|
|
|
def attach(self, **kwargs):
|
|
"""
|
|
Attach to this container.
|
|
|
|
:py:meth:`logs` is a wrapper around this method, which you can
|
|
use instead if you want to fetch/stream container output without first
|
|
retrieving the entire backlog.
|
|
|
|
Args:
|
|
stdout (bool): Include stdout.
|
|
stderr (bool): Include stderr.
|
|
stream (bool): Return container output progressively as an iterator
|
|
of strings, rather than a single string.
|
|
logs (bool): Include the container's previous output.
|
|
|
|
Returns:
|
|
By default, the container's output as a single string.
|
|
|
|
If ``stream=True``, an iterator of output strings.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.attach(self.id, **kwargs)
|
|
|
|
def attach_socket(self, **kwargs):
|
|
"""
|
|
Like :py:meth:`attach`, but returns the underlying socket-like object
|
|
for the HTTP request.
|
|
|
|
Args:
|
|
params (dict): Dictionary of request parameters (e.g. ``stdout``,
|
|
``stderr``, ``stream``).
|
|
ws (bool): Use websockets instead of raw HTTP.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.attach_socket(self.id, **kwargs)
|
|
|
|
def commit(self, repository=None, tag=None, **kwargs):
|
|
"""
|
|
Commit a container to an image. Similar to the ``docker commit``
|
|
command.
|
|
|
|
Args:
|
|
repository (str): The repository to push the image to
|
|
tag (str): The tag to push
|
|
message (str): A commit message
|
|
author (str): The name of the author
|
|
changes (str): Dockerfile instructions to apply while committing
|
|
conf (dict): The configuration for the container. See the
|
|
`Engine API documentation
|
|
<https://docs.docker.com/reference/api/docker_remote_api/>`_
|
|
for full details.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
|
|
resp = self.client.api.commit(self.id, repository=repository, tag=tag,
|
|
**kwargs)
|
|
return self.client.images.get(resp['Id'])
|
|
|
|
def diff(self):
|
|
"""
|
|
Inspect changes on a container's filesystem.
|
|
|
|
Returns:
|
|
(str)
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.diff(self.id)
|
|
|
|
def exec_run(self, cmd, stdout=True, stderr=True, stdin=False, tty=False,
|
|
privileged=False, user='', detach=False, stream=False,
|
|
socket=False, environment=None, workdir=None, demux=False):
|
|
"""
|
|
Run a command inside this container. Similar to
|
|
``docker exec``.
|
|
|
|
Args:
|
|
cmd (str or list): Command to be executed
|
|
stdout (bool): Attach to stdout. Default: ``True``
|
|
stderr (bool): Attach to stderr. Default: ``True``
|
|
stdin (bool): Attach to stdin. Default: ``False``
|
|
tty (bool): Allocate a pseudo-TTY. Default: False
|
|
privileged (bool): Run as privileged.
|
|
user (str): User to execute command as. Default: root
|
|
detach (bool): If true, detach from the exec command.
|
|
Default: False
|
|
stream (bool): Stream response data. Default: False
|
|
socket (bool): Return the connection socket to allow custom
|
|
read/write operations. Default: False
|
|
environment (dict or list): A dictionary or a list of strings in
|
|
the following format ``["PASSWORD=xxx"]`` or
|
|
``{"PASSWORD": "xxx"}``.
|
|
workdir (str): Path to working directory for this exec session
|
|
demux (bool): Return stdout and stderr separately
|
|
|
|
Returns:
|
|
(ExecResult): A tuple of (exit_code, output)
|
|
exit_code: (int):
|
|
Exit code for the executed command or ``None`` if
|
|
either ``stream```or ``socket`` is ``True``.
|
|
output: (generator, bytes, or tuple):
|
|
If ``stream=True``, a generator yielding response chunks.
|
|
If ``socket=True``, a socket object for the connection.
|
|
If ``demux=True``, a tuple of two bytes: stdout and stderr.
|
|
A bytestring containing response data otherwise.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
resp = self.client.api.exec_create(
|
|
self.id, cmd, stdout=stdout, stderr=stderr, stdin=stdin, tty=tty,
|
|
privileged=privileged, user=user, environment=environment,
|
|
workdir=workdir,
|
|
)
|
|
exec_output = self.client.api.exec_start(
|
|
resp['Id'], detach=detach, tty=tty, stream=stream, socket=socket,
|
|
demux=demux
|
|
)
|
|
if socket or stream:
|
|
return ExecResult(None, exec_output)
|
|
|
|
return ExecResult(
|
|
self.client.api.exec_inspect(resp['Id'])['ExitCode'],
|
|
exec_output
|
|
)
|
|
|
|
def export(self, chunk_size=DEFAULT_DATA_CHUNK_SIZE):
|
|
"""
|
|
Export the contents of the container's filesystem as a tar archive.
|
|
|
|
Args:
|
|
chunk_size (int): The number of bytes returned by each iteration
|
|
of the generator. If ``None``, data will be streamed as it is
|
|
received. Default: 2 MB
|
|
|
|
Returns:
|
|
(str): The filesystem tar archive
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.export(self.id, chunk_size)
|
|
|
|
def get_archive(self, path, chunk_size=DEFAULT_DATA_CHUNK_SIZE):
|
|
"""
|
|
Retrieve a file or folder from the container in the form of a tar
|
|
archive.
|
|
|
|
Args:
|
|
path (str): Path to the file or folder to retrieve
|
|
chunk_size (int): The number of bytes returned by each iteration
|
|
of the generator. If ``None``, data will be streamed as it is
|
|
received. Default: 2 MB
|
|
|
|
Returns:
|
|
(tuple): First element is a raw tar data stream. Second element is
|
|
a dict containing ``stat`` information on the specified ``path``.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
|
|
Example:
|
|
|
|
>>> f = open('./sh_bin.tar', 'wb')
|
|
>>> bits, stat = container.get_archive('/bin/sh')
|
|
>>> print(stat)
|
|
{'name': 'sh', 'size': 1075464, 'mode': 493,
|
|
'mtime': '2018-10-01T15:37:48-07:00', 'linkTarget': ''}
|
|
>>> for chunk in bits:
|
|
... f.write(chunk)
|
|
>>> f.close()
|
|
"""
|
|
return self.client.api.get_archive(self.id, path, chunk_size)
|
|
|
|
def kill(self, signal=None):
|
|
"""
|
|
Kill or send a signal to the container.
|
|
|
|
Args:
|
|
signal (str or int): The signal to send. Defaults to ``SIGKILL``
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
|
|
return self.client.api.kill(self.id, signal=signal)
|
|
|
|
def logs(self, **kwargs):
|
|
"""
|
|
Get logs from this container. Similar to the ``docker logs`` command.
|
|
|
|
The ``stream`` parameter makes the ``logs`` function return a blocking
|
|
generator you can iterate over to retrieve log output as it happens.
|
|
|
|
Args:
|
|
stdout (bool): Get ``STDOUT``. Default ``True``
|
|
stderr (bool): Get ``STDERR``. Default ``True``
|
|
stream (bool): Stream the response. Default ``False``
|
|
timestamps (bool): Show timestamps. Default ``False``
|
|
tail (str or int): Output specified number of lines at the end of
|
|
logs. Either an integer of number of lines or the string
|
|
``all``. Default ``all``
|
|
since (datetime or int): Show logs since a given datetime or
|
|
integer epoch (in seconds)
|
|
follow (bool): Follow log output. Default ``False``
|
|
until (datetime or int): Show logs that occurred before the given
|
|
datetime or integer epoch (in seconds)
|
|
|
|
Returns:
|
|
(generator or str): Logs from the container.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.logs(self.id, **kwargs)
|
|
|
|
def pause(self):
|
|
"""
|
|
Pauses all processes within this container.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.pause(self.id)
|
|
|
|
def put_archive(self, path, data):
|
|
"""
|
|
Insert a file or folder in this container using a tar archive as
|
|
source.
|
|
|
|
Args:
|
|
path (str): Path inside the container where the file(s) will be
|
|
extracted. Must exist.
|
|
data (bytes): tar data to be extracted
|
|
|
|
Returns:
|
|
(bool): True if the call succeeds.
|
|
|
|
Raises:
|
|
:py:class:`~docker.errors.APIError` If an error occurs.
|
|
"""
|
|
return self.client.api.put_archive(self.id, path, data)
|
|
|
|
def remove(self, **kwargs):
|
|
"""
|
|
Remove this container. Similar to the ``docker rm`` command.
|
|
|
|
Args:
|
|
v (bool): Remove the volumes associated with the container
|
|
link (bool): Remove the specified link and not the underlying
|
|
container
|
|
force (bool): Force the removal of a running container (uses
|
|
``SIGKILL``)
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.remove_container(self.id, **kwargs)
|
|
|
|
def rename(self, name):
|
|
"""
|
|
Rename this container. Similar to the ``docker rename`` command.
|
|
|
|
Args:
|
|
name (str): New name for the container
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.rename(self.id, name)
|
|
|
|
def resize(self, height, width):
|
|
"""
|
|
Resize the tty session.
|
|
|
|
Args:
|
|
height (int): Height of tty session
|
|
width (int): Width of tty session
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.resize(self.id, height, width)
|
|
|
|
def restart(self, **kwargs):
|
|
"""
|
|
Restart this container. Similar to the ``docker restart`` command.
|
|
|
|
Args:
|
|
timeout (int): Number of seconds to try to stop for before killing
|
|
the container. Once killed it will then be restarted. Default
|
|
is 10 seconds.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.restart(self.id, **kwargs)
|
|
|
|
def start(self, **kwargs):
|
|
"""
|
|
Start this container. Similar to the ``docker start`` command, but
|
|
doesn't support attach options.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.start(self.id, **kwargs)
|
|
|
|
def stats(self, **kwargs):
|
|
"""
|
|
Stream statistics for this container. Similar to the
|
|
``docker stats`` command.
|
|
|
|
Args:
|
|
decode (bool): If set to true, stream will be decoded into dicts
|
|
on the fly. Only applicable if ``stream`` is True.
|
|
False by default.
|
|
stream (bool): If set to false, only the current stats will be
|
|
returned instead of a stream. True by default.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.stats(self.id, **kwargs)
|
|
|
|
def stop(self, **kwargs):
|
|
"""
|
|
Stops a container. Similar to the ``docker stop`` command.
|
|
|
|
Args:
|
|
timeout (int): Timeout in seconds to wait for the container to
|
|
stop before sending a ``SIGKILL``. Default: 10
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.stop(self.id, **kwargs)
|
|
|
|
def top(self, **kwargs):
|
|
"""
|
|
Display the running processes of the container.
|
|
|
|
Args:
|
|
ps_args (str): An optional arguments passed to ps (e.g. ``aux``)
|
|
|
|
Returns:
|
|
(str): The output of the top
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.top(self.id, **kwargs)
|
|
|
|
def unpause(self):
|
|
"""
|
|
Unpause all processes within the container.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.unpause(self.id)
|
|
|
|
def update(self, **kwargs):
|
|
"""
|
|
Update resource configuration of the containers.
|
|
|
|
Args:
|
|
blkio_weight (int): Block IO (relative weight), between 10 and 1000
|
|
cpu_period (int): Limit CPU CFS (Completely Fair Scheduler) period
|
|
cpu_quota (int): Limit CPU CFS (Completely Fair Scheduler) quota
|
|
cpu_shares (int): CPU shares (relative weight)
|
|
cpuset_cpus (str): CPUs in which to allow execution
|
|
cpuset_mems (str): MEMs in which to allow execution
|
|
mem_limit (int or str): Memory limit
|
|
mem_reservation (int or str): Memory soft limit
|
|
memswap_limit (int or str): Total memory (memory + swap), -1 to
|
|
disable swap
|
|
kernel_memory (int or str): Kernel memory limit
|
|
restart_policy (dict): Restart policy dictionary
|
|
|
|
Returns:
|
|
(dict): Dictionary containing a ``Warnings`` key.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.update_container(self.id, **kwargs)
|
|
|
|
def wait(self, **kwargs):
|
|
"""
|
|
Block until the container stops, then return its exit code. Similar to
|
|
the ``docker wait`` command.
|
|
|
|
Args:
|
|
timeout (int): Request timeout
|
|
condition (str): Wait until a container state reaches the given
|
|
condition, either ``not-running`` (default), ``next-exit``,
|
|
or ``removed``
|
|
|
|
Returns:
|
|
(dict): The API's response as a Python dictionary, including
|
|
the container's exit code under the ``StatusCode`` attribute.
|
|
|
|
Raises:
|
|
:py:class:`requests.exceptions.ReadTimeout`
|
|
If the timeout is exceeded.
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
return self.client.api.wait(self.id, **kwargs)
|
|
|
|
|
|
class ContainerCollection(Collection):
|
|
model = Container
|
|
|
|
def run(self, image, command=None, stdout=True, stderr=False,
|
|
remove=False, **kwargs):
|
|
"""
|
|
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.
|
|
cgroup_parent (str): Override the default parent cgroup.
|
|
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_rt_period (int): Limit CPU real-time period in microseconds.
|
|
cpu_rt_runtime (int): Limit CPU real-time runtime in microseconds.
|
|
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): Additional 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`.
|
|
kernel_memory (int or str): Kernel memory limit
|
|
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): Mapping of links using the
|
|
``{'container': 'alias'}`` format. The alias is optional.
|
|
Containers declared in this dict will be linked to the new
|
|
container using the provided alias. Default: ``None``.
|
|
log_config (LogConfig): Logging configuration.
|
|
lxc_conf (dict): LXC config.
|
|
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_reservation (int or str): Memory soft limit
|
|
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}``
|
|
|
|
runtime (str): Runtime to use with this container.
|
|
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 :py:class:`docker.types.Ulimit` instances.
|
|
use_config_proxy (bool): If ``True``, and if the docker client
|
|
configuration file (``~/.docker/config.json`` by default)
|
|
contains a proxy configuration, the corresponding environment
|
|
variables will be set in the container being built.
|
|
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``
|
|
uts_mode (str): Sets the UTS namespace mode for the container.
|
|
Supported values are: ``host``
|
|
version (str): The version of the API to use. Set to ``auto`` to
|
|
automatically detect the server's version. Default: ``1.35``
|
|
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.
|
|
|
|
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.
|
|
"""
|
|
if isinstance(image, Image):
|
|
image = image.id
|
|
stream = kwargs.pop('stream', False)
|
|
detach = kwargs.pop('detach', False)
|
|
platform = kwargs.pop('platform', None)
|
|
|
|
if detach and remove:
|
|
if version_gte(self.client.api._version, '1.25'):
|
|
kwargs["auto_remove"] = True
|
|
else:
|
|
raise RuntimeError("The options 'detach' and 'remove' cannot "
|
|
"be used together in api versions < 1.25.")
|
|
|
|
if kwargs.get('network') and kwargs.get('network_mode'):
|
|
raise RuntimeError(
|
|
'The options "network" and "network_mode" can not be used '
|
|
'together.'
|
|
)
|
|
|
|
try:
|
|
container = self.create(image=image, command=command,
|
|
detach=detach, **kwargs)
|
|
except ImageNotFound:
|
|
self.client.images.pull(image, platform=platform)
|
|
container = self.create(image=image, command=command,
|
|
detach=detach, **kwargs)
|
|
|
|
container.start()
|
|
|
|
if detach:
|
|
return container
|
|
|
|
logging_driver = container.attrs['HostConfig']['LogConfig']['Type']
|
|
|
|
out = None
|
|
if logging_driver == 'json-file' or logging_driver == 'journald':
|
|
out = container.logs(
|
|
stdout=stdout, stderr=stderr, stream=True, follow=True
|
|
)
|
|
|
|
exit_status = container.wait()['StatusCode']
|
|
if exit_status != 0:
|
|
out = None
|
|
if not kwargs.get('auto_remove'):
|
|
out = container.logs(stdout=False, stderr=True)
|
|
|
|
if remove:
|
|
container.remove()
|
|
if exit_status != 0:
|
|
raise ContainerError(
|
|
container, exit_status, command, image, out
|
|
)
|
|
|
|
return out if stream or out is None else b''.join(
|
|
[line for line in out]
|
|
)
|
|
|
|
def create(self, image, command=None, **kwargs):
|
|
"""
|
|
Create a container without starting it. Similar to ``docker create``.
|
|
|
|
Takes the same arguments as :py:meth:`run`, except for ``stdout``,
|
|
``stderr``, and ``remove``.
|
|
|
|
Returns:
|
|
A :py:class:`Container` object.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.ImageNotFound`
|
|
If the specified image does not exist.
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
if isinstance(image, Image):
|
|
image = image.id
|
|
kwargs['image'] = image
|
|
kwargs['command'] = command
|
|
kwargs['version'] = self.client.api._version
|
|
create_kwargs = _create_container_args(kwargs)
|
|
resp = self.client.api.create_container(**create_kwargs)
|
|
return self.get(resp['Id'])
|
|
|
|
def get(self, container_id):
|
|
"""
|
|
Get a container by name or ID.
|
|
|
|
Args:
|
|
container_id (str): Container name or ID.
|
|
|
|
Returns:
|
|
A :py:class:`Container` object.
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.NotFound`
|
|
If the container does not exist.
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
resp = self.client.api.inspect_container(container_id)
|
|
return self.prepare_model(resp)
|
|
|
|
def list(self, all=False, before=None, filters=None, limit=-1, since=None,
|
|
sparse=False, ignore_removed=False):
|
|
"""
|
|
List containers. Similar to the ``docker ps`` command.
|
|
|
|
Args:
|
|
all (bool): Show all containers. Only running containers are shown
|
|
by default
|
|
since (str): Show only containers created since Id or Name, include
|
|
non-running ones
|
|
before (str): Show only container created before Id or Name,
|
|
include non-running ones
|
|
limit (int): Show `limit` last created containers, include
|
|
non-running ones
|
|
filters (dict): Filters to be processed on the image list.
|
|
Available filters:
|
|
|
|
- `exited` (int): Only containers with specified exit code
|
|
- `status` (str): One of ``restarting``, ``running``,
|
|
``paused``, ``exited``
|
|
- `label` (str): format either ``"key"`` or ``"key=value"``
|
|
- `id` (str): The id of the container.
|
|
- `name` (str): The name of the container.
|
|
- `ancestor` (str): Filter by container ancestor. Format of
|
|
``<image-name>[:tag]``, ``<image-id>``, or
|
|
``<image@digest>``.
|
|
- `before` (str): Only containers created before a particular
|
|
container. Give the container name or id.
|
|
- `since` (str): Only containers created after a particular
|
|
container. Give container name or id.
|
|
|
|
A comprehensive list can be found in the documentation for
|
|
`docker ps
|
|
<https://docs.docker.com/engine/reference/commandline/ps>`_.
|
|
|
|
sparse (bool): Do not inspect containers. Returns partial
|
|
information, but guaranteed not to block. Use
|
|
:py:meth:`Container.reload` on resulting objects to retrieve
|
|
all attributes. Default: ``False``
|
|
ignore_removed (bool): Ignore failures due to missing containers
|
|
when attempting to inspect containers from the original list.
|
|
Set to ``True`` if race conditions are likely. Has no effect
|
|
if ``sparse=True``. Default: ``False``
|
|
|
|
Returns:
|
|
(list of :py:class:`Container`)
|
|
|
|
Raises:
|
|
:py:class:`docker.errors.APIError`
|
|
If the server returns an error.
|
|
"""
|
|
resp = self.client.api.containers(all=all, before=before,
|
|
filters=filters, limit=limit,
|
|
since=since)
|
|
if sparse:
|
|
return [self.prepare_model(r) for r in resp]
|
|
else:
|
|
containers = []
|
|
for r in resp:
|
|
try:
|
|
containers.append(self.get(r['Id']))
|
|
# a container may have been removed while iterating
|
|
except NotFound:
|
|
if not ignore_removed:
|
|
raise
|
|
return containers
|
|
|
|
def prune(self, filters=None):
|
|
return self.client.api.prune_containers(filters=filters)
|
|
prune.__doc__ = APIClient.prune_containers.__doc__
|
|
|
|
|
|
# kwargs to copy straight from run to create
|
|
RUN_CREATE_KWARGS = [
|
|
'command',
|
|
'detach',
|
|
'domainname',
|
|
'entrypoint',
|
|
'environment',
|
|
'healthcheck',
|
|
'hostname',
|
|
'image',
|
|
'labels',
|
|
'mac_address',
|
|
'name',
|
|
'network_disabled',
|
|
'stdin_open',
|
|
'stop_signal',
|
|
'tty',
|
|
'use_config_proxy',
|
|
'user',
|
|
'working_dir',
|
|
]
|
|
|
|
# kwargs to copy straight from run to host_config
|
|
RUN_HOST_CONFIG_KWARGS = [
|
|
'auto_remove',
|
|
'blkio_weight_device',
|
|
'blkio_weight',
|
|
'cap_add',
|
|
'cap_drop',
|
|
'cgroup_parent',
|
|
'cpu_count',
|
|
'cpu_percent',
|
|
'cpu_period',
|
|
'cpu_quota',
|
|
'cpu_shares',
|
|
'cpuset_cpus',
|
|
'cpuset_mems',
|
|
'cpu_rt_period',
|
|
'cpu_rt_runtime',
|
|
'device_cgroup_rules',
|
|
'device_read_bps',
|
|
'device_read_iops',
|
|
'device_write_bps',
|
|
'device_write_iops',
|
|
'devices',
|
|
'dns_opt',
|
|
'dns_search',
|
|
'dns',
|
|
'extra_hosts',
|
|
'group_add',
|
|
'init',
|
|
'init_path',
|
|
'ipc_mode',
|
|
'isolation',
|
|
'kernel_memory',
|
|
'links',
|
|
'log_config',
|
|
'lxc_conf',
|
|
'mem_limit',
|
|
'mem_reservation',
|
|
'mem_swappiness',
|
|
'memswap_limit',
|
|
'mounts',
|
|
'nano_cpus',
|
|
'network_mode',
|
|
'oom_kill_disable',
|
|
'oom_score_adj',
|
|
'pid_mode',
|
|
'pids_limit',
|
|
'privileged',
|
|
'publish_all_ports',
|
|
'read_only',
|
|
'restart_policy',
|
|
'security_opt',
|
|
'shm_size',
|
|
'storage_opt',
|
|
'sysctls',
|
|
'tmpfs',
|
|
'ulimits',
|
|
'userns_mode',
|
|
'uts_mode',
|
|
'version',
|
|
'volume_driver',
|
|
'volumes_from',
|
|
'runtime'
|
|
]
|
|
|
|
|
|
def _create_container_args(kwargs):
|
|
"""
|
|
Convert arguments to create() to arguments to create_container().
|
|
"""
|
|
# Copy over kwargs which can be copied directly
|
|
create_kwargs = {}
|
|
for key in copy.copy(kwargs):
|
|
if key in RUN_CREATE_KWARGS:
|
|
create_kwargs[key] = kwargs.pop(key)
|
|
host_config_kwargs = {}
|
|
for key in copy.copy(kwargs):
|
|
if key in RUN_HOST_CONFIG_KWARGS:
|
|
host_config_kwargs[key] = kwargs.pop(key)
|
|
|
|
# Process kwargs which are split over both create and host_config
|
|
ports = kwargs.pop('ports', {})
|
|
if ports:
|
|
host_config_kwargs['port_bindings'] = ports
|
|
|
|
volumes = kwargs.pop('volumes', {})
|
|
if volumes:
|
|
host_config_kwargs['binds'] = volumes
|
|
|
|
network = kwargs.pop('network', None)
|
|
if network:
|
|
create_kwargs['networking_config'] = {network: None}
|
|
host_config_kwargs['network_mode'] = network
|
|
|
|
# All kwargs should have been consumed by this point, so raise
|
|
# error if any are left
|
|
if kwargs:
|
|
raise create_unexpected_kwargs_error('run', kwargs)
|
|
|
|
create_kwargs['host_config'] = HostConfig(**host_config_kwargs)
|
|
|
|
# Fill in any kwargs which need processing by create_host_config first
|
|
port_bindings = create_kwargs['host_config'].get('PortBindings')
|
|
if port_bindings:
|
|
# sort to make consistent for tests
|
|
create_kwargs['ports'] = [tuple(p.split('/', 1))
|
|
for p in sorted(port_bindings.keys())]
|
|
if volumes:
|
|
if isinstance(volumes, dict):
|
|
create_kwargs['volumes'] = [
|
|
v.get('bind') for v in volumes.values()
|
|
]
|
|
else:
|
|
create_kwargs['volumes'] = [
|
|
_host_volume_from_bind(v) for v in volumes
|
|
]
|
|
return create_kwargs
|
|
|
|
|
|
def _host_volume_from_bind(bind):
|
|
drive, rest = ntpath.splitdrive(bind)
|
|
bits = rest.split(':', 1)
|
|
if len(bits) == 1 or bits[1] in ('ro', 'rw'):
|
|
return drive + bits[0]
|
|
else:
|
|
return bits[1].rstrip(':ro').rstrip(':rw')
|
|
|
|
|
|
ExecResult = namedtuple('ExecResult', 'exit_code,output')
|
|
""" A result of Container.exec_run with the properties ``exit_code`` and
|
|
``output``. """
|