summaryrefslogtreecommitdiff
path: root/docker/models/images.py
blob: cb9c80d21840fc8b1184324eea719b580758be59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
import re

import six

from ..api import APIClient
from ..errors import BuildError
from ..utils.json_stream import json_stream
from .resource import Collection, Model


class Image(Model):
    """
    An image on the server.
    """
    def __repr__(self):
        return "<%s: '%s'>" % (self.__class__.__name__, "', '".join(self.tags))

    @property
    def labels(self):
        """
        The labels of an image as dictionary.
        """
        result = self.attrs['Config'].get('Labels')
        return result or {}

    @property
    def short_id(self):
        """
        The ID of the image truncated to 10 characters, plus the ``sha256:``
        prefix.
        """
        if self.id.startswith('sha256:'):
            return self.id[:17]
        return self.id[:10]

    @property
    def tags(self):
        """
        The image's tags.
        """
        tags = self.attrs.get('RepoTags')
        if tags is None:
            tags = []
        return [tag for tag in tags if tag != '<none>:<none>']

    def history(self):
        """
        Show the history of an image.

        Returns:
            (str): The history of the image.

        Raises:
            :py:class:`docker.errors.APIError`
                If the server returns an error.
        """
        return self.client.api.history(self.id)

    def save(self):
        """
        Get a tarball of an image. Similar to the ``docker save`` command.

        Returns:
            (urllib3.response.HTTPResponse object): The response from the
            daemon.

        Raises:
            :py:class:`docker.errors.APIError`
                If the server returns an error.

        Example:

            >>> image = cli.images.get("fedora:latest")
            >>> resp = image.save()
            >>> f = open('/tmp/fedora-latest.tar', 'w')
            >>> for chunk in resp.stream():
            >>>     f.write(chunk)
            >>> f.close()
        """
        return self.client.api.get_image(self.id)

    def tag(self, repository, tag=None, **kwargs):
        """
        Tag this image into a repository. Similar to the ``docker tag``
        command.

        Args:
            repository (str): The repository to set for the tag
            tag (str): The tag name
            force (bool): Force

        Raises:
            :py:class:`docker.errors.APIError`
                If the server returns an error.

        Returns:
            (bool): ``True`` if successful
        """
        self.client.api.tag(self.id, repository, tag=tag, **kwargs)


class ImageCollection(Collection):
    model = Image

    def build(self, **kwargs):
        """
        Build an image and return it. Similar to the ``docker build``
        command. Either ``path`` or ``fileobj`` must be set.

        If you have a tar file for the Docker build context (including a
        Dockerfile) already, pass a readable file-like object to ``fileobj``
        and also pass ``custom_context=True``. If the stream is compressed
        also, set ``encoding`` to the correct value (e.g ``gzip``).

        If you want to get the raw output of the build, use the
        :py:meth:`~docker.api.build.BuildApiMixin.build` method in the
        low-level API.

        Args:
            path (str): Path to the directory containing the Dockerfile
            fileobj: A file object to use as the Dockerfile. (Or a file-like
                object)
            tag (str): A tag to add to the final image
            quiet (bool): Whether to return the status
            nocache (bool): Don't use the cache when set to ``True``
            rm (bool): Remove intermediate containers. The ``docker build``
                command now defaults to ``--rm=true``, but we have kept the old
                default of `False` to preserve backward compatibility
            stream (bool): *Deprecated for API version > 1.8 (always True)*.
                Return a blocking generator you can iterate over to retrieve
                build output as it happens
            timeout (int): HTTP timeout
            custom_context (bool): Optional if using ``fileobj``
            encoding (str): The encoding for a stream. Set to ``gzip`` for
                compressing
            pull (bool): Downloads any updates to the FROM image in Dockerfiles
            forcerm (bool): Always remove intermediate containers, even after
                unsuccessful builds
            dockerfile (str): path within the build context to the Dockerfile
            buildargs (dict): A dictionary of build arguments
            container_limits (dict): A dictionary of limits applied to each
                container created by the build process. Valid keys:

                - memory (int): set memory limit for build
                - memswap (int): Total memory (memory + swap), -1 to disable
                    swap
                - cpushares (int): CPU shares (relative weight)
                - cpusetcpus (str): CPUs in which to allow execution, e.g.,
                    ``"0-3"``, ``"0,1"``
            decode (bool): If set to ``True``, the returned stream will be
                decoded into dicts on the fly. Default ``False``.
            cache_from (list): A list of images used for build cache
                resolution.

        Returns:
            (:py:class:`Image`): The built image.

        Raises:
            :py:class:`docker.errors.BuildError`
                If there is an error during the build.
            :py:class:`docker.errors.APIError`
                If the server returns any other error.
            ``TypeError``
                If neither ``path`` nor ``fileobj`` is specified.
        """
        resp = self.client.api.build(**kwargs)
        if isinstance(resp, six.string_types):
            return self.get(resp)
        events = list(json_stream(resp))
        if not events:
            return BuildError('Unknown')
        for event in events:
            if 'stream' in event:
                match = re.search(r'(Successfully built |sha256:)([0-9a-f]+)',
                                  event.get('stream', ''))
                if match:
                    image_id = match.group(2)
                    return self.get(image_id)

        event = events[-1]
        raise BuildError(event.get('error') or event)

    def get(self, name):
        """
        Gets an image.

        Args:
            name (str): The name of the image.

        Returns:
            (:py:class:`Image`): The image.

        Raises:
            :py:class:`docker.errors.ImageNotFound` If the image does not
            exist.
            :py:class:`docker.errors.APIError`
                If the server returns an error.
        """
        return self.prepare_model(self.client.api.inspect_image(name))

    def list(self, name=None, all=False, filters=None):
        """
        List images on the server.

        Args:
            name (str): Only show images belonging to the repository ``name``
            all (bool): Show intermediate image layers. By default, these are
                filtered out.
            filters (dict): Filters to be processed on the image list.
                Available filters:
                - ``dangling`` (bool)
                - ``label`` (str): format either ``key`` or ``key=value``

        Returns:
            (list of :py:class:`Image`): The images.

        Raises:
            :py:class:`docker.errors.APIError`
                If the server returns an error.
        """
        resp = self.client.api.images(name=name, all=all, filters=filters)
        return [self.prepare_model(r) for r in resp]

    def load(self, data):
        """
        Load an image that was previously saved using
        :py:meth:`~docker.models.images.Image.save` (or ``docker save``).
        Similar to ``docker load``.

        Args:
            data (binary): Image data to be loaded.

        Raises:
            :py:class:`docker.errors.APIError`
                If the server returns an error.
        """
        return self.client.api.load_image(data)

    def pull(self, name, **kwargs):
        """
        Pull an image of the given name and return it. Similar to the
        ``docker pull`` command.

        If you want to get the raw pull output, use the
        :py:meth:`~docker.api.image.ImageApiMixin.pull` method in the
        low-level API.

        Args:
            repository (str): The repository to pull
            tag (str): The tag to pull
            insecure_registry (bool): Use an insecure registry
            auth_config (dict): Override the credentials that
                :py:meth:`~docker.client.DockerClient.login` has set for
                this request. ``auth_config`` should contain the ``username``
                and ``password`` keys to be valid.

        Returns:
            (:py:class:`Image`): The image that has been pulled.

        Raises:
            :py:class:`docker.errors.APIError`
                If the server returns an error.

        Example:

            >>> image = client.images.pull('busybox')
        """
        self.client.api.pull(name, **kwargs)
        return self.get(name)

    def push(self, repository, tag=None, **kwargs):
        return self.client.api.push(repository, tag=tag, **kwargs)
    push.__doc__ = APIClient.push.__doc__

    def remove(self, *args, **kwargs):
        self.client.api.remove_image(*args, **kwargs)
    remove.__doc__ = APIClient.remove_image.__doc__

    def search(self, *args, **kwargs):
        return self.client.api.search(*args, **kwargs)
    search.__doc__ = APIClient.search.__doc__

    def prune(self, filters=None):
        return self.client.api.prune_images(filters=filters)
    prune.__doc__ = APIClient.prune_images.__doc__