Skip to content

Commit

Permalink
feat: support cpuperiod and cpuquota build arguments (Docker v1.19+)
Browse files Browse the repository at this point in the history
Add support for the new container limits introduced in Docker v1.19
for restricting cpu usage during build.

See https://docs.docker.com/engine/api/version-history/#v119-api-changes

Signed-off-by: Lucy Linder <lucy.derlin@gmail.com>
  • Loading branch information
derlin committed May 31, 2024
1 parent a365202 commit c6f715b
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 4 deletions.
11 changes: 11 additions & 0 deletions docker/api/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
- cpushares (int): CPU shares (relative weight)
- cpusetcpus (str): CPUs in which to allow execution, e.g.,
``"0-3"``, ``"0,1"``
- cpuperiod (int): (Docker API v1.19+) The length of a CPU
period in microseconds
- cpuquota (int): (Docker API v1.19+) Microseconds of CPU
time that the container can get in a CPU period
decode (bool): If set to ``True``, the returned stream will be
decoded into dicts on the fly. Default ``False``
shmsize (int): Size of `/dev/shm` in bytes. The size must be
Expand Down Expand Up @@ -135,6 +139,13 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
raise errors.DockerException(
f"invalid tag '{tag}': invalid reference format"
)
introduced_in = constants.CONTAINER_LIMITS_KEYS[key]
if introduced_in is not None:
if utils.version_lt(self._version, introduced_in):
raise errors.InvalidVersion(
f"container limit '{key}' was only introduced"
f" in API version {introduced_in}"
)
if custom_context:
if not fileobj:
raise TypeError("You must specify fileobj with custom_context")
Expand Down
11 changes: 8 additions & 3 deletions docker/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
MINIMUM_DOCKER_API_VERSION = '1.24'
DEFAULT_TIMEOUT_SECONDS = 60
STREAM_HEADER_SIZE_BYTES = 8
CONTAINER_LIMITS_KEYS = [
'memory', 'memswap', 'cpushares', 'cpusetcpus'
]
CONTAINER_LIMITS_KEYS = {
'memory': None,
'memswap': None,
'cpushares': None,
'cpusetcpus': None,
'cpuperiod': "1.19",
'cpuquota': "1.19",
}

DEFAULT_HTTP_HOST = "127.0.0.1"
DEFAULT_UNIX_SOCKET = "http+unix:///var/run/docker.sock"
Expand Down
4 changes: 4 additions & 0 deletions docker/models/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ def build(self, **kwargs):
- cpushares (int): CPU shares (relative weight)
- cpusetcpus (str): CPUs in which to allow execution, e.g.,
``"0-3"``, ``"0,1"``
- cpuperiod (int): (Docker API v1.19+) The length of a CPU
period in microseconds
- cpuquota (int): (Docker API v1.19+) Microseconds of CPU
time that the container can get in a CPU period
shmsize (int): Size of `/dev/shm` in bytes. The size must be
greater than 0. If omitted the system uses 64MB
labels (dict): A dictionary of labels to set on the image
Expand Down
12 changes: 11 additions & 1 deletion tests/unit/api_build_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from docker import auth, errors
from docker.api.build import process_dockerfile

from ..helpers import make_tree
from ..helpers import make_tree, requires_api_version
from .api_test import BaseAPIClientTest, fake_request, url_prefix


Expand Down Expand Up @@ -133,6 +133,16 @@ def test_build_container_with_container_limits(self):
},
)

@requires_api_version('1.19')
def test_build_container_with_container_limits_cpu(self):
self.client.build(
".",
container_limits={
"cpuquota": 50000,
"cpuperiod": 100000,
},
)

def test_build_container_invalid_container_limits(self):
with pytest.raises(docker.errors.DockerException):
self.client.build(".", container_limits={"foo": "bar"})
Expand Down

0 comments on commit c6f715b

Please sign in to comment.